From 93e5f0b65ab8bf5cfdc699887eb3fbd877e252d9 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 15 Jun 2017 20:12:52 +0300 Subject: drm/i915: Make intel_digital_port_connected() work for any port MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the missing port A handling to intel_digital_port_connected() and also separate SPT from the CPT/LPT code a bit. Cc: Manasi Navare Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/20170615171252.11921-1-ville.syrjala@linux.intel.com Reviewed-by: Manasi Navare --- drivers/gpu/drm/i915/intel_dp.c | 83 ++++++++++++++++++++++++++++++++++------- 1 file changed, 70 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 7a3a42c95381..2eb6e0ff143a 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4444,8 +4444,6 @@ static bool ibx_digital_port_connected(struct drm_i915_private *dev_priv, u32 bit; switch (port->port) { - case PORT_A: - return true; case PORT_B: bit = SDE_PORTB_HOTPLUG; break; @@ -4469,8 +4467,6 @@ static bool cpt_digital_port_connected(struct drm_i915_private *dev_priv, u32 bit; switch (port->port) { - case PORT_A: - return true; case PORT_B: bit = SDE_PORTB_HOTPLUG_CPT; break; @@ -4480,12 +4476,28 @@ static bool cpt_digital_port_connected(struct drm_i915_private *dev_priv, case PORT_D: bit = SDE_PORTD_HOTPLUG_CPT; break; + default: + MISSING_CASE(port->port); + return false; + } + + return I915_READ(SDEISR) & bit; +} + +static bool spt_digital_port_connected(struct drm_i915_private *dev_priv, + struct intel_digital_port *port) +{ + u32 bit; + + switch (port->port) { + case PORT_A: + bit = SDE_PORTA_HOTPLUG_SPT; + break; case PORT_E: bit = SDE_PORTE_HOTPLUG_SPT; break; default: - MISSING_CASE(port->port); - return false; + return cpt_digital_port_connected(dev_priv, port); } return I915_READ(SDEISR) & bit; @@ -4537,6 +4549,42 @@ static bool gm45_digital_port_connected(struct drm_i915_private *dev_priv, return I915_READ(PORT_HOTPLUG_STAT) & bit; } +static bool ilk_digital_port_connected(struct drm_i915_private *dev_priv, + struct intel_digital_port *port) +{ + if (port->port == PORT_A) + return I915_READ(DEISR) & DE_DP_A_HOTPLUG; + else + return ibx_digital_port_connected(dev_priv, port); +} + +static bool snb_digital_port_connected(struct drm_i915_private *dev_priv, + struct intel_digital_port *port) +{ + if (port->port == PORT_A) + return I915_READ(DEISR) & DE_DP_A_HOTPLUG; + else + return cpt_digital_port_connected(dev_priv, port); +} + +static bool ivb_digital_port_connected(struct drm_i915_private *dev_priv, + struct intel_digital_port *port) +{ + if (port->port == PORT_A) + return I915_READ(DEISR) & DE_DP_A_HOTPLUG_IVB; + else + return cpt_digital_port_connected(dev_priv, port); +} + +static bool bdw_digital_port_connected(struct drm_i915_private *dev_priv, + struct intel_digital_port *port) +{ + if (port->port == PORT_A) + return I915_READ(GEN8_DE_PORT_ISR) & GEN8_PORT_DP_A_HOTPLUG; + else + return cpt_digital_port_connected(dev_priv, port); +} + static bool bxt_digital_port_connected(struct drm_i915_private *dev_priv, struct intel_digital_port *intel_dig_port) { @@ -4573,16 +4621,25 @@ static bool bxt_digital_port_connected(struct drm_i915_private *dev_priv, bool intel_digital_port_connected(struct drm_i915_private *dev_priv, struct intel_digital_port *port) { - if (HAS_PCH_IBX(dev_priv)) - return ibx_digital_port_connected(dev_priv, port); - else if (HAS_PCH_SPLIT(dev_priv)) - return cpt_digital_port_connected(dev_priv, port); + if (HAS_GMCH_DISPLAY(dev_priv)) { + if (IS_GM45(dev_priv)) + return gm45_digital_port_connected(dev_priv, port); + else + return g4x_digital_port_connected(dev_priv, port); + } + + if (IS_GEN5(dev_priv)) + return ilk_digital_port_connected(dev_priv, port); + else if (IS_GEN6(dev_priv)) + return snb_digital_port_connected(dev_priv, port); + else if (IS_GEN7(dev_priv)) + return ivb_digital_port_connected(dev_priv, port); + else if (IS_GEN8(dev_priv)) + return bdw_digital_port_connected(dev_priv, port); else if (IS_GEN9_LP(dev_priv)) return bxt_digital_port_connected(dev_priv, port); - else if (IS_GM45(dev_priv)) - return gm45_digital_port_connected(dev_priv, port); else - return g4x_digital_port_connected(dev_priv, port); + return spt_digital_port_connected(dev_priv, port); } static struct edid * -- cgit v1.2.3 From 1f588aeb60b4412019546ce596f179635abc2ac3 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Mon, 19 Jun 2017 11:39:32 -0700 Subject: drm/i915/cnl: Fix RMW on ddi vswing sequence. Paulo noticed that we were missing few bits clear before writing values back to the register on these RMW MMIO operations. v2: Remove "POST_" from CURSOR_COEFF_MASK. (Paulo). v3: Remove unnecessary braces. (Jani). Fixes: cf54ca8bc567 ("drm/i915/cnl: Implement voltage swing sequence.") Cc: Paulo Zanoni Cc: Manasi Navare Cc: Jani Nikula Signed-off-by: Rodrigo Vivi Reviewed-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1497897572-22520-1-git-send-email-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/i915_reg.h | 9 +++++++++ drivers/gpu/drm/i915/intel_ddi.c | 7 +++++++ 2 files changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index bd535f12db18..c8647cfa81ba 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1764,8 +1764,11 @@ enum skl_disp_power_wells { _CNL_PORT_TX_DW2_LN0_AE, \ _CNL_PORT_TX_DW2_LN0_F) #define SWING_SEL_UPPER(x) ((x >> 3) << 15) +#define SWING_SEL_UPPER_MASK (1 << 15) #define SWING_SEL_LOWER(x) ((x & 0x7) << 11) +#define SWING_SEL_LOWER_MASK (0x7 << 11) #define RCOMP_SCALAR(x) ((x) << 0) +#define RCOMP_SCALAR_MASK (0xFF << 0) #define _CNL_PORT_TX_DW4_GRP_AE 0x162350 #define _CNL_PORT_TX_DW4_GRP_B 0x1623D0 @@ -1795,8 +1798,11 @@ enum skl_disp_power_wells { _CNL_PORT_TX_DW4_LN0_F) #define LOADGEN_SELECT (1 << 31) #define POST_CURSOR_1(x) ((x) << 12) +#define POST_CURSOR_1_MASK (0x3F << 12) #define POST_CURSOR_2(x) ((x) << 6) +#define POST_CURSOR_2_MASK (0x3F << 6) #define CURSOR_COEFF(x) ((x) << 0) +#define CURSOR_COEFF_MASK (0x3F << 6) #define _CNL_PORT_TX_DW5_GRP_AE 0x162354 #define _CNL_PORT_TX_DW5_GRP_B 0x1623D4 @@ -1825,7 +1831,9 @@ enum skl_disp_power_wells { #define TX_TRAINING_EN (1 << 31) #define TAP3_DISABLE (1 << 29) #define SCALING_MODE_SEL(x) ((x) << 18) +#define SCALING_MODE_SEL_MASK (0x7 << 18) #define RTERM_SELECT(x) ((x) << 3) +#define RTERM_SELECT_MASK (0x7 << 3) #define _CNL_PORT_TX_DW7_GRP_AE 0x16235C #define _CNL_PORT_TX_DW7_GRP_B 0x1623DC @@ -1852,6 +1860,7 @@ enum skl_disp_power_wells { _CNL_PORT_TX_DW7_LN0_AE, \ _CNL_PORT_TX_DW7_LN0_F) #define N_SCALAR(x) ((x) << 24) +#define N_SCALAR_MASK (0x7F << 24) /* The spec defines this only for BXT PHY0, but lets assume that this * would exist for PHY1 too if it had a second channel. diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index db8093863f0c..80e96f1f49d2 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1813,11 +1813,14 @@ static void cnl_ddi_vswing_program(struct drm_i915_private *dev_priv, /* Set PORT_TX_DW5 Scaling Mode Sel to 010b. */ val = I915_READ(CNL_PORT_TX_DW5_LN0(port)); + val &= ~SCALING_MODE_SEL_MASK; val |= SCALING_MODE_SEL(2); I915_WRITE(CNL_PORT_TX_DW5_GRP(port), val); /* Program PORT_TX_DW2 */ val = I915_READ(CNL_PORT_TX_DW2_LN0(port)); + val &= ~(SWING_SEL_LOWER_MASK | SWING_SEL_UPPER_MASK | + RCOMP_SCALAR_MASK); val |= SWING_SEL_UPPER(ddi_translations[level].dw2_swing_sel); val |= SWING_SEL_LOWER(ddi_translations[level].dw2_swing_sel); /* Rcomp scalar is fixed as 0x98 for every table entry */ @@ -1828,6 +1831,8 @@ static void cnl_ddi_vswing_program(struct drm_i915_private *dev_priv, /* We cannot write to GRP. It would overrite individual loadgen */ for (ln = 0; ln < 4; ln++) { val = I915_READ(CNL_PORT_TX_DW4_LN(port, ln)); + val &= ~(POST_CURSOR_1_MASK | POST_CURSOR_2_MASK | + CURSOR_COEFF_MASK); val |= POST_CURSOR_1(ddi_translations[level].dw4_post_cursor_1); val |= POST_CURSOR_2(ddi_translations[level].dw4_post_cursor_2); val |= CURSOR_COEFF(ddi_translations[level].dw4_cursor_coeff); @@ -1837,12 +1842,14 @@ static void cnl_ddi_vswing_program(struct drm_i915_private *dev_priv, /* Program PORT_TX_DW5 */ /* All DW5 values are fixed for every table entry */ val = I915_READ(CNL_PORT_TX_DW5_LN0(port)); + val &= ~RTERM_SELECT_MASK; val |= RTERM_SELECT(6); val |= TAP3_DISABLE; I915_WRITE(CNL_PORT_TX_DW5_GRP(port), val); /* Program PORT_TX_DW7 */ val = I915_READ(CNL_PORT_TX_DW7_LN0(port)); + val &= ~N_SCALAR_MASK; val |= N_SCALAR(ddi_translations[level].dw7_n_scalar); I915_WRITE(CNL_PORT_TX_DW7_GRP(port), val); } -- cgit v1.2.3 From fc5e9d63a8db40e9e3a3b180be33d44af8a3cee8 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 24 May 2017 16:52:05 +0200 Subject: drm/sti: Drop drm_vblank_cleanup Seems entirely cargo-culted. Cc: Benjamin Gaignard Cc: Vincent Abriou Acked-by: Vincent Abriou Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170524145212.27837-31-daniel.vetter@ffwll.ch --- drivers/gpu/drm/sti/sti_drv.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c index a4b574283269..06ef1e3886cf 100644 --- a/drivers/gpu/drm/sti/sti_drv.c +++ b/drivers/gpu/drm/sti/sti_drv.c @@ -237,7 +237,6 @@ static void sti_cleanup(struct drm_device *ddev) } drm_kms_helper_poll_fini(ddev); - drm_vblank_cleanup(ddev); component_unbind_all(ddev->dev, ddev); kfree(private); ddev->dev_private = NULL; -- cgit v1.2.3 From 00a9121b8698ddf7fcb18e107405afacc35f748a Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 24 May 2017 16:52:08 +0200 Subject: drm/tegra: Drop drm_vblank_cleanup Again, doesn't seem to serve a purpose. Cc: Thierry Reding Acked-by: Thierry Reding Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170524145212.27837-34-daniel.vetter@ffwll.ch --- drivers/gpu/drm/tegra/drm.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index 51c48a8e00ec..0d8839244c3a 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -213,12 +213,10 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags) err = tegra_drm_fb_init(drm); if (err < 0) - goto vblank; + goto device; return 0; -vblank: - drm_vblank_cleanup(drm); device: host1x_device_exit(device); fbdev: @@ -247,7 +245,6 @@ static void tegra_drm_unload(struct drm_device *drm) drm_kms_helper_poll_fini(drm); tegra_drm_fb_exit(drm); drm_mode_config_cleanup(drm); - drm_vblank_cleanup(drm); err = host1x_device_exit(device); if (err < 0) -- cgit v1.2.3 From 57d30230c573e3f1a49ae7e0f7f8b73b17881415 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 24 May 2017 16:51:45 +0200 Subject: drm/doc: vblank cleanup Unify and review everything, plus make sure it's all correct markup. Drop the kernel-doc for internal functions. Also rework the overview section, it's become rather outdated. Unfortuantely the kernel-doc in drm_driver isn't rendered yet, but that will change as soon as drm_driver is kernel-docified properly. Also document properly that drm_vblank_cleanup is optional, the core calls this already. v2: Make it clear that cleanup happens in drm_dev_fini for drivers with their own ->release callback (Thierry). Acked-by: Thierry Reding Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170524145212.27837-11-daniel.vetter@ffwll.ch --- Documentation/gpu/drm-kms.rst | 56 +-------------- drivers/gpu/drm/drm_vblank.c | 158 ++++++++++++++++++++---------------------- include/drm/drmP.h | 37 ++++++++-- include/drm/drm_crtc.h | 3 + 4 files changed, 113 insertions(+), 141 deletions(-) (limited to 'drivers') diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst index 0749000ab3d7..307284125d7a 100644 --- a/Documentation/gpu/drm-kms.rst +++ b/Documentation/gpu/drm-kms.rst @@ -551,60 +551,8 @@ various modules/drivers. Vertical Blanking ================= -Vertical blanking plays a major role in graphics rendering. To achieve -tear-free display, users must synchronize page flips and/or rendering to -vertical blanking. The DRM API offers ioctls to perform page flips -synchronized to vertical blanking and wait for vertical blanking. - -The DRM core handles most of the vertical blanking management logic, -which involves filtering out spurious interrupts, keeping race-free -blanking counters, coping with counter wrap-around and resets and -keeping use counts. It relies on the driver to generate vertical -blanking interrupts and optionally provide a hardware vertical blanking -counter. Drivers must implement the following operations. - -- int (\*enable_vblank) (struct drm_device \*dev, int crtc); void - (\*disable_vblank) (struct drm_device \*dev, int crtc); - Enable or disable vertical blanking interrupts for the given CRTC. - -- u32 (\*get_vblank_counter) (struct drm_device \*dev, int crtc); - Retrieve the value of the vertical blanking counter for the given - CRTC. If the hardware maintains a vertical blanking counter its value - should be returned. Otherwise drivers can use the - :c:func:`drm_vblank_count()` helper function to handle this - operation. - -Drivers must initialize the vertical blanking handling core with a call -to :c:func:`drm_vblank_init()` in their load operation. - -Vertical blanking interrupts can be enabled by the DRM core or by -drivers themselves (for instance to handle page flipping operations). -The DRM core maintains a vertical blanking use count to ensure that the -interrupts are not disabled while a user still needs them. To increment -the use count, drivers call :c:func:`drm_vblank_get()`. Upon -return vertical blanking interrupts are guaranteed to be enabled. - -To decrement the use count drivers call -:c:func:`drm_vblank_put()`. Only when the use count drops to zero -will the DRM core disable the vertical blanking interrupts after a delay -by scheduling a timer. The delay is accessible through the -vblankoffdelay module parameter or the ``drm_vblank_offdelay`` global -variable and expressed in milliseconds. Its default value is 5000 ms. -Zero means never disable, and a negative value means disable -immediately. Drivers may override the behaviour by setting the -:c:type:`struct drm_device ` -vblank_disable_immediate flag, which when set causes vblank interrupts -to be disabled immediately regardless of the drm_vblank_offdelay -value. The flag should only be set if there's a properly working -hardware vblank counter present. - -When a vertical blanking interrupt occurs drivers only need to call the -:c:func:`drm_handle_vblank()` function to account for the -interrupt. - -Resources allocated by :c:func:`drm_vblank_init()` must be freed -with a call to :c:func:`drm_vblank_cleanup()` in the driver unload -operation handler. +.. kernel-doc:: drivers/gpu/drm/drm_vblank.c + :doc: vblank handling Vertical Blanking and Interrupt Handling Functions Reference ------------------------------------------------------------ diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index 463e4d81fb0d..d833b202f3c7 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -31,6 +31,41 @@ #include "drm_trace.h" #include "drm_internal.h" +/** + * DOC: vblank handling + * + * Vertical blanking plays a major role in graphics rendering. To achieve + * tear-free display, users must synchronize page flips and/or rendering to + * vertical blanking. The DRM API offers ioctls to perform page flips + * synchronized to vertical blanking and wait for vertical blanking. + * + * The DRM core handles most of the vertical blanking management logic, which + * involves filtering out spurious interrupts, keeping race-free blanking + * counters, coping with counter wrap-around and resets and keeping use counts. + * It relies on the driver to generate vertical blanking interrupts and + * optionally provide a hardware vertical blanking counter. + * + * Drivers must initialize the vertical blanking handling core with a call to + * drm_vblank_init(). Minimally, a driver needs to implement + * &drm_crtc_funcs.enable_vblank and &drm_crtc_funcs.disable_vblank plus call + * drm_crtc_handle_vblank() in it's vblank interrupt handler for working vblank + * support. + * + * Vertical blanking interrupts can be enabled by the DRM core or by drivers + * themselves (for instance to handle page flipping operations). The DRM core + * maintains a vertical blanking use count to ensure that the interrupts are not + * disabled while a user still needs them. To increment the use count, drivers + * call drm_crtc_vblank_get() and release the vblank reference again with + * drm_crtc_vblank_put(). In between these two calls vblank interrupts are + * guaranteed to be enabled. + * + * On many hardware disabling the vblank interrupt cannot be done in a race-free + * manner, see &drm_driver.vblank_disable_immediate and + * &drm_driver.max_vblank_count. In that case the vblank core only disables the + * vblanks after a timer has expired, which can be configured through the + * ``vblankoffdelay`` module parameter. + */ + /* Retry timestamp calculation up to 3 times to satisfy * drm_timestamp_precision before giving up. */ @@ -262,11 +297,12 @@ static u32 drm_vblank_count(struct drm_device *dev, unsigned int pipe) * drm_accurate_vblank_count - retrieve the master vblank counter * @crtc: which counter to retrieve * - * This function is similar to @drm_crtc_vblank_count but this - * function interpolates to handle a race with vblank irq's. + * This function is similar to drm_crtc_vblank_count() but this function + * interpolates to handle a race with vblank interrupts using the high precision + * timestamping support. * - * This is mostly useful for hardware that can obtain the scanout - * position, but doesn't have a frame counter. + * This is mostly useful for hardware that can obtain the scanout position, but + * doesn't have a hardware frame counter. */ u32 drm_accurate_vblank_count(struct drm_crtc *crtc) { @@ -362,10 +398,14 @@ static void vblank_disable_fn(unsigned long arg) * drm_vblank_cleanup - cleanup vblank support * @dev: DRM device * - * This function cleans up any resources allocated in drm_vblank_init. + * This function cleans up any resources allocated in drm_vblank_init(). It is + * called by the DRM core when @dev is finalized. + * + * Drivers can call drm_vblank_cleanup() if they need to quiescent the vblank + * interrupt in their unload code. But in general this should be handled by + * disabling all active &drm_crtc through e.g. drm_atomic_helper_shutdown, which + * should end up calling drm_crtc_vblank_off(). * - * Drivers which don't use drm_irq_install() need to set &drm_device.irq_enabled - * themselves, to signal to the DRM core that vblank interrupts are enabled. */ void drm_vblank_cleanup(struct drm_device *dev) { @@ -396,6 +436,9 @@ EXPORT_SYMBOL(drm_vblank_cleanup); * @num_crtcs: number of CRTCs supported by @dev * * This function initializes vblank support for @num_crtcs display pipelines. + * Drivers do not need to call drm_vblank_cleanup(), cleanup is already handled + * by the DRM core, or through calling drm_dev_fini() for drivers with a + * &drm_driver.release callback. * * Returns: * Zero on success or a negative error code on failure. @@ -468,11 +511,11 @@ EXPORT_SYMBOL(drm_crtc_vblank_waitqueue); * @crtc: drm_crtc whose timestamp constants should be updated. * @mode: display mode containing the scanout timings * - * Calculate and store various constants which are later - * needed by vblank and swap-completion timestamping, e.g, - * by drm_calc_vbltimestamp_from_scanoutpos(). They are - * derived from CRTC's true scanout timing, so they take - * things like panel scaling or other adjustments into account. + * Calculate and store various constants which are later needed by vblank and + * swap-completion timestamping, e.g, by + * drm_calc_vbltimestamp_from_scanoutpos(). They are derived from CRTC's true + * scanout timing, so they take things like panel scaling or other adjustments + * into account. */ void drm_calc_timestamping_constants(struct drm_crtc *crtc, const struct drm_display_mode *mode) @@ -535,25 +578,14 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants); * if flag is set. * * Implements calculation of exact vblank timestamps from given drm_display_mode - * timings and current video scanout position of a CRTC. This can be called from - * within get_vblank_timestamp() implementation of a kms driver to implement the - * actual timestamping. - * - * Should return timestamps conforming to the OML_sync_control OpenML - * extension specification. The timestamp corresponds to the end of - * the vblank interval, aka start of scanout of topmost-leftmost display - * pixel in the following video frame. - * - * Requires support for optional dev->driver->get_scanout_position() - * in kms driver, plus a bit of setup code to provide a drm_display_mode - * that corresponds to the true scanout timing. - * - * The current implementation only handles standard video modes. It - * returns as no operation if a doublescan or interlaced video mode is - * active. Higher level code is expected to handle this. + * timings and current video scanout position of a CRTC. This can be directly + * used as the &drm_driver.get_vblank_timestamp implementation of a kms driver + * if &drm_driver.get_scanout_position is implemented. * - * This function can be used to implement the &drm_driver.get_vblank_timestamp - * directly, if the driver implements the &drm_driver.get_scanout_position hook. + * The current implementation only handles standard video modes. For double scan + * and interlaced modes the driver is supposed to adjust the hardware mode + * (taken from &drm_crtc_state.adjusted mode for atomic modeset drivers) to + * match the scanout position reported. * * Note that atomic drivers must call drm_calc_timestamping_constants() before * enabling a CRTC. The atomic helpers already take care of that in @@ -738,7 +770,9 @@ drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe, * * Fetches the "cooked" vblank count value that represents the number of * vblank events since the system was booted, including lost events due to - * modesetting activity. + * modesetting activity. Note that this timer isn't correct against a racing + * vblank interrupt (since it only reports the software vblank counter), see + * drm_accurate_vblank_count() for such use-cases. * * Returns: * The software vblank counter. @@ -749,20 +783,6 @@ u32 drm_crtc_vblank_count(struct drm_crtc *crtc) } EXPORT_SYMBOL(drm_crtc_vblank_count); -/** - * drm_vblank_count_and_time - retrieve "cooked" vblank counter value and the - * system timestamp corresponding to that vblank counter value. - * @dev: DRM device - * @pipe: index of CRTC whose counter to retrieve - * @vblanktime: Pointer to struct timeval to receive the vblank timestamp. - * - * Fetches the "cooked" vblank count value that represents the number of - * vblank events since the system was booted, including lost events due to - * modesetting activity. Returns corresponding system timestamp of the time - * of the vblank interval that corresponds to the current vblank counter value. - * - * This is the legacy version of drm_crtc_vblank_count_and_time(). - */ static u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe, struct timeval *vblanktime) { @@ -852,8 +872,8 @@ static void send_vblank_event(struct drm_device *dev, * handler by calling drm_crtc_send_vblank_event() and make sure that there's no * possible race with the hardware committing the atomic update. * - * Caller must hold event lock. Caller must also hold a vblank reference for - * the event @e, which will be dropped when the next vblank arrives. + * Caller must hold a vblank reference for the event @e, which will be dropped + * when the next vblank arrives. */ void drm_crtc_arm_vblank_event(struct drm_crtc *crtc, struct drm_pending_vblank_event *e) @@ -913,14 +933,6 @@ static int __enable_vblank(struct drm_device *dev, unsigned int pipe) return dev->driver->enable_vblank(dev, pipe); } -/** - * drm_vblank_enable - enable the vblank interrupt on a CRTC - * @dev: DRM device - * @pipe: CRTC index - * - * Returns: - * Zero on success or a negative error code on failure. - */ static int drm_vblank_enable(struct drm_device *dev, unsigned int pipe) { struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; @@ -958,19 +970,6 @@ static int drm_vblank_enable(struct drm_device *dev, unsigned int pipe) return ret; } -/** - * drm_vblank_get - get a reference count on vblank events - * @dev: DRM device - * @pipe: index of CRTC to own - * - * Acquire a reference count on vblank events to avoid having them disabled - * while in use. - * - * This is the legacy version of drm_crtc_vblank_get(). - * - * Returns: - * Zero on success or a negative error code on failure. - */ static int drm_vblank_get(struct drm_device *dev, unsigned int pipe) { struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; @@ -1014,16 +1013,6 @@ int drm_crtc_vblank_get(struct drm_crtc *crtc) } EXPORT_SYMBOL(drm_crtc_vblank_get); -/** - * drm_vblank_put - release ownership of vblank events - * @dev: DRM device - * @pipe: index of CRTC to release - * - * Release ownership of a given vblank counter, turning off interrupts - * if possible. Disable interrupts after drm_vblank_offdelay milliseconds. - * - * This is the legacy version of drm_crtc_vblank_put(). - */ static void drm_vblank_put(struct drm_device *dev, unsigned int pipe) { struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; @@ -1067,6 +1056,8 @@ EXPORT_SYMBOL(drm_crtc_vblank_put); * This waits for one vblank to pass on @pipe, using the irq driver interfaces. * It is a failure to call this when the vblank irq for @pipe is disabled, e.g. * due to lack of driver support or because the crtc is off. + * + * This is the legacy version of drm_crtc_wait_one_vblank(). */ void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe) { @@ -1116,7 +1107,7 @@ EXPORT_SYMBOL(drm_crtc_wait_one_vblank); * stored so that drm_vblank_on can restore it again. * * Drivers must use this function when the hardware vblank counter can get - * reset, e.g. when suspending. + * reset, e.g. when suspending or disabling the @crtc in general. */ void drm_crtc_vblank_off(struct drm_crtc *crtc) { @@ -1184,6 +1175,8 @@ EXPORT_SYMBOL(drm_crtc_vblank_off); * drm_crtc_vblank_on() functions. The difference compared to * drm_crtc_vblank_off() is that this function doesn't save the vblank counter * and hence doesn't need to call any driver hooks. + * + * This is useful for recovering driver state e.g. on driver load, or on resume. */ void drm_crtc_vblank_reset(struct drm_crtc *crtc) { @@ -1212,9 +1205,10 @@ EXPORT_SYMBOL(drm_crtc_vblank_reset); * @crtc: CRTC in question * * This functions restores the vblank interrupt state captured with - * drm_crtc_vblank_off() again. Note that calls to drm_crtc_vblank_on() and - * drm_crtc_vblank_off() can be unbalanced and so can also be unconditionally called - * in driver load code to reflect the current hardware state of the crtc. + * drm_crtc_vblank_off() again and is generally called when enabling @crtc. Note + * that calls to drm_crtc_vblank_on() and drm_crtc_vblank_off() can be + * unbalanced and so can also be unconditionally called in driver load code to + * reflect the current hardware state of the crtc. */ void drm_crtc_vblank_on(struct drm_crtc *crtc) { diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 39df16af7a4a..3aa3809ab524 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -387,22 +387,49 @@ struct drm_device { bool irq_enabled; int irq; - /* + /** + * @vblank_disable_immediate: + * * If true, vblank interrupt will be disabled immediately when the * refcount drops to zero, as opposed to via the vblank disable * timer. - * This can be set to true it the hardware has a working vblank - * counter and the driver uses drm_vblank_on() and drm_vblank_off() - * appropriately. + * + * This can be set to true it the hardware has a working vblank counter + * with high-precision timestamping (otherwise there are races) and the + * driver uses drm_crtc_vblank_on() and drm_crtc_vblank_off() + * appropriately. See also @max_vblank_count and + * &drm_crtc_funcs.get_vblank_counter. */ bool vblank_disable_immediate; - /* array of size num_crtcs */ + /** + * @vblank: + * + * Array of vblank tracking structures, one per &struct drm_crtc. For + * historical reasons (vblank support predates kernel modesetting) this + * is free-standing and not part of &struct drm_crtc itself. It must be + * initialized explicitly by calling drm_vblank_init(). + */ struct drm_vblank_crtc *vblank; spinlock_t vblank_time_lock; /**< Protects vblank count and time updates during vblank enable/disable */ spinlock_t vbl_lock; + /** + * @max_vblank_count: + * + * Maximum value of the vblank registers. This value +1 will result in a + * wrap-around of the vblank register. It is used by the vblank core to + * handle wrap-arounds. + * + * If set to zero the vblank core will try to guess the elapsed vblanks + * between times when the vblank interrupt is disabled through + * high-precision timestamps. That approach is suffering from small + * races and imprecision over longer time periods, hence exposing a + * hardware vblank counter is always recommended. + * + * If non-zeor, &drm_crtc_funcs.get_vblank_counter must be set. + */ u32 max_vblank_count; /**< size of vblank counter register */ /** diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 629a5fe075b3..3a911a64c257 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -685,6 +685,9 @@ struct drm_crtc_funcs { * drm_crtc_vblank_off() and drm_crtc_vblank_on() when disabling or * enabling a CRTC. * + * See also &drm_device.vblank_disable_immediate and + * &drm_device.max_vblank_count. + * * Returns: * * Raw vblank counter value. -- cgit v1.2.3 From b6dcaaac44746cf32ee489639b06d3668e473386 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 24 May 2017 16:51:46 +0200 Subject: drm/vblank: _ioctl posfix for ioctl handler I alwasy get confused about drm_wait_vblank for a split second until I realize it's the ioctl handler. Unconfuse me, and do it for the legacy modeset vblank control ioctl too. While at it also noticed that I misplaced the irq ioctl handler in the internal header file. Acked-by: Thierry Reding Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170524145212.27837-12-daniel.vetter@ffwll.ch --- drivers/gpu/drm/drm_internal.h | 12 ++++++++---- drivers/gpu/drm/drm_ioctl.c | 4 ++-- drivers/gpu/drm/drm_vblank.c | 22 ++++------------------ 3 files changed, 14 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index ba3f5fb21959..5cf9e03b5457 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h @@ -58,12 +58,16 @@ extern unsigned int drm_timestamp_monotonic; void drm_vblank_disable_and_save(struct drm_device *dev, unsigned int pipe); /* IOCTLS */ -int drm_wait_vblank(struct drm_device *dev, void *data, - struct drm_file *filp); +int drm_wait_vblank_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp); +int drm_legacy_modeset_ctl_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); + +/* drm_irq.c */ + +/* IOCTLS */ int drm_legacy_irq_control(struct drm_device *dev, void *data, struct drm_file *file_priv); -int drm_legacy_modeset_ctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); /* drm_auth.c */ int drm_getmagic(struct drm_device *dev, void *data, diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 865e3ee4d743..c8547d223e85 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -600,9 +600,9 @@ static const struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_legacy_sg_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_legacy_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_legacy_modeset_ctl, 0), + DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_legacy_modeset_ctl_ioctl, 0), DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index d833b202f3c7..4ef7d310d5be 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -1293,8 +1293,8 @@ static void drm_legacy_vblank_post_modeset(struct drm_device *dev, } } -int drm_legacy_modeset_ctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_legacy_modeset_ctl_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) { struct drm_modeset_ctl *modeset = data; unsigned int pipe; @@ -1413,22 +1413,8 @@ static bool drm_wait_vblank_is_query(union drm_wait_vblank *vblwait) _DRM_VBLANK_NEXTONMISS)); } -/* - * Wait for VBLANK. - * - * \param inode device inode. - * \param file_priv DRM file private. - * \param cmd command. - * \param data user argument, pointing to a drm_wait_vblank structure. - * \return zero on success or a negative number on failure. - * - * This function enables the vblank interrupt on the pipe requested, then - * sleeps waiting for the requested sequence number to occur, and drops - * the vblank interrupt refcount afterwards. (vblank IRQ disable follows that - * after a timeout with no further vblank waits scheduled). - */ -int drm_wait_vblank(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_wait_vblank_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) { struct drm_vblank_crtc *vblank; union drm_wait_vblank *vblwait = data; -- cgit v1.2.3 From ca814b25538a5b2c0a8de6665191725f41608f2c Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 24 May 2017 16:51:47 +0200 Subject: drm/vblank: Consistent drm_crtc_ prefix We use drm_crtc_ for all the new-style vblank functions which directly take a struct drm_crtc *. drm_accurate_vblank_count was the odd one out, correct this to appease my OCD. Acked-by: Thierry Reding Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170524145212.27837-13-daniel.vetter@ffwll.ch --- drivers/gpu/drm/drm_vblank.c | 8 ++++---- drivers/gpu/drm/i915/i915_irq.c | 2 +- drivers/gpu/drm/i915/intel_display.c | 2 +- drivers/gpu/drm/nouveau/nv50_display.c | 2 +- include/drm/drm_vblank.h | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index 4ef7d310d5be..7e3f59182571 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -294,7 +294,7 @@ static u32 drm_vblank_count(struct drm_device *dev, unsigned int pipe) } /** - * drm_accurate_vblank_count - retrieve the master vblank counter + * drm_crtc_accurate_vblank_count - retrieve the master vblank counter * @crtc: which counter to retrieve * * This function is similar to drm_crtc_vblank_count() but this function @@ -304,7 +304,7 @@ static u32 drm_vblank_count(struct drm_device *dev, unsigned int pipe) * This is mostly useful for hardware that can obtain the scanout position, but * doesn't have a hardware frame counter. */ -u32 drm_accurate_vblank_count(struct drm_crtc *crtc) +u32 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; unsigned int pipe = drm_crtc_index(crtc); @@ -323,7 +323,7 @@ u32 drm_accurate_vblank_count(struct drm_crtc *crtc) return vblank; } -EXPORT_SYMBOL(drm_accurate_vblank_count); +EXPORT_SYMBOL(drm_crtc_accurate_vblank_count); static void __disable_vblank(struct drm_device *dev, unsigned int pipe) { @@ -772,7 +772,7 @@ drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe, * vblank events since the system was booted, including lost events due to * modesetting activity. Note that this timer isn't correct against a racing * vblank interrupt (since it only reports the software vblank counter), see - * drm_accurate_vblank_count() for such use-cases. + * drm_crtc_accurate_vblank_count() for such use-cases. * * Returns: * The software vblank counter. diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 04493ef1d2f7..3f8b2ee8da8c 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1601,7 +1601,7 @@ static void display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, crcs[3] = crc3; crcs[4] = crc4; drm_crtc_add_crc_entry(&crtc->base, true, - drm_accurate_vblank_count(&crtc->base), + drm_crtc_accurate_vblank_count(&crtc->base), crcs); } } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e6e26705c138..636c64ee00a8 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12566,7 +12566,7 @@ u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc) struct drm_device *dev = crtc->base.dev; if (!dev->max_vblank_count) - return drm_accurate_vblank_count(&crtc->base); + return drm_crtc_accurate_vblank_count(&crtc->base); return dev->driver->get_vblank_counter(dev, crtc->pipe); } diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index e9189e59216b..28cb24624c31 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -4032,7 +4032,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) if (crtc->state->event) { unsigned long flags; /* Get correct count/ts if racing with vblank irq */ - drm_accurate_vblank_count(crtc); + drm_crtc_accurate_vblank_count(crtc); spin_lock_irqsave(&crtc->dev->event_lock, flags); drm_crtc_send_vblank_event(crtc, crtc->state->event); spin_unlock_irqrestore(&crtc->dev->event_lock, flags); diff --git a/include/drm/drm_vblank.h b/include/drm/drm_vblank.h index 4cde47332dfa..4ceef128582f 100644 --- a/include/drm/drm_vblank.h +++ b/include/drm/drm_vblank.h @@ -169,7 +169,7 @@ void drm_crtc_vblank_off(struct drm_crtc *crtc); void drm_crtc_vblank_reset(struct drm_crtc *crtc); void drm_crtc_vblank_on(struct drm_crtc *crtc); void drm_vblank_cleanup(struct drm_device *dev); -u32 drm_accurate_vblank_count(struct drm_crtc *crtc); +u32 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc); bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, unsigned int pipe, int *max_error, -- cgit v1.2.3 From 76bba2cdb56d2a55c0dd4c3432221881d8c9adcc Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 24 May 2017 16:51:38 +0200 Subject: drm/udl: Remove dummy busid callback Since commit ca8e2ad71013049bc88a10b11d83712bfe56cdd4 Author: Thierry Reding Date: Fri Apr 11 15:23:00 2014 +0200 drm: Introduce drm_dev_set_unique() the ->set_busid callback is optional. On top of that the udl one isn't really fully compliant with the drm uabi, but since only modesetting ever binds to it (there's no 3d accel on udl) it doesn't matter. Still, can't harm to aling and use the default used by everyone else. Acked-by: Thierry Reding Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170524145212.27837-4-daniel.vetter@ffwll.ch --- drivers/gpu/drm/udl/udl_drv.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c index cd8b01727734..0f02e1acf0ba 100644 --- a/drivers/gpu/drm/udl/udl_drv.c +++ b/drivers/gpu/drm/udl/udl_drv.c @@ -11,11 +11,6 @@ #include #include "udl_drv.h" -static int udl_driver_set_busid(struct drm_device *d, struct drm_master *m) -{ - return 0; -} - static int udl_usb_suspend(struct usb_interface *interface, pm_message_t message) { @@ -52,7 +47,6 @@ static struct drm_driver driver = { .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME, .load = udl_driver_load, .unload = udl_driver_unload, - .set_busid = udl_driver_set_busid, /* gem hooks */ .gem_free_object = udl_gem_free_object, -- cgit v1.2.3 From 5c484cee7ef9c4fd29fa0ba09640d55960977145 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 24 May 2017 16:51:39 +0200 Subject: drm: Remove drm_driver->set_busid hook The only special-case is pci devices, and we can easily handle this in the core. Do so and drop a pile of boilerplate from drivers. Acked-by: Thierry Reding Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170524145212.27837-5-daniel.vetter@ffwll.ch --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 1 - drivers/gpu/drm/ast/ast_drv.c | 1 - drivers/gpu/drm/bochs/bochs_drv.c | 1 - drivers/gpu/drm/cirrus/cirrus_drv.c | 1 - drivers/gpu/drm/drm_internal.h | 1 + drivers/gpu/drm/drm_ioctl.c | 4 ++-- drivers/gpu/drm/drm_pci.c | 1 - drivers/gpu/drm/gma500/psb_drv.c | 1 - drivers/gpu/drm/i810/i810_drv.c | 1 - drivers/gpu/drm/i915/i915_drv.c | 1 - drivers/gpu/drm/mga/mga_drv.c | 1 - drivers/gpu/drm/mgag200/mgag200_drv.c | 1 - drivers/gpu/drm/nouveau/nouveau_drm.c | 1 - drivers/gpu/drm/qxl/qxl_drv.c | 2 -- drivers/gpu/drm/r128/r128_drv.c | 1 - drivers/gpu/drm/radeon/radeon_drv.c | 1 - drivers/gpu/drm/savage/savage_drv.c | 1 - drivers/gpu/drm/sis/sis_drv.c | 1 - drivers/gpu/drm/tdfx/tdfx_drv.c | 1 - drivers/gpu/drm/via/via_drv.c | 1 - drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 1 - include/drm/drm_drv.h | 2 -- include/drm/drm_pci.h | 7 ------- 23 files changed, 3 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 31eddd85eb40..e7a4bce6358d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -734,7 +734,6 @@ static struct drm_driver kms_driver = { .open = amdgpu_driver_open_kms, .postclose = amdgpu_driver_postclose_kms, .lastclose = amdgpu_driver_lastclose_kms, - .set_busid = drm_pci_set_busid, .unload = amdgpu_driver_unload_kms, .get_vblank_counter = amdgpu_get_vblank_counter_kms, .enable_vblank = amdgpu_enable_vblank_kms, diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c index fd7c9eec92e4..f6794745a024 100644 --- a/drivers/gpu/drm/ast/ast_drv.c +++ b/drivers/gpu/drm/ast/ast_drv.c @@ -197,7 +197,6 @@ static struct drm_driver driver = { .load = ast_driver_load, .unload = ast_driver_unload, - .set_busid = drm_pci_set_busid, .fops = &ast_fops, .name = DRIVER_NAME, diff --git a/drivers/gpu/drm/bochs/bochs_drv.c b/drivers/gpu/drm/bochs/bochs_drv.c index aa342515ddf4..8fccd3cf000d 100644 --- a/drivers/gpu/drm/bochs/bochs_drv.c +++ b/drivers/gpu/drm/bochs/bochs_drv.c @@ -84,7 +84,6 @@ static struct drm_driver bochs_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET, .load = bochs_load, .unload = bochs_unload, - .set_busid = drm_pci_set_busid, .fops = &bochs_fops, .name = "bochs-drm", .desc = "bochs dispi vga interface (qemu stdvga)", diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c index d893ea21a359..c48b9eb76712 100644 --- a/drivers/gpu/drm/cirrus/cirrus_drv.c +++ b/drivers/gpu/drm/cirrus/cirrus_drv.c @@ -132,7 +132,6 @@ static struct drm_driver driver = { .driver_features = DRIVER_MODESET | DRIVER_GEM, .load = cirrus_driver_load, .unload = cirrus_driver_unload, - .set_busid = drm_pci_set_busid, .fops = &cirrus_driver_fops, .name = DRIVER_NAME, .desc = DRIVER_DESC, diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index 5cf9e03b5457..116de27cf8f3 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h @@ -32,6 +32,7 @@ void drm_lastclose(struct drm_device *dev); int drm_irq_by_busid(struct drm_device *dev, void *data, struct drm_file *file_priv); void drm_pci_agp_destroy(struct drm_device *dev); +int drm_pci_set_busid(struct drm_device *dev, struct drm_master *master); /* drm_prime.c */ int drm_prime_handle_to_fd_ioctl(struct drm_device *dev, void *data, diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index c8547d223e85..aa49a2241404 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -143,8 +143,8 @@ static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv) if (master->unique != NULL) drm_unset_busid(dev, master); - if (dev->driver->set_busid) { - ret = dev->driver->set_busid(dev, master); + if (dev_is_pci(dev->dev)) { + ret = drm_pci_set_busid(dev, master); if (ret) { drm_unset_busid(dev, master); return ret; diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c index 1eb4fc3eee20..ad31d95e77c9 100644 --- a/drivers/gpu/drm/drm_pci.c +++ b/drivers/gpu/drm/drm_pci.c @@ -149,7 +149,6 @@ int drm_pci_set_busid(struct drm_device *dev, struct drm_master *master) master->unique_len = strlen(master->unique); return 0; } -EXPORT_SYMBOL(drm_pci_set_busid); static int drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p) { diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index 1f9b35afefee..37d4c36c80f2 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -480,7 +480,6 @@ static struct drm_driver driver = { .load = psb_driver_load, .unload = psb_driver_unload, .lastclose = psb_driver_lastclose, - .set_busid = drm_pci_set_busid, .num_ioctls = ARRAY_SIZE(psb_ioctls), .irq_preinstall = psb_irq_preinstall, diff --git a/drivers/gpu/drm/i810/i810_drv.c b/drivers/gpu/drm/i810/i810_drv.c index 37fd0906f807..e1c35c710e24 100644 --- a/drivers/gpu/drm/i810/i810_drv.c +++ b/drivers/gpu/drm/i810/i810_drv.c @@ -59,7 +59,6 @@ static struct drm_driver driver = { .load = i810_driver_load, .lastclose = i810_driver_lastclose, .preclose = i810_driver_preclose, - .set_busid = drm_pci_set_busid, .dma_quiescent = i810_driver_dma_quiescent, .ioctls = i810_ioctls, .fops = &i810_driver_fops, diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 3036d4835b0f..6033355d9469 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -2622,7 +2622,6 @@ static struct drm_driver driver = { .open = i915_driver_open, .lastclose = i915_driver_lastclose, .postclose = i915_driver_postclose, - .set_busid = drm_pci_set_busid, .gem_close_object = i915_gem_close_object, .gem_free_object_unlocked = i915_gem_free_object, diff --git a/drivers/gpu/drm/mga/mga_drv.c b/drivers/gpu/drm/mga/mga_drv.c index 63ba0699d107..2a36ec611a44 100644 --- a/drivers/gpu/drm/mga/mga_drv.c +++ b/drivers/gpu/drm/mga/mga_drv.c @@ -62,7 +62,6 @@ static struct drm_driver driver = { .load = mga_driver_load, .unload = mga_driver_unload, .lastclose = mga_driver_lastclose, - .set_busid = drm_pci_set_busid, .dma_quiescent = mga_driver_dma_quiescent, .get_vblank_counter = mga_get_vblank_counter, .enable_vblank = mga_enable_vblank, diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index 9ac007880328..53a5982a04c7 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -91,7 +91,6 @@ static struct drm_driver driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET, .load = mgag200_driver_load, .unload = mgag200_driver_unload, - .set_busid = drm_pci_set_busid, .fops = &mgag200_driver_fops, .name = DRIVER_NAME, .desc = DRIVER_DESC, diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index c3dc75fee700..3e1a8da9b20f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -1102,7 +1102,6 @@ static int __init nouveau_drm_init(void) { driver_pci = driver_stub; - driver_pci.set_busid = drm_pci_set_busid; driver_platform = driver_stub; nouveau_display_options(); diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c index c2fc201d9e1b..bb2d8da7e553 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.c +++ b/drivers/gpu/drm/qxl/qxl_drv.c @@ -262,8 +262,6 @@ static struct drm_driver qxl_driver = { DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_ATOMIC, - .set_busid = drm_pci_set_busid, - .dumb_create = qxl_mode_dumb_create, .dumb_map_offset = qxl_mode_dumb_mmap, .dumb_destroy = drm_gem_dumb_destroy, diff --git a/drivers/gpu/drm/r128/r128_drv.c b/drivers/gpu/drm/r128/r128_drv.c index a982be57d1ef..1d43c434328d 100644 --- a/drivers/gpu/drm/r128/r128_drv.c +++ b/drivers/gpu/drm/r128/r128_drv.c @@ -62,7 +62,6 @@ static struct drm_driver driver = { .load = r128_driver_load, .preclose = r128_driver_preclose, .lastclose = r128_driver_lastclose, - .set_busid = drm_pci_set_busid, .get_vblank_counter = r128_get_vblank_counter, .enable_vblank = r128_enable_vblank, .disable_vblank = r128_disable_vblank, diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 6f906abd612b..dd5e86dafb29 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -545,7 +545,6 @@ static struct drm_driver kms_driver = { .open = radeon_driver_open_kms, .postclose = radeon_driver_postclose_kms, .lastclose = radeon_driver_lastclose_kms, - .set_busid = drm_pci_set_busid, .unload = radeon_driver_unload_kms, .get_vblank_counter = radeon_get_vblank_counter_kms, .enable_vblank = radeon_enable_vblank_kms, diff --git a/drivers/gpu/drm/savage/savage_drv.c b/drivers/gpu/drm/savage/savage_drv.c index 78c6d8e9b42c..2a08da09dbcf 100644 --- a/drivers/gpu/drm/savage/savage_drv.c +++ b/drivers/gpu/drm/savage/savage_drv.c @@ -55,7 +55,6 @@ static struct drm_driver driver = { .preclose = savage_reclaim_buffers, .lastclose = savage_driver_lastclose, .unload = savage_driver_unload, - .set_busid = drm_pci_set_busid, .ioctls = savage_ioctls, .dma_ioctl = savage_bci_buffers, .fops = &savage_driver_fops, diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c index 7f05da13ea5e..cdaced381f5d 100644 --- a/drivers/gpu/drm/sis/sis_drv.c +++ b/drivers/gpu/drm/sis/sis_drv.c @@ -104,7 +104,6 @@ static struct drm_driver driver = { .open = sis_driver_open, .preclose = sis_reclaim_buffers_locked, .postclose = sis_driver_postclose, - .set_busid = drm_pci_set_busid, .dma_quiescent = sis_idle, .lastclose = sis_lastclose, .ioctls = sis_ioctls, diff --git a/drivers/gpu/drm/tdfx/tdfx_drv.c b/drivers/gpu/drm/tdfx/tdfx_drv.c index c54138c3a376..acd5f8162bb6 100644 --- a/drivers/gpu/drm/tdfx/tdfx_drv.c +++ b/drivers/gpu/drm/tdfx/tdfx_drv.c @@ -55,7 +55,6 @@ static const struct file_operations tdfx_driver_fops = { static struct drm_driver driver = { .driver_features = DRIVER_LEGACY, - .set_busid = drm_pci_set_busid, .fops = &tdfx_driver_fops, .name = DRIVER_NAME, .desc = DRIVER_DESC, diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c index 9e0e5392b6ec..0ca4e0489c0b 100644 --- a/drivers/gpu/drm/via/via_drv.c +++ b/drivers/gpu/drm/via/via_drv.c @@ -77,7 +77,6 @@ static struct drm_driver driver = { .open = via_driver_open, .preclose = via_reclaim_buffers_locked, .postclose = via_driver_postclose, - .set_busid = drm_pci_set_busid, .context_dtor = via_final_context, .get_vblank_counter = via_get_vblank_counter, .enable_vblank = via_enable_vblank, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 4a641555b960..63218033b0be 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -1531,7 +1531,6 @@ static struct drm_driver driver = { .master_drop = vmw_master_drop, .open = vmw_driver_open, .postclose = vmw_postclose, - .set_busid = drm_pci_set_busid, .dumb_create = vmw_dumb_create, .dumb_map_offset = vmw_dumb_map_offset, diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h index 18f3181674e8..e4de59bc52c8 100644 --- a/include/drm/drm_drv.h +++ b/include/drm/drm_drv.h @@ -172,8 +172,6 @@ struct drm_driver { */ void (*release) (struct drm_device *); - int (*set_busid)(struct drm_device *dev, struct drm_master *master); - /** * @get_vblank_counter: * diff --git a/include/drm/drm_pci.h b/include/drm/drm_pci.h index 4579fac1080c..961b16f9b553 100644 --- a/include/drm/drm_pci.h +++ b/include/drm/drm_pci.h @@ -49,7 +49,6 @@ void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver); int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, struct drm_driver *driver); -int drm_pci_set_busid(struct drm_device *dev, struct drm_master *master); #else static inline int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, @@ -57,12 +56,6 @@ static inline int drm_get_pci_dev(struct pci_dev *pdev, { return -ENOSYS; } - -static inline int drm_pci_set_busid(struct drm_device *dev, - struct drm_master *master) -{ - return -ENOSYS; -} #endif #define DRM_PCIE_SPEED_25 1 -- cgit v1.2.3 From 10631d724deff712343d96dd3017cd323349f761 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 24 May 2017 16:51:40 +0200 Subject: drm/pci: Deprecate drm_pci_init/exit completely The magic switching between proper pci driver and shadow-attach isn't useful anymore since there's no ums+kms drivers left. Let's split this up properly, calling pci_register_driver for kms drivers and renaming the shadow-attach init to drm_legacy_pci_init/exit. Acked-by: Thierry Reding Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170524145212.27837-6-daniel.vetter@ffwll.ch --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 ++-- drivers/gpu/drm/ast/ast_drv.c | 4 ++-- drivers/gpu/drm/bochs/bochs_drv.c | 4 ++-- drivers/gpu/drm/cirrus/cirrus_drv.c | 4 ++-- drivers/gpu/drm/drm_pci.c | 39 ++++++++++----------------------- drivers/gpu/drm/gma500/psb_drv.c | 4 ++-- drivers/gpu/drm/i810/i810_drv.c | 4 ++-- drivers/gpu/drm/mga/mga_drv.c | 4 ++-- drivers/gpu/drm/mgag200/mgag200_drv.c | 5 +++-- drivers/gpu/drm/nouveau/nouveau_drm.c | 11 ++++++++-- drivers/gpu/drm/qxl/qxl_drv.c | 4 ++-- drivers/gpu/drm/r128/r128_drv.c | 4 ++-- drivers/gpu/drm/radeon/radeon_drv.c | 5 ++--- drivers/gpu/drm/savage/savage_drv.c | 4 ++-- drivers/gpu/drm/sis/sis_drv.c | 4 ++-- drivers/gpu/drm/tdfx/tdfx_drv.c | 4 ++-- drivers/gpu/drm/via/via_drv.c | 4 ++-- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 4 ++-- include/drm/drm_pci.h | 4 ++-- 19 files changed, 56 insertions(+), 64 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index e7a4bce6358d..4911d304d8b9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -816,7 +816,7 @@ static int __init amdgpu_init(void) driver->num_ioctls = amdgpu_max_kms_ioctl; amdgpu_register_atpx_handler(); /* let modprobe override vga console setting */ - return drm_pci_init(driver, pdriver); + return pci_register_driver(pdriver); error_sched: amdgpu_fence_slab_fini(); @@ -831,7 +831,7 @@ error_sync: static void __exit amdgpu_exit(void) { amdgpu_amdkfd_fini(); - drm_pci_exit(driver, pdriver); + pci_unregister_driver(pdriver); amdgpu_unregister_atpx_handler(); amdgpu_sync_fini(); amd_sched_fence_slab_fini(); diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c index f6794745a024..3022b39c00f3 100644 --- a/drivers/gpu/drm/ast/ast_drv.c +++ b/drivers/gpu/drm/ast/ast_drv.c @@ -220,11 +220,11 @@ static int __init ast_init(void) if (ast_modeset == 0) return -EINVAL; - return drm_pci_init(&driver, &ast_pci_driver); + return pci_register_driver(&ast_pci_driver); } static void __exit ast_exit(void) { - drm_pci_exit(&driver, &ast_pci_driver); + pci_unregister_driver(&ast_pci_driver); } module_init(ast_init); diff --git a/drivers/gpu/drm/bochs/bochs_drv.c b/drivers/gpu/drm/bochs/bochs_drv.c index 8fccd3cf000d..a1d28845da5f 100644 --- a/drivers/gpu/drm/bochs/bochs_drv.c +++ b/drivers/gpu/drm/bochs/bochs_drv.c @@ -223,12 +223,12 @@ static int __init bochs_init(void) if (bochs_modeset == 0) return -EINVAL; - return drm_pci_init(&bochs_driver, &bochs_pci_driver); + return pci_register_driver(&bochs_pci_driver); } static void __exit bochs_exit(void) { - drm_pci_exit(&bochs_driver, &bochs_pci_driver); + pci_unregister_driver(&bochs_pci_driver); } module_init(bochs_init); diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c index c48b9eb76712..910c300f5c37 100644 --- a/drivers/gpu/drm/cirrus/cirrus_drv.c +++ b/drivers/gpu/drm/cirrus/cirrus_drv.c @@ -165,12 +165,12 @@ static int __init cirrus_init(void) if (cirrus_modeset == 0) return -EINVAL; - return drm_pci_init(&driver, &cirrus_pci_driver); + return pci_register_driver(&cirrus_pci_driver); } static void __exit cirrus_exit(void) { - drm_pci_exit(&driver, &cirrus_pci_driver); + pci_unregister_driver(&cirrus_pci_driver); } module_init(cirrus_init); diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c index ad31d95e77c9..1235c9877d6f 100644 --- a/drivers/gpu/drm/drm_pci.c +++ b/drivers/gpu/drm/drm_pci.c @@ -280,20 +280,15 @@ err_free: EXPORT_SYMBOL(drm_get_pci_dev); /** - * drm_pci_init - Register matching PCI devices with the DRM subsystem + * drm_legacy_pci_init - shadow-attach a legacy DRM PCI driver * @driver: DRM device driver * @pdriver: PCI device driver * - * Initializes a drm_device structures, registering the stubs and initializing - * the AGP device. - * - * NOTE: This function is deprecated. Modern modesetting drm drivers should use - * pci_register_driver() directly, this function only provides shadow-binding - * support for old legacy drivers on top of that core pci function. + * This is only used by legacy dri1 drivers and deprecated. * * Return: 0 on success or a negative error code on failure. */ -int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver) +int drm_legacy_pci_init(struct drm_driver *driver, struct pci_driver *pdriver) { struct pci_dev *pdev = NULL; const struct pci_device_id *pid; @@ -301,8 +296,8 @@ int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver) DRM_DEBUG("\n"); - if (!(driver->driver_features & DRIVER_LEGACY)) - return pci_register_driver(pdriver); + if (WARN_ON(!(driver->driver_features & DRIVER_LEGACY))) + return -EINVAL; /* If not using KMS, fall back to stealth mode manual scanning. */ INIT_LIST_HEAD(&driver->legacy_dev_list); @@ -329,6 +324,7 @@ int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver) } return 0; } +EXPORT_SYMBOL(drm_legacy_pci_init); int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *mask) { @@ -390,11 +386,6 @@ EXPORT_SYMBOL(drm_pcie_get_max_link_width); #else -int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver) -{ - return -1; -} - void drm_pci_agp_destroy(struct drm_device *dev) {} int drm_irq_by_busid(struct drm_device *dev, void *data, @@ -404,27 +395,21 @@ int drm_irq_by_busid(struct drm_device *dev, void *data, } #endif -EXPORT_SYMBOL(drm_pci_init); - /** - * drm_pci_exit - Unregister matching PCI devices from the DRM subsystem + * drm_legacy_pci_exit - unregister shadow-attach legacy DRM driver * @driver: DRM device driver * @pdriver: PCI device driver * - * Unregisters one or more devices matched by a PCI driver from the DRM - * subsystem. - * - * NOTE: This function is deprecated. Modern modesetting drm drivers should use - * pci_unregister_driver() directly, this function only provides shadow-binding - * support for old legacy drivers on top of that core pci function. + * Unregister a DRM driver shadow-attached through drm_legacy_pci_init(). This + * is deprecated and only used by dri1 drivers. */ -void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver) +void drm_legacy_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver) { struct drm_device *dev, *tmp; DRM_DEBUG("\n"); if (!(driver->driver_features & DRIVER_LEGACY)) { - pci_unregister_driver(pdriver); + WARN_ON(1); } else { list_for_each_entry_safe(dev, tmp, &driver->legacy_dev_list, legacy_dev_list) { @@ -434,4 +419,4 @@ void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver) } DRM_INFO("Module unloaded\n"); } -EXPORT_SYMBOL(drm_pci_exit); +EXPORT_SYMBOL(drm_legacy_pci_exit); diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index 37d4c36c80f2..747c06b227c5 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -516,12 +516,12 @@ static struct pci_driver psb_pci_driver = { static int __init psb_init(void) { - return drm_pci_init(&driver, &psb_pci_driver); + return pci_register_driver(&psb_pci_driver); } static void __exit psb_exit(void) { - drm_pci_exit(&driver, &psb_pci_driver); + pci_unregister_driver(&psb_pci_driver); } late_initcall(psb_init); diff --git a/drivers/gpu/drm/i810/i810_drv.c b/drivers/gpu/drm/i810/i810_drv.c index e1c35c710e24..c69d5c487f51 100644 --- a/drivers/gpu/drm/i810/i810_drv.c +++ b/drivers/gpu/drm/i810/i810_drv.c @@ -82,12 +82,12 @@ static int __init i810_init(void) return -EINVAL; } driver.num_ioctls = i810_max_ioctl; - return drm_pci_init(&driver, &i810_pci_driver); + return drm_legacy_pci_init(&driver, &i810_pci_driver); } static void __exit i810_exit(void) { - drm_pci_exit(&driver, &i810_pci_driver); + drm_legacy_pci_exit(&driver, &i810_pci_driver); } module_init(i810_init); diff --git a/drivers/gpu/drm/mga/mga_drv.c b/drivers/gpu/drm/mga/mga_drv.c index 2a36ec611a44..1aad27813c23 100644 --- a/drivers/gpu/drm/mga/mga_drv.c +++ b/drivers/gpu/drm/mga/mga_drv.c @@ -89,12 +89,12 @@ static struct pci_driver mga_pci_driver = { static int __init mga_init(void) { driver.num_ioctls = mga_max_ioctl; - return drm_pci_init(&driver, &mga_pci_driver); + return drm_legacy_pci_init(&driver, &mga_pci_driver); } static void __exit mga_exit(void) { - drm_pci_exit(&driver, &mga_pci_driver); + drm_legacy_pci_exit(&driver, &mga_pci_driver); } module_init(mga_init); diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index 53a5982a04c7..4189160af726 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -119,12 +119,13 @@ static int __init mgag200_init(void) if (mgag200_modeset == 0) return -EINVAL; - return drm_pci_init(&driver, &mgag200_pci_driver); + + return pci_register_driver(&mgag200_pci_driver); } static void __exit mgag200_exit(void) { - drm_pci_exit(&driver, &mgag200_pci_driver); + pci_unregister_driver(&mgag200_pci_driver); } module_init(mgag200_init); diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 3e1a8da9b20f..efa5489c5aed 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -1120,7 +1120,12 @@ nouveau_drm_init(void) nouveau_register_dsm_handler(); nouveau_backlight_ctor(); - return drm_pci_init(&driver_pci, &nouveau_drm_pci_driver); + +#ifdef CONFIG_PCI + return pci_register_driver(&nouveau_drm_pci_driver); +#else + return 0; +#endif } static void __exit @@ -1129,7 +1134,9 @@ nouveau_drm_exit(void) if (!nouveau_modeset) return; - drm_pci_exit(&driver_pci, &nouveau_drm_pci_driver); +#ifdef CONFIG_PCI + pci_unregister_driver(&nouveau_drm_pci_driver); +#endif nouveau_backlight_dtor(); nouveau_unregister_dsm_handler(); diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c index bb2d8da7e553..15c97b16ee21 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.c +++ b/drivers/gpu/drm/qxl/qxl_drv.c @@ -301,12 +301,12 @@ static int __init qxl_init(void) if (qxl_modeset == 0) return -EINVAL; qxl_driver.num_ioctls = qxl_max_ioctls; - return drm_pci_init(&qxl_driver, &qxl_pci_driver); + return pci_register_driver(&qxl_pci_driver); } static void __exit qxl_exit(void) { - drm_pci_exit(&qxl_driver, &qxl_pci_driver); + pci_unregister_driver(&qxl_pci_driver); } module_init(qxl_init); diff --git a/drivers/gpu/drm/r128/r128_drv.c b/drivers/gpu/drm/r128/r128_drv.c index 1d43c434328d..0d2b7e42b3a7 100644 --- a/drivers/gpu/drm/r128/r128_drv.c +++ b/drivers/gpu/drm/r128/r128_drv.c @@ -95,12 +95,12 @@ static int __init r128_init(void) { driver.num_ioctls = r128_max_ioctl; - return drm_pci_init(&driver, &r128_pci_driver); + return drm_legacy_pci_init(&driver, &r128_pci_driver); } static void __exit r128_exit(void) { - drm_pci_exit(&driver, &r128_pci_driver); + drm_legacy_pci_exit(&driver, &r128_pci_driver); } module_init(r128_init); diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index dd5e86dafb29..0d02349674f6 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -619,14 +619,13 @@ static int __init radeon_init(void) return -EINVAL; } - /* let modprobe override vga console setting */ - return drm_pci_init(driver, pdriver); + return pci_register_driver(pdriver); } static void __exit radeon_exit(void) { radeon_kfd_fini(); - drm_pci_exit(driver, pdriver); + pci_unregister_driver(pdriver); radeon_unregister_atpx_handler(); } diff --git a/drivers/gpu/drm/savage/savage_drv.c b/drivers/gpu/drm/savage/savage_drv.c index 2a08da09dbcf..2bddeb8bf457 100644 --- a/drivers/gpu/drm/savage/savage_drv.c +++ b/drivers/gpu/drm/savage/savage_drv.c @@ -74,12 +74,12 @@ static struct pci_driver savage_pci_driver = { static int __init savage_init(void) { driver.num_ioctls = savage_max_ioctl; - return drm_pci_init(&driver, &savage_pci_driver); + return drm_legacy_pci_init(&driver, &savage_pci_driver); } static void __exit savage_exit(void) { - drm_pci_exit(&driver, &savage_pci_driver); + drm_legacy_pci_exit(&driver, &savage_pci_driver); } module_init(savage_init); diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c index cdaced381f5d..e04a92658cd7 100644 --- a/drivers/gpu/drm/sis/sis_drv.c +++ b/drivers/gpu/drm/sis/sis_drv.c @@ -124,12 +124,12 @@ static struct pci_driver sis_pci_driver = { static int __init sis_init(void) { driver.num_ioctls = sis_max_ioctl; - return drm_pci_init(&driver, &sis_pci_driver); + return drm_legacy_pci_init(&driver, &sis_pci_driver); } static void __exit sis_exit(void) { - drm_pci_exit(&driver, &sis_pci_driver); + drm_legacy_pci_exit(&driver, &sis_pci_driver); } module_init(sis_init); diff --git a/drivers/gpu/drm/tdfx/tdfx_drv.c b/drivers/gpu/drm/tdfx/tdfx_drv.c index acd5f8162bb6..3a1476818c65 100644 --- a/drivers/gpu/drm/tdfx/tdfx_drv.c +++ b/drivers/gpu/drm/tdfx/tdfx_drv.c @@ -71,12 +71,12 @@ static struct pci_driver tdfx_pci_driver = { static int __init tdfx_init(void) { - return drm_pci_init(&driver, &tdfx_pci_driver); + return drm_legacy_pci_init(&driver, &tdfx_pci_driver); } static void __exit tdfx_exit(void) { - drm_pci_exit(&driver, &tdfx_pci_driver); + drm_legacy_pci_exit(&driver, &tdfx_pci_driver); } module_init(tdfx_init); diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c index 0ca4e0489c0b..aaf766f7cca2 100644 --- a/drivers/gpu/drm/via/via_drv.c +++ b/drivers/gpu/drm/via/via_drv.c @@ -106,12 +106,12 @@ static int __init via_init(void) { driver.num_ioctls = via_max_ioctl; via_init_command_verifier(); - return drm_pci_init(&driver, &via_pci_driver); + return drm_legacy_pci_init(&driver, &via_pci_driver); } static void __exit via_exit(void) { - drm_pci_exit(&driver, &via_pci_driver); + drm_legacy_pci_exit(&driver, &via_pci_driver); } module_init(via_init); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 63218033b0be..204bf181b69e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -1570,7 +1570,7 @@ static int __init vmwgfx_init(void) if (vgacon_text_force()) return -EINVAL; - ret = drm_pci_init(&driver, &vmw_pci_driver); + ret = pci_register_driver(&vmw_pci_driver); if (ret) DRM_ERROR("Failed initializing DRM.\n"); return ret; @@ -1578,7 +1578,7 @@ static int __init vmwgfx_init(void) static void __exit vmwgfx_exit(void) { - drm_pci_exit(&driver, &vmw_pci_driver); + pci_unregister_driver(&vmw_pci_driver); } module_init(vmwgfx_init); diff --git a/include/drm/drm_pci.h b/include/drm/drm_pci.h index 961b16f9b553..674599025d7d 100644 --- a/include/drm/drm_pci.h +++ b/include/drm/drm_pci.h @@ -43,8 +43,8 @@ struct drm_dma_handle *drm_pci_alloc(struct drm_device *dev, size_t size, size_t align); void drm_pci_free(struct drm_device *dev, struct drm_dma_handle * dmah); -int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver); -void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver); +int drm_legacy_pci_init(struct drm_driver *driver, struct pci_driver *pdriver); +void drm_legacy_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver); #ifdef CONFIG_PCI int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, -- cgit v1.2.3 From bb2eaba6458ace16f7e3504de8788374cb42b43d Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 31 May 2017 11:20:45 +0200 Subject: drm/doc: Improve ioctl/fops docs a bit more I spotted a markup issue, plus adding the descriptions in drm_driver. Plus a few more links while at it. I'm still mildly unhappy with the split between fops and ioctls, but I still think having the ioctls in the uapi chapter makes more sense. Oh well ... v2: Rebase. v3: Move misplace hunk to the right patch. Cc: Stefan Agner Acked-by: Thierry Reding Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170531092045.3950-1-daniel.vetter@ffwll.ch --- Documentation/gpu/drm-internals.rst | 2 ++ Documentation/gpu/drm-uapi.rst | 2 ++ drivers/gpu/drm/drm_file.c | 7 ++++++- drivers/gpu/drm/drm_ioctl.c | 5 ++++- include/drm/drm_drv.h | 18 ++++++++++++++++++ 5 files changed, 32 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/Documentation/gpu/drm-internals.rst b/Documentation/gpu/drm-internals.rst index f6882ad0b3c3..bece92258647 100644 --- a/Documentation/gpu/drm-internals.rst +++ b/Documentation/gpu/drm-internals.rst @@ -198,6 +198,8 @@ drivers. Open/Close, File Operations and IOCTLs ====================================== +.. _drm_driver_fops: + File Operations --------------- diff --git a/Documentation/gpu/drm-uapi.rst b/Documentation/gpu/drm-uapi.rst index 858457567d3d..679373b4a03f 100644 --- a/Documentation/gpu/drm-uapi.rst +++ b/Documentation/gpu/drm-uapi.rst @@ -160,6 +160,8 @@ other hand, a driver requires shared state between clients which is visible to user-space and accessible beyond open-file boundaries, they cannot support render nodes. +.. _drm_driver_ioctl: + IOCTL Support on Device Nodes ============================= diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c index caad93dab54b..6631f61b66ca 100644 --- a/drivers/gpu/drm/drm_file.c +++ b/drivers/gpu/drm/drm_file.c @@ -75,7 +75,7 @@ DEFINE_MUTEX(drm_global_mutex); * for drivers which use the CMA GEM helpers it's drm_gem_cma_mmap(). * * No other file operations are supported by the DRM userspace API. Overall the - * following is an example #file_operations structure:: + * following is an example &file_operations structure:: * * static const example_drm_fops = { * .owner = THIS_MODULE, @@ -92,6 +92,11 @@ DEFINE_MUTEX(drm_global_mutex); * For plain GEM based drivers there is the DEFINE_DRM_GEM_FOPS() macro, and for * CMA based drivers there is the DEFINE_DRM_GEM_CMA_FOPS() macro to make this * simpler. + * + * The driver's &file_operations must be stored in &drm_driver.fops. + * + * For driver-private IOCTL handling see the more detailed discussion in + * :ref:`IOCTL support in the userland interfaces chapter`. */ static int drm_open_helper(struct file *filp, struct drm_minor *minor); diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index aa49a2241404..3a36b3717c28 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -683,7 +683,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = { * * DRM driver private IOCTL must be in the range from DRM_COMMAND_BASE to * DRM_COMMAND_END. Finally you need an array of &struct drm_ioctl_desc to wire - * up the handlers and set the access rights: + * up the handlers and set the access rights:: * * static const struct drm_ioctl_desc my_driver_ioctls[] = { * DRM_IOCTL_DEF_DRV(MY_DRIVER_OPERATION, my_driver_operation, @@ -692,6 +692,9 @@ static const struct drm_ioctl_desc drm_ioctls[] = { * * And then assign this to the &drm_driver.ioctls field in your driver * structure. + * + * See the separate chapter on :ref:`file operations` for how + * the driver-specific IOCTLs are wired up. */ /** diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h index e4de59bc52c8..f495eee01302 100644 --- a/include/drm/drm_drv.h +++ b/include/drm/drm_drv.h @@ -515,8 +515,26 @@ struct drm_driver { char *date; u32 driver_features; + + /** + * @ioctls: + * + * Array of driver-private IOCTL description entries. See the chapter on + * :ref:`IOCTL support in the userland interfaces + * chapter` for the full details. + */ + const struct drm_ioctl_desc *ioctls; + /** @num_ioctls: Number of entries in @ioctls. */ int num_ioctls; + + /** + * @fops: + * + * File operations for the DRM device node. See the discussion in + * :ref:`file operations` for in-depth coverage and + * some examples. + */ const struct file_operations *fops; /* Everything below here is for legacy driver, never use! */ -- cgit v1.2.3 From c50a115b6e916b93f6fee0ede8ec1358b083c840 Mon Sep 17 00:00:00 2001 From: Jose Abreu Date: Thu, 25 May 2017 15:19:22 +0100 Subject: drm: vc4: Use crtc->mode_valid() and encoder->mode_valid() callbacks Now that we have a callback to check if crtc and encoder supports a given mode we can use it in vc4 so that we restrict the number of probed modes to the ones we can actually display. Also, remove the mode_fixup() calls as these are no longer needed because mode_valid() will be called before. Signed-off-by: Jose Abreu Cc: Carlos Palminha Cc: Daniel Vetter Cc: Eric Anholt Cc: David Airlie Reviewed-by: Neil Armstrong Compile-tested and Reviewed-by: Eric Anholt Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/5bea792f91074688c88a2dab8b0a90eec6e98fdf.1495720737.git.joabreu@synopsys.com --- drivers/gpu/drm/vc4/vc4_crtc.c | 13 ++++++------- drivers/gpu/drm/vc4/vc4_dpi.c | 13 ++++++------- 2 files changed, 12 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 403bbd5f99a9..e3f03efe719b 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -546,18 +546,17 @@ static void vc4_crtc_enable(struct drm_crtc *crtc) drm_crtc_vblank_on(crtc); } -static bool vc4_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) +static enum drm_mode_status vc4_crtc_mode_valid(struct drm_crtc *crtc, + const struct drm_display_mode *mode) { /* Do not allow doublescan modes from user space */ - if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) { + if (mode->flags & DRM_MODE_FLAG_DBLSCAN) { DRM_DEBUG_KMS("[CRTC:%d] Doublescan mode rejected.\n", crtc->base.id); - return false; + return MODE_NO_DBLESCAN; } - return true; + return MODE_OK; } static int vc4_crtc_atomic_check(struct drm_crtc *crtc, @@ -867,7 +866,7 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = { .mode_set_nofb = vc4_crtc_mode_set_nofb, .disable = vc4_crtc_disable, .enable = vc4_crtc_enable, - .mode_fixup = vc4_crtc_mode_fixup, + .mode_valid = vc4_crtc_mode_valid, .atomic_check = vc4_crtc_atomic_check, .atomic_flush = vc4_crtc_atomic_flush, }; diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c index 2e0fe46aeb2e..519cefef800d 100644 --- a/drivers/gpu/drm/vc4/vc4_dpi.c +++ b/drivers/gpu/drm/vc4/vc4_dpi.c @@ -224,20 +224,19 @@ static void vc4_dpi_encoder_enable(struct drm_encoder *encoder) DRM_ERROR("Failed to set clock rate: %d\n", ret); } -static bool vc4_dpi_encoder_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) +static enum drm_mode_status vc4_dpi_encoder_mode_valid(struct drm_encoder *encoder, + const struct drm_display_mode *mode) { - if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) - return false; + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + return MODE_NO_INTERLACE; - return true; + return MODE_OK; } static const struct drm_encoder_helper_funcs vc4_dpi_encoder_helper_funcs = { .disable = vc4_dpi_encoder_disable, .enable = vc4_dpi_encoder_enable, - .mode_fixup = vc4_dpi_encoder_mode_fixup, + .mode_valid = vc4_dpi_encoder_mode_valid, }; static const struct of_device_id vc4_dpi_dt_match[] = { -- cgit v1.2.3 From d7b66de513179065408908a79cfbe3a11a15e6eb Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 20 Jun 2017 11:42:28 +0200 Subject: drm: More links for gamma support helpers It's not obvious that when using the new color manager stuff you still need to wire up the legacy helper to get legacy LUT support. Improve this with more links. drm_crtc_funcs->gamma_set already explains this properly. Cc: Peter Rosin Cc: Boris Brezillon Reviewed-by: Boris Brezillon Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170620094228.4757-1-daniel.vetter@ffwll.ch --- drivers/gpu/drm/drm_color_mgmt.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index 3eda500fc005..fe0982708e95 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -128,6 +128,9 @@ EXPORT_SYMBOL(drm_color_lut_extract); * optional. The gamma and degamma properties are only attached if * their size is not 0 and ctm_property is only attached if has_ctm is * true. + * + * Drivers should use drm_atomic_helper_legacy_gamma_set() to implement the + * legacy &drm_crtc_funcs.gamma_set callback. */ void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc, uint degamma_lut_size, -- cgit v1.2.3 From 6daac7990a4451f68400068aa97254b8e4f8d977 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Tue, 20 Jun 2017 10:12:11 +0530 Subject: drm: sti: sti_dvo: make of_device_ids const. of_device_ids are not supposed to change at runtime. All functions working with of_device_ids provided by work with const of_device_ids. So mark the non-const structs as const. File size before: text data bss dec hex filename 4222 664 0 4886 1316 drivers/gpu/drm/sti/sti_dvo.o File size after constify dvo_of_match: text data bss dec hex filename 4638 248 0 4886 1316 drivers/gpu/drm/sti/sti_dvo.o Signed-off-by: Arvind Yadav Signed-off-by: Benjamin Gaignard Link: http://patchwork.freedesktop.org/patch/msgid/d5ac3cb4c43338419308d658b9bcb59b7540471e.1497868332.git.arvind.yadav.cs@gmail.com --- drivers/gpu/drm/sti/sti_dvo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c index 24ebc6b2f34d..a51cd9f754db 100644 --- a/drivers/gpu/drm/sti/sti_dvo.c +++ b/drivers/gpu/drm/sti/sti_dvo.c @@ -582,7 +582,7 @@ static int sti_dvo_remove(struct platform_device *pdev) return 0; } -static struct of_device_id dvo_of_match[] = { +static const struct of_device_id dvo_of_match[] = { { .compatible = "st,stih407-dvo", }, { /* end node */ } }; -- cgit v1.2.3 From 4c952eaba7789e0b1f2c146e839fd82c5a290241 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Tue, 20 Jun 2017 10:35:34 +0530 Subject: drm: sti: sti_hqvdp: make of_device_ids const. of_device_ids are not supposed to change at runtime. All functions working with of_device_ids provided by work with const of_device_ids. So mark the non-const structs as const. File size before: text data bss dec hex filename 15845 640 0 16485 4065 drivers/gpu/drm/sti/sti_hqvdp.o File size after constify hqvdp_of_match: text data bss dec hex filename 16229 224 0 16453 4045 drivers/gpu/drm/sti/sti_hqvdp.o Signed-off-by: Arvind Yadav Signed-off-by: Benjamin Gaignard Link: http://patchwork.freedesktop.org/patch/msgid/0a6ae44cf7d0fb54380809ae0e52234dbd3f367a.1497934979.git.arvind.yadav.cs@gmail.com --- drivers/gpu/drm/sti/sti_hqvdp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c index a1c161f77804..1234f87bce20 100644 --- a/drivers/gpu/drm/sti/sti_hqvdp.c +++ b/drivers/gpu/drm/sti/sti_hqvdp.c @@ -1395,7 +1395,7 @@ static int sti_hqvdp_remove(struct platform_device *pdev) return 0; } -static struct of_device_id hqvdp_of_match[] = { +static const struct of_device_id hqvdp_of_match[] = { { .compatible = "st,stih407-hqvdp", }, { /* end node */ } }; -- cgit v1.2.3 From 33def1ff7b09645f3631059ad9ce23e2c65e9016 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Fri, 16 Jun 2017 14:03:38 +0100 Subject: drm/i915: Simplify intel_engines_init We do not want to carry on over missing constructors and don't need a duplicated engine mask checking which is already done in the setup phase. Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_engine_cs.c | 36 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index a4487c5b7e37..3b46c1f7b88b 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -291,11 +291,9 @@ cleanup: */ int intel_engines_init(struct drm_i915_private *dev_priv) { - struct intel_device_info *device_info = mkwrite_device_info(dev_priv); struct intel_engine_cs *engine; enum intel_engine_id id, err_id; - unsigned int mask = 0; - int err = 0; + int err; for_each_engine(engine, dev_priv, id) { const struct engine_class_info *class_info = @@ -306,40 +304,30 @@ int intel_engines_init(struct drm_i915_private *dev_priv) init = class_info->init_execlists; else init = class_info->init_legacy; - if (!init) { - kfree(engine); - dev_priv->engine[id] = NULL; - continue; - } + + err = -EINVAL; + err_id = id; + + if (GEM_WARN_ON(!init)) + goto cleanup; err = init(engine); - if (err) { - err_id = id; + if (err) goto cleanup; - } GEM_BUG_ON(!engine->submit_request); - mask |= ENGINE_MASK(id); } - /* - * Catch failures to update intel_engines table when the new engines - * are added to the driver by a warning and disabling the forgotten - * engines. - */ - if (WARN_ON(mask != INTEL_INFO(dev_priv)->ring_mask)) - device_info->ring_mask = mask; - - device_info->num_rings = hweight32(mask); - return 0; cleanup: for_each_engine(engine, dev_priv, id) { - if (id >= err_id) + if (id >= err_id) { kfree(engine); - else + dev_priv->engine[id] = NULL; + } else { dev_priv->gt.cleanup_engine(engine); + } } return err; } -- cgit v1.2.3 From c58949f4185020d6d447698818fc7614adec69cf Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Mon, 19 Jun 2017 11:59:17 +0100 Subject: drm/i915: Do not re-calculate num_rings locally Since bb8f0f5abdd7 ("drm/i915: Split intel_engine allocation and initialisation") intel_info->num_rings is set early in the load sequence and so available to be used direclty in the 2nd load phase. Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/20170616130339.23015-1-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/intel_ringbuffer.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index acd1da9b62a3..5224b7abb8a3 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -2140,7 +2140,7 @@ static void intel_ring_default_vfuncs(struct drm_i915_private *dev_priv, engine->emit_breadcrumb = gen6_sema_emit_breadcrumb; - num_rings = hweight32(INTEL_INFO(dev_priv)->ring_mask) - 1; + num_rings = INTEL_INFO(dev_priv)->num_rings - 1; if (INTEL_GEN(dev_priv) >= 8) { engine->emit_breadcrumb_sz += num_rings * 6; } else { @@ -2184,8 +2184,7 @@ int intel_init_render_ring_buffer(struct intel_engine_cs *engine) engine->semaphore.signal = gen8_rcs_signal; - num_rings = - hweight32(INTEL_INFO(dev_priv)->ring_mask) - 1; + num_rings = INTEL_INFO(dev_priv)->num_rings - 1; engine->emit_breadcrumb_sz += num_rings * 8; } } else if (INTEL_GEN(dev_priv) >= 6) { -- cgit v1.2.3 From d0a2987866b6cc1acd3ed37f9cd52e5c8dced005 Mon Sep 17 00:00:00 2001 From: Liviu Dudau Date: Tue, 20 Jun 2017 11:23:20 +0100 Subject: drm: Convert CMA fbdev console suspend helpers to use bool drm_fbdev_cma_set_suspend{,_unlocked} use an integer parameter to describe whether the intended state is a suspend or a resume. It then passes the value to drm_fb_helper_set_suspend{,_unlocked} which uses a boolean. Switch to using bool everywhere. Signed-off-by: Liviu Dudau Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170620102320.8849-1-Liviu.Dudau@arm.com --- drivers/gpu/drm/drm_fb_cma_helper.c | 4 ++-- include/drm/drm_fb_cma_helper.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c index 53f9bdf470d7..ade319d10e70 100644 --- a/drivers/gpu/drm/drm_fb_cma_helper.c +++ b/drivers/gpu/drm/drm_fb_cma_helper.c @@ -640,7 +640,7 @@ EXPORT_SYMBOL_GPL(drm_fbdev_cma_hotplug_event); * Calls drm_fb_helper_set_suspend, which is a wrapper around * fb_set_suspend implemented by fbdev core. */ -void drm_fbdev_cma_set_suspend(struct drm_fbdev_cma *fbdev_cma, int state) +void drm_fbdev_cma_set_suspend(struct drm_fbdev_cma *fbdev_cma, bool state) { if (fbdev_cma) drm_fb_helper_set_suspend(&fbdev_cma->fb_helper, state); @@ -657,7 +657,7 @@ EXPORT_SYMBOL(drm_fbdev_cma_set_suspend); * fb_set_suspend implemented by fbdev core. */ void drm_fbdev_cma_set_suspend_unlocked(struct drm_fbdev_cma *fbdev_cma, - int state) + bool state) { if (fbdev_cma) drm_fb_helper_set_suspend_unlocked(&fbdev_cma->fb_helper, diff --git a/include/drm/drm_fb_cma_helper.h b/include/drm/drm_fb_cma_helper.h index 199a63f48659..a323781afc3f 100644 --- a/include/drm/drm_fb_cma_helper.h +++ b/include/drm/drm_fb_cma_helper.h @@ -24,9 +24,9 @@ void drm_fbdev_cma_fini(struct drm_fbdev_cma *fbdev_cma); void drm_fbdev_cma_restore_mode(struct drm_fbdev_cma *fbdev_cma); void drm_fbdev_cma_hotplug_event(struct drm_fbdev_cma *fbdev_cma); -void drm_fbdev_cma_set_suspend(struct drm_fbdev_cma *fbdev_cma, int state); +void drm_fbdev_cma_set_suspend(struct drm_fbdev_cma *fbdev_cma, bool state); void drm_fbdev_cma_set_suspend_unlocked(struct drm_fbdev_cma *fbdev_cma, - int state); + bool state); void drm_fb_cma_destroy(struct drm_framebuffer *fb); int drm_fb_cma_create_handle(struct drm_framebuffer *fb, -- cgit v1.2.3 From 829a0af29f70612f505302cc785a1ddd2bac148b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 20 Jun 2017 12:05:45 +0100 Subject: drm/i915: Group all the global context information together Create a substruct to hold all the global context state under drm_i915_private. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20170620110547.15947-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_debugfs.c | 4 +-- drivers/gpu/drm/i915/i915_drv.c | 9 +++--- drivers/gpu/drm/i915/i915_drv.h | 20 ++++++++------ drivers/gpu/drm/i915/i915_gem.c | 13 ++++----- drivers/gpu/drm/i915/i915_gem_context.c | 35 +++++++++++++----------- drivers/gpu/drm/i915/i915_gem_context.h | 14 ++++++---- drivers/gpu/drm/i915/i915_perf.c | 2 +- drivers/gpu/drm/i915/i915_sysfs.c | 2 +- drivers/gpu/drm/i915/intel_lrc.c | 2 +- drivers/gpu/drm/i915/selftests/mock_context.c | 2 +- drivers/gpu/drm/i915/selftests/mock_gem_device.c | 4 +-- 11 files changed, 58 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 4577b0af6886..6103d0079d16 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1966,7 +1966,7 @@ static int i915_context_status(struct seq_file *m, void *unused) if (ret) return ret; - list_for_each_entry(ctx, &dev_priv->context_list, link) { + list_for_each_entry(ctx, &dev_priv->contexts.list, link) { seq_printf(m, "HW context %u ", ctx->hw_id); if (ctx->pid) { struct task_struct *task; @@ -2072,7 +2072,7 @@ static int i915_dump_lrc(struct seq_file *m, void *unused) if (ret) return ret; - list_for_each_entry(ctx, &dev_priv->context_list, link) + list_for_each_entry(ctx, &dev_priv->contexts.list, link) for_each_engine(engine, dev_priv, id) i915_dump_lrc_obj(m, ctx, engine); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index ee2325b180e7..36585b6e3718 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -588,13 +588,13 @@ static void i915_gem_fini(struct drm_i915_private *dev_priv) mutex_lock(&dev_priv->drm.struct_mutex); intel_uc_fini_hw(dev_priv); i915_gem_cleanup_engines(dev_priv); - i915_gem_context_fini(dev_priv); + i915_gem_contexts_fini(dev_priv); i915_gem_cleanup_userptr(dev_priv); mutex_unlock(&dev_priv->drm.struct_mutex); i915_gem_drain_freed_objects(dev_priv); - WARN_ON(!list_empty(&dev_priv->context_list)); + WARN_ON(!list_empty(&dev_priv->contexts.list)); } static int i915_load_modeset_init(struct drm_device *dev) @@ -1425,9 +1425,10 @@ static void i915_driver_release(struct drm_device *dev) static int i915_driver_open(struct drm_device *dev, struct drm_file *file) { + struct drm_i915_private *i915 = to_i915(dev); int ret; - ret = i915_gem_open(dev, file); + ret = i915_gem_open(i915, file); if (ret) return ret; @@ -1457,7 +1458,7 @@ static void i915_driver_postclose(struct drm_device *dev, struct drm_file *file) struct drm_i915_file_private *file_priv = file->driver_priv; mutex_lock(&dev->struct_mutex); - i915_gem_context_close(dev, file); + i915_gem_context_close(file); i915_gem_release(dev, file); mutex_unlock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e2d2b785cb65..fb627df0fa87 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2235,13 +2235,6 @@ struct drm_i915_private { DECLARE_HASHTABLE(mm_structs, 7); struct mutex mm_lock; - /* The hw wants to have a stable context identifier for the lifetime - * of the context (for OA, PASID, faults, etc). This is limited - * in execlists to 21 bits. - */ - struct ida context_hw_ida; -#define MAX_CONTEXT_HW_ID (1<<21) /* exclusive */ - /* Kernel Modesetting */ struct intel_crtc *plane_to_crtc_mapping[I915_MAX_PIPES]; @@ -2320,7 +2313,16 @@ struct drm_i915_private { */ struct mutex av_mutex; - struct list_head context_list; + struct { + struct list_head list; + + /* The hw wants to have a stable context identifier for the + * lifetime of the context (for OA, PASID, faults, etc). + * This is limited in execlists to 21 bits. + */ + struct ida hw_ida; +#define MAX_CONTEXT_HW_ID (1<<21) /* exclusive */ + } contexts; u32 fdi_rx_config; @@ -3498,7 +3500,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, void i915_gem_object_unpin_from_display_plane(struct i915_vma *vma); int i915_gem_object_attach_phys(struct drm_i915_gem_object *obj, int align); -int i915_gem_open(struct drm_device *dev, struct drm_file *file); +int i915_gem_open(struct drm_i915_private *i915, struct drm_file *file); void i915_gem_release(struct drm_device *dev, struct drm_file *file); int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 7dcac3bfb771..c2213016fd86 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3098,7 +3098,7 @@ void i915_gem_set_wedged(struct drm_i915_private *dev_priv) stop_machine(__i915_gem_set_wedged_BKL, dev_priv, NULL); - i915_gem_context_lost(dev_priv); + i915_gem_contexts_lost(dev_priv); mod_delayed_work(dev_priv->wq, &dev_priv->gt.idle_work, 0); } @@ -4564,7 +4564,7 @@ int i915_gem_suspend(struct drm_i915_private *dev_priv) goto err_unlock; assert_kernel_context_is_current(dev_priv); - i915_gem_context_lost(dev_priv); + i915_gem_contexts_lost(dev_priv); mutex_unlock(&dev->struct_mutex); intel_guc_suspend(dev_priv); @@ -4811,7 +4811,7 @@ int i915_gem_init(struct drm_i915_private *dev_priv) if (ret) goto out_unlock; - ret = i915_gem_context_init(dev_priv); + ret = i915_gem_contexts_init(dev_priv); if (ret) goto out_unlock; @@ -4921,7 +4921,6 @@ i915_gem_load_init(struct drm_i915_private *dev_priv) if (err) goto err_priorities; - INIT_LIST_HEAD(&dev_priv->context_list); INIT_WORK(&dev_priv->mm.free_work, __i915_gem_free_work); init_llist_head(&dev_priv->mm.free_list); INIT_LIST_HEAD(&dev_priv->mm.unbound_list); @@ -5045,7 +5044,7 @@ void i915_gem_release(struct drm_device *dev, struct drm_file *file) } } -int i915_gem_open(struct drm_device *dev, struct drm_file *file) +int i915_gem_open(struct drm_i915_private *i915, struct drm_file *file) { struct drm_i915_file_private *file_priv; int ret; @@ -5057,7 +5056,7 @@ int i915_gem_open(struct drm_device *dev, struct drm_file *file) return -ENOMEM; file->driver_priv = file_priv; - file_priv->dev_priv = to_i915(dev); + file_priv->dev_priv = i915; file_priv->file = file; INIT_LIST_HEAD(&file_priv->rps.link); @@ -5066,7 +5065,7 @@ int i915_gem_open(struct drm_device *dev, struct drm_file *file) file_priv->bsd_engine = -1; - ret = i915_gem_context_open(dev, file); + ret = i915_gem_context_open(i915, file); if (ret) kfree(file_priv); diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 39ed58a21fc1..7a6a667c23ec 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -188,7 +188,7 @@ void i915_gem_context_free(struct kref *ctx_ref) list_del(&ctx->link); - ida_simple_remove(&ctx->i915->context_hw_ida, ctx->hw_id); + ida_simple_remove(&ctx->i915->contexts.hw_ida, ctx->hw_id); kfree(ctx); } @@ -205,7 +205,7 @@ static int assign_hw_id(struct drm_i915_private *dev_priv, unsigned *out) { int ret; - ret = ida_simple_get(&dev_priv->context_hw_ida, + ret = ida_simple_get(&dev_priv->contexts.hw_ida, 0, MAX_CONTEXT_HW_ID, GFP_KERNEL); if (ret < 0) { /* Contexts are only released when no longer active. @@ -213,7 +213,7 @@ static int assign_hw_id(struct drm_i915_private *dev_priv, unsigned *out) * stale contexts and try again. */ i915_gem_retire_requests(dev_priv); - ret = ida_simple_get(&dev_priv->context_hw_ida, + ret = ida_simple_get(&dev_priv->contexts.hw_ida, 0, MAX_CONTEXT_HW_ID, GFP_KERNEL); if (ret < 0) return ret; @@ -265,7 +265,7 @@ __create_hw_context(struct drm_i915_private *dev_priv, } kref_init(&ctx->ref); - list_add_tail(&ctx->link, &dev_priv->context_list); + list_add_tail(&ctx->link, &dev_priv->contexts.list); ctx->i915 = dev_priv; ctx->priority = I915_PRIORITY_NORMAL; @@ -418,7 +418,7 @@ out: return ctx; } -int i915_gem_context_init(struct drm_i915_private *dev_priv) +int i915_gem_contexts_init(struct drm_i915_private *dev_priv) { struct i915_gem_context *ctx; @@ -427,6 +427,8 @@ int i915_gem_context_init(struct drm_i915_private *dev_priv) if (WARN_ON(dev_priv->kernel_context)) return 0; + INIT_LIST_HEAD(&dev_priv->contexts.list); + if (intel_vgpu_active(dev_priv) && HAS_LOGICAL_RING_CONTEXTS(dev_priv)) { if (!i915.enable_execlists) { @@ -437,7 +439,7 @@ int i915_gem_context_init(struct drm_i915_private *dev_priv) /* Using the simple ida interface, the max is limited by sizeof(int) */ BUILD_BUG_ON(MAX_CONTEXT_HW_ID > INT_MAX); - ida_init(&dev_priv->context_hw_ida); + ida_init(&dev_priv->contexts.hw_ida); ctx = i915_gem_create_context(dev_priv, NULL); if (IS_ERR(ctx)) { @@ -463,7 +465,7 @@ int i915_gem_context_init(struct drm_i915_private *dev_priv) return 0; } -void i915_gem_context_lost(struct drm_i915_private *dev_priv) +void i915_gem_contexts_lost(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; enum intel_engine_id id; @@ -484,7 +486,7 @@ void i915_gem_context_lost(struct drm_i915_private *dev_priv) if (!i915.enable_execlists) { struct i915_gem_context *ctx; - list_for_each_entry(ctx, &dev_priv->context_list, link) { + list_for_each_entry(ctx, &dev_priv->contexts.list, link) { if (!i915_gem_context_is_default(ctx)) continue; @@ -503,7 +505,7 @@ void i915_gem_context_lost(struct drm_i915_private *dev_priv) } } -void i915_gem_context_fini(struct drm_i915_private *dev_priv) +void i915_gem_contexts_fini(struct drm_i915_private *dev_priv) { struct i915_gem_context *dctx = dev_priv->kernel_context; @@ -514,7 +516,7 @@ void i915_gem_context_fini(struct drm_i915_private *dev_priv) context_close(dctx); dev_priv->kernel_context = NULL; - ida_destroy(&dev_priv->context_hw_ida); + ida_destroy(&dev_priv->contexts.hw_ida); } static int context_idr_cleanup(int id, void *p, void *data) @@ -525,16 +527,17 @@ static int context_idr_cleanup(int id, void *p, void *data) return 0; } -int i915_gem_context_open(struct drm_device *dev, struct drm_file *file) +int i915_gem_context_open(struct drm_i915_private *i915, + struct drm_file *file) { struct drm_i915_file_private *file_priv = file->driver_priv; struct i915_gem_context *ctx; idr_init(&file_priv->context_idr); - mutex_lock(&dev->struct_mutex); - ctx = i915_gem_create_context(to_i915(dev), file_priv); - mutex_unlock(&dev->struct_mutex); + mutex_lock(&i915->drm.struct_mutex); + ctx = i915_gem_create_context(i915, file_priv); + mutex_unlock(&i915->drm.struct_mutex); GEM_BUG_ON(i915_gem_context_is_kernel(ctx)); @@ -546,11 +549,11 @@ int i915_gem_context_open(struct drm_device *dev, struct drm_file *file) return 0; } -void i915_gem_context_close(struct drm_device *dev, struct drm_file *file) +void i915_gem_context_close(struct drm_file *file) { struct drm_i915_file_private *file_priv = file->driver_priv; - lockdep_assert_held(&dev->struct_mutex); + lockdep_assert_held(&file_priv->dev_priv->drm.struct_mutex); idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL); idr_destroy(&file_priv->context_idr); diff --git a/drivers/gpu/drm/i915/i915_gem_context.h b/drivers/gpu/drm/i915/i915_gem_context.h index 82c99ba92ad3..808f878db812 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.h +++ b/drivers/gpu/drm/i915/i915_gem_context.h @@ -273,13 +273,17 @@ static inline bool i915_gem_context_is_kernel(struct i915_gem_context *ctx) } /* i915_gem_context.c */ -int __must_check i915_gem_context_init(struct drm_i915_private *dev_priv); -void i915_gem_context_lost(struct drm_i915_private *dev_priv); -void i915_gem_context_fini(struct drm_i915_private *dev_priv); -int i915_gem_context_open(struct drm_device *dev, struct drm_file *file); -void i915_gem_context_close(struct drm_device *dev, struct drm_file *file); +int __must_check i915_gem_contexts_init(struct drm_i915_private *dev_priv); +void i915_gem_contexts_lost(struct drm_i915_private *dev_priv); +void i915_gem_contexts_fini(struct drm_i915_private *dev_priv); + +int i915_gem_context_open(struct drm_i915_private *i915, + struct drm_file *file); +void i915_gem_context_close(struct drm_file *file); + int i915_switch_context(struct drm_i915_gem_request *req); int i915_gem_switch_to_kernel_context(struct drm_i915_private *dev_priv); + void i915_gem_context_free(struct kref *ctx_ref); struct i915_gem_context * i915_gem_context_create_gvt(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 38c44407bafc..d1771e8fe4a8 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -1746,7 +1746,7 @@ static int gen8_configure_all_contexts(struct drm_i915_private *dev_priv, goto out; /* Update all contexts now that we've stalled the submission. */ - list_for_each_entry(ctx, &dev_priv->context_list, link) { + list_for_each_entry(ctx, &dev_priv->contexts.list, link) { struct intel_context *ce = &ctx->engine[RCS]; u32 *regs; diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index 1eef3fae4db3..3a481062f219 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -209,7 +209,7 @@ i915_l3_write(struct file *filp, struct kobject *kobj, memcpy(*remap_info + (offset/4), buf, count); /* NB: We defer the remapping until we switch to the context */ - list_for_each_entry(ctx, &dev_priv->context_list, link) + list_for_each_entry(ctx, &dev_priv->contexts.list, link) ctx->remap_slice |= (1<context_list, link) { + list_for_each_entry(ctx, &dev_priv->contexts.list, link) { for_each_engine(engine, dev_priv, id) { struct intel_context *ce = &ctx->engine[engine->id]; u32 *reg; diff --git a/drivers/gpu/drm/i915/selftests/mock_context.c b/drivers/gpu/drm/i915/selftests/mock_context.c index f8b9cc212b02..243325b97d4c 100644 --- a/drivers/gpu/drm/i915/selftests/mock_context.c +++ b/drivers/gpu/drm/i915/selftests/mock_context.c @@ -48,7 +48,7 @@ mock_context(struct drm_i915_private *i915, if (!ctx->vma_lut.ht) goto err_free; - ret = ida_simple_get(&i915->context_hw_ida, + ret = ida_simple_get(&i915->contexts.hw_ida, 0, MAX_CONTEXT_HW_ID, GFP_KERNEL); if (ret < 0) goto err_vma_ht; diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index 627e2aa09766..0ddb70a16550 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c @@ -61,7 +61,7 @@ static void mock_device_release(struct drm_device *dev) mutex_lock(&i915->drm.struct_mutex); for_each_engine(engine, i915, id) mock_engine_free(engine); - i915_gem_context_fini(i915); + i915_gem_contexts_fini(i915); mutex_unlock(&i915->drm.struct_mutex); drain_workqueue(i915->wq); @@ -160,7 +160,7 @@ struct drm_i915_private *mock_gem_device(void) INIT_LIST_HEAD(&i915->mm.unbound_list); INIT_LIST_HEAD(&i915->mm.bound_list); - ida_init(&i915->context_hw_ida); + ida_init(&i915->contexts.hw_ida); INIT_DELAYED_WORK(&i915->gt.retire_work, mock_retire_work_handler); INIT_DELAYED_WORK(&i915->gt.idle_work, mock_idle_work_handler); -- cgit v1.2.3 From 5f09a9c8ab6b16eefbcf81635330d68481af1edc Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 20 Jun 2017 12:05:46 +0100 Subject: drm/i915: Allow contexts to be unreferenced locklessly If we move the actual cleanup of the context to a worker, we can allow the final free to be called from any context and avoid undue latency in the caller. v2: Negotiate handling the delayed contexts free by flushing the workqueue before calling i915_gem_context_fini() and performing the final free of the kernel context directly v3: Flush deferred frees before new context allocations Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20170620110547.15947-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gvt/scheduler.c | 2 +- drivers/gpu/drm/i915/i915_drv.c | 2 + drivers/gpu/drm/i915/i915_drv.h | 23 +-------- drivers/gpu/drm/i915/i915_gem_context.c | 59 +++++++++++++++++++----- drivers/gpu/drm/i915/i915_gem_context.h | 15 +++++- drivers/gpu/drm/i915/i915_perf.c | 4 +- drivers/gpu/drm/i915/selftests/i915_vma.c | 8 +++- drivers/gpu/drm/i915/selftests/mock_context.c | 9 ++++ drivers/gpu/drm/i915/selftests/mock_context.h | 2 + drivers/gpu/drm/i915/selftests/mock_gem_device.c | 3 +- 10 files changed, 88 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index 488fdea348a9..2b8a80c9c18b 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -620,7 +620,7 @@ err: void intel_vgpu_clean_gvt_context(struct intel_vgpu *vgpu) { - i915_gem_context_put_unlocked(vgpu->shadow_ctx); + i915_gem_context_put(vgpu->shadow_ctx); } int intel_vgpu_init_gvt_context(struct intel_vgpu *vgpu) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 36585b6e3718..fe3d46ee4ddc 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -585,6 +585,8 @@ static const struct vga_switcheroo_client_ops i915_switcheroo_ops = { static void i915_gem_fini(struct drm_i915_private *dev_priv) { + flush_workqueue(dev_priv->wq); + mutex_lock(&dev_priv->drm.struct_mutex); intel_uc_fini_hw(dev_priv); i915_gem_cleanup_engines(dev_priv); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index fb627df0fa87..0f1330adc37b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2315,6 +2315,8 @@ struct drm_i915_private { struct { struct list_head list; + struct llist_head free_list; + struct work_struct free_work; /* The hw wants to have a stable context identifier for the * lifetime of the context (for OA, PASID, faults, etc). @@ -3545,27 +3547,6 @@ i915_gem_context_lookup(struct drm_i915_file_private *file_priv, u32 id) return ctx; } -static inline struct i915_gem_context * -i915_gem_context_get(struct i915_gem_context *ctx) -{ - kref_get(&ctx->ref); - return ctx; -} - -static inline void i915_gem_context_put(struct i915_gem_context *ctx) -{ - lockdep_assert_held(&ctx->i915->drm.struct_mutex); - kref_put(&ctx->ref, i915_gem_context_free); -} - -static inline void i915_gem_context_put_unlocked(struct i915_gem_context *ctx) -{ - struct mutex *lock = &ctx->i915->drm.struct_mutex; - - if (kref_put_mutex(&ctx->ref, i915_gem_context_free, lock)) - mutex_unlock(lock); -} - static inline struct intel_timeline * i915_gem_context_lookup_timeline(struct i915_gem_context *ctx, struct intel_engine_cs *engine) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 7a6a667c23ec..9cf96380af9f 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -158,13 +158,11 @@ static void vma_lut_free(struct i915_gem_context *ctx) kvfree(lut->ht); } -void i915_gem_context_free(struct kref *ctx_ref) +static void i915_gem_context_free(struct i915_gem_context *ctx) { - struct i915_gem_context *ctx = container_of(ctx_ref, typeof(*ctx), ref); int i; lockdep_assert_held(&ctx->i915->drm.struct_mutex); - trace_i915_context_free(ctx); GEM_BUG_ON(!i915_gem_context_is_closed(ctx)); vma_lut_free(ctx); @@ -192,6 +190,37 @@ void i915_gem_context_free(struct kref *ctx_ref) kfree(ctx); } +static void contexts_free(struct drm_i915_private *i915) +{ + struct llist_node *freed = llist_del_all(&i915->contexts.free_list); + struct i915_gem_context *ctx; + + lockdep_assert_held(&i915->drm.struct_mutex); + + llist_for_each_entry(ctx, freed, free_link) + i915_gem_context_free(ctx); +} + +static void contexts_free_worker(struct work_struct *work) +{ + struct drm_i915_private *i915 = + container_of(work, typeof(*i915), contexts.free_work); + + mutex_lock(&i915->drm.struct_mutex); + contexts_free(i915); + mutex_unlock(&i915->drm.struct_mutex); +} + +void i915_gem_context_release(struct kref *ref) +{ + struct i915_gem_context *ctx = container_of(ref, typeof(*ctx), ref); + struct drm_i915_private *i915 = ctx->i915; + + trace_i915_context_free(ctx); + if (llist_add(&ctx->free_link, &i915->contexts.free_list)) + queue_work(i915->wq, &i915->contexts.free_work); +} + static void context_close(struct i915_gem_context *ctx) { i915_gem_context_set_closed(ctx); @@ -428,6 +457,8 @@ int i915_gem_contexts_init(struct drm_i915_private *dev_priv) return 0; INIT_LIST_HEAD(&dev_priv->contexts.list); + INIT_WORK(&dev_priv->contexts.free_work, contexts_free_worker); + init_llist_head(&dev_priv->contexts.free_list); if (intel_vgpu_active(dev_priv) && HAS_LOGICAL_RING_CONTEXTS(dev_priv)) { @@ -505,18 +536,20 @@ void i915_gem_contexts_lost(struct drm_i915_private *dev_priv) } } -void i915_gem_contexts_fini(struct drm_i915_private *dev_priv) +void i915_gem_contexts_fini(struct drm_i915_private *i915) { - struct i915_gem_context *dctx = dev_priv->kernel_context; - - lockdep_assert_held(&dev_priv->drm.struct_mutex); + struct i915_gem_context *ctx; - GEM_BUG_ON(!i915_gem_context_is_kernel(dctx)); + lockdep_assert_held(&i915->drm.struct_mutex); - context_close(dctx); - dev_priv->kernel_context = NULL; + /* Keep the context so that we can free it immediately ourselves */ + ctx = i915_gem_context_get(fetch_and_zero(&i915->kernel_context)); + GEM_BUG_ON(!i915_gem_context_is_kernel(ctx)); + context_close(ctx); + i915_gem_context_free(ctx); - ida_destroy(&dev_priv->contexts.hw_ida); + /* Must free all deferred contexts (via flush_workqueue) first */ + ida_destroy(&i915->contexts.hw_ida); } static int context_idr_cleanup(int id, void *p, void *data) @@ -957,6 +990,10 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, if (ret) return ret; + /* Reap stale contexts */ + i915_gem_retire_requests(dev_priv); + contexts_free(dev_priv); + ctx = i915_gem_create_context(dev_priv, file_priv); mutex_unlock(&dev->struct_mutex); if (IS_ERR(ctx)) diff --git a/drivers/gpu/drm/i915/i915_gem_context.h b/drivers/gpu/drm/i915/i915_gem_context.h index 808f878db812..61146f4aa168 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.h +++ b/drivers/gpu/drm/i915/i915_gem_context.h @@ -86,6 +86,7 @@ struct i915_gem_context { /** link: place with &drm_i915_private.context_list */ struct list_head link; + struct llist_node free_link; /** * @ref: reference count @@ -284,7 +285,7 @@ void i915_gem_context_close(struct drm_file *file); int i915_switch_context(struct drm_i915_gem_request *req); int i915_gem_switch_to_kernel_context(struct drm_i915_private *dev_priv); -void i915_gem_context_free(struct kref *ctx_ref); +void i915_gem_context_release(struct kref *ctx_ref); struct i915_gem_context * i915_gem_context_create_gvt(struct drm_device *dev); @@ -299,4 +300,16 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data, int i915_gem_context_reset_stats_ioctl(struct drm_device *dev, void *data, struct drm_file *file); +static inline struct i915_gem_context * +i915_gem_context_get(struct i915_gem_context *ctx) +{ + kref_get(&ctx->ref); + return ctx; +} + +static inline void i915_gem_context_put(struct i915_gem_context *ctx) +{ + kref_put(&ctx->ref, i915_gem_context_release); +} + #endif /* !__I915_GEM_CONTEXT_H__ */ diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index d1771e8fe4a8..afd8260cd096 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -2444,7 +2444,7 @@ static void i915_perf_destroy_locked(struct i915_perf_stream *stream) list_del(&stream->link); if (stream->ctx) - i915_gem_context_put_unlocked(stream->ctx); + i915_gem_context_put(stream->ctx); kfree(stream); } @@ -2633,7 +2633,7 @@ err_alloc: kfree(stream); err_ctx: if (specific_ctx) - i915_gem_context_put_unlocked(specific_ctx); + i915_gem_context_put(specific_ctx); err: return ret; } diff --git a/drivers/gpu/drm/i915/selftests/i915_vma.c b/drivers/gpu/drm/i915/selftests/i915_vma.c index fb9072d5877f..2e86ec136b35 100644 --- a/drivers/gpu/drm/i915/selftests/i915_vma.c +++ b/drivers/gpu/drm/i915/selftests/i915_vma.c @@ -186,16 +186,20 @@ static int igt_vma_create(void *arg) goto end; } - list_for_each_entry_safe(ctx, cn, &contexts, link) + list_for_each_entry_safe(ctx, cn, &contexts, link) { + list_del_init(&ctx->link); mock_context_close(ctx); + } } end: /* Final pass to lookup all created contexts */ err = create_vmas(i915, &objects, &contexts); out: - list_for_each_entry_safe(ctx, cn, &contexts, link) + list_for_each_entry_safe(ctx, cn, &contexts, link) { + list_del_init(&ctx->link); mock_context_close(ctx); + } list_for_each_entry_safe(obj, on, &objects, st_link) i915_gem_object_put(obj); diff --git a/drivers/gpu/drm/i915/selftests/mock_context.c b/drivers/gpu/drm/i915/selftests/mock_context.c index 243325b97d4c..9c7c68181f82 100644 --- a/drivers/gpu/drm/i915/selftests/mock_context.c +++ b/drivers/gpu/drm/i915/selftests/mock_context.c @@ -86,3 +86,12 @@ void mock_context_close(struct i915_gem_context *ctx) i915_gem_context_put(ctx); } + +void mock_init_contexts(struct drm_i915_private *i915) +{ + INIT_LIST_HEAD(&i915->contexts.list); + ida_init(&i915->contexts.hw_ida); + + INIT_WORK(&i915->contexts.free_work, contexts_free_worker); + init_llist_head(&i915->contexts.free_list); +} diff --git a/drivers/gpu/drm/i915/selftests/mock_context.h b/drivers/gpu/drm/i915/selftests/mock_context.h index 2427e5c0916a..383941a61124 100644 --- a/drivers/gpu/drm/i915/selftests/mock_context.h +++ b/drivers/gpu/drm/i915/selftests/mock_context.h @@ -25,6 +25,8 @@ #ifndef __MOCK_CONTEXT_H #define __MOCK_CONTEXT_H +void mock_init_contexts(struct drm_i915_private *i915); + struct i915_gem_context * mock_context(struct drm_i915_private *i915, const char *name); diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index 0ddb70a16550..47613d20bba8 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c @@ -57,6 +57,7 @@ static void mock_device_release(struct drm_device *dev) cancel_delayed_work_sync(&i915->gt.retire_work); cancel_delayed_work_sync(&i915->gt.idle_work); + flush_workqueue(i915->wq); mutex_lock(&i915->drm.struct_mutex); for_each_engine(engine, i915, id) @@ -160,7 +161,7 @@ struct drm_i915_private *mock_gem_device(void) INIT_LIST_HEAD(&i915->mm.unbound_list); INIT_LIST_HEAD(&i915->mm.bound_list); - ida_init(&i915->contexts.hw_ida); + mock_init_contexts(i915); INIT_DELAYED_WORK(&i915->gt.retire_work, mock_retire_work_handler); INIT_DELAYED_WORK(&i915->gt.idle_work, mock_idle_work_handler); -- cgit v1.2.3 From 1acfc104cdf8a3408f0e83b4115d4419c6315005 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 20 Jun 2017 12:05:47 +0100 Subject: drm/i915: Enable rcu-only context lookups Whilst the contents of the context is still protected by the big struct_mutex, this is not much of an improvement. It is just one tiny step towards reducing our BKL. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20170620110547.15947-3-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h | 16 +++++-- drivers/gpu/drm/i915/i915_gem_context.c | 77 ++++++++++++++---------------- drivers/gpu/drm/i915/i915_gem_context.h | 5 ++ drivers/gpu/drm/i915/i915_gem_execbuffer.c | 21 ++++---- 4 files changed, 64 insertions(+), 55 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0f1330adc37b..69219b5d1198 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3533,16 +3533,22 @@ void i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj, void i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj, struct sg_table *pages); +static inline struct i915_gem_context * +__i915_gem_context_lookup_rcu(struct drm_i915_file_private *file_priv, u32 id) +{ + return idr_find(&file_priv->context_idr, id); +} + static inline struct i915_gem_context * i915_gem_context_lookup(struct drm_i915_file_private *file_priv, u32 id) { struct i915_gem_context *ctx; - lockdep_assert_held(&file_priv->dev_priv->drm.struct_mutex); - - ctx = idr_find(&file_priv->context_idr, id); - if (!ctx) - return ERR_PTR(-ENOENT); + rcu_read_lock(); + ctx = __i915_gem_context_lookup_rcu(file_priv, id); + if (ctx && !kref_get_unless_zero(&ctx->ref)) + ctx = NULL; + rcu_read_unlock(); return ctx; } diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 9cf96380af9f..71d2ea7dab64 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -187,7 +187,7 @@ static void i915_gem_context_free(struct i915_gem_context *ctx) list_del(&ctx->link); ida_simple_remove(&ctx->i915->contexts.hw_ida, ctx->hw_id); - kfree(ctx); + kfree_rcu(ctx, rcu); } static void contexts_free(struct drm_i915_private *i915) @@ -1021,20 +1021,19 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data, if (args->ctx_id == DEFAULT_CONTEXT_HANDLE) return -ENOENT; - ret = i915_mutex_lock_interruptible(dev); - if (ret) - return ret; - ctx = i915_gem_context_lookup(file_priv, args->ctx_id); - if (IS_ERR(ctx)) { - mutex_unlock(&dev->struct_mutex); - return PTR_ERR(ctx); - } + if (!ctx) + return -ENOENT; + + ret = mutex_lock_interruptible(&dev->struct_mutex); + if (ret) + goto out; __destroy_hw_context(ctx, file_priv); mutex_unlock(&dev->struct_mutex); - DRM_DEBUG("HW context %d destroyed\n", args->ctx_id); +out: + i915_gem_context_put(ctx); return 0; } @@ -1044,17 +1043,11 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data, struct drm_i915_file_private *file_priv = file->driver_priv; struct drm_i915_gem_context_param *args = data; struct i915_gem_context *ctx; - int ret; - - ret = i915_mutex_lock_interruptible(dev); - if (ret) - return ret; + int ret = 0; ctx = i915_gem_context_lookup(file_priv, args->ctx_id); - if (IS_ERR(ctx)) { - mutex_unlock(&dev->struct_mutex); - return PTR_ERR(ctx); - } + if (!ctx) + return -ENOENT; args->size = 0; switch (args->param) { @@ -1082,8 +1075,8 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data, ret = -EINVAL; break; } - mutex_unlock(&dev->struct_mutex); + i915_gem_context_put(ctx); return ret; } @@ -1095,15 +1088,13 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data, struct i915_gem_context *ctx; int ret; + ctx = i915_gem_context_lookup(file_priv, args->ctx_id); + if (!ctx) + return -ENOENT; + ret = i915_mutex_lock_interruptible(dev); if (ret) - return ret; - - ctx = i915_gem_context_lookup(file_priv, args->ctx_id); - if (IS_ERR(ctx)) { - mutex_unlock(&dev->struct_mutex); - return PTR_ERR(ctx); - } + goto out; switch (args->param) { case I915_CONTEXT_PARAM_BAN_PERIOD: @@ -1141,6 +1132,8 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data, } mutex_unlock(&dev->struct_mutex); +out: + i915_gem_context_put(ctx); return ret; } @@ -1155,27 +1148,31 @@ int i915_gem_context_reset_stats_ioctl(struct drm_device *dev, if (args->flags || args->pad) return -EINVAL; - ret = i915_mutex_lock_interruptible(dev); - if (ret) - return ret; + ret = -ENOENT; + rcu_read_lock(); + ctx = __i915_gem_context_lookup_rcu(file->driver_priv, args->ctx_id); + if (!ctx) + goto out; - ctx = i915_gem_context_lookup(file->driver_priv, args->ctx_id); - if (IS_ERR(ctx)) { - mutex_unlock(&dev->struct_mutex); - return PTR_ERR(ctx); - } + /* + * We opt for unserialised reads here. This may result in tearing + * in the extremely unlikely event of a GPU hang on this context + * as we are querying them. If we need that extra layer of protection, + * we should wrap the hangstats with a seqlock. + */ if (capable(CAP_SYS_ADMIN)) args->reset_count = i915_reset_count(&dev_priv->gpu_error); else args->reset_count = 0; - args->batch_active = ctx->guilty_count; - args->batch_pending = ctx->active_count; - - mutex_unlock(&dev->struct_mutex); + args->batch_active = READ_ONCE(ctx->guilty_count); + args->batch_pending = READ_ONCE(ctx->active_count); - return 0; + ret = 0; +out: + rcu_read_unlock(); + return ret; } #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) diff --git a/drivers/gpu/drm/i915/i915_gem_context.h b/drivers/gpu/drm/i915/i915_gem_context.h index 61146f4aa168..04320f80f9f4 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.h +++ b/drivers/gpu/drm/i915/i915_gem_context.h @@ -99,6 +99,11 @@ struct i915_gem_context { */ struct kref ref; + /** + * @rcu: rcu_head for deferred freeing. + */ + struct rcu_head rcu; + /** * @flags: small set of booleans */ diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index eb46dfa374a7..35d1f8e8906e 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -669,16 +669,17 @@ static int eb_select_context(struct i915_execbuffer *eb) struct i915_gem_context *ctx; ctx = i915_gem_context_lookup(eb->file->driver_priv, eb->args->rsvd1); - if (unlikely(IS_ERR(ctx))) - return PTR_ERR(ctx); + if (unlikely(!ctx)) + return -ENOENT; if (unlikely(i915_gem_context_is_banned(ctx))) { DRM_DEBUG("Context %u tried to submit while banned\n", ctx->user_handle); + i915_gem_context_put(ctx); return -EIO; } - eb->ctx = i915_gem_context_get(ctx); + eb->ctx = ctx; eb->vm = ctx->ppgtt ? &ctx->ppgtt->base : &eb->i915->ggtt.base; eb->context_flags = 0; @@ -2127,7 +2128,6 @@ i915_gem_do_execbuffer(struct drm_device *dev, if (DBG_FORCE_RELOC || !(args->flags & I915_EXEC_NO_RELOC)) args->flags |= __EXEC_HAS_RELOC; eb.exec = exec; - eb.ctx = NULL; eb.invalid_flags = __EXEC_OBJECT_UNKNOWN_FLAGS; if (USES_FULL_PPGTT(eb.i915)) eb.invalid_flags |= EXEC_OBJECT_NEEDS_GTT; @@ -2182,6 +2182,10 @@ i915_gem_do_execbuffer(struct drm_device *dev, if (eb_create(&eb)) return -ENOMEM; + err = eb_select_context(&eb); + if (unlikely(err)) + goto err_destroy; + /* * Take a local wakeref for preparing to dispatch the execbuf as * we expect to access the hardware fairly frequently in the @@ -2190,14 +2194,11 @@ i915_gem_do_execbuffer(struct drm_device *dev, * 100ms. */ intel_runtime_pm_get(eb.i915); + err = i915_mutex_lock_interruptible(dev); if (err) goto err_rpm; - err = eb_select_context(&eb); - if (unlikely(err)) - goto err_unlock; - err = eb_relocate(&eb); if (err) /* @@ -2333,11 +2334,11 @@ err_batch_unpin: err_vma: if (eb.exec) eb_release_vmas(&eb); - i915_gem_context_put(eb.ctx); -err_unlock: mutex_unlock(&dev->struct_mutex); err_rpm: intel_runtime_pm_put(eb.i915); + i915_gem_context_put(eb.ctx); +err_destroy: eb_destroy(&eb); if (out_fence_fd != -1) put_unused_fd(out_fence_fd); -- cgit v1.2.3 From d5367307d409e7476ce18cada304da80949b57c7 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 20 Jun 2017 10:57:43 +0100 Subject: drm/i915: Wait for concurrent global resets to complete If we enter i915_handle_error() a second time and a global reset is already in progress, we can simply wait for completion of the first reset. Currently we exit early prior to the actual reset being performed -- the worst of both worlds! v2: Plug into the existing reset_queue, and remember that kselftests is playing games with I915_RESET_BACKOFF to prevent hangcheck from screwing up. v3: Rename to i915_reset_device to fit in better with i915_reset_engine Signed-off-by: Chris Wilson Cc: Mika Kuoppala Cc: Michel Thierry Reviewed-by: Michel Thierry Link: http://patchwork.freedesktop.org/patch/msgid/20170620095751.13127-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_irq.c | 23 +++++++++++------------ drivers/gpu/drm/i915/selftests/intel_hangcheck.c | 4 ++++ 2 files changed, 15 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 4cd9ee1ba332..8e9f4378b5a7 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2600,13 +2600,13 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) } /** - * i915_reset_and_wakeup - do process context error handling work + * i915_reset_device - do process context error handling work * @dev_priv: i915 device private * * Fire an error uevent so userspace can see that a hang or error * was detected. */ -static void i915_reset_and_wakeup(struct drm_i915_private *dev_priv) +static void i915_reset_device(struct drm_i915_private *dev_priv) { struct kobject *kobj = &dev_priv->drm.primary->kdev->kobj; char *error_event[] = { I915_ERROR_UEVENT "=1", NULL }; @@ -2646,13 +2646,6 @@ static void i915_reset_and_wakeup(struct drm_i915_private *dev_priv) if (!test_bit(I915_WEDGED, &dev_priv->gpu_error.flags)) kobject_uevent_env(kobj, KOBJ_CHANGE, reset_done_event); - - /* - * Note: The wake_up also serves as a memory barrier so that - * waiters see the updated value of the dev_priv->gpu_error. - */ - clear_bit(I915_RESET_BACKOFF, &dev_priv->gpu_error.flags); - wake_up_all(&dev_priv->gpu_error.reset_queue); } static inline void @@ -2744,11 +2737,17 @@ void i915_handle_error(struct drm_i915_private *dev_priv, if (!engine_mask) goto out; - if (test_and_set_bit(I915_RESET_BACKOFF, - &dev_priv->gpu_error.flags)) + if (test_and_set_bit(I915_RESET_BACKOFF, &dev_priv->gpu_error.flags)) { + wait_event(dev_priv->gpu_error.reset_queue, + !test_bit(I915_RESET_BACKOFF, + &dev_priv->gpu_error.flags)); goto out; + } + + i915_reset_device(dev_priv); - i915_reset_and_wakeup(dev_priv); + clear_bit(I915_RESET_BACKOFF, &dev_priv->gpu_error.flags); + wake_up_all(&dev_priv->gpu_error.reset_queue); out: intel_runtime_pm_put(dev_priv); diff --git a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c index aa31d6c0cdfb..cc00a361f0fa 100644 --- a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c +++ b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c @@ -316,6 +316,8 @@ static int igt_global_reset(void *arg) GEM_BUG_ON(test_bit(I915_RESET_HANDOFF, &i915->gpu_error.flags)); clear_bit(I915_RESET_BACKOFF, &i915->gpu_error.flags); + wake_up_all(&i915->gpu_error.reset_queue); + if (i915_terminally_wedged(&i915->gpu_error)) err = -EIO; @@ -404,6 +406,7 @@ fini: unlock: mutex_unlock(&i915->drm.struct_mutex); clear_bit(I915_RESET_BACKOFF, &i915->gpu_error.flags); + wake_up_all(&i915->gpu_error.reset_queue); if (i915_terminally_wedged(&i915->gpu_error)) return -EIO; @@ -519,6 +522,7 @@ fini: unlock: mutex_unlock(&i915->drm.struct_mutex); clear_bit(I915_RESET_BACKOFF, &i915->gpu_error.flags); + wake_up_all(&i915->gpu_error.reset_queue); if (i915_terminally_wedged(&i915->gpu_error)) return -EIO; -- cgit v1.2.3 From c64992e035d7cb2b469f933e33ee89625df97df5 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Tue, 20 Jun 2017 10:57:44 +0100 Subject: drm/i915: Look for active requests earlier in the reset path And store the active request so that we only search for it once. v2: Check for request completion inside _prepare_engine, don't use ECANCELED, remove unnecessary null checks (Chris). v3: Capture active requests during reset_prepare and store it the engine hangcheck obj. v4: Rename commit, change i915_gem_reset_request to just confirm the active_request is still incomplete, instead of engine_stalled (Chris). v5: With style; pass the active request to gem_reset_engine, keep single return in reset_prepare_engine (Chris). v6: Moved before reset-engine code appears (Chris) Suggested-by: Chris Wilson Reviewed-by: Chris Wilson (v5) Signed-off-by: Michel Thierry Link: http://patchwork.freedesktop.org/patch/msgid/20170615201828.23144-2-michel.thierry@intel.com Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/20170620095751.13127-3-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c | 15 ++++++++------- drivers/gpu/drm/i915/intel_ringbuffer.h | 1 + 2 files changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index c2213016fd86..37d1cbf82beb 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2839,7 +2839,7 @@ int i915_gem_reset_prepare(struct drm_i915_private *dev_priv) /* Ensure irq handler finishes, and not run again. */ for_each_engine(engine, dev_priv, id) { - struct drm_i915_gem_request *request; + struct drm_i915_gem_request *request = NULL; /* Prevent the signaler thread from updating the request * state (by calling dma_fence_signal) as we are processing @@ -2871,6 +2871,8 @@ int i915_gem_reset_prepare(struct drm_i915_private *dev_priv) if (request && request->fence.error == -EIO) err = -EIO; /* Previous reset failed! */ } + + engine->hangcheck.active_request = request; } i915_gem_revoke_fences(dev_priv); @@ -2924,7 +2926,7 @@ static void engine_skip_context(struct drm_i915_gem_request *request) static bool i915_gem_reset_request(struct drm_i915_gem_request *request) { /* Read once and return the resolution */ - const bool guilty = engine_stalled(request->engine); + const bool guilty = !i915_gem_request_completed(request); /* The guilty request will get skipped on a hung engine. * @@ -2958,11 +2960,9 @@ static bool i915_gem_reset_request(struct drm_i915_gem_request *request) return guilty; } -static void i915_gem_reset_engine(struct intel_engine_cs *engine) +static void i915_gem_reset_engine(struct intel_engine_cs *engine, + struct drm_i915_gem_request *request) { - struct drm_i915_gem_request *request; - - request = i915_gem_find_active_request(engine); if (request && i915_gem_reset_request(request)) { DRM_DEBUG_DRIVER("resetting %s to restart from tail of request 0x%x\n", engine->name, request->global_seqno); @@ -2988,7 +2988,7 @@ void i915_gem_reset(struct drm_i915_private *dev_priv) for_each_engine(engine, dev_priv, id) { struct i915_gem_context *ctx; - i915_gem_reset_engine(engine); + i915_gem_reset_engine(engine, engine->hangcheck.active_request); ctx = fetch_and_zero(&engine->last_retired_context); if (ctx) engine->context_unpin(engine, ctx); @@ -3012,6 +3012,7 @@ void i915_gem_reset_finish(struct drm_i915_private *dev_priv) lockdep_assert_held(&dev_priv->drm.struct_mutex); for_each_engine(engine, dev_priv, id) { + engine->hangcheck.active_request = NULL; tasklet_enable(&engine->irq_tasklet); kthread_unpark(engine->breadcrumbs.signaler); } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 6aa20ac8cde3..d33c93444c0d 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -121,6 +121,7 @@ struct intel_engine_hangcheck { unsigned long action_timestamp; int deadlock; struct intel_instdone instdone; + struct drm_i915_gem_request *active_request; bool stalled; }; -- cgit v1.2.3 From ed35dd7b259f10bff34e64847995f291ae8b490c Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Tue, 20 Jun 2017 10:57:45 +0100 Subject: drm/i915: Update i915.reset to handle engine resets In preparation for engine reset work update this parameter to handle more than one type of reset. Default at the moment is still full gpu reset. Cc: Chris Wilson Cc: Mika Kuoppala Signed-off-by: Arun Siluvery Signed-off-by: Michel Thierry Link: http://patchwork.freedesktop.org/patch/msgid/20170615201828.23144-3-michel.thierry@intel.com Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/20170620095751.13127-4-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_params.c | 6 +++--- drivers/gpu/drm/i915/i915_params.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index b6a7e363d076..045cadb77285 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -46,7 +46,7 @@ struct i915_params i915 __read_mostly = { .prefault_disable = 0, .load_detect_test = 0, .force_reset_modeset_test = 0, - .reset = true, + .reset = 1, .error_capture = true, .invert_brightness = 0, .disable_display = 0, @@ -115,8 +115,8 @@ MODULE_PARM_DESC(vbt_sdvo_panel_type, "Override/Ignore selection of SDVO panel mode in the VBT " "(-2=ignore, -1=auto [default], index in VBT BIOS table)"); -module_param_named_unsafe(reset, i915.reset, bool, 0600); -MODULE_PARM_DESC(reset, "Attempt GPU resets (default: true)"); +module_param_named_unsafe(reset, i915.reset, int, 0600); +MODULE_PARM_DESC(reset, "Attempt GPU resets (0=disabled, 1=full gpu reset [default], 2=engine reset)"); #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) module_param_named(error_capture, i915.error_capture, bool, 0600); diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index 34148cc8637c..febbfdbd30bd 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h @@ -51,6 +51,7 @@ func(int, use_mmio_flip); \ func(int, mmio_debug); \ func(int, edp_vswing); \ + func(int, reset); \ func(unsigned int, inject_load_failure); \ /* leave bools at the end to not create holes */ \ func(bool, alpha_support); \ @@ -60,7 +61,6 @@ func(bool, prefault_disable); \ func(bool, load_detect_test); \ func(bool, force_reset_modeset_test); \ - func(bool, reset); \ func(bool, error_capture); \ func(bool, disable_display); \ func(bool, verbose_state_checks); \ -- cgit v1.2.3 From 142bc7d99bcfd17a9bc66b46eb1b5d1b93364549 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Tue, 20 Jun 2017 10:57:46 +0100 Subject: drm/i915: Modify error handler for per engine hang recovery This is a preparatory patch which modifies error handler to do per engine hang recovery. The actual patch which implements this sequence follows later in the series. The aim is to prepare existing recovery function to adapt to this new function where applicable (which fails at this point because core implementation is lacking) and continue recovery using legacy full gpu reset. A helper function is also added to query the availability of engine reset. A subsequent patch will add the capability to query which type of reset is present (engine -> full -> no-reset) via the get-param ioctl. It has been decided that the error events that are used to notify user of reset will only be sent in case if full chip reset. In case of just single (or multiple) engine resets, userspace won't be notified by these events. Note that this implementation of engine reset is for i915 directly submitting to the ELSP, where the driver manages the hang detection, recovery and resubmission. With GuC submission these tasks are shared between driver and firmware; i915 will still responsible for detecting a hang, and when it does it will have to request GuC to reset that Engine and remind the firmware about the outstanding submissions. This will be added in different patch. v2: rebase, advertise engine reset availability in platform definition, add note about GuC submission. v3: s/*engine_reset*/*reset_engine*/. (Chris) Handle reset as 2 level resets, by first going to engine only and fall backing to full/chip reset as needed, i.e. reset_engine will need the struct_mutex. v4: Pass the engine mask to i915_reset. (Chris) v5: Rebase, update selftests. v6: Rebase, prepare for mutex-less reset engine. v7: Pass reset_engine mask as a function parameter, and iterate over the engine mask for reset_engine. (Chris) v8: Use i915.reset >=2 in has_reset_engine; remove redundant reset logging; add a reset-engine-in-progress flag to prevent concurrent resets, and avoid dual purposing of reset-backoff. (Chris) v9: Support reset of different engines in parallel (Chris) v10: Handle reset-engine flag locking better (Chris) v11: Squash in reporting of per-engine-reset availability. Cc: Chris Wilson Cc: Mika Kuoppala Signed-off-by: Ian Lister Signed-off-by: Tomas Elf Signed-off-by: Arun Siluvery Signed-off-by: Michel Thierry Link: http://patchwork.freedesktop.org/patch/msgid/20170615201828.23144-4-michel.thierry@intel.com Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/20170620095751.13127-5-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.c | 15 +++++++++++++++ drivers/gpu/drm/i915/i915_drv.h | 10 ++++++++++ drivers/gpu/drm/i915/i915_irq.c | 38 +++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_pci.c | 5 ++++- drivers/gpu/drm/i915/intel_uncore.c | 11 +++++++++++ 5 files changed, 78 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index fe3d46ee4ddc..e5b31e29382c 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -331,6 +331,8 @@ static int i915_getparam(struct drm_device *dev, void *data, break; case I915_PARAM_HAS_GPU_RESET: value = i915.enable_hangcheck && intel_has_gpu_reset(dev_priv); + if (value && intel_has_reset_engine(dev_priv)) + value = 2; break; case I915_PARAM_HAS_RESOURCE_STREAMER: value = HAS_RESOURCE_STREAMER(dev_priv); @@ -1915,6 +1917,19 @@ error: goto finish; } +/** + * i915_reset_engine - reset GPU engine to recover from a hang + * @engine: engine to reset + * + * Reset a specific GPU engine. Useful if a hang is detected. + * Returns zero on successful reset or otherwise an error code. + */ +int i915_reset_engine(struct intel_engine_cs *engine) +{ + /* FIXME: replace me with engine reset sequence */ + return -ENODEV; +} + static int i915_pm_suspend(struct device *kdev) { struct pci_dev *pdev = to_pci_dev(kdev); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 69219b5d1198..4220abe1f28b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -752,6 +752,7 @@ struct intel_csr { func(has_csr); \ func(has_ddi); \ func(has_dp_mst); \ + func(has_reset_engine); \ func(has_fbc); \ func(has_fpga_dbg); \ func(has_full_ppgtt); \ @@ -1549,6 +1550,12 @@ struct i915_gpu_error { * inspect the bit and do the reset directly, otherwise the worker * waits for the struct_mutex. * + * #I915_RESET_ENGINE[num_engines] - Since the driver doesn't need to + * acquire the struct_mutex to reset an engine, we need an explicit + * flag to prevent two concurrent reset attempts in the same engine. + * As the number of engines continues to grow, allocate the flags from + * the most significant bits. + * * #I915_WEDGED - If reset fails and we can no longer use the GPU, * we set the #I915_WEDGED bit. Prior to command submission, e.g. * i915_gem_request_alloc(), this bit is checked and the sequence @@ -1558,6 +1565,7 @@ struct i915_gpu_error { #define I915_RESET_BACKOFF 0 #define I915_RESET_HANDOFF 1 #define I915_WEDGED (BITS_PER_LONG - 1) +#define I915_RESET_ENGINE (I915_WEDGED - I915_NUM_ENGINES) /** * Waitqueue to signal when a hang is detected. Used to for waiters @@ -3092,6 +3100,8 @@ extern void i915_driver_unload(struct drm_device *dev); extern int intel_gpu_reset(struct drm_i915_private *dev_priv, u32 engine_mask); extern bool intel_has_gpu_reset(struct drm_i915_private *dev_priv); extern void i915_reset(struct drm_i915_private *dev_priv); +extern int i915_reset_engine(struct intel_engine_cs *engine); +extern bool intel_has_reset_engine(struct drm_i915_private *dev_priv); extern int intel_guc_reset(struct drm_i915_private *dev_priv); extern void intel_engine_init_hangcheck(struct intel_engine_cs *engine); extern void intel_hangcheck_init(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 8e9f4378b5a7..f25e73fe567c 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2715,6 +2715,8 @@ void i915_handle_error(struct drm_i915_private *dev_priv, u32 engine_mask, const char *fmt, ...) { + struct intel_engine_cs *engine; + unsigned int tmp; va_list args; char error_msg[80]; @@ -2734,9 +2736,31 @@ void i915_handle_error(struct drm_i915_private *dev_priv, i915_capture_error_state(dev_priv, engine_mask, error_msg); i915_clear_error_registers(dev_priv); + /* + * Try engine reset when available. We fall back to full reset if + * single reset fails. + */ + if (intel_has_reset_engine(dev_priv)) { + for_each_engine_masked(engine, dev_priv, engine_mask, tmp) { + BUILD_BUG_ON(I915_RESET_HANDOFF >= I915_RESET_ENGINE); + if (test_and_set_bit(I915_RESET_ENGINE + engine->id, + &dev_priv->gpu_error.flags)) + continue; + + if (i915_reset_engine(engine) == 0) + engine_mask &= ~intel_engine_flag(engine); + + clear_bit(I915_RESET_ENGINE + engine->id, + &dev_priv->gpu_error.flags); + wake_up_bit(&dev_priv->gpu_error.flags, + I915_RESET_ENGINE + engine->id); + } + } + if (!engine_mask) goto out; + /* Full reset needs the mutex, stop any other user trying to do so. */ if (test_and_set_bit(I915_RESET_BACKOFF, &dev_priv->gpu_error.flags)) { wait_event(dev_priv->gpu_error.reset_queue, !test_bit(I915_RESET_BACKOFF, @@ -2744,8 +2768,22 @@ void i915_handle_error(struct drm_i915_private *dev_priv, goto out; } + /* Prevent any other reset-engine attempt. */ + for_each_engine(engine, dev_priv, tmp) { + while (test_and_set_bit(I915_RESET_ENGINE + engine->id, + &dev_priv->gpu_error.flags)) + wait_on_bit(&dev_priv->gpu_error.flags, + I915_RESET_ENGINE + engine->id, + TASK_UNINTERRUPTIBLE); + } + i915_reset_device(dev_priv); + for_each_engine(engine, dev_priv, tmp) { + clear_bit(I915_RESET_ENGINE + engine->id, + &dev_priv->gpu_error.flags); + } + clear_bit(I915_RESET_BACKOFF, &dev_priv->gpu_error.flags); wake_up_all(&dev_priv->gpu_error.reset_queue); diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 506ec32b9e53..04aaf553e3fa 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -310,7 +310,8 @@ static const struct intel_device_info intel_haswell_info = { BDW_COLORS, \ .has_logical_ring_contexts = 1, \ .has_full_48bit_ppgtt = 1, \ - .has_64bit_reloc = 1 + .has_64bit_reloc = 1, \ + .has_reset_engine = 1 #define BDW_PLATFORM \ BDW_FEATURES, \ @@ -342,6 +343,7 @@ static const struct intel_device_info intel_cherryview_info = { .has_gmch_display = 1, .has_aliasing_ppgtt = 1, .has_full_ppgtt = 1, + .has_reset_engine = 1, .display_mmio_offset = VLV_DISPLAY_BASE, GEN_CHV_PIPEOFFSETS, CURSOR_OFFSETS, @@ -387,6 +389,7 @@ static const struct intel_device_info intel_skylake_gt3_info = { .has_aliasing_ppgtt = 1, \ .has_full_ppgtt = 1, \ .has_full_48bit_ppgtt = 1, \ + .has_reset_engine = 1, \ GEN_DEFAULT_PIPEOFFSETS, \ IVB_CURSOR_OFFSETS, \ BDW_COLORS diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 9882724bc2b6..1ed3dd8df850 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -1719,6 +1719,17 @@ bool intel_has_gpu_reset(struct drm_i915_private *dev_priv) return intel_get_gpu_reset(dev_priv) != NULL; } +/* + * When GuC submission is enabled, GuC manages ELSP and can initiate the + * engine reset too. For now, fall back to full GPU reset if it is enabled. + */ +bool intel_has_reset_engine(struct drm_i915_private *dev_priv) +{ + return (dev_priv->info.has_reset_engine && + !dev_priv->guc.execbuf_client && + i915.reset >= 2); +} + int intel_guc_reset(struct drm_i915_private *dev_priv) { int ret; -- cgit v1.2.3 From a1ef70e144534777965426393dcaa1721e908e83 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Tue, 20 Jun 2017 10:57:47 +0100 Subject: drm/i915: Add support for per engine reset recovery This change implements support for per-engine reset as an initial, less intrusive hang recovery option to be attempted before falling back to the legacy full GPU reset recovery mode if necessary. This is only supported from Gen8 onwards. Hangchecker determines which engines are hung and invokes error handler to recover from it. Error handler schedules recovery for each of those engines that are hung. The recovery procedure is as follows, - identifies the request that caused the hang and it is dropped - force engine to idle: this is done by issuing a reset request - reset the engine - re-init the engine to resume submissions. If engine reset fails then we fall back to heavy weight full gpu reset which resets all engines and reinitiazes complete state of HW and SW. v2: Rebase. v3: s/*engine_reset*/*reset_engine*/; freeze engine and irqs before calling i915_gem_reset_engine (Chris). v4: Rebase, modify i915_gem_reset_prepare to use a ring mask and reuse the function for reset_engine. v5: intel_reset_engine_start/cancel instead of request/unrequest_reset. v6: Clean up reset_engine function to not require mutex, i.e. no need to call revoke/restore_fences and _retire_requests (Chris). v7: Remove leftovers from v5, i.e. no need to disable irq, hold forcewake or wakeup the handoff bit (Chris). v8: engine_retire_requests should be (and it was) static; explain that we have to re-init the engine after reset, which is why the init_hw call is needed; check reset-in-progress flag (Chris). v9: Rebase, include code to pass the active request to gem_reset_engine (as it is already done in full reset). Remove unnecessary intel_reset_engine_start/cancel, these are executed as part of the reset. v10: Rebase, use the right I915_RESET_ENGINE flag. v11: Fixup to call reset_finish_engine even on error. Cc: Chris Wilson Cc: Mika Kuoppala Signed-off-by: Tomas Elf Signed-off-by: Arun Siluvery Signed-off-by: Michel Thierry Link: http://patchwork.freedesktop.org/patch/msgid/20170615201828.23144-6-michel.thierry@intel.com Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/20170620095751.13127-6-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.c | 50 +++++++++++++++++++++- drivers/gpu/drm/i915/i915_drv.h | 5 +++ drivers/gpu/drm/i915/i915_gem.c | 93 +++++++++++++++++++++++++---------------- 3 files changed, 110 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index e5b31e29382c..2ecac000e5da 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1923,11 +1923,57 @@ error: * * Reset a specific GPU engine. Useful if a hang is detected. * Returns zero on successful reset or otherwise an error code. + * + * Procedure is: + * - identifies the request that caused the hang and it is dropped + * - reset engine (which will force the engine to idle) + * - re-init/configure engine */ int i915_reset_engine(struct intel_engine_cs *engine) { - /* FIXME: replace me with engine reset sequence */ - return -ENODEV; + struct i915_gpu_error *error = &engine->i915->gpu_error; + struct drm_i915_gem_request *active_request; + int ret; + + GEM_BUG_ON(!test_bit(I915_RESET_ENGINE + engine->id, &error->flags)); + + DRM_DEBUG_DRIVER("resetting %s\n", engine->name); + + active_request = i915_gem_reset_prepare_engine(engine); + if (IS_ERR(active_request)) { + DRM_DEBUG_DRIVER("Previous reset failed, promote to full reset\n"); + ret = PTR_ERR(active_request); + goto out; + } + + /* + * The request that caused the hang is stuck on elsp, we know the + * active request and can drop it, adjust head to skip the offending + * request to resume executing remaining requests in the queue. + */ + i915_gem_reset_engine(engine, active_request); + + /* Finally, reset just this engine. */ + ret = intel_gpu_reset(engine->i915, intel_engine_flag(engine)); + + i915_gem_reset_finish_engine(engine); + + if (ret) { + /* If we fail here, we expect to fallback to a global reset */ + DRM_DEBUG_DRIVER("Failed to reset %s, ret=%d\n", + engine->name, ret); + goto out; + } + + /* + * The engine and its registers (and workarounds in case of render) + * have been reset to their default values. Follow the init_ring + * process to program RING_MODE, HWSP and re-enable submission. + */ + ret = engine->init_hw(engine); + +out: + return ret; } static int i915_pm_suspend(struct device *kdev) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4220abe1f28b..152e30750dd4 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3474,11 +3474,16 @@ static inline u32 i915_reset_count(struct i915_gpu_error *error) return READ_ONCE(error->reset_count); } +struct drm_i915_gem_request * +i915_gem_reset_prepare_engine(struct intel_engine_cs *engine); int i915_gem_reset_prepare(struct drm_i915_private *dev_priv); void i915_gem_reset(struct drm_i915_private *dev_priv); +void i915_gem_reset_finish_engine(struct intel_engine_cs *engine); void i915_gem_reset_finish(struct drm_i915_private *dev_priv); void i915_gem_set_wedged(struct drm_i915_private *dev_priv); bool i915_gem_unset_wedged(struct drm_i915_private *dev_priv); +void i915_gem_reset_engine(struct intel_engine_cs *engine, + struct drm_i915_gem_request *request); void i915_gem_init_mmio(struct drm_i915_private *i915); int __must_check i915_gem_init(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 37d1cbf82beb..1353491c1010 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2831,45 +2831,61 @@ static bool engine_stalled(struct intel_engine_cs *engine) return true; } +/* + * Ensure irq handler finishes, and not run again. + * Also return the active request so that we only search for it once. + */ +struct drm_i915_gem_request * +i915_gem_reset_prepare_engine(struct intel_engine_cs *engine) +{ + struct drm_i915_gem_request *request = NULL; + + /* Prevent the signaler thread from updating the request + * state (by calling dma_fence_signal) as we are processing + * the reset. The write from the GPU of the seqno is + * asynchronous and the signaler thread may see a different + * value to us and declare the request complete, even though + * the reset routine have picked that request as the active + * (incomplete) request. This conflict is not handled + * gracefully! + */ + kthread_park(engine->breadcrumbs.signaler); + + /* Prevent request submission to the hardware until we have + * completed the reset in i915_gem_reset_finish(). If a request + * is completed by one engine, it may then queue a request + * to a second via its engine->irq_tasklet *just* as we are + * calling engine->init_hw() and also writing the ELSP. + * Turning off the engine->irq_tasklet until the reset is over + * prevents the race. + */ + tasklet_kill(&engine->irq_tasklet); + tasklet_disable(&engine->irq_tasklet); + + if (engine->irq_seqno_barrier) + engine->irq_seqno_barrier(engine); + + if (engine_stalled(engine)) { + request = i915_gem_find_active_request(engine); + if (request && request->fence.error == -EIO) + request = ERR_PTR(-EIO); /* Previous reset failed! */ + } + + return request; +} + int i915_gem_reset_prepare(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; + struct drm_i915_gem_request *request; enum intel_engine_id id; int err = 0; - /* Ensure irq handler finishes, and not run again. */ for_each_engine(engine, dev_priv, id) { - struct drm_i915_gem_request *request = NULL; - - /* Prevent the signaler thread from updating the request - * state (by calling dma_fence_signal) as we are processing - * the reset. The write from the GPU of the seqno is - * asynchronous and the signaler thread may see a different - * value to us and declare the request complete, even though - * the reset routine have picked that request as the active - * (incomplete) request. This conflict is not handled - * gracefully! - */ - kthread_park(engine->breadcrumbs.signaler); - - /* Prevent request submission to the hardware until we have - * completed the reset in i915_gem_reset_finish(). If a request - * is completed by one engine, it may then queue a request - * to a second via its engine->irq_tasklet *just* as we are - * calling engine->init_hw() and also writing the ELSP. - * Turning off the engine->irq_tasklet until the reset is over - * prevents the race. - */ - tasklet_kill(&engine->irq_tasklet); - tasklet_disable(&engine->irq_tasklet); - - if (engine->irq_seqno_barrier) - engine->irq_seqno_barrier(engine); - - if (engine_stalled(engine)) { - request = i915_gem_find_active_request(engine); - if (request && request->fence.error == -EIO) - err = -EIO; /* Previous reset failed! */ + request = i915_gem_reset_prepare_engine(engine); + if (IS_ERR(request)) { + err = PTR_ERR(request); + continue; } engine->hangcheck.active_request = request; @@ -2960,8 +2976,8 @@ static bool i915_gem_reset_request(struct drm_i915_gem_request *request) return guilty; } -static void i915_gem_reset_engine(struct intel_engine_cs *engine, - struct drm_i915_gem_request *request) +void i915_gem_reset_engine(struct intel_engine_cs *engine, + struct drm_i915_gem_request *request) { if (request && i915_gem_reset_request(request)) { DRM_DEBUG_DRIVER("resetting %s to restart from tail of request 0x%x\n", @@ -3004,6 +3020,12 @@ void i915_gem_reset(struct drm_i915_private *dev_priv) } } +void i915_gem_reset_finish_engine(struct intel_engine_cs *engine) +{ + tasklet_enable(&engine->irq_tasklet); + kthread_unpark(engine->breadcrumbs.signaler); +} + void i915_gem_reset_finish(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; @@ -3013,8 +3035,7 @@ void i915_gem_reset_finish(struct drm_i915_private *dev_priv) for_each_engine(engine, dev_priv, id) { engine->hangcheck.active_request = NULL; - tasklet_enable(&engine->irq_tasklet); - kthread_unpark(engine->breadcrumbs.signaler); + i915_gem_reset_finish_engine(engine); } } -- cgit v1.2.3 From 702c8f8e5daba24777b29899fb9576fe64a924ea Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Tue, 20 Jun 2017 10:57:48 +0100 Subject: drm/i915: Add engine reset count to error state Driver maintains count of how many times a given engine is reset, useful to capture this in error state also. It gives an idea of how engine is coping up with the workloads it is executing before this error state. A follow-up patch will provide this information in debugfs. v2: s/engine_reset/reset_engine/ (Chris) Define count as unsigned int (Tvrtko) Cc: Chris Wilson Cc: Mika Kuoppala Signed-off-by: Arun Siluvery Signed-off-by: Michel Thierry Link: http://patchwork.freedesktop.org/patch/msgid/20170615201828.23144-7-michel.thierry@intel.com Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/20170620095751.13127-7-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.c | 3 +++ drivers/gpu/drm/i915/i915_drv.h | 10 ++++++++++ drivers/gpu/drm/i915/i915_gpu_error.c | 3 +++ 3 files changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 2ecac000e5da..d35a114c46ed 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1971,7 +1971,10 @@ int i915_reset_engine(struct intel_engine_cs *engine) * process to program RING_MODE, HWSP and re-enable submission. */ ret = engine->init_hw(engine); + if (ret) + goto out; + error->reset_engine_count[engine->id]++; out: return ret; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 152e30750dd4..90cc63e5ced8 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -917,6 +917,7 @@ struct i915_gpu_state { enum intel_engine_hangcheck_action hangcheck_action; struct i915_address_space *vm; int num_requests; + u32 reset_count; /* position of active request inside the ring */ u32 rq_head, rq_post, rq_tail; @@ -1567,6 +1568,9 @@ struct i915_gpu_error { #define I915_WEDGED (BITS_PER_LONG - 1) #define I915_RESET_ENGINE (I915_WEDGED - I915_NUM_ENGINES) + /** Number of times an engine has been reset */ + u32 reset_engine_count[I915_NUM_ENGINES]; + /** * Waitqueue to signal when a hang is detected. Used to for waiters * to release the struct_mutex for the reset to procede. @@ -3474,6 +3478,12 @@ static inline u32 i915_reset_count(struct i915_gpu_error *error) return READ_ONCE(error->reset_count); } +static inline u32 i915_reset_engine_count(struct i915_gpu_error *error, + struct intel_engine_cs *engine) +{ + return READ_ONCE(error->reset_engine_count[engine->id]); +} + struct drm_i915_gem_request * i915_gem_reset_prepare_engine(struct intel_engine_cs *engine); int i915_gem_reset_prepare(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index e18f350bc364..ae70283470a6 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -463,6 +463,7 @@ static void error_print_engine(struct drm_i915_error_state_buf *m, err_printf(m, " hangcheck action timestamp: %lu, %u ms ago\n", ee->hangcheck_timestamp, jiffies_to_msecs(jiffies - ee->hangcheck_timestamp)); + err_printf(m, " engine reset count: %u\n", ee->reset_count); error_print_request(m, " ELSP[0]: ", &ee->execlist[0]); error_print_request(m, " ELSP[1]: ", &ee->execlist[1]); @@ -1236,6 +1237,8 @@ static void error_record_engine_registers(struct i915_gpu_state *error, ee->hangcheck_timestamp = engine->hangcheck.action_timestamp; ee->hangcheck_action = engine->hangcheck.action; ee->hangcheck_stalled = engine->hangcheck.stalled; + ee->reset_count = i915_reset_engine_count(&dev_priv->gpu_error, + engine); if (USES_PPGTT(dev_priv)) { int i; -- cgit v1.2.3 From 061d06a21cd1e049f1f36fcf14d68893e9fb9493 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Tue, 20 Jun 2017 10:57:49 +0100 Subject: drm/i915: Export per-engine reset count info to debugfs A new variable is added to export the reset counts to debugfs, this includes full gpu reset and engine reset count. This is useful for tests where they are expected to trigger reset; these counts are checked before and after the test to ensure the same. v2: Include reset engine count in i915_engine_info too (Chris). Cc: Chris Wilson Cc: Mika Kuoppala Signed-off-by: Arun Siluvery Signed-off-by: Michel Thierry Link: http://patchwork.freedesktop.org/patch/msgid/20170615201828.23144-8-michel.thierry@intel.com Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/20170620095751.13127-8-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_debugfs.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 6103d0079d16..1f1176b6400e 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1403,6 +1403,23 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) return 0; } +static int i915_reset_info(struct seq_file *m, void *unused) +{ + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct i915_gpu_error *error = &dev_priv->gpu_error; + struct intel_engine_cs *engine; + enum intel_engine_id id; + + seq_printf(m, "full gpu reset = %u\n", i915_reset_count(error)); + + for_each_engine(engine, dev_priv, id) { + seq_printf(m, "%s = %u\n", engine->name, + i915_reset_engine_count(error, engine)); + } + + return 0; +} + static int ironlake_drpc_info(struct seq_file *m) { struct drm_i915_private *dev_priv = node_to_i915(m->private); @@ -3285,6 +3302,7 @@ static int i915_display_info(struct seq_file *m, void *unused) static int i915_engine_info(struct seq_file *m, void *unused) { struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct i915_gpu_error *error = &dev_priv->gpu_error; struct intel_engine_cs *engine; enum intel_engine_id id; @@ -3308,6 +3326,8 @@ static int i915_engine_info(struct seq_file *m, void *unused) engine->hangcheck.seqno, jiffies_to_msecs(jiffies - engine->hangcheck.action_timestamp), engine->timeline->inflight_seqnos); + seq_printf(m, "\tReset count: %d\n", + i915_reset_engine_count(error, engine)); rcu_read_lock(); @@ -4820,6 +4840,7 @@ static const struct drm_info_list i915_debugfs_list[] = { {"i915_huc_load_status", i915_huc_load_status_info, 0}, {"i915_frequency_info", i915_frequency_info, 0}, {"i915_hangcheck_info", i915_hangcheck_info, 0}, + {"i915_reset_info", i915_reset_info, 0}, {"i915_drpc_info", i915_drpc_info, 0}, {"i915_emon_status", i915_emon_status, 0}, {"i915_ring_freq_table", i915_ring_freq_table, 0}, -- cgit v1.2.3 From abeb4def31d9c3dbf06052e65cd884730ec8667e Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Tue, 20 Jun 2017 10:57:50 +0100 Subject: drm/i915/selftests: reset engine self tests Check that we can reset specific engines, also check the fallback to full reset if something didn't work. v2: rebase. v3: use RESET_ENGINE_IN_PROGRESS flag. v4: use I915_RESET_ENGINE flag. Signed-off-by: Michel Thierry Link: http://patchwork.freedesktop.org/patch/msgid/20170615201828.23144-12-michel.thierry@intel.com Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/20170620095751.13127-9-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/selftests/intel_hangcheck.c | 148 +++++++++++++++++++++++ 1 file changed, 148 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c index cc00a361f0fa..af475189bd52 100644 --- a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c +++ b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c @@ -324,6 +324,54 @@ static int igt_global_reset(void *arg) return err; } +static int igt_reset_engine(void *arg) +{ + struct drm_i915_private *i915 = arg; + struct intel_engine_cs *engine; + enum intel_engine_id id; + unsigned int reset_count, reset_engine_count; + int err = 0; + + /* Check that we can issue a global GPU and engine reset */ + + if (!intel_has_reset_engine(i915)) + return 0; + + for_each_engine(engine, i915, id) { + set_bit(I915_RESET_ENGINE + engine->id, &i915->gpu_error.flags); + reset_count = i915_reset_count(&i915->gpu_error); + reset_engine_count = i915_reset_engine_count(&i915->gpu_error, + engine); + + err = i915_reset_engine(engine); + if (err) { + pr_err("i915_reset_engine failed\n"); + break; + } + + if (i915_reset_count(&i915->gpu_error) != reset_count) { + pr_err("Full GPU reset recorded! (engine reset expected)\n"); + err = -EINVAL; + break; + } + + if (i915_reset_engine_count(&i915->gpu_error, engine) == + reset_engine_count) { + pr_err("No %s engine reset recorded!\n", engine->name); + err = -EINVAL; + break; + } + + clear_bit(I915_RESET_ENGINE + engine->id, + &i915->gpu_error.flags); + } + + if (i915_terminally_wedged(&i915->gpu_error)) + err = -EIO; + + return err; +} + static u32 fake_hangcheck(struct drm_i915_gem_request *rq) { u32 reset_count; @@ -530,13 +578,113 @@ unlock: return err; } +static int igt_render_engine_reset_fallback(void *arg) +{ + struct drm_i915_private *i915 = arg; + struct intel_engine_cs *engine = i915->engine[RCS]; + struct hang h; + struct drm_i915_gem_request *rq; + unsigned int reset_count, reset_engine_count; + int err = 0; + + /* Check that we can issue a global GPU and engine reset */ + + if (!intel_has_reset_engine(i915)) + return 0; + + set_bit(I915_RESET_BACKOFF, &i915->gpu_error.flags); + mutex_lock(&i915->drm.struct_mutex); + + err = hang_init(&h, i915); + if (err) + goto unlock; + + rq = hang_create_request(&h, engine, i915->kernel_context); + if (IS_ERR(rq)) { + err = PTR_ERR(rq); + goto fini; + } + + i915_gem_request_get(rq); + __i915_add_request(rq, true); + + /* make reset engine fail */ + rq->fence.error = -EIO; + + if (!wait_for_hang(&h, rq)) { + pr_err("Failed to start request %x\n", rq->fence.seqno); + err = -EIO; + goto out_rq; + } + + reset_engine_count = i915_reset_engine_count(&i915->gpu_error, engine); + reset_count = fake_hangcheck(rq); + + /* unlock since we'll call handle_error */ + mutex_unlock(&i915->drm.struct_mutex); + clear_bit(I915_RESET_BACKOFF, &i915->gpu_error.flags); + wake_up_all(&i915->gpu_error.reset_queue); + + i915_handle_error(i915, intel_engine_flag(engine), "live test"); + + if (i915_reset_engine_count(&i915->gpu_error, engine) != + reset_engine_count) { + pr_err("render engine reset recorded! (full reset expected)\n"); + err = -EINVAL; + goto out_rq; + } + + if (i915_reset_count(&i915->gpu_error) == reset_count) { + pr_err("No full GPU reset recorded!\n"); + err = -EINVAL; + goto out_rq; + } + + /* + * by using fence.error = -EIO, full reset sets the wedged flag, do one + * more full reset to re-enable the hw. + */ + if (i915_terminally_wedged(&i915->gpu_error)) { + set_bit(I915_RESET_BACKOFF, &i915->gpu_error.flags); + mutex_lock(&i915->drm.struct_mutex); + rq->fence.error = 0; + + set_bit(I915_RESET_HANDOFF, &i915->gpu_error.flags); + i915_reset(i915); + GEM_BUG_ON(test_bit(I915_RESET_HANDOFF, + &i915->gpu_error.flags)); + + if (i915_reset_count(&i915->gpu_error) == reset_count) { + pr_err("No full GPU reset recorded!\n"); + err = -EINVAL; + goto out_rq; + } + } + +out_rq: + i915_gem_request_put(rq); +fini: + hang_fini(&h); +unlock: + mutex_unlock(&i915->drm.struct_mutex); + clear_bit(I915_RESET_BACKOFF, &i915->gpu_error.flags); + wake_up_all(&i915->gpu_error.reset_queue); + + if (i915_terminally_wedged(&i915->gpu_error)) + return -EIO; + + return err; +} + int intel_hangcheck_live_selftests(struct drm_i915_private *i915) { static const struct i915_subtest tests[] = { SUBTEST(igt_hang_sanitycheck), SUBTEST(igt_global_reset), + SUBTEST(igt_reset_engine), SUBTEST(igt_wait_reset), SUBTEST(igt_reset_queue), + SUBTEST(igt_render_engine_reset_fallback), }; if (!intel_has_gpu_reset(i915)) -- cgit v1.2.3 From d3d3765fc1c176ff472a503d909508820c3f99d6 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Tue, 20 Jun 2017 10:57:51 +0100 Subject: drm/i915: Enable Engine reset and recovery support This feature is made available only from Gen8, for previous gen devices driver uses legacy full gpu reset. Cc: Chris Wilson Cc: Mika Kuoppala Signed-off-by: Tomas Elf Signed-off-by: Arun Siluvery Signed-off-by: Michel Thierry Link: http://patchwork.freedesktop.org/patch/msgid/20170615201828.23144-10-michel.thierry@intel.com Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/20170620095751.13127-10-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_params.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index 045cadb77285..14e2c2e57f96 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -46,7 +46,7 @@ struct i915_params i915 __read_mostly = { .prefault_disable = 0, .load_detect_test = 0, .force_reset_modeset_test = 0, - .reset = 1, + .reset = 2, .error_capture = true, .invert_brightness = 0, .disable_display = 0, @@ -116,7 +116,7 @@ MODULE_PARM_DESC(vbt_sdvo_panel_type, "(-2=ignore, -1=auto [default], index in VBT BIOS table)"); module_param_named_unsafe(reset, i915.reset, int, 0600); -MODULE_PARM_DESC(reset, "Attempt GPU resets (0=disabled, 1=full gpu reset [default], 2=engine reset)"); +MODULE_PARM_DESC(reset, "Attempt GPU resets (0=disabled, 1=full gpu reset, 2=engine reset [default])"); #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) module_param_named(error_capture, i915.error_capture, bool, 0600); -- cgit v1.2.3 From 25ffaa67459e988e73210543f7e05dfbf3f16163 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 20 Jun 2017 13:43:20 +0100 Subject: drm/i915: Pass the right flags to i915_vma_move_to_active() i915_vma_move_to_active() takes the execobject flags and not a boolean! Instead of passing EXEC_OBJECT_WRITE we passed true [i.e. EXEC_OBJECT_NEEDS_FENCE] causing us to start tracking the vma->last_fence access and since we forgot to clear that on unbinding, we caused a use-after-free. [ 321.263854] BUG: KASAN: use-after-free in i915_gem_request_retire+0x1728/0x1740 [i915] [ 321.264001] Read of size 8 at addr ffff880100fc67d8 by task gem_exec_reloc/2868 [ 321.264181] CPU: 0 PID: 2868 Comm: gem_exec_reloc Not tainted 4.12.0-rc6-CI-Custom_2759+ #1 [ 321.264195] Hardware name: GIGABYTE GB-BXBT-1900/MZBAYAB-00, BIOS F6 02/17/2015 [ 321.264208] Call Trace: [ 321.264234] dump_stack+0x67/0x99 [ 321.264260] print_address_description+0x77/0x290 [ 321.264437] ? i915_gem_request_retire+0x1728/0x1740 [i915] [ 321.264459] kasan_report+0x269/0x350 [ 321.264487] __asan_report_load8_noabort+0x14/0x20 [ 321.264660] i915_gem_request_retire+0x1728/0x1740 [i915] [ 321.264841] ? intel_ring_context_pin+0x131/0x690 [i915] [ 321.265021] i915_gem_request_alloc+0x2c6/0x1220 [i915] [ 321.265044] ? _raw_spin_unlock_irqrestore+0x3d/0x60 [ 321.265226] i915_gem_do_execbuffer+0xac0/0x2a20 [i915] [ 321.265250] ? __lock_acquire+0xceb/0x5450 [ 321.265269] ? entry_SYSCALL_64_fastpath+0x1c/0xb1 [ 321.265291] ? kvmalloc_node+0x6b/0x80 [ 321.265310] ? kvmalloc_node+0x6b/0x80 [ 321.265489] ? eb_relocate_slow+0xbe0/0xbe0 [i915] [ 321.265520] ? ___slab_alloc.constprop.28+0x2ab/0x3d0 [ 321.265549] ? debug_check_no_locks_freed+0x280/0x280 [ 321.265591] ? __might_fault+0xc6/0x1b0 [ 321.265782] i915_gem_execbuffer2+0x14a/0x3f0 [i915] [ 321.265815] drm_ioctl+0x4ba/0xaa0 [ 321.265986] ? i915_gem_execbuffer+0xde0/0xde0 [i915] [ 321.266017] ? drm_getunique+0x270/0x270 [ 321.266068] do_vfs_ioctl+0x17f/0xfa0 [ 321.266091] ? __fget+0x1ba/0x330 [ 321.266112] ? lock_acquire+0x390/0x390 [ 321.266133] ? ioctl_preallocate+0x1d0/0x1d0 [ 321.266164] ? __fget+0x1db/0x330 [ 321.266194] ? __fget_light+0x79/0x1f0 [ 321.266219] SyS_ioctl+0x3c/0x70 [ 321.266247] entry_SYSCALL_64_fastpath+0x1c/0xb1 [ 321.266265] RIP: 0033:0x7fcede207357 [ 321.266279] RSP: 002b:00007ffef0effe58 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 [ 321.266307] RAX: ffffffffffffffda RBX: 0000000000000002 RCX: 00007fcede207357 [ 321.266321] RDX: 00007ffef0effef0 RSI: 0000000040406469 RDI: 0000000000000004 [ 321.266335] RBP: ffffffff812097c6 R08: 0000000000000008 R09: 0000000000000000 [ 321.266349] R10: 0000000000000008 R11: 0000000000000246 R12: ffff880116bcff98 [ 321.266363] R13: ffffffff81cb7cb3 R14: ffff880116bcff70 R15: 0000000000000000 [ 321.266385] ? __this_cpu_preempt_check+0x13/0x20 [ 321.266406] ? trace_hardirqs_off_caller+0x1d6/0x2c0 [ 321.266487] Allocated by task 2868: [ 321.266568] save_stack_trace+0x16/0x20 [ 321.266586] kasan_kmalloc+0xee/0x180 [ 321.266602] kasan_slab_alloc+0x12/0x20 [ 321.266620] kmem_cache_alloc+0xc7/0x2e0 [ 321.266795] i915_vma_instance+0x28c/0x1540 [i915] [ 321.266964] eb_lookup_vmas+0x5a7/0x2250 [i915] [ 321.267130] i915_gem_do_execbuffer+0x69a/0x2a20 [i915] [ 321.267296] i915_gem_execbuffer2+0x14a/0x3f0 [i915] [ 321.267315] drm_ioctl+0x4ba/0xaa0 [ 321.267333] do_vfs_ioctl+0x17f/0xfa0 [ 321.267350] SyS_ioctl+0x3c/0x70 [ 321.267369] entry_SYSCALL_64_fastpath+0x1c/0xb1 [ 321.267428] Freed by task 177: [ 321.267502] save_stack_trace+0x16/0x20 [ 321.267521] kasan_slab_free+0xad/0x180 [ 321.267539] kmem_cache_free+0xc5/0x340 [ 321.267710] i915_vma_unbind+0x666/0x10a0 [i915] [ 321.267880] i915_vma_close+0x23a/0x2f0 [i915] [ 321.268048] __i915_gem_free_objects+0x17d/0xc70 [i915] [ 321.268215] __i915_gem_free_work+0x49/0x70 [i915] [ 321.268234] process_one_work+0x66f/0x1410 [ 321.268252] worker_thread+0xe1/0xe90 [ 321.268269] kthread+0x304/0x410 [ 321.268285] ret_from_fork+0x27/0x40 [ 321.268346] The buggy address belongs to the object at ffff880100fc6640 which belongs to the cache i915_vma of size 656 [ 321.268550] The buggy address is located 408 bytes inside of 656-byte region [ffff880100fc6640, ffff880100fc68d0) [ 321.268741] The buggy address belongs to the page: [ 321.268837] page:ffffea000403f000 count:1 mapcount:0 mapping: (null) index:0xffff880100fc5980 compound_mapcount: 0 [ 321.269045] flags: 0x8000000000008100(slab|head) [ 321.269147] raw: 8000000000008100 0000000000000000 ffff880100fc5980 00000001001e001d [ 321.269312] raw: ffffea0004038e20 ffff880116b46240 ffff88011646c640 0000000000000000 [ 321.269484] page dumped because: kasan: bad access detected [ 321.269665] Memory state around the buggy address: [ 321.269778] ffff880100fc6680: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 321.269949] ffff880100fc6700: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 321.270115] >ffff880100fc6780: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 321.270279] ^ [ 321.270410] ffff880100fc6800: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 321.270576] ffff880100fc6880: fb fb fb fb fb fb fb fb fb fb fc fc fc fc fc fc [ 321.270740] ================================================================== [ 321.270903] Disabling lock debugging due to kernel taint Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=101511 Fixes: 7dd4f6729f92 ("drm/i915: Async GPU relocation processing") Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Cc: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20170620124321.1108-2-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 35d1f8e8906e..b2457556591c 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1200,7 +1200,7 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb, reservation_object_unlock(batch->resv); i915_vma_unpin(batch); - i915_vma_move_to_active(vma, rq, true); + i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE); reservation_object_lock(vma->resv, NULL); reservation_object_add_excl_fence(vma->resv, &rq->fence); reservation_object_unlock(vma->resv); -- cgit v1.2.3 From 85909716621702c777de512377fe952fb5677aec Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Tue, 20 Jun 2017 10:44:33 +0530 Subject: drm: armada: make of_device_ids const. of_device_ids are not supposed to change at runtime. All functions working with of_device_ids provided by work with const of_device_ids. So mark the non-const structs as const. File size before: text data bss dec hex filename 8836 744 0 9580 256c drivers/gpu/drm/armada/armada_crtc.o File size after constify armada_lcd_of_match: text data bss dec hex filename 9220 328 0 9548 254c drivers/gpu/drm/armada/armada_crtc.o Signed-off-by: Arvind Yadav Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/ff9a9a908cf347775ab62cfadfde986de72dcf13.1497935382.git.arvind.yadav.cs@gmail.com --- drivers/gpu/drm/armada/armada_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 4fe19fde84f9..94b76bdd7553 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -1364,7 +1364,7 @@ static int armada_lcd_remove(struct platform_device *pdev) return 0; } -static struct of_device_id armada_lcd_of_match[] = { +static const struct of_device_id armada_lcd_of_match[] = { { .compatible = "marvell,dove-lcd", .data = &armada510_ops, -- cgit v1.2.3 From a25bcadd0d9204d9d9e00de4d71d7be570f44c6c Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Wed, 21 Jun 2017 16:34:20 +1000 Subject: drm/i915: select CRC32 kbuild test robot found a build failure when building with thin archives: http://marc.info/?l=linux-kbuild&m=149802285009737&w=2 Signed-off-by: Nicholas Piggin Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170621063420.24913-1-npiggin@gmail.com --- drivers/gpu/drm/i915/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index a5cd5dacf055..e9e64e8e9765 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -21,6 +21,7 @@ config DRM_I915 select ACPI_BUTTON if ACPI select SYNC_FILE select IOSF_MBI + select CRC32 help Choose this option if you have a system that has "Intel Graphics Media Accelerator" or "HD Graphics" integrated graphics, -- cgit v1.2.3 From 760a898d8069111704e1bd43f00ebf369ae46e57 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 20 Jun 2017 13:43:19 +0100 Subject: drm/i915: Retire the VMA's fence tracker before unbinding Since we may track unfenced access (GPU access to the vma that explicitly requires no fence), vma->last_fence may be set without any attached fence (vma->fence) and so will not be flushed when we call i915_vma_put_fence(). Since we stopped doing a full retire of the activity trackers for unbind, we need to explicitly retire each tracker. Fixes: b0decaf75bd9 ("drm/i915: Track active vma requests") Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Cc: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20170620124321.1108-1-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_vma.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index 532c709febbd..1cfe137cdc32 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -672,6 +672,11 @@ int i915_vma_unbind(struct i915_vma *vma) break; } + if (!ret) { + ret = i915_gem_active_retire(&vma->last_fence, + &vma->vm->i915->drm.struct_mutex); + } + __i915_vma_unpin(vma); if (ret) return ret; -- cgit v1.2.3 From 7a3bc034ed5c4b57c145a025070739ec41434e94 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 20 Jun 2017 13:43:21 +0100 Subject: drm/i915: Assert the vma's active tracking is clear before free In looking at a use-after-free on Baytrail, it looks like the VMA's activity tracking is suspect. Add some asserts to catch freeing the VMA before we have decoupled all of its i915_gem_active trackers. References: https://bugs.freedesktop.org/show_bug.cgi?id=101511 Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20170620124321.1108-3-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_vma.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index 1cfe137cdc32..958be0a95960 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -579,11 +579,17 @@ err_unpin: static void i915_vma_destroy(struct i915_vma *vma) { + int i; + GEM_BUG_ON(vma->node.allocated); GEM_BUG_ON(i915_vma_is_active(vma)); GEM_BUG_ON(!i915_vma_is_closed(vma)); GEM_BUG_ON(vma->fence); + for (i = 0; i < ARRAY_SIZE(vma->last_read); i++) + GEM_BUG_ON(i915_gem_active_isset(&vma->last_read[i])); + GEM_BUG_ON(i915_gem_active_isset(&vma->last_fence)); + list_del(&vma->vm_link); if (!i915_vma_is_ggtt(vma)) i915_ppgtt_put(i915_vm_to_ppgtt(vma->vm)); @@ -680,9 +686,8 @@ int i915_vma_unbind(struct i915_vma *vma) __i915_vma_unpin(vma); if (ret) return ret; - - GEM_BUG_ON(i915_vma_is_active(vma)); } + GEM_BUG_ON(i915_vma_is_active(vma)); if (i915_vma_is_pinned(vma)) return -EBUSY; -- cgit v1.2.3 From 0caf81b5c53d9bd332a95dbcb44db8de0b397a7c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 17 Jun 2017 12:57:44 +0100 Subject: drm/i915: Hold struct_mutex for per-file stats in debugfs/i915_gem_object As we walk the obj->vma_list in per_file_stats(), we need to hold struct_mutex to prevent alteration of that list. Fixes: 1d2ac403ae3b ("drm: Protect dev->filelist with its own mutex") Fixes: c84455b4bacc ("drm/i915: Move debug only per-request pid tracking from request to ctx") Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=101460 Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20170617115744.4452-1-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_debugfs.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 1f1176b6400e..f7aa6cbe3a2e 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -292,6 +292,8 @@ static int per_file_stats(int id, void *ptr, void *data) struct file_stats *stats = data; struct i915_vma *vma; + lockdep_assert_held(&obj->base.dev->struct_mutex); + stats->count++; stats->total += obj->base.size; if (!obj->bind_count) @@ -476,6 +478,8 @@ static int i915_gem_object_info(struct seq_file *m, void *data) struct drm_i915_gem_request *request; struct task_struct *task; + mutex_lock(&dev->struct_mutex); + memset(&stats, 0, sizeof(stats)); stats.file_priv = file->driver_priv; spin_lock(&file->table_lock); @@ -487,7 +491,6 @@ static int i915_gem_object_info(struct seq_file *m, void *data) * still alive (e.g. get_pid(current) => fork() => exit()). * Therefore, we need to protect this ->comm access using RCU. */ - mutex_lock(&dev->struct_mutex); request = list_first_entry_or_null(&file_priv->mm.request_list, struct drm_i915_gem_request, client_link); @@ -497,6 +500,7 @@ static int i915_gem_object_info(struct seq_file *m, void *data) PIDTYPE_PID); print_file_stats(m, task ? task->comm : "", stats); rcu_read_unlock(); + mutex_unlock(&dev->struct_mutex); } mutex_unlock(&dev->filelist_mutex); -- cgit v1.2.3 From 6c8e54714cc54d080189e42fb40b24dddfe85339 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 29 Mar 2017 16:44:00 +0200 Subject: drm/atmel-hlcdc: Remove unnecessary NULL check drm_fbdev_cma_hotplug_event() already checks for NULL pointers before dereferencing, so callers don't need to do that. Reviewed-by: Daniel Vetter Signed-off-by: Thierry Reding Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170329144401.1804-11-thierry.reding@gmail.com --- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c index 30dbffdb45a3..51d22ad9a3a3 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c @@ -451,8 +451,7 @@ static void atmel_hlcdc_fb_output_poll_changed(struct drm_device *dev) { struct atmel_hlcdc_dc *dc = dev->dev_private; - if (dc->fbdev) - drm_fbdev_cma_hotplug_event(dc->fbdev); + drm_fbdev_cma_hotplug_event(dc->fbdev); } struct atmel_hlcdc_dc_commit { -- cgit v1.2.3 From 5a1535b110d73ed8d29c504eeb5fa92ac5b47cd9 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 29 Mar 2017 16:44:01 +0200 Subject: drm/rockchip: Remove unnecessary NULL check The expression &private->fbdev_helper can never be NULL, so the check is completely unnecessary. Reviewed-by: Daniel Vetter Signed-off-by: Thierry Reding Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170329144401.1804-12-thierry.reding@gmail.com --- drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c index 81f9548672b0..df6bceabeca8 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c @@ -168,10 +168,8 @@ err_gem_object_unreference: static void rockchip_drm_output_poll_changed(struct drm_device *dev) { struct rockchip_drm_private *private = dev->dev_private; - struct drm_fb_helper *fb_helper = &private->fbdev_helper; - if (fb_helper) - drm_fb_helper_hotplug_event(fb_helper); + drm_fb_helper_hotplug_event(&private->fbdev_helper); } static void -- cgit v1.2.3 From c284a0bdb18d73d5480ca53598e8fead412c6653 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Wed, 21 Jun 2017 15:45:55 +0530 Subject: drm: sti: sti_hqvdp: undo preparation of a clock source. Undo preparation of a clock source, if sti_hqvdp_start_xp70 and sti_hqvdp_atomic_check are not successful. Signed-off-by: Arvind Yadav Signed-off-by: Benjamin Gaignard Link: http://patchwork.freedesktop.org/patch/msgid/7afad3012fb6e40f43a1eb5a64dc6364c38bd052.1498039961.git.arvind.yadav.cs@gmail.com --- drivers/gpu/drm/sti/sti_hqvdp.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c index 1234f87bce20..53a46dda8bd5 100644 --- a/drivers/gpu/drm/sti/sti_hqvdp.c +++ b/drivers/gpu/drm/sti/sti_hqvdp.c @@ -958,6 +958,7 @@ static void sti_hqvdp_start_xp70(struct sti_hqvdp *hqvdp) } if (i == POLL_MAX_ATTEMPT) { DRM_ERROR("Could not reset\n"); + clk_disable_unprepare(hqvdp->clk); goto out; } @@ -994,6 +995,7 @@ static void sti_hqvdp_start_xp70(struct sti_hqvdp *hqvdp) } if (i == POLL_MAX_ATTEMPT) { DRM_ERROR("Could not boot\n"); + clk_disable_unprepare(hqvdp->clk); goto out; } @@ -1081,6 +1083,7 @@ static int sti_hqvdp_atomic_check(struct drm_plane *drm_plane, &hqvdp->vtg_nb, crtc)) { DRM_ERROR("Cannot register VTG notifier\n"); + clk_disable_unprepare(hqvdp->clk_pix_main); return -EINVAL; } hqvdp->vtg_registered = true; -- cgit v1.2.3 From 4ee056f41807858b2eae263e74ae8b81800c0337 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 21 Jun 2017 13:48:04 +0100 Subject: drm/i915: Cancel pending execlist tasklet upon wedging Highly unlikely, but if the stop_machine() did suspend the tasklet, we want to make sure that when it wakes it finds there is nothing to do. Otherwise, it will loudly complain that the ELSP port tracking no longer matches the hardware, and we will be mightly confused. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20170621124804.4529-1-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_gem.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 1353491c1010..ae3ce1314bd1 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3092,6 +3092,13 @@ static void engine_set_wedged(struct intel_engine_cs *engine) engine->execlist_first = NULL; spin_unlock_irqrestore(&engine->timeline->lock, flags); + + /* The port is checked prior to scheduling a tasklet, but + * just in case we have suspended the tasklet to do the + * wedging make sure that when it wakes, it decides there + * is no work to do by clearing the irq_posted bit. + */ + clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted); } } -- cgit v1.2.3 From 22a884cfe5a49b6fd63f10ff137906028b4cf923 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 21 Jun 2017 15:04:29 +0200 Subject: drm: Check for drm_device->dev in drm_set_busid I've failed to remember that we have virtual drivers like vgem which have no underlying struct device. Fix this asap. Reported-by: Chris Wilson Cc: Chris Wilson Reviewed-by: Chris Wilson Fixes: 5c484cee7ef9 ("drm: Remove drm_driver->set_busid hook") Cc: Thierry Reding Cc: Daniel Vetter Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170621130429.20537-1-daniel.vetter@ffwll.ch --- drivers/gpu/drm/drm_ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 3a36b3717c28..d74473570acd 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -143,7 +143,7 @@ static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv) if (master->unique != NULL) drm_unset_busid(dev, master); - if (dev_is_pci(dev->dev)) { + if (dev->dev && dev_is_pci(dev->dev)) { ret = drm_pci_set_busid(dev, master); if (ret) { drm_unset_busid(dev, master); -- cgit v1.2.3 From edeb729f7929d1372ab426a7f56fd0b337ba5751 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 16 Jun 2017 10:30:33 +0200 Subject: drm/vc4: Send a VBLANK event when disabling a CRTC VBLANK events are missed when the CRTC is being disabled because the driver does not wait till the end of the frame before stopping the HVS and PV blocks. In this case, we should explicitly issue a VBLANK event if there's one waiting. Signed-off-by: Boris Brezillon Reviewed-by: Eric Anholt Link: http://patchwork.freedesktop.org/patch/msgid/1497601833-24588-1-git-send-email-boris.brezillon@free-electrons.com --- drivers/gpu/drm/vc4/vc4_crtc.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index e3f03efe719b..30a1df11e063 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -518,6 +518,19 @@ static void vc4_crtc_disable(struct drm_crtc *crtc) WARN_ON_ONCE((HVS_READ(SCALER_DISPSTATX(chan)) & (SCALER_DISPSTATX_FULL | SCALER_DISPSTATX_EMPTY)) != SCALER_DISPSTATX_EMPTY); + + /* + * Make sure we issue a vblank event after disabling the CRTC if + * someone was waiting it. + */ + if (crtc->state->event) { + unsigned long flags; + + spin_lock_irqsave(&dev->event_lock, flags); + drm_crtc_send_vblank_event(crtc, crtc->state->event); + crtc->state->event = NULL; + spin_unlock_irqrestore(&dev->event_lock, flags); + } } static void vc4_crtc_enable(struct drm_crtc *crtc) -- cgit v1.2.3 From 10f9818307230a7d8d8b47f38be128d02872d3d2 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 21 Jun 2017 10:28:46 +0200 Subject: drm/shmob: Drop drm_vblank_cleanup It doesn't do anything in the driver load error paths that the drm core doesn't also do (cleanup is done in drm_dev_fini). Cc: Laurent Pinchart Acked-by: Laurent Pinchart Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170621082850.13224-10-daniel.vetter@ffwll.ch --- drivers/gpu/drm/shmobile/shmob_drm_drv.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/shmobile/shmob_drm_drv.c b/drivers/gpu/drm/shmobile/shmob_drm_drv.c index 800d1d2c435d..c2ca07357aac 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_drv.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_drv.c @@ -277,7 +277,7 @@ static int shmob_drm_probe(struct platform_device *pdev) ret = drm_irq_install(ddev, platform_get_irq(pdev, 0)); if (ret < 0) { dev_err(&pdev->dev, "failed to install IRQ handler\n"); - goto err_vblank_cleanup; + goto err_modeset_cleanup; } /* @@ -292,8 +292,6 @@ static int shmob_drm_probe(struct platform_device *pdev) err_irq_uninstall: drm_irq_uninstall(ddev); -err_vblank_cleanup: - drm_vblank_cleanup(ddev); err_modeset_cleanup: drm_kms_helper_poll_fini(ddev); drm_mode_config_cleanup(ddev); -- cgit v1.2.3 From 33b6b7b12d144de7e892a64cb75d086110c87da1 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 21 Jun 2017 10:28:49 +0200 Subject: drm/zte: Drop drm_vblank_cleanup It again looks all cargo-culted for no good reasons. Cc: Shawn Guo Acked-by: Shawn Guo Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170621082850.13224-13-daniel.vetter@ffwll.ch --- drivers/gpu/drm/zte/zx_drm_drv.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/zte/zx_drm_drv.c b/drivers/gpu/drm/zte/zx_drm_drv.c index f46c855d274b..fe1aa5315e19 100644 --- a/drivers/gpu/drm/zte/zx_drm_drv.c +++ b/drivers/gpu/drm/zte/zx_drm_drv.c @@ -149,7 +149,6 @@ out_fbdev_fini: out_poll_fini: drm_kms_helper_poll_fini(drm); drm_mode_config_cleanup(drm); - drm_vblank_cleanup(drm); out_unbind: component_unbind_all(dev, drm); out_unregister: @@ -171,7 +170,6 @@ static void zx_drm_unbind(struct device *dev) } drm_kms_helper_poll_fini(drm); drm_mode_config_cleanup(drm); - drm_vblank_cleanup(drm); component_unbind_all(dev, drm); dev_set_drvdata(dev, NULL); drm->dev_private = NULL; -- cgit v1.2.3 From 2b3d860efa3461af109469e6de2eea48f6ef5cdd Mon Sep 17 00:00:00 2001 From: Jose Abreu Date: Thu, 25 May 2017 15:19:17 +0100 Subject: drm: arcpgu: Use crtc->mode_valid() callback Now that we have a callback to check if crtc supports a given mode we can use it in arcpgu so that we restrict the number of probbed modes to the ones we can actually display. This is specially useful because arcpgu crtc is responsible to set a clock value in the commit() stage but unfortunatelly this clock does not support all the needed ranges. Also, remove the atomic_check() callback as mode_valid() callback will be called before. Signed-off-by: Jose Abreu Reviewed-by: Alexey Brodkin Cc: Carlos Palminha Cc: Alexey Brodkin Cc: Daniel Vetter Cc: Dave Airlie Cc: Laurent Pinchart Changes v4->v5: - Change commit message to "arcpgu" (Alexey) Changes v3->v4: - Do not use aux function (Laurent) Reviewed-by: Neil Armstrong Acked-by: Dave Airlie Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/c3bcd69016c77f68a03ff3cb6b22ca6f90e930b0.1495720737.git.joabreu@synopsys.com --- drivers/gpu/drm/arc/arcpgu_crtc.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c index ad9a95916f1f..99fbdaecf100 100644 --- a/drivers/gpu/drm/arc/arcpgu_crtc.c +++ b/drivers/gpu/drm/arc/arcpgu_crtc.c @@ -64,6 +64,19 @@ static const struct drm_crtc_funcs arc_pgu_crtc_funcs = { .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, }; +enum drm_mode_status arc_pgu_crtc_mode_valid(struct drm_crtc *crtc, + const struct drm_display_mode *mode) +{ + struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc); + long rate, clk_rate = mode->clock * 1000; + + rate = clk_round_rate(arcpgu->clk, clk_rate); + if (rate != clk_rate) + return MODE_NOCLOCK; + + return MODE_OK; +} + static void arc_pgu_crtc_mode_set_nofb(struct drm_crtc *crtc) { struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc); @@ -129,20 +142,6 @@ static void arc_pgu_crtc_disable(struct drm_crtc *crtc) ~ARCPGU_CTRL_ENABLE_MASK); } -static int arc_pgu_crtc_atomic_check(struct drm_crtc *crtc, - struct drm_crtc_state *state) -{ - struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc); - struct drm_display_mode *mode = &state->adjusted_mode; - long rate, clk_rate = mode->clock * 1000; - - rate = clk_round_rate(arcpgu->clk, clk_rate); - if (rate != clk_rate) - return -EINVAL; - - return 0; -} - static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc, struct drm_crtc_state *state) { @@ -158,6 +157,7 @@ static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc, } static const struct drm_crtc_helper_funcs arc_pgu_crtc_helper_funcs = { + .mode_valid = arc_pgu_crtc_mode_valid, .mode_set = drm_helper_crtc_mode_set, .mode_set_base = drm_helper_crtc_mode_set_base, .mode_set_nofb = arc_pgu_crtc_mode_set_nofb, @@ -165,7 +165,6 @@ static const struct drm_crtc_helper_funcs arc_pgu_crtc_helper_funcs = { .disable = arc_pgu_crtc_disable, .prepare = arc_pgu_crtc_disable, .commit = arc_pgu_crtc_enable, - .atomic_check = arc_pgu_crtc_atomic_check, .atomic_begin = arc_pgu_crtc_atomic_begin, }; -- cgit v1.2.3 From 51d05e1b29676a0425749a1533b87e3ad3c6f176 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 22 Jun 2017 11:47:22 +0100 Subject: drm/i915: Clear execbuf's vma backpointer upon release commit 2889caa92321 ("drm/i915: Eliminate lots of iterations over the execobjects array") jiggled around the error handling and replace a test that we cleaned up properly after ourselves with an assertion. That assertion failed because in the release function (moments after the assertion) we were indeed forgetting to mark the vma as cleared. The consequence was when testing an invalid relocation address, we would try to release the vma twice (following the couple of attempts to verify the address) and on the second release notice that the first release was incomplete. Testcase: igt/gem_reloc_overflow/invalid-address Fixes: 2889caa92321 ("drm/i915: Eliminate lots of iterations over the execobjects array") Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Cc: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20170622104722.2583-1-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index b2457556591c..ec33b358fba9 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -879,6 +879,7 @@ static void eb_release_vmas(const struct i915_execbuffer *eb) GEM_BUG_ON(vma->exec_entry != entry); vma->exec_entry = NULL; + __exec_to_vma(entry) = 0; if (entry->flags & __EXEC_OBJECT_HAS_PIN) __eb_unreserve_vma(vma, entry); -- cgit v1.2.3 From 0108648749bfa5713ed0ceede2ee091f428a29d7 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 2 Jun 2017 10:32:06 +0200 Subject: drm: Add drm_atomic_helper_wait_for_flip_done() Add an helper to wait for all page flips of an atomic state to be done. v2: - Pimp kerneldoc as discussed with Boris on irc - Add missing doc for @dev. - Use old_state for consitency with wait_for_vblanks Signed-off-by: Boris Brezillon (v1) Acked-by: Boris Brezillon Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1496392332-8722-2-git-send-email-boris.brezillon@free-electrons.com --- drivers/gpu/drm/drm_atomic_helper.c | 43 +++++++++++++++++++++++++++++++- include/drm/drm_atomic_helper.h | 3 +++ include/drm/drm_modeset_helper_vtables.h | 3 ++- 3 files changed, 47 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 93b0221d5d0f..45b4f34bebcd 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1185,9 +1185,13 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_fences); * * Helper to, after atomic commit, wait for vblanks on all effected * crtcs (ie. before cleaning up old framebuffers using - * drm_atomic_helper_cleanup_planes()). It will only wait on crtcs where the + * drm_atomic_helper_cleanup_planes()). It will only wait on CRTCs where the * framebuffers have actually changed to optimize for the legacy cursor and * plane update use-case. + * + * Drivers using the nonblocking commit tracking support initialized by calling + * drm_atomic_helper_setup_commit() should look at + * drm_atomic_helper_wait_for_flip_done() as an alternative. */ void drm_atomic_helper_wait_for_vblanks(struct drm_device *dev, @@ -1234,6 +1238,43 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev, } EXPORT_SYMBOL(drm_atomic_helper_wait_for_vblanks); +/** + * drm_atomic_helper_wait_for_flip_done - wait for all page flips to be done + * @dev: DRM device + * @old_state: atomic state object with old state structures + * + * Helper to, after atomic commit, wait for page flips on all effected + * crtcs (ie. before cleaning up old framebuffers using + * drm_atomic_helper_cleanup_planes()). Compared to + * drm_atomic_helper_wait_for_vblanks() this waits for the completion of on all + * CRTCs, assuming that cursors-only updates are signalling their completion + * immediately (or using a different path). + * + * This requires that drivers use the nonblocking commit tracking support + * initialized using drm_atomic_helper_setup_commit(). + */ +void drm_atomic_helper_wait_for_flip_done(struct drm_device *dev, + struct drm_atomic_state *old_state) +{ + struct drm_crtc_state *crtc_state; + struct drm_crtc *crtc; + int i; + + for_each_crtc_in_state(old_state, crtc, crtc_state, i) { + struct drm_crtc_commit *commit = old_state->crtcs[i].commit; + int ret; + + if (!commit) + continue; + + ret = wait_for_completion_timeout(&commit->flip_done, 10 * HZ); + if (ret == 0) + DRM_ERROR("[CRTC:%d:%s] flip_done timed out\n", + crtc->base.id, crtc->name); + } +} +EXPORT_SYMBOL(drm_atomic_helper_wait_for_flip_done); + /** * drm_atomic_helper_commit_tail - commit atomic update to hardware * @old_state: atomic state object with old state structures diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index f0a8678ae98e..3bfeb2b2f746 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -52,6 +52,9 @@ int drm_atomic_helper_wait_for_fences(struct drm_device *dev, void drm_atomic_helper_wait_for_vblanks(struct drm_device *dev, struct drm_atomic_state *old_state); +void drm_atomic_helper_wait_for_flip_done(struct drm_device *dev, + struct drm_atomic_state *old_state); + void drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev, struct drm_atomic_state *old_state); diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h index 85984b208218..474a1029ec79 100644 --- a/include/drm/drm_modeset_helper_vtables.h +++ b/include/drm/drm_modeset_helper_vtables.h @@ -1169,7 +1169,8 @@ struct drm_mode_config_helper_funcs { * After the atomic update is committed to the hardware this hook needs * to call drm_atomic_helper_commit_hw_done(). Then wait for the upate * to be executed by the hardware, for example using - * drm_atomic_helper_wait_for_vblanks(), and then clean up the old + * drm_atomic_helper_wait_for_vblanks() or + * drm_atomic_helper_wait_for_flip_done(), and then clean up the old * framebuffers using drm_atomic_helper_cleanup_planes(). * * When disabling a CRTC this hook _must_ stall for the commit to -- cgit v1.2.3 From 4a234c5fae1686c8327edeaabc0f2d6fb86db470 Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Thu, 22 Jun 2017 10:58:36 +0100 Subject: drm/i915: pass the vma to insert_entries The vma already contains most of the information we need for insertion. But also in preparation for supporting huge gtt pages, it would be useful to know the details of the vma, such that we can we can easily determine the page sizes we are allowed to use when inserting into the 48b PPGTT. This is especially true for 64K where we can't just arbitrarily use it, since we require aligning/padding the vm space to 2M, which sometimes we can't enforce in the upper levels. Suggested-by: Chris Wilson Signed-off-by: Matthew Auld Cc: Joonas Lahtinen Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/20170622095836.6800-1-matthew.auld@intel.com Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_gem_gtt.c | 68 +++++++++++---------------- drivers/gpu/drm/i915/i915_gem_gtt.h | 3 +- drivers/gpu/drm/i915/selftests/i915_gem_gtt.c | 10 +++- drivers/gpu/drm/i915/selftests/mock_gtt.c | 3 +- 4 files changed, 38 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 61fc7e90a7da..de67084d5fcf 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -207,8 +207,7 @@ static int ppgtt_bind_vma(struct i915_vma *vma, if (vma->obj->gt_ro) pte_flags |= PTE_READ_ONLY; - vma->vm->insert_entries(vma->vm, vma->pages, vma->node.start, - cache_level, pte_flags); + vma->vm->insert_entries(vma->vm, vma, cache_level, pte_flags); return 0; } @@ -907,37 +906,35 @@ gen8_ppgtt_insert_pte_entries(struct i915_hw_ppgtt *ppgtt, } static void gen8_ppgtt_insert_3lvl(struct i915_address_space *vm, - struct sg_table *pages, - u64 start, + struct i915_vma *vma, enum i915_cache_level cache_level, u32 unused) { - struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm); + struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vma->vm); struct sgt_dma iter = { - .sg = pages->sgl, + .sg = vma->pages->sgl, .dma = sg_dma_address(iter.sg), .max = iter.dma + iter.sg->length, }; - struct gen8_insert_pte idx = gen8_insert_pte(start); + struct gen8_insert_pte idx = gen8_insert_pte(vma->node.start); gen8_ppgtt_insert_pte_entries(ppgtt, &ppgtt->pdp, &iter, &idx, cache_level); } static void gen8_ppgtt_insert_4lvl(struct i915_address_space *vm, - struct sg_table *pages, - u64 start, + struct i915_vma *vma, enum i915_cache_level cache_level, u32 unused) { struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm); struct sgt_dma iter = { - .sg = pages->sgl, + .sg = vma->pages->sgl, .dma = sg_dma_address(iter.sg), .max = iter.dma + iter.sg->length, }; struct i915_page_directory_pointer **pdps = ppgtt->pml4.pdps; - struct gen8_insert_pte idx = gen8_insert_pte(start); + struct gen8_insert_pte idx = gen8_insert_pte(vma->node.start); while (gen8_ppgtt_insert_pte_entries(ppgtt, pdps[idx.pml4e++], &iter, &idx, cache_level)) @@ -1621,13 +1618,12 @@ static void gen6_ppgtt_clear_range(struct i915_address_space *vm, } static void gen6_ppgtt_insert_entries(struct i915_address_space *vm, - struct sg_table *pages, - u64 start, + struct i915_vma *vma, enum i915_cache_level cache_level, u32 flags) { struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm); - unsigned first_entry = start >> PAGE_SHIFT; + unsigned first_entry = vma->node.start >> PAGE_SHIFT; unsigned act_pt = first_entry / GEN6_PTES; unsigned act_pte = first_entry % GEN6_PTES; const u32 pte_encode = vm->pte_encode(0, cache_level, flags); @@ -1635,7 +1631,7 @@ static void gen6_ppgtt_insert_entries(struct i915_address_space *vm, gen6_pte_t *vaddr; vaddr = kmap_atomic_px(ppgtt->pd.page_table[act_pt]); - iter.sg = pages->sgl; + iter.sg = vma->pages->sgl; iter.dma = sg_dma_address(iter.sg); iter.max = iter.dma + iter.sg->length; do { @@ -2090,8 +2086,7 @@ static void gen8_ggtt_insert_page(struct i915_address_space *vm, } static void gen8_ggtt_insert_entries(struct i915_address_space *vm, - struct sg_table *st, - u64 start, + struct i915_vma *vma, enum i915_cache_level level, u32 unused) { @@ -2102,8 +2097,8 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm, dma_addr_t addr; gtt_entries = (gen8_pte_t __iomem *)ggtt->gsm; - gtt_entries += start >> PAGE_SHIFT; - for_each_sgt_dma(addr, sgt_iter, st) + gtt_entries += vma->node.start >> PAGE_SHIFT; + for_each_sgt_dma(addr, sgt_iter, vma->pages) gen8_set_pte(gtt_entries++, pte_encode | addr); wmb(); @@ -2137,17 +2132,16 @@ static void gen6_ggtt_insert_page(struct i915_address_space *vm, * mapped BAR (dev_priv->mm.gtt->gtt). */ static void gen6_ggtt_insert_entries(struct i915_address_space *vm, - struct sg_table *st, - u64 start, + struct i915_vma *vma, enum i915_cache_level level, u32 flags) { struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm); gen6_pte_t __iomem *entries = (gen6_pte_t __iomem *)ggtt->gsm; - unsigned int i = start >> PAGE_SHIFT; + unsigned int i = vma->node.start >> PAGE_SHIFT; struct sgt_iter iter; dma_addr_t addr; - for_each_sgt_dma(addr, iter, st) + for_each_sgt_dma(addr, iter, vma->pages) iowrite32(vm->pte_encode(addr, level, flags), &entries[i++]); wmb(); @@ -2229,8 +2223,7 @@ static void bxt_vtd_ggtt_insert_page__BKL(struct i915_address_space *vm, struct insert_entries { struct i915_address_space *vm; - struct sg_table *st; - u64 start; + struct i915_vma *vma; enum i915_cache_level level; }; @@ -2238,19 +2231,18 @@ static int bxt_vtd_ggtt_insert_entries__cb(void *_arg) { struct insert_entries *arg = _arg; - gen8_ggtt_insert_entries(arg->vm, arg->st, arg->start, arg->level, 0); + gen8_ggtt_insert_entries(arg->vm, arg->vma, arg->level, 0); bxt_vtd_ggtt_wa(arg->vm); return 0; } static void bxt_vtd_ggtt_insert_entries__BKL(struct i915_address_space *vm, - struct sg_table *st, - u64 start, + struct i915_vma *vma, enum i915_cache_level level, u32 unused) { - struct insert_entries arg = { vm, st, start, level }; + struct insert_entries arg = { vma->vm, vma, level }; stop_machine(bxt_vtd_ggtt_insert_entries__cb, &arg, NULL); } @@ -2316,15 +2308,15 @@ static void i915_ggtt_insert_page(struct i915_address_space *vm, } static void i915_ggtt_insert_entries(struct i915_address_space *vm, - struct sg_table *pages, - u64 start, + struct i915_vma *vma, enum i915_cache_level cache_level, u32 unused) { unsigned int flags = (cache_level == I915_CACHE_NONE) ? AGP_USER_MEMORY : AGP_USER_CACHED_MEMORY; - intel_gtt_insert_sg_entries(pages, start >> PAGE_SHIFT, flags); + intel_gtt_insert_sg_entries(vma->pages, vma->node.start >> PAGE_SHIFT, + flags); } static void i915_ggtt_clear_range(struct i915_address_space *vm, @@ -2353,8 +2345,7 @@ static int ggtt_bind_vma(struct i915_vma *vma, pte_flags |= PTE_READ_ONLY; intel_runtime_pm_get(i915); - vma->vm->insert_entries(vma->vm, vma->pages, vma->node.start, - cache_level, pte_flags); + vma->vm->insert_entries(vma->vm, vma, cache_level, pte_flags); intel_runtime_pm_put(i915); /* @@ -2407,16 +2398,13 @@ static int aliasing_gtt_bind_vma(struct i915_vma *vma, goto err_pages; } - appgtt->base.insert_entries(&appgtt->base, - vma->pages, vma->node.start, - cache_level, pte_flags); + appgtt->base.insert_entries(&appgtt->base, vma, cache_level, + pte_flags); } if (flags & I915_VMA_GLOBAL_BIND) { intel_runtime_pm_get(i915); - vma->vm->insert_entries(vma->vm, - vma->pages, vma->node.start, - cache_level, pte_flags); + vma->vm->insert_entries(vma->vm, vma, cache_level, pte_flags); intel_runtime_pm_put(i915); } diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index 1b2a56c3e5d3..b4e3aa7c0ce1 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -313,8 +313,7 @@ struct i915_address_space { enum i915_cache_level cache_level, u32 flags); void (*insert_entries)(struct i915_address_space *vm, - struct sg_table *st, - u64 start, + struct i915_vma *vma, enum i915_cache_level cache_level, u32 flags); void (*cleanup)(struct i915_address_space *vm); diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c index 50710e3f1caa..6b132caffa18 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c @@ -197,6 +197,9 @@ static int lowlevel_hole(struct drm_i915_private *i915, { I915_RND_STATE(seed_prng); unsigned int size; + struct i915_vma mock_vma; + + memset(&mock_vma, 0, sizeof(struct i915_vma)); /* Keep creating larger objects until one cannot fit into the hole */ for (size = 12; (hole_end - hole_start) >> size; size++) { @@ -255,8 +258,11 @@ static int lowlevel_hole(struct drm_i915_private *i915, vm->allocate_va_range(vm, addr, BIT_ULL(size))) break; - vm->insert_entries(vm, obj->mm.pages, addr, - I915_CACHE_NONE, 0); + mock_vma.pages = obj->mm.pages; + mock_vma.node.size = BIT_ULL(size); + mock_vma.node.start = addr; + + vm->insert_entries(vm, &mock_vma, I915_CACHE_NONE, 0); } count = n; diff --git a/drivers/gpu/drm/i915/selftests/mock_gtt.c b/drivers/gpu/drm/i915/selftests/mock_gtt.c index a61309c7cb3e..f2118cf535a0 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gtt.c +++ b/drivers/gpu/drm/i915/selftests/mock_gtt.c @@ -33,8 +33,7 @@ static void mock_insert_page(struct i915_address_space *vm, } static void mock_insert_entries(struct i915_address_space *vm, - struct sg_table *st, - u64 start, + struct i915_vma *vma, enum i915_cache_level level, u32 flags) { } -- cgit v1.2.3 From b9eb89b21fa3f759d775fbd50236ece663771736 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 20 Jun 2017 16:03:06 +0300 Subject: drm/i915: Use HAS_PCH_CPT() everywhere MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have a few cases comparing pch_type directly. Let's just replace them with HAS_PCH_CPT() since CPT/PPT is what they're looking for. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/20170620130310.13245-2-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/intel_device_info.c | 2 +- drivers/gpu/drm/i915/intel_sdvo.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index 77d3214e1a77..5f91ddc78c7a 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -363,7 +363,7 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv) */ if (fuse_strap & ILK_INTERNAL_DISPLAY_DISABLE || sfuse_strap & SFUSE_STRAP_DISPLAY_DISABLED || - (dev_priv->pch_type == PCH_CPT && + (HAS_PCH_CPT(dev_priv) && !(sfuse_strap & SFUSE_STRAP_FUSE_LOCK))) { DRM_INFO("Display fused off, disabling\n"); info->num_pipes = 0; diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 3f8f30b412cd..f902922d4ae6 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1343,7 +1343,7 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder, sdvox |= (9 << 19) | SDVO_BORDER_ENABLE; } - if (INTEL_PCH_TYPE(dev_priv) >= PCH_CPT) + if (HAS_PCH_CPT(dev_priv)) sdvox |= SDVO_PIPE_SEL_CPT(crtc->pipe); else sdvox |= SDVO_PIPE_SEL(crtc->pipe); -- cgit v1.2.3 From aa0321300651df92dad7925a1da7fcaaf2f78c57 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 20 Jun 2017 16:03:07 +0300 Subject: drm/i915: s/Couar/Cougar/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix a typo in the PCH type debug message. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/20170620130310.13245-3-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/i915_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index d35a114c46ed..7ef113d062f5 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -132,7 +132,7 @@ static enum intel_pch intel_virt_detect_pch(struct drm_i915_private *dev_priv) DRM_DEBUG_KMS("Assuming Ibex Peak PCH\n"); } else if (IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv)) { ret = PCH_CPT; - DRM_DEBUG_KMS("Assuming CouarPoint PCH\n"); + DRM_DEBUG_KMS("Assuming CougarPoint PCH\n"); } else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { ret = PCH_LPT; DRM_DEBUG_KMS("Assuming LynxPoint PCH\n"); -- cgit v1.2.3 From 243dec586fca7f9acd08c0e5a9d7884fe5e9c848 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 20 Jun 2017 16:03:08 +0300 Subject: drm/i915: Document that PPT==CPT and WPT==LPT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For our purposes PPT is equivalent to CPT, and WPT is equivalent to LPT. Document that fact. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/20170620130310.13245-4-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/i915_drv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 90cc63e5ced8..96372f6e9cac 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1150,8 +1150,8 @@ struct i915_psr { enum intel_pch { PCH_NONE = 0, /* No PCH present */ PCH_IBX, /* Ibexpeak PCH */ - PCH_CPT, /* Cougarpoint PCH */ - PCH_LPT, /* Lynxpoint PCH */ + PCH_CPT, /* Cougarpoint/Pantherpoint PCH */ + PCH_LPT, /* Lynxpoint/Wildcatpoint PCH */ PCH_SPT, /* Sunrisepoint PCH */ PCH_KBP, /* Kabypoint PCH */ PCH_CNP, /* Cannonpoint PCH */ -- cgit v1.2.3 From d4cdbf0334c01ac2fa29238bd7b87142ea0f5740 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 20 Jun 2017 16:03:09 +0300 Subject: drm/i915: Clean up some expressions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Write the '!(SNB||IVB)' checks in the CPT/PPT detections as '!SNB && !IVB' to make it less messy looking, and clear out some useless parens the from the virtualization PCH detection case. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/20170620130310.13245-5-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/i915_drv.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 7ef113d062f5..80a6d4d13e6f 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -185,15 +185,15 @@ static void intel_detect_pch(struct drm_i915_private *dev_priv) dev_priv->pch_id = id; dev_priv->pch_type = PCH_CPT; DRM_DEBUG_KMS("Found CougarPoint PCH\n"); - WARN_ON(!(IS_GEN6(dev_priv) || - IS_IVYBRIDGE(dev_priv))); + WARN_ON(!IS_GEN6(dev_priv) && + !IS_IVYBRIDGE(dev_priv)); } else if (id == INTEL_PCH_PPT_DEVICE_ID_TYPE) { /* PantherPoint is CPT compatible */ dev_priv->pch_id = id; dev_priv->pch_type = PCH_CPT; DRM_DEBUG_KMS("Found PantherPoint PCH\n"); - WARN_ON(!(IS_GEN6(dev_priv) || - IS_IVYBRIDGE(dev_priv))); + WARN_ON(!IS_GEN6(dev_priv) && + !IS_IVYBRIDGE(dev_priv)); } else if (id == INTEL_PCH_LPT_DEVICE_ID_TYPE) { dev_priv->pch_id = id; dev_priv->pch_type = PCH_LPT; @@ -240,9 +240,9 @@ static void intel_detect_pch(struct drm_i915_private *dev_priv) DRM_DEBUG_KMS("Found CannonPoint LP PCH\n"); WARN_ON(!IS_CANNONLAKE(dev_priv) && !IS_COFFEELAKE(dev_priv)); - } else if ((id == INTEL_PCH_P2X_DEVICE_ID_TYPE) || - (id == INTEL_PCH_P3X_DEVICE_ID_TYPE) || - ((id == INTEL_PCH_QEMU_DEVICE_ID_TYPE) && + } else if (id == INTEL_PCH_P2X_DEVICE_ID_TYPE || + id == INTEL_PCH_P3X_DEVICE_ID_TYPE || + (id == INTEL_PCH_QEMU_DEVICE_ID_TYPE && pch->subsystem_vendor == PCI_SUBVENDOR_ID_REDHAT_QUMRANET && pch->subsystem_device == -- cgit v1.2.3 From c5e855d07834d67f30fab07e7d7316b090b8073f Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 21 Jun 2017 20:49:44 +0300 Subject: drm/i915: Always use 9 bits of the LPC bridge device ID for PCH detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the code less confusiong by always using the top 9 bits of the LPC bridge device ID to detect the PCH type. We need to add a bit of new code for WPT, and we need to adjust the KBP ID as well. All the other pre-CNP IDs are fine as is. The virtualization cases I think are fine. These P2X and P3X IDs actually just look like the old PIIX4 and PIIX3 IDs to me. Not sure why they're not called PIIX3/4 though. The qemu one has a comment saying the full ID is 0x2918 which is fine with 9 bits. v2: Keep the CNP ID as 0xa300 (DK) Cc: Dhinakaran Pandiyan Reviewed-by: Jani Nikula Reviewed-by: Dhinakaran Pandiyan Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/20170621174944.23306-1-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/i915_drv.c | 35 ++++++++++++++++++++--------------- drivers/gpu/drm/i915/i915_drv.h | 13 ++++++++----- 2 files changed, 28 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 80a6d4d13e6f..370429e2071f 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -173,29 +173,25 @@ static void intel_detect_pch(struct drm_i915_private *dev_priv) while ((pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, pch))) { if (pch->vendor == PCI_VENDOR_ID_INTEL) { unsigned short id = pch->device & INTEL_PCH_DEVICE_ID_MASK; - unsigned short id_ext = pch->device & - INTEL_PCH_DEVICE_ID_MASK_EXT; + + dev_priv->pch_id = id; if (id == INTEL_PCH_IBX_DEVICE_ID_TYPE) { - dev_priv->pch_id = id; dev_priv->pch_type = PCH_IBX; DRM_DEBUG_KMS("Found Ibex Peak PCH\n"); WARN_ON(!IS_GEN5(dev_priv)); } else if (id == INTEL_PCH_CPT_DEVICE_ID_TYPE) { - dev_priv->pch_id = id; dev_priv->pch_type = PCH_CPT; DRM_DEBUG_KMS("Found CougarPoint PCH\n"); WARN_ON(!IS_GEN6(dev_priv) && !IS_IVYBRIDGE(dev_priv)); } else if (id == INTEL_PCH_PPT_DEVICE_ID_TYPE) { /* PantherPoint is CPT compatible */ - dev_priv->pch_id = id; dev_priv->pch_type = PCH_CPT; DRM_DEBUG_KMS("Found PantherPoint PCH\n"); WARN_ON(!IS_GEN6(dev_priv) && !IS_IVYBRIDGE(dev_priv)); } else if (id == INTEL_PCH_LPT_DEVICE_ID_TYPE) { - dev_priv->pch_id = id; dev_priv->pch_type = PCH_LPT; DRM_DEBUG_KMS("Found LynxPoint PCH\n"); WARN_ON(!IS_HASWELL(dev_priv) && @@ -203,39 +199,49 @@ static void intel_detect_pch(struct drm_i915_private *dev_priv) WARN_ON(IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv)); } else if (id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) { - dev_priv->pch_id = id; dev_priv->pch_type = PCH_LPT; DRM_DEBUG_KMS("Found LynxPoint LP PCH\n"); WARN_ON(!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)); WARN_ON(!IS_HSW_ULT(dev_priv) && !IS_BDW_ULT(dev_priv)); + } else if (id == INTEL_PCH_WPT_DEVICE_ID_TYPE) { + /* WildcatPoint is LPT compatible */ + dev_priv->pch_type = PCH_LPT; + DRM_DEBUG_KMS("Found WildcatPoint PCH\n"); + WARN_ON(!IS_HASWELL(dev_priv) && + !IS_BROADWELL(dev_priv)); + WARN_ON(IS_HSW_ULT(dev_priv) || + IS_BDW_ULT(dev_priv)); + } else if (id == INTEL_PCH_WPT_LP_DEVICE_ID_TYPE) { + /* WildcatPoint is LPT compatible */ + dev_priv->pch_type = PCH_LPT; + DRM_DEBUG_KMS("Found WildcatPoint LP PCH\n"); + WARN_ON(!IS_HASWELL(dev_priv) && + !IS_BROADWELL(dev_priv)); + WARN_ON(!IS_HSW_ULT(dev_priv) && + !IS_BDW_ULT(dev_priv)); } else if (id == INTEL_PCH_SPT_DEVICE_ID_TYPE) { - dev_priv->pch_id = id; dev_priv->pch_type = PCH_SPT; DRM_DEBUG_KMS("Found SunrisePoint PCH\n"); WARN_ON(!IS_SKYLAKE(dev_priv) && !IS_KABYLAKE(dev_priv)); - } else if (id_ext == INTEL_PCH_SPT_LP_DEVICE_ID_TYPE) { - dev_priv->pch_id = id_ext; + } else if (id == INTEL_PCH_SPT_LP_DEVICE_ID_TYPE) { dev_priv->pch_type = PCH_SPT; DRM_DEBUG_KMS("Found SunrisePoint LP PCH\n"); WARN_ON(!IS_SKYLAKE(dev_priv) && !IS_KABYLAKE(dev_priv)); } else if (id == INTEL_PCH_KBP_DEVICE_ID_TYPE) { - dev_priv->pch_id = id; dev_priv->pch_type = PCH_KBP; DRM_DEBUG_KMS("Found KabyPoint PCH\n"); WARN_ON(!IS_SKYLAKE(dev_priv) && !IS_KABYLAKE(dev_priv)); } else if (id == INTEL_PCH_CNP_DEVICE_ID_TYPE) { - dev_priv->pch_id = id; dev_priv->pch_type = PCH_CNP; DRM_DEBUG_KMS("Found CannonPoint PCH\n"); WARN_ON(!IS_CANNONLAKE(dev_priv) && !IS_COFFEELAKE(dev_priv)); - } else if (id_ext == INTEL_PCH_CNP_LP_DEVICE_ID_TYPE) { - dev_priv->pch_id = id_ext; + } else if (id == INTEL_PCH_CNP_LP_DEVICE_ID_TYPE) { dev_priv->pch_type = PCH_CNP; DRM_DEBUG_KMS("Found CannonPoint LP PCH\n"); WARN_ON(!IS_CANNONLAKE(dev_priv) && @@ -247,7 +253,6 @@ static void intel_detect_pch(struct drm_i915_private *dev_priv) PCI_SUBVENDOR_ID_REDHAT_QUMRANET && pch->subsystem_device == PCI_SUBDEVICE_ID_QEMU)) { - dev_priv->pch_id = id; dev_priv->pch_type = intel_virt_detect_pch(dev_priv); } else diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 96372f6e9cac..5524e6fc9476 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3011,16 +3011,17 @@ intel_info(const struct drm_i915_private *dev_priv) #define HAS_POOLED_EU(dev_priv) ((dev_priv)->info.has_pooled_eu) -#define INTEL_PCH_DEVICE_ID_MASK 0xff00 -#define INTEL_PCH_DEVICE_ID_MASK_EXT 0xff80 +#define INTEL_PCH_DEVICE_ID_MASK 0xff80 #define INTEL_PCH_IBX_DEVICE_ID_TYPE 0x3b00 #define INTEL_PCH_CPT_DEVICE_ID_TYPE 0x1c00 #define INTEL_PCH_PPT_DEVICE_ID_TYPE 0x1e00 #define INTEL_PCH_LPT_DEVICE_ID_TYPE 0x8c00 #define INTEL_PCH_LPT_LP_DEVICE_ID_TYPE 0x9c00 +#define INTEL_PCH_WPT_DEVICE_ID_TYPE 0x8c80 +#define INTEL_PCH_WPT_LP_DEVICE_ID_TYPE 0x9c80 #define INTEL_PCH_SPT_DEVICE_ID_TYPE 0xA100 #define INTEL_PCH_SPT_LP_DEVICE_ID_TYPE 0x9D00 -#define INTEL_PCH_KBP_DEVICE_ID_TYPE 0xA200 +#define INTEL_PCH_KBP_DEVICE_ID_TYPE 0xA280 #define INTEL_PCH_CNP_DEVICE_ID_TYPE 0xA300 #define INTEL_PCH_CNP_LP_DEVICE_ID_TYPE 0x9D80 #define INTEL_PCH_P2X_DEVICE_ID_TYPE 0x7100 @@ -3035,9 +3036,11 @@ intel_info(const struct drm_i915_private *dev_priv) #define HAS_PCH_SPT(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_SPT) #define HAS_PCH_LPT(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_LPT) #define HAS_PCH_LPT_LP(dev_priv) \ - ((dev_priv)->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) + ((dev_priv)->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE || \ + (dev_priv)->pch_id == INTEL_PCH_WPT_LP_DEVICE_ID_TYPE) #define HAS_PCH_LPT_H(dev_priv) \ - ((dev_priv)->pch_id == INTEL_PCH_LPT_DEVICE_ID_TYPE) + ((dev_priv)->pch_id == INTEL_PCH_LPT_DEVICE_ID_TYPE || \ + (dev_priv)->pch_id == INTEL_PCH_WPT_DEVICE_ID_TYPE) #define HAS_PCH_CPT(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_CPT) #define HAS_PCH_IBX(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_IBX) #define HAS_PCH_NOP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_NOP) -- cgit v1.2.3 From 7d2818f54e38e40232c65866b58c8b627dbf5711 Mon Sep 17 00:00:00 2001 From: Mario Kleiner Date: Thu, 22 Jun 2017 03:28:11 +0200 Subject: drm/vc4: Allow vblank_disable_immediate on non-fw-kms. (v2) With instantaneous high precision vblank timestamping that updates at leading edge of vblank, the emulated "hw vblank counter" from vblank timestamping which increments at leading edge of vblank, and reliable page flip execution and completion at leading edge of vblank, we should meet the requirements for fast vblank irq disable/enable. Testing against rpi-4.12-rc5 Linux kernel with timing measurement equipment indicates this works fine, so allow immediate vblank disable for power saving. For debugging in case of unexpected trouble, booting with kernel cmdline option drm.vblankoffdelay=0 would keep vblank irqs on to approximate old behavior. v2: Respin onto drm-misc-next, per Eric's suggestion. Drop !vc4->firmware_kms check, as the firmware_kms implementation does not exist in upstream. Signed-off-by: Mario Kleiner Cc: Eric Anholt Reviewed-by: Eric Anholt Link: http://patchwork.freedesktop.org/patch/msgid/20170622012811.2139-1-mario.kleiner.de@gmail.com --- drivers/gpu/drm/vc4/vc4_kms.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index bc6ecdc6f104..c2c9f82b2df1 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -241,6 +241,9 @@ int vc4_kms_load(struct drm_device *dev) sema_init(&vc4->async_modeset, 1); + /* Set support for vblank irq fast disable, before drm_vblank_init() */ + dev->vblank_disable_immediate = true; + ret = drm_vblank_init(dev, dev->mode_config.num_crtc); if (ret < 0) { dev_err(dev->dev, "failed to initialize vblank\n"); -- cgit v1.2.3 From 334dbd69c604cb33d906a30195010d090e6eb80c Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 21 Jun 2017 11:49:59 -0700 Subject: drm/vc4: Hook up plane prepare_fb to lookup dma-buf reservations. This way drm_atomic_helper_wait_for_fences() will actually do something. The vc4_seqno_cb has been doing the fence waits on V3D manually, so far. Signed-off-by: Eric Anholt Link: http://patchwork.freedesktop.org/patch/msgid/20170621185002.28563-1-eric@anholt.net Acked-by: Daniel Vetter Reviewed-by: Boris Brezillon --- drivers/gpu/drm/vc4/vc4_plane.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index fa6809d8b0fe..8853e9a4f005 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -759,9 +759,26 @@ void vc4_plane_async_set_fb(struct drm_plane *plane, struct drm_framebuffer *fb) vc4_state->dlist[vc4_state->ptr0_offset] = addr; } +static int vc4_prepare_fb(struct drm_plane *plane, + struct drm_plane_state *state) +{ + struct vc4_bo *bo; + struct dma_fence *fence; + + if ((plane->state->fb == state->fb) || !state->fb) + return 0; + + bo = to_vc4_bo(&drm_fb_cma_get_gem_obj(state->fb, 0)->base); + fence = reservation_object_get_excl_rcu(bo->resv); + drm_atomic_set_fence_for_plane(state, fence); + + return 0; +} + static const struct drm_plane_helper_funcs vc4_plane_helper_funcs = { .atomic_check = vc4_plane_atomic_check, .atomic_update = vc4_plane_atomic_update, + .prepare_fb = vc4_prepare_fb, }; static void vc4_plane_destroy(struct drm_plane *plane) -- cgit v1.2.3 From 53ad06949d3b18ffeb530ff876b1ae35e7640f39 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 21 Jun 2017 11:50:00 -0700 Subject: drm/vc4: Wait for fences interruptibly in blocking mode. We should allow SIGIO and things to interrupt us before we get to the no-error stage of the commit process. This code is effectively copied from drm_atomic_helper_commit(). Signed-off-by: Eric Anholt Link: http://patchwork.freedesktop.org/patch/msgid/20170621185002.28563-2-eric@anholt.net Acked-by: Daniel Vetter Reviewed-by: Boris Brezillon --- drivers/gpu/drm/vc4/vc4_kms.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index c2c9f82b2df1..86fcdb0bd75f 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -142,6 +142,16 @@ static int vc4_atomic_commit(struct drm_device *dev, return ret; } + if (!nonblock) { + ret = drm_atomic_helper_wait_for_fences(dev, state, true); + if (ret) { + drm_atomic_helper_cleanup_planes(dev, state); + kfree(c); + up(&vc4->async_modeset); + return ret; + } + } + for_each_plane_in_state(state, plane, new_state, i) { if ((plane->state->fb != new_state->fb) && new_state->fb) { struct drm_gem_cma_object *cma_bo = -- cgit v1.2.3 From cf1b372ec11dae9fe7dcc26f47cb4bc939db0c32 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 21 Jun 2017 11:50:01 -0700 Subject: drm/vc4: Use the atomic state's commit workqueue. Now that we're using the atomic helpers for fence waits, we can use the same codepath as drm_atomic_helper_commit() does for async, getting rid of our custom vc4_commit struct. Signed-off-by: Eric Anholt Link: http://patchwork.freedesktop.org/patch/msgid/20170621185002.28563-3-eric@anholt.net Acked-by: Daniel Vetter Reviewed-by: Boris Brezillon --- drivers/gpu/drm/vc4/vc4_kms.c | 71 ++++++++----------------------------------- 1 file changed, 13 insertions(+), 58 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index 86fcdb0bd75f..27edae427025 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -29,16 +29,9 @@ static void vc4_output_poll_changed(struct drm_device *dev) drm_fbdev_cma_hotplug_event(vc4->fbdev); } -struct vc4_commit { - struct drm_device *dev; - struct drm_atomic_state *state; - struct vc4_seqno_cb cb; -}; - static void -vc4_atomic_complete_commit(struct vc4_commit *c) +vc4_atomic_complete_commit(struct drm_atomic_state *state) { - struct drm_atomic_state *state = c->state; struct drm_device *dev = state->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); @@ -72,28 +65,14 @@ vc4_atomic_complete_commit(struct vc4_commit *c) drm_atomic_state_put(state); up(&vc4->async_modeset); - - kfree(c); -} - -static void -vc4_atomic_complete_commit_seqno_cb(struct vc4_seqno_cb *cb) -{ - struct vc4_commit *c = container_of(cb, struct vc4_commit, cb); - - vc4_atomic_complete_commit(c); } -static struct vc4_commit *commit_init(struct drm_atomic_state *state) +static void commit_work(struct work_struct *work) { - struct vc4_commit *c = kzalloc(sizeof(*c), GFP_KERNEL); - - if (!c) - return NULL; - c->dev = state->dev; - c->state = state; - - return c; + struct drm_atomic_state *state = container_of(work, + struct drm_atomic_state, + commit_work); + vc4_atomic_complete_commit(state); } /** @@ -115,29 +94,19 @@ static int vc4_atomic_commit(struct drm_device *dev, { struct vc4_dev *vc4 = to_vc4_dev(dev); int ret; - int i; - uint64_t wait_seqno = 0; - struct vc4_commit *c; - struct drm_plane *plane; - struct drm_plane_state *new_state; - - c = commit_init(state); - if (!c) - return -ENOMEM; ret = drm_atomic_helper_setup_commit(state, nonblock); if (ret) return ret; + INIT_WORK(&state->commit_work, commit_work); + ret = down_interruptible(&vc4->async_modeset); - if (ret) { - kfree(c); + if (ret) return ret; - } ret = drm_atomic_helper_prepare_planes(dev, state); if (ret) { - kfree(c); up(&vc4->async_modeset); return ret; } @@ -146,22 +115,11 @@ static int vc4_atomic_commit(struct drm_device *dev, ret = drm_atomic_helper_wait_for_fences(dev, state, true); if (ret) { drm_atomic_helper_cleanup_planes(dev, state); - kfree(c); up(&vc4->async_modeset); return ret; } } - for_each_plane_in_state(state, plane, new_state, i) { - if ((plane->state->fb != new_state->fb) && new_state->fb) { - struct drm_gem_cma_object *cma_bo = - drm_fb_cma_get_gem_obj(new_state->fb, 0); - struct vc4_bo *bo = to_vc4_bo(&cma_bo->base); - - wait_seqno = max(bo->seqno, wait_seqno); - } - } - /* * This is the point of no return - everything below never fails except * when the hw goes bonghits. Which means we can commit the new state on @@ -187,13 +145,10 @@ static int vc4_atomic_commit(struct drm_device *dev, */ drm_atomic_state_get(state); - if (nonblock) { - vc4_queue_seqno_cb(dev, &c->cb, wait_seqno, - vc4_atomic_complete_commit_seqno_cb); - } else { - vc4_wait_for_seqno(dev, wait_seqno, ~0ull, false); - vc4_atomic_complete_commit(c); - } + if (nonblock) + queue_work(system_unbound_wq, &state->commit_work); + else + vc4_atomic_complete_commit(state); return 0; } -- cgit v1.2.3 From 55a0b9d70a6c571b7d4f2f7eecb451c73b2f94a0 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 21 Jun 2017 11:50:02 -0700 Subject: drm/vc4: Remove dead vc4_event_pending(). It is no longer used as of commit 34c8ea400ff6 ("drm/vc4: Mimic drm_atomic_helper_commit() behavior") Signed-off-by: Eric Anholt Link: http://patchwork.freedesktop.org/patch/msgid/20170621185002.28563-4-eric@anholt.net Acked-by: Daniel Vetter Reviewed-by: Boris Brezillon --- drivers/gpu/drm/vc4/vc4_crtc.c | 8 -------- drivers/gpu/drm/vc4/vc4_drv.h | 1 - 2 files changed, 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 30a1df11e063..f20c01759c0d 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -674,14 +674,6 @@ static void vc4_disable_vblank(struct drm_crtc *crtc) CRTC_WRITE(PV_INTEN, 0); } -/* Must be called with the event lock held */ -bool vc4_event_pending(struct drm_crtc *crtc) -{ - struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); - - return !!vc4_crtc->event; -} - static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc) { struct drm_crtc *crtc = &vc4_crtc->base; diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index df22698d62ee..1047953216a8 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -491,7 +491,6 @@ int vc4_bo_stats_debugfs(struct seq_file *m, void *arg); /* vc4_crtc.c */ extern struct platform_driver vc4_crtc_driver; -bool vc4_event_pending(struct drm_crtc *crtc); int vc4_crtc_debugfs_regs(struct seq_file *m, void *arg); bool vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id, bool in_vblank_irq, int *vpos, int *hpos, -- cgit v1.2.3 From ae7c59f0e7daf337d8ae95ecb42ae586883c29f4 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Thu, 22 Jun 2017 07:03:10 +0200 Subject: drm: atmel-hlcdc: add missing .set_property helper to the crtc The default implementation should be used. Signed-off-by: Peter Rosin Signed-off-by: Boris Brezillon Link: http://patchwork.freedesktop.org/patch/msgid/1498107791-17450-2-git-send-email-peda@axentia.se --- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c index 53489859997b..cc00ce3bbaa5 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c @@ -429,6 +429,7 @@ static const struct drm_crtc_funcs atmel_hlcdc_crtc_funcs = { .atomic_destroy_state = atmel_hlcdc_crtc_destroy_state, .enable_vblank = atmel_hlcdc_crtc_enable_vblank, .disable_vblank = atmel_hlcdc_crtc_disable_vblank, + .set_property = drm_atomic_helper_crtc_set_property, }; int atmel_hlcdc_crtc_create(struct drm_device *dev) -- cgit v1.2.3 From 364a7bf574ebbd7c001a1c3f79816d0480062f80 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Thu, 22 Jun 2017 07:03:11 +0200 Subject: drm: atmel-hlcdc: add support for 8-bit color lookup table mode All layers of all supported chips support this, the only variable is the base address of the lookup table in the register map. Acked-by: Daniel Vetter Signed-off-by: Peter Rosin Signed-off-by: Boris Brezillon Link: http://patchwork.freedesktop.org/patch/msgid/1498107791-17450-3-git-send-email-peda@axentia.se --- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 5 +++++ drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 14 ++++++++++++ drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h | 16 ++++++++++++++ drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 29 +++++++++++++++++++++++++ 4 files changed, 64 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c index cc00ce3bbaa5..f6b8c5908a20 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c @@ -430,6 +430,7 @@ static const struct drm_crtc_funcs atmel_hlcdc_crtc_funcs = { .enable_vblank = atmel_hlcdc_crtc_enable_vblank, .disable_vblank = atmel_hlcdc_crtc_disable_vblank, .set_property = drm_atomic_helper_crtc_set_property, + .gamma_set = drm_atomic_helper_legacy_gamma_set, }; int atmel_hlcdc_crtc_create(struct drm_device *dev) @@ -485,6 +486,10 @@ int atmel_hlcdc_crtc_create(struct drm_device *dev) drm_crtc_helper_add(&crtc->base, &lcdc_crtc_helper_funcs); drm_crtc_vblank_reset(&crtc->base); + drm_mode_crtc_set_gamma_size(&crtc->base, ATMEL_HLCDC_CLUT_SIZE); + drm_crtc_enable_color_mgmt(&crtc->base, 0, false, + ATMEL_HLCDC_CLUT_SIZE); + dc->crtc = &crtc->base; return 0; diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c index 51d22ad9a3a3..516d9547d331 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c @@ -42,6 +42,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9n12_layers[] = { .default_color = 3, .general_config = 4, }, + .clut_offset = 0x400, }, }; @@ -73,6 +74,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = { .disc_pos = 5, .disc_size = 6, }, + .clut_offset = 0x400, }, { .name = "overlay1", @@ -91,6 +93,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = { .chroma_key_mask = 8, .general_config = 9, }, + .clut_offset = 0x800, }, { .name = "high-end-overlay", @@ -112,6 +115,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = { .scaler_config = 13, .csc = 14, }, + .clut_offset = 0x1000, }, { .name = "cursor", @@ -131,6 +135,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = { .chroma_key_mask = 8, .general_config = 9, }, + .clut_offset = 0x1400, }, }; @@ -162,6 +167,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = { .disc_pos = 5, .disc_size = 6, }, + .clut_offset = 0x600, }, { .name = "overlay1", @@ -180,6 +186,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = { .chroma_key_mask = 8, .general_config = 9, }, + .clut_offset = 0xa00, }, { .name = "overlay2", @@ -198,6 +205,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = { .chroma_key_mask = 8, .general_config = 9, }, + .clut_offset = 0xe00, }, { .name = "high-end-overlay", @@ -223,6 +231,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = { }, .csc = 14, }, + .clut_offset = 0x1200, }, { .name = "cursor", @@ -244,6 +253,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = { .general_config = 9, .scaler_config = 13, }, + .clut_offset = 0x1600, }, }; @@ -275,6 +285,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d4_layers[] = { .disc_pos = 5, .disc_size = 6, }, + .clut_offset = 0x600, }, { .name = "overlay1", @@ -293,6 +304,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d4_layers[] = { .chroma_key_mask = 8, .general_config = 9, }, + .clut_offset = 0xa00, }, { .name = "overlay2", @@ -311,6 +323,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d4_layers[] = { .chroma_key_mask = 8, .general_config = 9, }, + .clut_offset = 0xe00, }, { .name = "high-end-overlay", @@ -336,6 +349,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d4_layers[] = { }, .csc = 14, }, + .clut_offset = 0x1200, }, }; diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h index b0596a84c1b8..4237b0446721 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h @@ -88,6 +88,11 @@ #define ATMEL_HLCDC_YUV422SWP BIT(17) #define ATMEL_HLCDC_DSCALEOPT BIT(20) +#define ATMEL_HLCDC_C1_MODE ATMEL_HLCDC_CLUT_MODE(0) +#define ATMEL_HLCDC_C2_MODE ATMEL_HLCDC_CLUT_MODE(1) +#define ATMEL_HLCDC_C4_MODE ATMEL_HLCDC_CLUT_MODE(2) +#define ATMEL_HLCDC_C8_MODE ATMEL_HLCDC_CLUT_MODE(3) + #define ATMEL_HLCDC_XRGB4444_MODE ATMEL_HLCDC_RGB_MODE(0) #define ATMEL_HLCDC_ARGB4444_MODE ATMEL_HLCDC_RGB_MODE(1) #define ATMEL_HLCDC_RGBA4444_MODE ATMEL_HLCDC_RGB_MODE(2) @@ -142,6 +147,8 @@ #define ATMEL_HLCDC_DMA_CHANNEL_DSCR_DONE BIT(2) #define ATMEL_HLCDC_DMA_CHANNEL_DSCR_OVERRUN BIT(3) +#define ATMEL_HLCDC_CLUT_SIZE 256 + #define ATMEL_HLCDC_MAX_LAYERS 6 /** @@ -259,6 +266,7 @@ struct atmel_hlcdc_layer_desc { int id; int regs_offset; int cfgs_offset; + int clut_offset; struct atmel_hlcdc_formats *formats; struct atmel_hlcdc_layer_cfg_layout layout; int max_width; @@ -414,6 +422,14 @@ static inline u32 atmel_hlcdc_layer_read_cfg(struct atmel_hlcdc_layer *layer, (cfgid * sizeof(u32))); } +static inline void atmel_hlcdc_layer_write_clut(struct atmel_hlcdc_layer *layer, + unsigned int c, u32 val) +{ + regmap_write(layer->regmap, + layer->desc->clut_offset + c * sizeof(u32), + val); +} + static inline void atmel_hlcdc_layer_init(struct atmel_hlcdc_layer *layer, const struct atmel_hlcdc_layer_desc *desc, struct regmap *regmap) diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c index 1124200bb280..b5bd9b005225 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c @@ -83,6 +83,7 @@ drm_plane_state_to_atmel_hlcdc_plane_state(struct drm_plane_state *s) #define SUBPIXEL_MASK 0xffff static uint32_t rgb_formats[] = { + DRM_FORMAT_C8, DRM_FORMAT_XRGB4444, DRM_FORMAT_ARGB4444, DRM_FORMAT_RGBA4444, @@ -100,6 +101,7 @@ struct atmel_hlcdc_formats atmel_hlcdc_plane_rgb_formats = { }; static uint32_t rgb_and_yuv_formats[] = { + DRM_FORMAT_C8, DRM_FORMAT_XRGB4444, DRM_FORMAT_ARGB4444, DRM_FORMAT_RGBA4444, @@ -128,6 +130,9 @@ struct atmel_hlcdc_formats atmel_hlcdc_plane_rgb_and_yuv_formats = { static int atmel_hlcdc_format_to_plane_mode(u32 format, u32 *mode) { switch (format) { + case DRM_FORMAT_C8: + *mode = ATMEL_HLCDC_C8_MODE; + break; case DRM_FORMAT_XRGB4444: *mode = ATMEL_HLCDC_XRGB4444_MODE; break; @@ -424,6 +429,29 @@ static void atmel_hlcdc_plane_update_format(struct atmel_hlcdc_plane *plane, ATMEL_HLCDC_LAYER_FORMAT_CFG, cfg); } +static void atmel_hlcdc_plane_update_clut(struct atmel_hlcdc_plane *plane) +{ + struct drm_crtc *crtc = plane->base.crtc; + struct drm_color_lut *lut; + int idx; + + if (!crtc || !crtc->state) + return; + + if (!crtc->state->color_mgmt_changed || !crtc->state->gamma_lut) + return; + + lut = (struct drm_color_lut *)crtc->state->gamma_lut->data; + + for (idx = 0; idx < ATMEL_HLCDC_CLUT_SIZE; idx++, lut++) { + u32 val = ((lut->red << 8) & 0xff0000) | + (lut->green & 0xff00) | + (lut->blue >> 8); + + atmel_hlcdc_layer_write_clut(&plane->layer, idx, val); + } +} + static void atmel_hlcdc_plane_update_buffers(struct atmel_hlcdc_plane *plane, struct atmel_hlcdc_plane_state *state) { @@ -768,6 +796,7 @@ static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p, atmel_hlcdc_plane_update_pos_and_size(plane, state); atmel_hlcdc_plane_update_general_settings(plane, state); atmel_hlcdc_plane_update_format(plane, state); + atmel_hlcdc_plane_update_clut(plane); atmel_hlcdc_plane_update_buffers(plane, state); atmel_hlcdc_plane_update_disc_area(plane, state); -- cgit v1.2.3 From 6445e394c54b61974491fccbf2e4fcd990d2fa8b Mon Sep 17 00:00:00 2001 From: Mark Yao Date: Thu, 22 Jun 2017 15:17:24 +0800 Subject: drm/rockchip: dw_hdmi: add RK3399 HDMI support RK3399 and RK3288 shared the same HDMI IP controller, only some light difference with GRF configure. Signed-off-by: Yakir Yang Signed-off-by: Mark Yao Acked-by: Rob Herring --- .../bindings/display/rockchip/dw_hdmi-rockchip.txt | 4 +- drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 67 ++++++++++++++++++---- 2 files changed, 59 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt b/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt index 046076c6b277..7039a15b0d04 100644 --- a/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt +++ b/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt @@ -11,7 +11,9 @@ following device-specific properties. Required properties: -- compatible: Shall contain "rockchip,rk3288-dw-hdmi". +- compatible: should be one of the following: + "rockchip,rk3288-dw-hdmi" + "rockchip,rk3399-dw-hdmi" - reg: See dw_hdmi.txt. - reg-io-width: See dw_hdmi.txt. Shall be 4. - interrupts: HDMI interrupt number diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index f8208489724e..e7bab14134da 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -20,13 +20,30 @@ #include "rockchip_drm_drv.h" #include "rockchip_drm_vop.h" -#define GRF_SOC_CON6 0x025c -#define HDMI_SEL_VOP_LIT (1 << 4) +#define RK3288_GRF_SOC_CON6 0x025C +#define RK3288_HDMI_LCDC_SEL BIT(4) +#define RK3399_GRF_SOC_CON20 0x6250 +#define RK3399_HDMI_LCDC_SEL BIT(6) + +#define HIWORD_UPDATE(val, mask) (val | (mask) << 16) + +/** + * struct rockchip_hdmi_chip_data - splite the grf setting of kind of chips + * @lcdsel_grf_reg: grf register offset of lcdc select + * @lcdsel_big: reg value of selecting vop big for HDMI + * @lcdsel_lit: reg value of selecting vop little for HDMI + */ +struct rockchip_hdmi_chip_data { + u32 lcdsel_grf_reg; + u32 lcdsel_big; + u32 lcdsel_lit; +}; struct rockchip_hdmi { struct device *dev; struct regmap *regmap; struct drm_encoder encoder; + const struct rockchip_hdmi_chip_data *chip_data; }; #define to_rockchip_hdmi(x) container_of(x, struct rockchip_hdmi, x) @@ -198,17 +215,20 @@ static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder) { struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); u32 val; - int mux; + int ret; - mux = drm_of_encoder_active_endpoint_id(hdmi->dev->of_node, encoder); - if (mux) - val = HDMI_SEL_VOP_LIT | (HDMI_SEL_VOP_LIT << 16); + ret = drm_of_encoder_active_endpoint_id(hdmi->dev->of_node, encoder); + if (ret) + val = hdmi->chip_data->lcdsel_lit; else - val = HDMI_SEL_VOP_LIT << 16; + val = hdmi->chip_data->lcdsel_big; + + ret = regmap_write(hdmi->regmap, hdmi->chip_data->lcdsel_grf_reg, val); + if (ret != 0) + dev_err(hdmi->dev, "Could not write to GRF: %d\n", ret); - regmap_write(hdmi->regmap, GRF_SOC_CON6, val); dev_dbg(hdmi->dev, "vop %s output to hdmi\n", - (mux) ? "LIT" : "BIG"); + ret ? "LIT" : "BIG"); } static int @@ -232,16 +252,40 @@ static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_fun .atomic_check = dw_hdmi_rockchip_encoder_atomic_check, }; -static const struct dw_hdmi_plat_data rockchip_hdmi_drv_data = { +static struct rockchip_hdmi_chip_data rk3288_chip_data = { + .lcdsel_grf_reg = RK3288_GRF_SOC_CON6, + .lcdsel_big = HIWORD_UPDATE(0, RK3288_HDMI_LCDC_SEL), + .lcdsel_lit = HIWORD_UPDATE(RK3288_HDMI_LCDC_SEL, RK3288_HDMI_LCDC_SEL), +}; + +static const struct dw_hdmi_plat_data rk3288_hdmi_drv_data = { + .mode_valid = dw_hdmi_rockchip_mode_valid, + .mpll_cfg = rockchip_mpll_cfg, + .cur_ctr = rockchip_cur_ctr, + .phy_config = rockchip_phy_config, + .phy_data = &rk3288_chip_data, +}; + +static struct rockchip_hdmi_chip_data rk3399_chip_data = { + .lcdsel_grf_reg = RK3399_GRF_SOC_CON20, + .lcdsel_big = HIWORD_UPDATE(0, RK3399_HDMI_LCDC_SEL), + .lcdsel_lit = HIWORD_UPDATE(RK3399_HDMI_LCDC_SEL, RK3399_HDMI_LCDC_SEL), +}; + +static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = { .mode_valid = dw_hdmi_rockchip_mode_valid, .mpll_cfg = rockchip_mpll_cfg, .cur_ctr = rockchip_cur_ctr, .phy_config = rockchip_phy_config, + .phy_data = &rk3399_chip_data, }; static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = { { .compatible = "rockchip,rk3288-dw-hdmi", - .data = &rockchip_hdmi_drv_data + .data = &rk3288_hdmi_drv_data + }, + { .compatible = "rockchip,rk3399-dw-hdmi", + .data = &rk3399_hdmi_drv_data }, {}, }; @@ -268,6 +312,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, match = of_match_node(dw_hdmi_rockchip_dt_ids, pdev->dev.of_node); plat_data = match->data; hdmi->dev = &pdev->dev; + hdmi->chip_data = plat_data->phy_data; encoder = &hdmi->encoder; encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node); -- cgit v1.2.3 From 5e3bc6d1ab48a20cbce3d59d42937bc977ec61cf Mon Sep 17 00:00:00 2001 From: Mark Yao Date: Fri, 9 Jun 2017 15:10:41 +0800 Subject: drm/rockchip: dw_hdmi: introduce the VPLL clock setting For RK3399 HDMI, there is an external clock need for HDMI PHY, and it should keep the same clock rate with VOP DCLK. VPLL have supported the clock for HDMI PHY, but there is no clock divider bewteen VPLL and HDMI PHY. So we need to set the VPLL rate manually in HDMI driver. Signed-off-by: Yakir Yang Signed-off-by: Mark Yao Acked-by: Rob Herring --- .../bindings/display/rockchip/dw_hdmi-rockchip.txt | 2 +- drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 25 +++++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt b/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt index 7039a15b0d04..122d4e8b879b 100644 --- a/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt +++ b/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt @@ -32,7 +32,7 @@ Optional properties I2C master controller. - clock-names: See dw_hdmi.txt. The "cec" clock is optional. - clock-names: May contain "cec" as defined in dw_hdmi.txt. - +- clock-names: May contain "vpll", external clock for some hdmi phy. Example: diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index e7bab14134da..c00d7e273e84 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -7,10 +7,12 @@ * (at your option) any later version. */ +#include +#include #include #include -#include #include + #include #include #include @@ -44,6 +46,7 @@ struct rockchip_hdmi { struct regmap *regmap; struct drm_encoder encoder; const struct rockchip_hdmi_chip_data *chip_data; + struct clk *vpll_clk; }; #define to_rockchip_hdmi(x) container_of(x, struct rockchip_hdmi, x) @@ -160,6 +163,7 @@ static const struct dw_hdmi_phy_config rockchip_phy_config[] = { static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) { struct device_node *np = hdmi->dev->of_node; + int ret; hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); if (IS_ERR(hdmi->regmap)) { @@ -167,6 +171,22 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) return PTR_ERR(hdmi->regmap); } + hdmi->vpll_clk = devm_clk_get(hdmi->dev, "vpll"); + if (PTR_ERR(hdmi->vpll_clk) == -ENOENT) { + hdmi->vpll_clk = NULL; + } else if (PTR_ERR(hdmi->vpll_clk) == -EPROBE_DEFER) { + return -EPROBE_DEFER; + } else if (IS_ERR(hdmi->vpll_clk)) { + dev_err(hdmi->dev, "failed to get grf clock\n"); + return PTR_ERR(hdmi->vpll_clk); + } + + ret = clk_prepare_enable(hdmi->vpll_clk); + if (ret) { + dev_err(hdmi->dev, "Failed to enable HDMI vpll: %d\n", ret); + return ret; + } + return 0; } @@ -209,6 +229,9 @@ static void dw_hdmi_rockchip_encoder_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adj_mode) { + struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); + + clk_set_rate(hdmi->vpll_clk, adj_mode->clock * 1000); } static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder) -- cgit v1.2.3 From 8814b40bf6b2293eede832d35957b4e9ba495ae3 Mon Sep 17 00:00:00 2001 From: Mark Yao Date: Fri, 9 Jun 2017 15:10:46 +0800 Subject: drm/rockchip: dw_hdmi: introduce the pclk for grf For RK3399's GRF module, if we want to operate the graphic related grf registers, we need to enable the pclk_vio_grf which supply power for VIO GRF IOs, so it's better to introduce an optional grf clock in driver. Signed-off-by: Yakir Yang Signed-off-by: Mark Yao Acked-by: Rob Herring --- .../bindings/display/rockchip/dw_hdmi-rockchip.txt | 1 + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt b/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt index 122d4e8b879b..fad8b7619647 100644 --- a/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt +++ b/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt @@ -32,6 +32,7 @@ Optional properties I2C master controller. - clock-names: See dw_hdmi.txt. The "cec" clock is optional. - clock-names: May contain "cec" as defined in dw_hdmi.txt. +- clock-names: May contain "grf", power for grf io. - clock-names: May contain "vpll", external clock for some hdmi phy. Example: diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index c00d7e273e84..ccd5d595ada7 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -47,6 +47,7 @@ struct rockchip_hdmi { struct drm_encoder encoder; const struct rockchip_hdmi_chip_data *chip_data; struct clk *vpll_clk; + struct clk *grf_clk; }; #define to_rockchip_hdmi(x) container_of(x, struct rockchip_hdmi, x) @@ -181,6 +182,16 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) return PTR_ERR(hdmi->vpll_clk); } + hdmi->grf_clk = devm_clk_get(hdmi->dev, "grf"); + if (PTR_ERR(hdmi->grf_clk) == -ENOENT) { + hdmi->grf_clk = NULL; + } else if (PTR_ERR(hdmi->grf_clk) == -EPROBE_DEFER) { + return -EPROBE_DEFER; + } else if (IS_ERR(hdmi->grf_clk)) { + dev_err(hdmi->dev, "failed to get grf clock\n"); + return PTR_ERR(hdmi->grf_clk); + } + ret = clk_prepare_enable(hdmi->vpll_clk); if (ret) { dev_err(hdmi->dev, "Failed to enable HDMI vpll: %d\n", ret); @@ -246,10 +257,17 @@ static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder) else val = hdmi->chip_data->lcdsel_big; + ret = clk_prepare_enable(hdmi->grf_clk); + if (ret < 0) { + dev_err(hdmi->dev, "failed to enable grfclk %d\n", ret); + return; + } + ret = regmap_write(hdmi->regmap, hdmi->chip_data->lcdsel_grf_reg, val); if (ret != 0) dev_err(hdmi->dev, "Could not write to GRF: %d\n", ret); + clk_disable_unprepare(hdmi->grf_clk); dev_dbg(hdmi->dev, "vop %s output to hdmi\n", ret ? "LIT" : "BIG"); } -- cgit v1.2.3 From 6545135a5ed2eac064f23bee3a19a81cfffbe573 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 20 Jun 2017 13:39:14 +0200 Subject: drm/qxl: fix __user annotations Drop them from u64 fields, tag local variables correctly instead. While being at it switch the code to use u64_to_user_ptr(). Signed-off-by: Gerd Hoffmann Acked-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170620113916.6967-2-kraxel@redhat.com --- drivers/gpu/drm/qxl/qxl_ioctl.c | 17 +++++++++-------- include/uapi/drm/qxl_drm.h | 6 +++--- 2 files changed, 12 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/qxl/qxl_ioctl.c b/drivers/gpu/drm/qxl/qxl_ioctl.c index 0b82a87916ae..31effed4a3c8 100644 --- a/drivers/gpu/drm/qxl/qxl_ioctl.c +++ b/drivers/gpu/drm/qxl/qxl_ioctl.c @@ -163,7 +163,7 @@ static int qxl_process_single_command(struct qxl_device *qdev, return -EINVAL; if (!access_ok(VERIFY_READ, - (void *)(unsigned long)cmd->command, + u64_to_user_ptr(cmd->command), cmd->command_size)) return -EFAULT; @@ -183,7 +183,9 @@ static int qxl_process_single_command(struct qxl_device *qdev, /* TODO copy slow path code from i915 */ fb_cmd = qxl_bo_kmap_atomic_page(qdev, cmd_bo, (release->release_offset & PAGE_SIZE)); - unwritten = __copy_from_user_inatomic_nocache(fb_cmd + sizeof(union qxl_release_info) + (release->release_offset & ~PAGE_SIZE), (void *)(unsigned long)cmd->command, cmd->command_size); + unwritten = __copy_from_user_inatomic_nocache + (fb_cmd + sizeof(union qxl_release_info) + (release->release_offset & ~PAGE_SIZE), + u64_to_user_ptr(cmd->command), cmd->command_size); { struct qxl_drawable *draw = fb_cmd; @@ -201,10 +203,9 @@ static int qxl_process_single_command(struct qxl_device *qdev, num_relocs = 0; for (i = 0; i < cmd->relocs_num; ++i) { struct drm_qxl_reloc reloc; + struct drm_qxl_reloc __user *u = u64_to_user_ptr(cmd->relocs); - if (copy_from_user(&reloc, - &((struct drm_qxl_reloc *)(uintptr_t)cmd->relocs)[i], - sizeof(reloc))) { + if (copy_from_user(&reloc, u + i, sizeof(reloc))) { ret = -EFAULT; goto out_free_bos; } @@ -282,10 +283,10 @@ static int qxl_execbuffer_ioctl(struct drm_device *dev, void *data, for (cmd_num = 0; cmd_num < execbuffer->commands_num; ++cmd_num) { - struct drm_qxl_command *commands = - (struct drm_qxl_command *)(uintptr_t)execbuffer->commands; + struct drm_qxl_command __user *commands = + u64_to_user_ptr(execbuffer->commands); - if (copy_from_user(&user_cmd, &commands[cmd_num], + if (copy_from_user(&user_cmd, commands + cmd_num, sizeof(user_cmd))) return -EFAULT; diff --git a/include/uapi/drm/qxl_drm.h b/include/uapi/drm/qxl_drm.h index 7eef42213051..880999d2d863 100644 --- a/include/uapi/drm/qxl_drm.h +++ b/include/uapi/drm/qxl_drm.h @@ -80,8 +80,8 @@ struct drm_qxl_reloc { }; struct drm_qxl_command { - __u64 __user command; /* void* */ - __u64 __user relocs; /* struct drm_qxl_reloc* */ + __u64 command; /* void* */ + __u64 relocs; /* struct drm_qxl_reloc* */ __u32 type; __u32 command_size; __u32 relocs_num; @@ -91,7 +91,7 @@ struct drm_qxl_command { struct drm_qxl_execbuffer { __u32 flags; /* for future use */ __u32 commands_num; - __u64 __user commands; /* struct drm_qxl_command* */ + __u64 commands; /* struct drm_qxl_command* */ }; struct drm_qxl_update_area { -- cgit v1.2.3 From 45dfe57771b141c41d5b609b0a0aaf7f4ddb8942 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 20 Jun 2017 13:39:15 +0200 Subject: drm/qxl: declare a bunch of functions as static Flagged by sparse. Signed-off-by: Gerd Hoffmann Acked-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170620113916.6967-3-kraxel@redhat.com --- drivers/gpu/drm/qxl/qxl_display.c | 18 +++++++++--------- drivers/gpu/drm/qxl/qxl_object.c | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index f5ef81595f5a..0059ea42736d 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -437,7 +437,7 @@ static void qxl_monitors_config_set(struct qxl_device *qdev, } -void qxl_mode_set_nofb(struct drm_crtc *crtc) +static void qxl_mode_set_nofb(struct drm_crtc *crtc) { struct qxl_device *qdev = crtc->dev->dev_private; struct qxl_crtc *qcrtc = to_qxl_crtc(crtc); @@ -475,8 +475,8 @@ static const struct drm_crtc_helper_funcs qxl_crtc_helper_funcs = { .atomic_flush = qxl_crtc_atomic_flush, }; -int qxl_primary_atomic_check(struct drm_plane *plane, - struct drm_plane_state *state) +static int qxl_primary_atomic_check(struct drm_plane *plane, + struct drm_plane_state *state) { struct qxl_device *qdev = plane->dev->dev_private; struct qxl_framebuffer *qfb; @@ -547,8 +547,8 @@ static void qxl_primary_atomic_disable(struct drm_plane *plane, } } -int qxl_plane_atomic_check(struct drm_plane *plane, - struct drm_plane_state *state) +static int qxl_plane_atomic_check(struct drm_plane *plane, + struct drm_plane_state *state) { return 0; } @@ -647,8 +647,8 @@ out_free_release: } -void qxl_cursor_atomic_disable(struct drm_plane *plane, - struct drm_plane_state *old_state) +static void qxl_cursor_atomic_disable(struct drm_plane *plane, + struct drm_plane_state *old_state) { struct qxl_device *qdev = plane->dev->dev_private; struct qxl_release *release; @@ -675,8 +675,8 @@ void qxl_cursor_atomic_disable(struct drm_plane *plane, qxl_release_fence_buffer_objects(release); } -int qxl_plane_prepare_fb(struct drm_plane *plane, - struct drm_plane_state *new_state) +static int qxl_plane_prepare_fb(struct drm_plane *plane, + struct drm_plane_state *new_state) { struct drm_gem_object *obj; struct qxl_bo *user_bo; diff --git a/drivers/gpu/drm/qxl/qxl_object.c b/drivers/gpu/drm/qxl/qxl_object.c index 9a7eef7dd604..0a67ddf19c3d 100644 --- a/drivers/gpu/drm/qxl/qxl_object.c +++ b/drivers/gpu/drm/qxl/qxl_object.c @@ -221,7 +221,7 @@ struct qxl_bo *qxl_bo_ref(struct qxl_bo *bo) return bo; } -int __qxl_bo_pin(struct qxl_bo *bo, u32 domain, u64 *gpu_addr) +static int __qxl_bo_pin(struct qxl_bo *bo, u32 domain, u64 *gpu_addr) { struct drm_device *ddev = bo->gem_base.dev; int r; @@ -244,7 +244,7 @@ int __qxl_bo_pin(struct qxl_bo *bo, u32 domain, u64 *gpu_addr) return r; } -int __qxl_bo_unpin(struct qxl_bo *bo) +static int __qxl_bo_unpin(struct qxl_bo *bo) { struct drm_device *ddev = bo->gem_base.dev; int r, i; -- cgit v1.2.3 From 747fddd4e85369630c212e04a78caf90e2ec8f48 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 20 Jun 2017 13:39:16 +0200 Subject: drm/qxl: move extern variable declaration header file Flagged by sparse. Signed-off-by: Gerd Hoffmann Acked-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170620113916.6967-4-kraxel@redhat.com --- drivers/gpu/drm/qxl/qxl_drv.c | 1 - drivers/gpu/drm/qxl/qxl_drv.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c index 15c97b16ee21..403e135895bf 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.c +++ b/drivers/gpu/drm/qxl/qxl_drv.c @@ -37,7 +37,6 @@ #include "qxl_drv.h" #include "qxl_object.h" -extern int qxl_max_ioctls; static const struct pci_device_id pciidlist[] = { { 0x1b36, 0x100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0 }, diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h index 3591d2330a09..3397a1907336 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.h +++ b/drivers/gpu/drm/qxl/qxl_drv.h @@ -64,6 +64,7 @@ extern int qxl_log_level; extern int qxl_num_crtc; +extern int qxl_max_ioctls; enum { QXL_INFO_LEVEL = 1, -- cgit v1.2.3 From 91e976777d4ad068ef61b005a192457a879c81dc Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 21 Jun 2017 10:28:38 +0200 Subject: drm/amd|radeon: Drop drm_vblank_cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both drivers shut down all crtc beforehand already, which will shut up any pending vblank (the only thing vblank_cleanup really does is disable the disable timer). Hence we don't need this here and can remove it. Cc: Alex Deucher Cc: Christian König Acked-by: Alex Deucher Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170621082850.13224-2-daniel.vetter@ffwll.ch --- drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c | 1 - drivers/gpu/drm/radeon/radeon_irq_kms.c | 1 - 2 files changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c index a6b7e367a860..4a15be658935 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c @@ -262,7 +262,6 @@ void amdgpu_irq_fini(struct amdgpu_device *adev) { unsigned i, j; - drm_vblank_cleanup(adev->ddev); if (adev->irq.installed) { drm_irq_uninstall(adev->ddev); adev->irq.installed = false; diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index 1b7528df7f7f..3efe07f3e3db 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c @@ -324,7 +324,6 @@ int radeon_irq_kms_init(struct radeon_device *rdev) */ void radeon_irq_kms_fini(struct radeon_device *rdev) { - drm_vblank_cleanup(rdev->ddev); if (rdev->irq.installed) { drm_irq_uninstall(rdev->ddev); rdev->irq.installed = false; -- cgit v1.2.3 From 8f6ece97da008f05fb01ab6964f58dedf860877e Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 21 Jun 2017 10:28:43 +0200 Subject: drm/mxsfb: Drop drm_vblank_cleanup Almost right but still racy, it's called before the interrupts are uninstalled. So let's just drop it. Cc: Marek Vasut Reviewed-by: Marek Vasut Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170621082850.13224-7-daniel.vetter@ffwll.ch --- drivers/gpu/drm/mxsfb/mxsfb_drv.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c index d1b9c34c7c00..1853557fef46 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c @@ -256,7 +256,6 @@ static void mxsfb_unload(struct drm_device *drm) drm_kms_helper_poll_fini(drm); drm_mode_config_cleanup(drm); - drm_vblank_cleanup(drm); pm_runtime_get_sync(drm->dev); drm_irq_uninstall(drm); -- cgit v1.2.3 From c03e53b030025e9243b6e5cb717ad143f3a442ce Mon Sep 17 00:00:00 2001 From: Puthikorn Voravootivat Date: Thu, 22 Jun 2017 12:03:37 -0700 Subject: drm/i915: Set PWM divider to match desired frequency in vbt Read desired PWM frequency from panel vbt and calculate the value for divider in DPCD address 0x724 and 0x728 to have as many bits as possible for PWM duty cyle for granularity of brightness adjustment while the frequency divisor is still within 25% of the desired value. Signed-off-by: Puthikorn Voravootivat Reviewed-by: Dhinakaran Pandiyan Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170622190339.142671-2-puthik@chromium.org --- drivers/gpu/drm/i915/intel_dp_aux_backlight.c | 98 ++++++++++++++++++++++++--- 1 file changed, 90 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/intel_dp_aux_backlight.c index 228ca06d9f0b..d2830ba3162e 100644 --- a/drivers/gpu/drm/i915/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/intel_dp_aux_backlight.c @@ -98,13 +98,87 @@ intel_dp_aux_set_backlight(const struct drm_connector_state *conn_state, u32 lev } } +/* + * Set PWM Frequency divider to match desired frequency in vbt. + * The PWM Frequency is calculated as 27Mhz / (F x P). + * - Where F = PWM Frequency Pre-Divider value programmed by field 7:0 of the + * EDP_BACKLIGHT_FREQ_SET register (DPCD Address 00728h) + * - Where P = 2^Pn, where Pn is the value programmed by field 4:0 of the + * EDP_PWMGEN_BIT_COUNT register (DPCD Address 00724h) + */ +static bool intel_dp_aux_set_pwm_freq(struct intel_connector *connector) +{ + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct intel_dp *intel_dp = enc_to_intel_dp(&connector->encoder->base); + int freq, fxp, fxp_min, fxp_max, fxp_actual, f = 1; + u8 pn, pn_min, pn_max; + + /* Find desired value of (F x P) + * Note that, if F x P is out of supported range, the maximum value or + * minimum value will applied automatically. So no need to check that. + */ + freq = dev_priv->vbt.backlight.pwm_freq_hz; + DRM_DEBUG_KMS("VBT defined backlight frequency %u Hz\n", freq); + if (!freq) { + DRM_DEBUG_KMS("Use panel default backlight frequency\n"); + return false; + } + + fxp = DIV_ROUND_CLOSEST(KHz(DP_EDP_BACKLIGHT_FREQ_BASE_KHZ), freq); + + /* Use highest possible value of Pn for more granularity of brightness + * adjustment while satifying the conditions below. + * - Pn is in the range of Pn_min and Pn_max + * - F is in the range of 1 and 255 + * - FxP is within 25% of desired value. + * Note: 25% is arbitrary value and may need some tweak. + */ + if (drm_dp_dpcd_readb(&intel_dp->aux, + DP_EDP_PWMGEN_BIT_COUNT_CAP_MIN, &pn_min) != 1) { + DRM_DEBUG_KMS("Failed to read pwmgen bit count cap min\n"); + return false; + } + if (drm_dp_dpcd_readb(&intel_dp->aux, + DP_EDP_PWMGEN_BIT_COUNT_CAP_MAX, &pn_max) != 1) { + DRM_DEBUG_KMS("Failed to read pwmgen bit count cap max\n"); + return false; + } + pn_min &= DP_EDP_PWMGEN_BIT_COUNT_MASK; + pn_max &= DP_EDP_PWMGEN_BIT_COUNT_MASK; + + fxp_min = DIV_ROUND_CLOSEST(fxp * 3, 4); + fxp_max = DIV_ROUND_CLOSEST(fxp * 5, 4); + if (fxp_min < (1 << pn_min) || (255 << pn_max) < fxp_max) { + DRM_DEBUG_KMS("VBT defined backlight frequency out of range\n"); + return false; + } + + for (pn = pn_max; pn >= pn_min; pn--) { + f = clamp(DIV_ROUND_CLOSEST(fxp, 1 << pn), 1, 255); + fxp_actual = f << pn; + if (fxp_min <= fxp_actual && fxp_actual <= fxp_max) + break; + } + + if (drm_dp_dpcd_writeb(&intel_dp->aux, + DP_EDP_PWMGEN_BIT_COUNT, pn) < 0) { + DRM_DEBUG_KMS("Failed to write aux pwmgen bit count\n"); + return false; + } + if (drm_dp_dpcd_writeb(&intel_dp->aux, + DP_EDP_BACKLIGHT_FREQ_SET, (u8) f) < 0) { + DRM_DEBUG_KMS("Failed to write aux backlight freq\n"); + return false; + } + return true; +} + static void intel_dp_aux_enable_backlight(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { struct intel_connector *connector = to_intel_connector(conn_state->connector); struct intel_dp *intel_dp = enc_to_intel_dp(&connector->encoder->base); - uint8_t dpcd_buf = 0; - uint8_t edp_backlight_mode = 0; + uint8_t dpcd_buf, new_dpcd_buf, edp_backlight_mode; if (drm_dp_dpcd_readb(&intel_dp->aux, DP_EDP_BACKLIGHT_MODE_SET_REGISTER, &dpcd_buf) != 1) { @@ -113,18 +187,15 @@ static void intel_dp_aux_enable_backlight(const struct intel_crtc_state *crtc_st return; } + new_dpcd_buf = dpcd_buf; edp_backlight_mode = dpcd_buf & DP_EDP_BACKLIGHT_CONTROL_MODE_MASK; switch (edp_backlight_mode) { case DP_EDP_BACKLIGHT_CONTROL_MODE_PWM: case DP_EDP_BACKLIGHT_CONTROL_MODE_PRESET: case DP_EDP_BACKLIGHT_CONTROL_MODE_PRODUCT: - dpcd_buf &= ~DP_EDP_BACKLIGHT_CONTROL_MODE_MASK; - dpcd_buf |= DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD; - if (drm_dp_dpcd_writeb(&intel_dp->aux, - DP_EDP_BACKLIGHT_MODE_SET_REGISTER, dpcd_buf) < 0) { - DRM_DEBUG_KMS("Failed to write aux backlight mode\n"); - } + new_dpcd_buf &= ~DP_EDP_BACKLIGHT_CONTROL_MODE_MASK; + new_dpcd_buf |= DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD; break; /* Do nothing when it is already DPCD mode */ @@ -133,6 +204,17 @@ static void intel_dp_aux_enable_backlight(const struct intel_crtc_state *crtc_st break; } + if (intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_FREQ_AUX_SET_CAP) + if (intel_dp_aux_set_pwm_freq(connector)) + new_dpcd_buf |= DP_EDP_BACKLIGHT_FREQ_AUX_SET_ENABLE; + + if (new_dpcd_buf != dpcd_buf) { + if (drm_dp_dpcd_writeb(&intel_dp->aux, + DP_EDP_BACKLIGHT_MODE_SET_REGISTER, new_dpcd_buf) < 0) { + DRM_DEBUG_KMS("Failed to write aux backlight mode\n"); + } + } + set_aux_backlight_enable(intel_dp, true); intel_dp_aux_set_backlight(conn_state, connector->panel.backlight.level); } -- cgit v1.2.3 From 560a758d39c616f83ac25ff6e0816a49ebe6401c Mon Sep 17 00:00:00 2001 From: Puthikorn Voravootivat Date: Thu, 22 Jun 2017 12:03:38 -0700 Subject: drm/i915: Add heuristic to determine better way to adjust brightness Add heuristic to decide that AUX or PWM pin should use for backlight brightness adjustment and modify i915 param description to have auto, force disable, and force enable. The heuristic to determine that using AUX pin is better than using PWM pin is that the panel support any of the feature list here. - Regional backlight brightness adjustment - Backlight PWM frequency set - More than 8 bits resolution of brightness level - Backlight enablement via AUX and not by BL_ENABLE pin Signed-off-by: Puthikorn Voravootivat Reviewed-by: Dhinakaran Pandiyan Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170622190339.142671-3-puthik@chromium.org --- drivers/gpu/drm/i915/i915_params.c | 7 +-- drivers/gpu/drm/i915/i915_params.h | 2 +- drivers/gpu/drm/i915/intel_dp_aux_backlight.c | 61 +++++++++++++++++++++++++-- 3 files changed, 63 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index 14e2c2e57f96..5b5ab15d191f 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -63,7 +63,7 @@ struct i915_params i915 __read_mostly = { .huc_firmware_path = NULL, .enable_dp_mst = true, .inject_load_failure = 0, - .enable_dpcd_backlight = false, + .enable_dpcd_backlight = -1, .enable_gvt = false, }; @@ -246,9 +246,10 @@ MODULE_PARM_DESC(enable_dp_mst, module_param_named_unsafe(inject_load_failure, i915.inject_load_failure, uint, 0400); MODULE_PARM_DESC(inject_load_failure, "Force an error after a number of failure check points (0:disabled (default), N:force failure at the Nth failure check point)"); -module_param_named(enable_dpcd_backlight, i915.enable_dpcd_backlight, bool, 0600); +module_param_named_unsafe(enable_dpcd_backlight, i915.enable_dpcd_backlight, int, 0600); MODULE_PARM_DESC(enable_dpcd_backlight, - "Enable support for DPCD backlight control (default:false)"); + "Enable support for DPCD backlight control " + "(-1:auto (default), 0:force disable, 1:force enabled if supported"); module_param_named(enable_gvt, i915.enable_gvt, bool, 0400); MODULE_PARM_DESC(enable_gvt, diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index febbfdbd30bd..0d6cf9138dc4 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h @@ -53,6 +53,7 @@ func(int, edp_vswing); \ func(int, reset); \ func(unsigned int, inject_load_failure); \ + func(int, enable_dpcd_backlight); \ /* leave bools at the end to not create holes */ \ func(bool, alpha_support); \ func(bool, enable_cmd_parser); \ @@ -66,7 +67,6 @@ func(bool, verbose_state_checks); \ func(bool, nuclear_pageflip); \ func(bool, enable_dp_mst); \ - func(bool, enable_dpcd_backlight); \ func(bool, enable_gvt) #define MEMBER(T, member) T member diff --git a/drivers/gpu/drm/i915/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/intel_dp_aux_backlight.c index d2830ba3162e..fea161727c6e 100644 --- a/drivers/gpu/drm/i915/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/intel_dp_aux_backlight.c @@ -251,15 +251,66 @@ intel_dp_aux_display_control_capable(struct intel_connector *connector) /* Check the eDP Display control capabilities registers to determine if * the panel can support backlight control over the aux channel */ - if (intel_dp->edp_dpcd[1] & DP_EDP_TCON_BACKLIGHT_ADJUSTMENT_CAP && - (intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP) && - !(intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_PWM_PIN_CAP)) { + if ((intel_dp->edp_dpcd[1] & DP_EDP_TCON_BACKLIGHT_ADJUSTMENT_CAP) && + (intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP)) { DRM_DEBUG_KMS("AUX Backlight Control Supported!\n"); return true; } return false; } +/* + * Heuristic function whether we should use AUX for backlight adjustment or not. + * + * We should use AUX for backlight brightness adjustment if panel doesn't this + * via PWM pin or using AUX is better than using PWM pin. + * + * The heuristic to determine that using AUX pin is better than using PWM pin is + * that the panel support any of the feature list here. + * - Regional backlight brightness adjustment + * - Backlight PWM frequency set + * - More than 8 bits resolution of brightness level + * - Backlight enablement via AUX and not by BL_ENABLE pin + * + * If all above are not true, assume that using PWM pin is better. + */ +static bool +intel_dp_aux_display_control_heuristic(struct intel_connector *connector) +{ + struct intel_dp *intel_dp = enc_to_intel_dp(&connector->encoder->base); + uint8_t reg_val; + + /* Panel doesn't support adjusting backlight brightness via PWN pin */ + if (!(intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_PWM_PIN_CAP)) + return true; + + /* Panel supports regional backlight brightness adjustment */ + if (drm_dp_dpcd_readb(&intel_dp->aux, DP_EDP_GENERAL_CAP_3, + ®_val) != 1) { + DRM_DEBUG_KMS("Failed to read DPCD register 0x%x\n", + DP_EDP_GENERAL_CAP_3); + return false; + } + if (reg_val > 0) + return true; + + /* Panel supports backlight PWM frequency set */ + if (intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_FREQ_AUX_SET_CAP) + return true; + + /* Panel supports more than 8 bits resolution of brightness level */ + if (intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_BYTE_COUNT) + return true; + + /* Panel supports enabling backlight via AUX but not by BL_ENABLE pin */ + if ((intel_dp->edp_dpcd[1] & DP_EDP_BACKLIGHT_AUX_ENABLE_CAP) && + !(intel_dp->edp_dpcd[1] & DP_EDP_BACKLIGHT_PIN_ENABLE_CAP)) + return true; + + return false; + +} + int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector) { struct intel_panel *panel = &intel_connector->panel; @@ -270,6 +321,10 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector) if (!intel_dp_aux_display_control_capable(intel_connector)) return -ENODEV; + if (i915.enable_dpcd_backlight == -1 && + !intel_dp_aux_display_control_heuristic(intel_connector)) + return -ENODEV; + panel->backlight.setup = intel_dp_aux_setup_backlight; panel->backlight.enable = intel_dp_aux_enable_backlight; panel->backlight.disable = intel_dp_aux_disable_backlight; -- cgit v1.2.3 From ae25eceab616d16a07bcaa434b84463d58a3bdc3 Mon Sep 17 00:00:00 2001 From: Puthikorn Voravootivat Date: Thu, 22 Jun 2017 12:03:39 -0700 Subject: drm/i915: Add option to support dynamic backlight via DPCD This patch adds option to enable dynamic backlight for eDP panel that supports this feature via DPCD register and set minimum / maximum brightness to 0% and 100% of the normal brightness. Signed-off-by: Puthikorn Voravootivat Reviewed-by: Dhinakaran Pandiyan Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170622190339.142671-4-puthik@chromium.org --- drivers/gpu/drm/i915/i915_params.c | 5 +++++ drivers/gpu/drm/i915/i915_params.h | 3 ++- drivers/gpu/drm/i915/intel_dp_aux_backlight.c | 26 ++++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index 5b5ab15d191f..88b9d3e6713a 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -65,6 +65,7 @@ struct i915_params i915 __read_mostly = { .inject_load_failure = 0, .enable_dpcd_backlight = -1, .enable_gvt = false, + .enable_dbc = true, }; module_param_named(modeset, i915.modeset, int, 0400); @@ -254,3 +255,7 @@ MODULE_PARM_DESC(enable_dpcd_backlight, module_param_named(enable_gvt, i915.enable_gvt, bool, 0400); MODULE_PARM_DESC(enable_gvt, "Enable support for Intel GVT-g graphics virtualization host support(default:false)"); + +module_param_named_unsafe(enable_dbc, i915.enable_dbc, bool, 0600); +MODULE_PARM_DESC(enable_dbc, + "Enable support for dynamic backlight control (default:true)"); diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index 0d6cf9138dc4..057e203e6bda 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h @@ -67,7 +67,8 @@ func(bool, verbose_state_checks); \ func(bool, nuclear_pageflip); \ func(bool, enable_dp_mst); \ - func(bool, enable_gvt) + func(bool, enable_gvt); \ + func(bool, enable_dbc) #define MEMBER(T, member) T member struct i915_params { diff --git a/drivers/gpu/drm/i915/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/intel_dp_aux_backlight.c index fea161727c6e..b25cd88fc1c5 100644 --- a/drivers/gpu/drm/i915/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/intel_dp_aux_backlight.c @@ -173,6 +173,24 @@ static bool intel_dp_aux_set_pwm_freq(struct intel_connector *connector) return true; } +/* +* Set minimum / maximum dynamic brightness percentage. This value is expressed +* as the percentage of normal brightness in 5% increments. +*/ +static bool +intel_dp_aux_set_dynamic_backlight_percent(struct intel_dp *intel_dp, + u32 min, u32 max) +{ + u8 dbc[] = { DIV_ROUND_CLOSEST(min, 5), DIV_ROUND_CLOSEST(max, 5) }; + + if (drm_dp_dpcd_write(&intel_dp->aux, DP_EDP_DBC_MINIMUM_BRIGHTNESS_SET, + dbc, sizeof(dbc)) < 0) { + DRM_DEBUG_KMS("Failed to write aux DBC brightness level\n"); + return false; + } + return true; +} + static void intel_dp_aux_enable_backlight(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { @@ -208,6 +226,14 @@ static void intel_dp_aux_enable_backlight(const struct intel_crtc_state *crtc_st if (intel_dp_aux_set_pwm_freq(connector)) new_dpcd_buf |= DP_EDP_BACKLIGHT_FREQ_AUX_SET_ENABLE; + if (i915.enable_dbc && + (intel_dp->edp_dpcd[2] & DP_EDP_DYNAMIC_BACKLIGHT_CAP)) { + if(intel_dp_aux_set_dynamic_backlight_percent(intel_dp, 0, 100)) { + new_dpcd_buf |= DP_EDP_DYNAMIC_BACKLIGHT_ENABLE; + DRM_DEBUG_KMS("Enable dynamic brightness.\n"); + } + } + if (new_dpcd_buf != dpcd_buf) { if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_EDP_BACKLIGHT_MODE_SET_REGISTER, new_dpcd_buf) < 0) { -- cgit v1.2.3 From 2bf5ccc25c5bc3c8eaf30c589f7d3a5e7490d3b9 Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Fri, 23 Jun 2017 17:54:18 +0800 Subject: drm: arcpgu: arc_pgu_crtc_mode_valid() can be static Signed-off-by: Fengguang Wu Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170623095418.GA68865@lkp-sbx04 --- drivers/gpu/drm/arc/arcpgu_crtc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c index 99fbdaecf100..611af74a31c0 100644 --- a/drivers/gpu/drm/arc/arcpgu_crtc.c +++ b/drivers/gpu/drm/arc/arcpgu_crtc.c @@ -64,8 +64,8 @@ static const struct drm_crtc_funcs arc_pgu_crtc_funcs = { .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, }; -enum drm_mode_status arc_pgu_crtc_mode_valid(struct drm_crtc *crtc, - const struct drm_display_mode *mode) +static enum drm_mode_status arc_pgu_crtc_mode_valid(struct drm_crtc *crtc, + const struct drm_display_mode *mode) { struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc); long rate, clk_rate = mode->clock * 1000; -- cgit v1.2.3 From 71bb23c707c141b176bc084179ca5ee58d5fd26a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 22 Jun 2017 14:46:17 +0100 Subject: drm/vgem: Pin our pages for dmabuf exports When the caller maps their dmabuf and we return an sg_table, the caller doesn't expect the pages beneath that sg_table to vanish on a whim (i.e. under mempressure). The contract is that the pages are pinned for the duration of the mapping (from dma_buf_map_attachment() to dma_buf_unmap_attachment). To comply, we need to introduce our own vgem_object.pages_pin_count and elevate it across the mapping. However, the drm_prime interface we use calls drv->prime_pin on dma_buf_attach and drv->prime_unpin on dma_buf_detach, which while that does cover the mapping is much broader than is desired -- but it will do for now. v2: also hold the pin across prime_vmap/vunmap Reported-by: Tomi Sarvela Testcase: igt/gem_concurrent_blit/*swap*vgem* Fixes: 5ba6c9ff961a ("drm/vgem: Fix mmaping") Signed-off-by: Chris Wilson Cc: Tomi Sarvela Cc: Laura Abbott Cc: Sean Paul Cc: Matthew Auld Cc: Daniel Vetter Cc: # needs a backport Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170622134617.17912-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/vgem/vgem_drv.c | 81 ++++++++++++++++++++++++++++++----------- drivers/gpu/drm/vgem/vgem_drv.h | 4 ++ 2 files changed, 64 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vgem/vgem_drv.c b/drivers/gpu/drm/vgem/vgem_drv.c index 18f401b442c2..c938af8c40cf 100644 --- a/drivers/gpu/drm/vgem/vgem_drv.c +++ b/drivers/gpu/drm/vgem/vgem_drv.c @@ -52,6 +52,7 @@ static void vgem_gem_free_object(struct drm_gem_object *obj) struct drm_vgem_gem_object *vgem_obj = to_vgem_bo(obj); kvfree(vgem_obj->pages); + mutex_destroy(&vgem_obj->pages_lock); if (obj->import_attach) drm_prime_gem_destroy(obj, vgem_obj->table); @@ -76,11 +77,15 @@ static int vgem_gem_fault(struct vm_fault *vmf) if (page_offset > num_pages) return VM_FAULT_SIGBUS; + ret = -ENOENT; + mutex_lock(&obj->pages_lock); if (obj->pages) { get_page(obj->pages[page_offset]); vmf->page = obj->pages[page_offset]; ret = 0; - } else { + } + mutex_unlock(&obj->pages_lock); + if (ret) { struct page *page; page = shmem_read_mapping_page( @@ -161,6 +166,8 @@ static struct drm_vgem_gem_object *__vgem_gem_create(struct drm_device *dev, return ERR_PTR(ret); } + mutex_init(&obj->pages_lock); + return obj; } @@ -274,37 +281,66 @@ static const struct file_operations vgem_driver_fops = { .release = drm_release, }; +static struct page **vgem_pin_pages(struct drm_vgem_gem_object *bo) +{ + mutex_lock(&bo->pages_lock); + if (bo->pages_pin_count++ == 0) { + struct page **pages; + + pages = drm_gem_get_pages(&bo->base); + if (IS_ERR(pages)) { + bo->pages_pin_count--; + mutex_unlock(&bo->pages_lock); + return pages; + } + + bo->pages = pages; + } + mutex_unlock(&bo->pages_lock); + + return bo->pages; +} + +static void vgem_unpin_pages(struct drm_vgem_gem_object *bo) +{ + mutex_lock(&bo->pages_lock); + if (--bo->pages_pin_count == 0) { + drm_gem_put_pages(&bo->base, bo->pages, true, true); + bo->pages = NULL; + } + mutex_unlock(&bo->pages_lock); +} + static int vgem_prime_pin(struct drm_gem_object *obj) { + struct drm_vgem_gem_object *bo = to_vgem_bo(obj); long n_pages = obj->size >> PAGE_SHIFT; struct page **pages; - /* Flush the object from the CPU cache so that importers can rely - * on coherent indirect access via the exported dma-address. - */ - pages = drm_gem_get_pages(obj); + pages = vgem_pin_pages(bo); if (IS_ERR(pages)) return PTR_ERR(pages); + /* Flush the object from the CPU cache so that importers can rely + * on coherent indirect access via the exported dma-address. + */ drm_clflush_pages(pages, n_pages); - drm_gem_put_pages(obj, pages, true, false); return 0; } -static struct sg_table *vgem_prime_get_sg_table(struct drm_gem_object *obj) +static void vgem_prime_unpin(struct drm_gem_object *obj) { - struct sg_table *st; - struct page **pages; + struct drm_vgem_gem_object *bo = to_vgem_bo(obj); - pages = drm_gem_get_pages(obj); - if (IS_ERR(pages)) - return ERR_CAST(pages); + vgem_unpin_pages(bo); +} - st = drm_prime_pages_to_sg(pages, obj->size >> PAGE_SHIFT); - drm_gem_put_pages(obj, pages, false, false); +static struct sg_table *vgem_prime_get_sg_table(struct drm_gem_object *obj) +{ + struct drm_vgem_gem_object *bo = to_vgem_bo(obj); - return st; + return drm_prime_pages_to_sg(bo->pages, bo->base.size >> PAGE_SHIFT); } static struct drm_gem_object* vgem_prime_import(struct drm_device *dev, @@ -333,6 +369,8 @@ static struct drm_gem_object *vgem_prime_import_sg_table(struct drm_device *dev, __vgem_gem_destroy(obj); return ERR_PTR(-ENOMEM); } + + obj->pages_pin_count++; /* perma-pinned */ drm_prime_sg_to_page_addr_arrays(obj->table, obj->pages, NULL, npages); return &obj->base; @@ -340,23 +378,23 @@ static struct drm_gem_object *vgem_prime_import_sg_table(struct drm_device *dev, static void *vgem_prime_vmap(struct drm_gem_object *obj) { + struct drm_vgem_gem_object *bo = to_vgem_bo(obj); long n_pages = obj->size >> PAGE_SHIFT; struct page **pages; - void *addr; - pages = drm_gem_get_pages(obj); + pages = vgem_pin_pages(bo); if (IS_ERR(pages)) return NULL; - addr = vmap(pages, n_pages, 0, pgprot_writecombine(PAGE_KERNEL)); - drm_gem_put_pages(obj, pages, false, false); - - return addr; + return vmap(pages, n_pages, 0, pgprot_writecombine(PAGE_KERNEL)); } static void vgem_prime_vunmap(struct drm_gem_object *obj, void *vaddr) { + struct drm_vgem_gem_object *bo = to_vgem_bo(obj); + vunmap(vaddr); + vgem_unpin_pages(bo); } static int vgem_prime_mmap(struct drm_gem_object *obj, @@ -409,6 +447,7 @@ static struct drm_driver vgem_driver = { .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_pin = vgem_prime_pin, + .gem_prime_unpin = vgem_prime_unpin, .gem_prime_import = vgem_prime_import, .gem_prime_export = drm_gem_prime_export, .gem_prime_import_sg_table = vgem_prime_import_sg_table, diff --git a/drivers/gpu/drm/vgem/vgem_drv.h b/drivers/gpu/drm/vgem/vgem_drv.h index 1aae01419112..5c8f6d619ff3 100644 --- a/drivers/gpu/drm/vgem/vgem_drv.h +++ b/drivers/gpu/drm/vgem/vgem_drv.h @@ -43,7 +43,11 @@ struct vgem_file { #define to_vgem_bo(x) container_of(x, struct drm_vgem_gem_object, base) struct drm_vgem_gem_object { struct drm_gem_object base; + struct page **pages; + unsigned int pages_pin_count; + struct mutex pages_lock; + struct sg_table *table; }; -- cgit v1.2.3 From 36703e79a982c8ce5a8e43833291f2719e92d0d1 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 22 Jun 2017 11:56:25 +0100 Subject: drm/i915: Break modeset deadlocks on reset Trying to do a modeset from within a reset is fraught with danger. We can fall into a cyclic deadlock where the modeset is waiting on a previous modeset that is waiting on a request, and since the GPU hung that request completion is waiting on the reset. As modesetting doesn't allow its locks to be broken and restarted, or for its *own* reset mechanism to take over the display, we have to do something very evil instead. If we detect that we are stuck waiting to prepare the display reset (by using a very simple timeout), resort to cancelling all in-flight requests and throwing the user data into /dev/null, which is marginally better than the driver locking up and keeping that data to itself. This is not a fix; this is just a workaround that unbreaks machines until we can resolve the deadlock in a way that doesn't lose data! v2: Move the retirement from set-wegded to the i915_reset() error path, after which we no longer any delayed worker cleanup for i915_handle_error() v3: C abuse for syntactic sugar v4: Cover all waits with the timeout to catch more driver breakage References: https://bugs.freedesktop.org/show_bug.cgi?id=99093 Signed-off-by: Chris Wilson Cc: Maarten Lankhorst Cc: Mika Kuoppala Cc: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20170622105625.16952-1-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_drv.c | 1 + drivers/gpu/drm/i915/i915_gem.c | 18 +++------- drivers/gpu/drm/i915/i915_irq.c | 80 ++++++++++++++++++++++++++++++----------- 3 files changed, 65 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 370429e2071f..43e925933688 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1919,6 +1919,7 @@ wakeup: error: i915_gem_set_wedged(dev_priv); + i915_gem_retire_requests(dev_priv); goto finish; } diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index ae3ce1314bd1..36d838677982 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3062,7 +3062,8 @@ static void engine_set_wedged(struct intel_engine_cs *engine) /* Mark all executing requests as skipped */ spin_lock_irqsave(&engine->timeline->lock, flags); list_for_each_entry(request, &engine->timeline->requests, link) - dma_fence_set_error(&request->fence, -EIO); + if (!i915_gem_request_completed(request)) + dma_fence_set_error(&request->fence, -EIO); spin_unlock_irqrestore(&engine->timeline->lock, flags); /* Mark all pending requests as complete so that any concurrent @@ -3108,6 +3109,7 @@ static int __i915_gem_set_wedged_BKL(void *data) struct intel_engine_cs *engine; enum intel_engine_id id; + set_bit(I915_WEDGED, &i915->gpu_error.flags); for_each_engine(engine, i915, id) engine_set_wedged(engine); @@ -3116,20 +3118,7 @@ static int __i915_gem_set_wedged_BKL(void *data) void i915_gem_set_wedged(struct drm_i915_private *dev_priv) { - lockdep_assert_held(&dev_priv->drm.struct_mutex); - set_bit(I915_WEDGED, &dev_priv->gpu_error.flags); - - /* Retire completed requests first so the list of inflight/incomplete - * requests is accurate and we don't try and mark successful requests - * as in error during __i915_gem_set_wedged_BKL(). - */ - i915_gem_retire_requests(dev_priv); - stop_machine(__i915_gem_set_wedged_BKL, dev_priv, NULL); - - i915_gem_contexts_lost(dev_priv); - - mod_delayed_work(dev_priv->wq, &dev_priv->gt.idle_work, 0); } bool i915_gem_unset_wedged(struct drm_i915_private *i915) @@ -3184,6 +3173,7 @@ bool i915_gem_unset_wedged(struct drm_i915_private *i915) * context and do not require stop_machine(). */ intel_engines_reset_default_submission(i915); + i915_gem_contexts_lost(i915); smp_mb__before_atomic(); /* complete takeover before enabling execbuf */ clear_bit(I915_WEDGED, &i915->gpu_error.flags); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index f25e73fe567c..e4934d5adc9e 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2599,6 +2599,46 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) return ret; } +struct wedge_me { + struct delayed_work work; + struct drm_i915_private *i915; + const char *name; +}; + +static void wedge_me(struct work_struct *work) +{ + struct wedge_me *w = container_of(work, typeof(*w), work.work); + + dev_err(w->i915->drm.dev, + "%s timed out, cancelling all in-flight rendering.\n", + w->name); + i915_gem_set_wedged(w->i915); +} + +static void __init_wedge(struct wedge_me *w, + struct drm_i915_private *i915, + long timeout, + const char *name) +{ + w->i915 = i915; + w->name = name; + + INIT_DELAYED_WORK_ONSTACK(&w->work, wedge_me); + schedule_delayed_work(&w->work, timeout); +} + +static void __fini_wedge(struct wedge_me *w) +{ + cancel_delayed_work_sync(&w->work); + destroy_delayed_work_on_stack(&w->work); + w->i915 = NULL; +} + +#define i915_wedge_on_timeout(W, DEV, TIMEOUT) \ + for (__init_wedge((W), (DEV), (TIMEOUT), __func__); \ + (W)->i915; \ + __fini_wedge((W))) + /** * i915_reset_device - do process context error handling work * @dev_priv: i915 device private @@ -2612,36 +2652,36 @@ static void i915_reset_device(struct drm_i915_private *dev_priv) char *error_event[] = { I915_ERROR_UEVENT "=1", NULL }; char *reset_event[] = { I915_RESET_UEVENT "=1", NULL }; char *reset_done_event[] = { I915_ERROR_UEVENT "=0", NULL }; + struct wedge_me w; kobject_uevent_env(kobj, KOBJ_CHANGE, error_event); DRM_DEBUG_DRIVER("resetting chip\n"); kobject_uevent_env(kobj, KOBJ_CHANGE, reset_event); - intel_prepare_reset(dev_priv); + /* Use a watchdog to ensure that our reset completes */ + i915_wedge_on_timeout(&w, dev_priv, 5*HZ) { + intel_prepare_reset(dev_priv); - set_bit(I915_RESET_HANDOFF, &dev_priv->gpu_error.flags); - wake_up_all(&dev_priv->gpu_error.wait_queue); + /* Signal that locked waiters should reset the GPU */ + set_bit(I915_RESET_HANDOFF, &dev_priv->gpu_error.flags); + wake_up_all(&dev_priv->gpu_error.wait_queue); - do { - /* - * All state reset _must_ be completed before we update the - * reset counter, for otherwise waiters might miss the reset - * pending state and not properly drop locks, resulting in - * deadlocks with the reset work. + /* Wait for anyone holding the lock to wakeup, without + * blocking indefinitely on struct_mutex. */ - if (mutex_trylock(&dev_priv->drm.struct_mutex)) { - i915_reset(dev_priv); - mutex_unlock(&dev_priv->drm.struct_mutex); - } - - /* We need to wait for anyone holding the lock to wakeup */ - } while (wait_on_bit_timeout(&dev_priv->gpu_error.flags, - I915_RESET_HANDOFF, - TASK_UNINTERRUPTIBLE, - HZ)); + do { + if (mutex_trylock(&dev_priv->drm.struct_mutex)) { + i915_reset(dev_priv); + mutex_unlock(&dev_priv->drm.struct_mutex); + } + } while (wait_on_bit_timeout(&dev_priv->gpu_error.flags, + I915_RESET_HANDOFF, + TASK_UNINTERRUPTIBLE, + 1)); - intel_finish_reset(dev_priv); + intel_finish_reset(dev_priv); + } if (!test_bit(I915_WEDGED, &dev_priv->gpu_error.flags)) kobject_uevent_env(kobj, -- cgit v1.2.3 From a3507e48d3f99a93a3056a34a5365f310434570f Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Wed, 21 Jun 2017 01:46:37 +0900 Subject: iio: light: tsl2563: use correct event code The TSL2563 driver provides three iio channels, two of which are raw ADC channels (channel 0 and channel 1) in the device and the remaining one is calculated by the two. The ADC channel 0 only supports programmable interrupt with threshold settings and this driver supports the event but the generated event code does not contain the corresponding iio channel type. This is going to change userspace ABI. Hopefully fixing this to be what it should always have been won't break any userspace code. Cc: Jonathan Cameron Signed-off-by: Akinobu Mita Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/light/tsl2563.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/light/tsl2563.c b/drivers/iio/light/tsl2563.c index e7d4ea75e007..7599693f7fe9 100644 --- a/drivers/iio/light/tsl2563.c +++ b/drivers/iio/light/tsl2563.c @@ -626,7 +626,7 @@ static irqreturn_t tsl2563_event_handler(int irq, void *private) struct tsl2563_chip *chip = iio_priv(dev_info); iio_push_event(dev_info, - IIO_UNMOD_EVENT_CODE(IIO_LIGHT, + IIO_UNMOD_EVENT_CODE(IIO_INTENSITY, 0, IIO_EV_TYPE_THRESH, IIO_EV_DIR_EITHER), -- cgit v1.2.3 From add6e6ab3ee0e237822e0951476d3df039b49ec8 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 22 Jun 2017 19:46:43 +0200 Subject: iio: pressure: st_pressure_core: disable multiread by default for LPS22HB Set multiread variable to false for LPS22HB pressure sensor since it is already enabled in CTRL_REG2. Previous configuration does not cause any issue in I2C communication since SUB Msb has no meaning whereas it breaks register address in SPI communication Fixes: e039e2f5b4da (iio:st_pressure:initial lps22hb sensor support) Signed-off-by: Lorenzo Bianconi Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/st_pressure_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c index fd0edca0e656..99448012b47f 100644 --- a/drivers/iio/pressure/st_pressure_core.c +++ b/drivers/iio/pressure/st_pressure_core.c @@ -456,7 +456,7 @@ static const struct st_sensor_settings st_press_sensors_settings[] = { .mask_od = 0x40, .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, }, - .multi_read_bit = true, + .multi_read_bit = false, .bootime = 2, }, }; -- cgit v1.2.3 From b3df5e65cc03696b0624a877d03a3ddf3ef43f52 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 21 Jun 2017 10:28:39 +0200 Subject: drm/hibmc: Drop drm_vblank_cleanup So this seems to be the first driver that does it the right way round, so fix it up by calling drm_atomic_helper_shutdown instead. We need to do that before the last kms user is gone (fbdev emulation), but before we start shutting down hw stuff like interrupts. Cc: Xinliang Liu Cc: Rongrong Zou Cc: Xinwei Kong Cc: Chen Feng Reviewed-by: Sean Paul Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170621082850.13224-3-daniel.vetter@ffwll.ch --- drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c index 2ffdbf9801bd..4d018ca98581 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c @@ -276,11 +276,12 @@ static int hibmc_unload(struct drm_device *dev) hibmc_fbdev_fini(priv); + drm_atomic_helper_shutdown(dev); + if (dev->irq_enabled) drm_irq_uninstall(dev); if (priv->msi_enabled) pci_disable_msi(dev->pdev); - drm_vblank_cleanup(dev); hibmc_kms_fini(priv); hibmc_mm_fini(priv); -- cgit v1.2.3 From 20db9a2a5a4cefdb41439c575dd74061354796b9 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 21 Jun 2017 10:28:40 +0200 Subject: drm/kirin: Drop drm_vblank_cleanup Again we probably want a drm_atomic_helper_shutdown somewhere, but that's a bit more analysis. Cc: Xinliang Liu Cc: Rongrong Zou Cc: Xinwei Kong Cc: Chen Feng Reviewed-by: Sean Paul Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170621082850.13224-4-daniel.vetter@ffwll.ch --- drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c index 9c903672f582..8065d6cb1d7f 100644 --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c @@ -41,7 +41,6 @@ static int kirin_drm_kms_cleanup(struct drm_device *dev) } #endif drm_kms_helper_poll_fini(dev); - drm_vblank_cleanup(dev); dc_ops->cleanup(to_platform_device(dev->dev)); drm_mode_config_cleanup(dev); devm_kfree(dev->dev, priv); -- cgit v1.2.3 From baf54385af7856eab151edb0822dc95e7f5c8b14 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 21 Jun 2017 10:28:41 +0200 Subject: drm/i915: Drop drm_vblank_cleanup On the load error path we can't have pending vblank interrupts, and on unload we already call drm_atomic_helper_shutdown beforehand! So all good to nuke it. Reviewed-by: Sean Paul Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170621082850.13224-5-daniel.vetter@ffwll.ch --- drivers/gpu/drm/i915/i915_drv.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 6033355d9469..8d583a2fbf46 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1264,7 +1264,7 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent) ret = i915_load_modeset_init(&dev_priv->drm); if (ret < 0) - goto out_cleanup_vblank; + goto out_cleanup_hw; i915_driver_register(dev_priv); @@ -1285,8 +1285,6 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent) return 0; -out_cleanup_vblank: - drm_vblank_cleanup(&dev_priv->drm); out_cleanup_hw: i915_driver_cleanup_hw(dev_priv); out_cleanup_mmio: @@ -1322,8 +1320,6 @@ void i915_driver_unload(struct drm_device *dev) i915_driver_unregister(dev_priv); - drm_vblank_cleanup(dev); - intel_modeset_cleanup(dev); /* -- cgit v1.2.3 From ed173e55c4948582b0d7800395875a5d4b9633fb Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 21 Jun 2017 10:28:42 +0200 Subject: drm/mtk: Drop drm_vblank_cleanup Seems entirely cargo-culted. Cc: CK Hu Cc: Philipp Zabel Reviewed-by: Sean Paul Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170621082850.13224-6-daniel.vetter@ffwll.ch Link: http://patchwork.freedesktop.org/patch/msgid/20170621082850.13224-7-daniel.vetter@ffwll.ch --- drivers/gpu/drm/mediatek/mtk_drm_drv.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index f6c8ec4c7dbc..56f802d0a51c 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -266,7 +266,6 @@ static void mtk_drm_kms_deinit(struct drm_device *drm) { drm_kms_helper_poll_fini(drm); - drm_vblank_cleanup(drm); component_unbind_all(drm->dev, drm); drm_mode_config_cleanup(drm); } -- cgit v1.2.3 From 0265ac99ede927277627c85ef2bca4940014f5c1 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 21 Jun 2017 10:28:44 +0200 Subject: drm/nouveau: Drop drm_vblank_cleanup nouveau_display_vblank_fini is called in the load error path (where it doesn't matter) and module unload (where vblanks have been shut down correctly already through drm_vblank_off), we can drop it. Cc: Ben Skeggs Cc: nouveau@lists.freedesktop.org Reviewed-by: Sean Paul Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170621082850.13224-8-daniel.vetter@ffwll.ch --- drivers/gpu/drm/nouveau/nouveau_display.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 6718c84fb862..0f3af939f5aa 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -159,8 +159,6 @@ nouveau_display_vblank_fini(struct drm_device *dev) { struct drm_crtc *crtc; - drm_vblank_cleanup(dev); - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); nvif_notify_fini(&nv_crtc->vblank); -- cgit v1.2.3 From 3f5857fc6284da371868c2216a96d6d392185b5e Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 21 Jun 2017 10:28:45 +0200 Subject: drm/rockchip: Drop drm_vblank_cleanup Either not relevant (in the load error paths) or done better already (in the unload code, by calling drm_atomic_helper_shutdown). Drop it. Cc: Mark Yao Reviewed-by: Sean Paul Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170621082850.13224-9-daniel.vetter@ffwll.ch --- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index c6b1b7f3a2a3..b9fbf4b1e8f0 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -177,7 +177,6 @@ err_fbdev_fini: rockchip_drm_fbdev_fini(drm_dev); err_kms_helper_poll_fini: drm_kms_helper_poll_fini(drm_dev); - drm_vblank_cleanup(drm_dev); err_unbind_all: component_unbind_all(dev, drm_dev); err_mode_config_cleanup: @@ -200,7 +199,6 @@ static void rockchip_drm_unbind(struct device *dev) drm_kms_helper_poll_fini(drm_dev); drm_atomic_helper_shutdown(drm_dev); - drm_vblank_cleanup(drm_dev); component_unbind_all(dev, drm_dev); drm_mode_config_cleanup(drm_dev); rockchip_iommu_cleanup(drm_dev); -- cgit v1.2.3 From 5cbdaccb0df9a57936ba3608e97433fc469954cb Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 21 Jun 2017 10:28:47 +0200 Subject: drm/udl: Drop drm_vblank_cleanup udl doesn't shut down the display, so stopping the vblank isn't going to do much good either. Just drop it. Cc: Dave Airlie Reviewed-by: Sean Paul Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170621082850.13224-11-daniel.vetter@ffwll.ch --- drivers/gpu/drm/udl/udl_main.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c index a9d93b871a15..0328b2c7b210 100644 --- a/drivers/gpu/drm/udl/udl_main.c +++ b/drivers/gpu/drm/udl/udl_main.c @@ -371,8 +371,6 @@ void udl_driver_unload(struct drm_device *dev) { struct udl_device *udl = dev->dev_private; - drm_vblank_cleanup(dev); - if (udl->urbs.count) udl_free_urb_list(dev); -- cgit v1.2.3 From 5f58e9742df3f1cdf1034a26569649f5f4fd776b Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 26 Jun 2017 18:19:48 +0200 Subject: drm/vmwgfx: Drop drm_vblank_cleanup Again stopping the vblank before uninstalling the irq handler is kinda the wrong way round, but the fb_off stuff should take care of disabling the dsiplay at least in most cases. So drop the drm_vblank_cleanup code since it's not really doing anything, it looks all cargo-culted. v2: Appease gcc better. v3: Simplify code (Sean Paul) Cc: Sinclair Yeh Cc: Thomas Hellstrom Reviewed-by: Sean Paul Reviewed-by: Thomas Hellstrom Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170626161949.25629-1-daniel.vetter@ffwll.ch --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 8 ++------ drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 2 -- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 4 ---- drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 9 --------- drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 27 +-------------------------- 5 files changed, 3 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index a8876b070168..5fab9edf359c 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1771,7 +1771,7 @@ int vmw_kms_init(struct vmw_private *dev_priv) int vmw_kms_close(struct vmw_private *dev_priv) { - int ret; + int ret = 0; /* * Docs says we should take the lock before calling this function @@ -1779,11 +1779,7 @@ int vmw_kms_close(struct vmw_private *dev_priv) * drm_encoder_cleanup which takes the lock we deadlock. */ drm_mode_config_cleanup(dev_priv->dev); - if (dev_priv->active_display_unit == vmw_du_screen_object) - ret = vmw_kms_sou_close_display(dev_priv); - else if (dev_priv->active_display_unit == vmw_du_screen_target) - ret = vmw_kms_stdu_close_display(dev_priv); - else + if (dev_priv->active_display_unit == vmw_du_legacy) ret = vmw_kms_ldu_close_display(dev_priv); return ret; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h index 13f2f1d2818a..f94b4ca38ab2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h @@ -405,7 +405,6 @@ int vmw_kms_update_proxy(struct vmw_resource *res, * Screen Objects display functions - vmwgfx_scrn.c */ int vmw_kms_sou_init_display(struct vmw_private *dev_priv); -int vmw_kms_sou_close_display(struct vmw_private *dev_priv); int vmw_kms_sou_do_surface_dirty(struct vmw_private *dev_priv, struct vmw_framebuffer *framebuffer, struct drm_clip_rect *clips, @@ -433,7 +432,6 @@ int vmw_kms_sou_readback(struct vmw_private *dev_priv, * Screen Target Display Unit functions - vmwgfx_stdu.c */ int vmw_kms_stdu_init_display(struct vmw_private *dev_priv); -int vmw_kms_stdu_close_display(struct vmw_private *dev_priv); int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv, struct vmw_framebuffer *framebuffer, struct drm_clip_rect *clips, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index d3987bcf53f8..449ed4fba0f2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -582,13 +582,9 @@ err_free: int vmw_kms_ldu_close_display(struct vmw_private *dev_priv) { - struct drm_device *dev = dev_priv->dev; - if (!dev_priv->ldu_priv) return -ENOSYS; - drm_vblank_cleanup(dev); - BUG_ON(!list_empty(&dev_priv->ldu_priv->active)); kfree(dev_priv->ldu_priv); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index 8d7dc9def7c2..3b917c9b0c21 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c @@ -746,15 +746,6 @@ int vmw_kms_sou_init_display(struct vmw_private *dev_priv) return 0; } -int vmw_kms_sou_close_display(struct vmw_private *dev_priv) -{ - struct drm_device *dev = dev_priv->dev; - - drm_vblank_cleanup(dev); - - return 0; -} - static int do_dmabuf_define_gmrfb(struct vmw_private *dev_priv, struct vmw_framebuffer *framebuffer) { diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c index bad31bdf09b6..b4d4074c0ae0 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c @@ -1634,36 +1634,11 @@ int vmw_kms_stdu_init_display(struct vmw_private *dev_priv) if (unlikely(ret != 0)) { DRM_ERROR("Failed to initialize STDU %d", i); - goto err_vblank_cleanup; + return ret; } } DRM_INFO("Screen Target Display device initialized\n"); - return 0; - -err_vblank_cleanup: - drm_vblank_cleanup(dev); - return ret; -} - - - -/** - * vmw_kms_stdu_close_display - Cleans up after vmw_kms_stdu_init_display - * - * @dev_priv: VMW DRM device - * - * Frees up any resources allocated by vmw_kms_stdu_init_display - * - * RETURNS: - * 0 on success - */ -int vmw_kms_stdu_close_display(struct vmw_private *dev_priv) -{ - struct drm_device *dev = dev_priv->dev; - - drm_vblank_cleanup(dev); - return 0; } -- cgit v1.2.3 From 770a17a5713af26d1490d4f669194ed959b88241 Mon Sep 17 00:00:00 2001 From: Manasi Navare Date: Mon, 26 Jun 2017 12:21:44 -0700 Subject: drm/i915/dp: Fix the t11_t12 panel power cycle delay from VBT read MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When we read the VBT t11_t12 value for panel power cycle delay, it is a zero based value so we need to 100ms to that. And then it needs to be multiplied by 10 to store it in 100usecs unit same as SW VBT. v3: * Add it as part of series v2: * Change the VBT value instead of HW readout and pp div (Ville Syrjala) Reviewed-by: Ville Syrjala Signed-off-by: Manasi Navare Cc: Ville Syrjala Cc: Clint Taylor Link: http://patchwork.freedesktop.org/patch/msgid/1498504905-21067-1-git-send-email-manasi.d.navare@intel.com Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_dp.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 2eb6e0ff143a..95ff5d678472 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -5259,6 +5259,11 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev, intel_pps_dump_state("cur", &cur); vbt = dev_priv->vbt.edp.pps; + /* T11_T12 delay is special and actually in units of 100ms, but zero + * based in the hw (so we need to add 100 ms). But the sw vbt + * table multiplies it with 1000 to make it in units of 100usec, + * too. */ + vbt.t11_t12 += 100 * 10; /* Upper limits from eDP 1.3 spec. Note that we use the clunky units of * our hw here, which are all in 100usec. */ -- cgit v1.2.3 From 12c8ca9cf9bf5d53918068b1ebbd17ac6ef1d2f3 Mon Sep 17 00:00:00 2001 From: Manasi Navare Date: Mon, 26 Jun 2017 12:21:45 -0700 Subject: drm/i915/dp: Remove -1/+1 from t11_t12 for Gen9_LP/CNP case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now the VBT.seq->t11_t12 value adds 100ms to both Gen9_LP as well as non Gen9_LP cases so no need to special case and do -1 during HW readout and +1 during pp_div write for Gen9_LP/CNP case. Reviewed-by: Ville Syrjala Signed-off-by: Manasi Navare Suggested-by: Ville Syrjala Cc: Ville Syrjala Cc: Clint Taylor Link: http://patchwork.freedesktop.org/patch/msgid/1498504905-21067-2-git-send-email-manasi.d.navare@intel.com Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_dp.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 95ff5d678472..0445d11224d4 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -5203,12 +5203,8 @@ intel_pps_readout_hw_state(struct drm_i915_private *dev_priv, PANEL_POWER_DOWN_DELAY_SHIFT; if (IS_GEN9_LP(dev_priv) || HAS_PCH_CNP(dev_priv)) { - u16 tmp = (pp_ctl & BXT_POWER_CYCLE_DELAY_MASK) >> - BXT_POWER_CYCLE_DELAY_SHIFT; - if (tmp > 0) - seq->t11_t12 = (tmp - 1) * 1000; - else - seq->t11_t12 = 0; + seq->t11_t12 = ((pp_ctl & BXT_POWER_CYCLE_DELAY_MASK) >> + BXT_POWER_CYCLE_DELAY_SHIFT) * 1000; } else { seq->t11_t12 = ((pp_div & PANEL_POWER_CYCLE_DELAY_MASK) >> PANEL_POWER_CYCLE_DELAY_SHIFT) * 1000; @@ -5367,7 +5363,7 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, if (IS_GEN9_LP(dev_priv) || HAS_PCH_CNP(dev_priv)) { pp_div = I915_READ(regs.pp_ctrl); pp_div &= ~BXT_POWER_CYCLE_DELAY_MASK; - pp_div |= (DIV_ROUND_UP((seq->t11_t12 + 1), 1000) + pp_div |= (DIV_ROUND_UP(seq->t11_t12, 1000) << BXT_POWER_CYCLE_DELAY_SHIFT); } else { pp_div = ((100 * div)/2 - 1) << PP_REFERENCE_DIVIDER_SHIFT; -- cgit v1.2.3 From 7141fd3e5ba90d09d2138ff1bbefd7cc43a82e94 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 21 Jun 2017 11:16:27 +0200 Subject: drm/atomic-helper: Simplify commit tracking locking The crtc->commit_lock only protects commit_list and commit_entry. If we chase the pointer from the drm_atomic_state update structure, then we don't need any locks (since we hold a reference already). Simplify the locking accordingly. Noticed while reviewing a patch from Boris. Cc: Boris Brezillon Reviewed-by: Sean Paul Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170621091627.30837-1-daniel.vetter@ffwll.ch --- drivers/gpu/drm/drm_atomic_helper.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 45b4f34bebcd..c4e4e8b5caeb 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1715,9 +1715,7 @@ void drm_atomic_helper_commit_hw_done(struct drm_atomic_state *old_state) /* backend must have consumed any event by now */ WARN_ON(new_crtc_state->event); - spin_lock(&crtc->commit_lock); complete_all(&commit->hw_done); - spin_unlock(&crtc->commit_lock); } } EXPORT_SYMBOL(drm_atomic_helper_commit_hw_done); @@ -1746,7 +1744,6 @@ void drm_atomic_helper_commit_cleanup_done(struct drm_atomic_state *old_state) if (WARN_ON(!commit)) continue; - spin_lock(&crtc->commit_lock); complete_all(&commit->cleanup_done); WARN_ON(!try_wait_for_completion(&commit->hw_done)); @@ -1756,8 +1753,6 @@ void drm_atomic_helper_commit_cleanup_done(struct drm_atomic_state *old_state) if (try_wait_for_completion(&commit->flip_done)) goto del_commit; - spin_unlock(&crtc->commit_lock); - /* We must wait for the vblank event to signal our completion * before releasing our reference, since the vblank work does * not hold a reference of its own. */ @@ -1767,8 +1762,8 @@ void drm_atomic_helper_commit_cleanup_done(struct drm_atomic_state *old_state) DRM_ERROR("[CRTC:%d:%s] flip_done timed out\n", crtc->base.id, crtc->name); - spin_lock(&crtc->commit_lock); del_commit: + spin_lock(&crtc->commit_lock); list_del(&commit->commit_entry); spin_unlock(&crtc->commit_lock); } -- cgit v1.2.3 From e38c2da01f76cca82b59ca612529b81df82a7cc7 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 26 Jun 2017 23:30:51 +0300 Subject: drm/i915: Disable MSI for all pre-gen5 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have pretty clear evidence that MSIs are getting lost on g4x and somehow the interrupt logic doesn't seem to recover from that state even if we try hard to clear the IIR. Disabling IER around the normal IIR clearing in the irq handler isn't sufficient to avoid this, so the problem really seems to be further up the interrupt chain. This should guarantee that there's always an edge if any IIR bits are set after the interrupt handler is done, which should normally guarantee that the CPU interrupt is generated. That approach seems to work perfectly on VLV/CHV, but apparently not on g4x. MSI is documented to be broken on 965gm at least. The chipset spec says MSI is defeatured because interrupts can be delayed or lost, which fits well with what we're seeing on g4x. Previously we've already disabled GMBUS interrupts on g4x because somehow GMBUS manages to raise legacy interrupts even when MSI is enabled. Since there's such widespread MSI breakahge all over in the pre-gen5 land let's just give up on MSI on these platforms. Seqno reporting might be negatively affected by this since the legcy interrupts aren't guaranteed to be ordered with the seqno writes, whereas MSI interrupts may be? But an occasioanlly missed seqno seems like a small price to pay for generally working interrupts. Cc: stable@vger.kernel.org Cc: Diego Viola Tested-by: Diego Viola Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=101261 Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/20170626203051.28480-1-ville.syrjala@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 43e925933688..a6bef9ee8703 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1141,10 +1141,12 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv) * and the registers being closely associated. * * According to chipset errata, on the 965GM, MSI interrupts may - * be lost or delayed, but we use them anyways to avoid - * stuck interrupts on some machines. + * be lost or delayed, and was defeatured. MSI interrupts seem to + * get lost on g4x as well, and interrupt delivery seems to stay + * properly dead afterwards. So we'll just disable them for all + * pre-gen5 chipsets. */ - if (!IS_I945G(dev_priv) && !IS_I945GM(dev_priv)) { + if (INTEL_GEN(dev_priv) >= 5) { if (pci_enable_msi(pdev) < 0) DRM_DEBUG_DRIVER("can't enable MSI"); } -- cgit v1.2.3 From 774eed4a408185d7a2cde16f40b1806d4fb1d531 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 23 Jun 2017 14:19:07 +0100 Subject: drm/i915/selftests: Fix mutex imbalance for igt_render_engine_reset_fallback Smatch spots: drivers/gpu/drm/i915/selftests/intel_hangcheck.c:669 igt_render_engine_reset_fallback() error: double unlock 'mutex:&i915->drm.struct_mutex' Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/20170623131907.24236-1-chris@chris-wilson.co.uk Reviewed-by: Michel Thierry --- drivers/gpu/drm/i915/selftests/intel_hangcheck.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c index af475189bd52..7096c3911cd3 100644 --- a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c +++ b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c @@ -597,12 +597,12 @@ static int igt_render_engine_reset_fallback(void *arg) err = hang_init(&h, i915); if (err) - goto unlock; + goto err_unlock; rq = hang_create_request(&h, engine, i915->kernel_context); if (IS_ERR(rq)) { err = PTR_ERR(rq); - goto fini; + goto err_fini; } i915_gem_request_get(rq); @@ -614,7 +614,7 @@ static int igt_render_engine_reset_fallback(void *arg) if (!wait_for_hang(&h, rq)) { pr_err("Failed to start request %x\n", rq->fence.seqno); err = -EIO; - goto out_rq; + goto err_request; } reset_engine_count = i915_reset_engine_count(&i915->gpu_error, engine); @@ -646,13 +646,14 @@ static int igt_render_engine_reset_fallback(void *arg) */ if (i915_terminally_wedged(&i915->gpu_error)) { set_bit(I915_RESET_BACKOFF, &i915->gpu_error.flags); - mutex_lock(&i915->drm.struct_mutex); rq->fence.error = 0; + mutex_lock(&i915->drm.struct_mutex); set_bit(I915_RESET_HANDOFF, &i915->gpu_error.flags); i915_reset(i915); GEM_BUG_ON(test_bit(I915_RESET_HANDOFF, &i915->gpu_error.flags)); + mutex_unlock(&i915->drm.struct_mutex); if (i915_reset_count(&i915->gpu_error) == reset_count) { pr_err("No full GPU reset recorded!\n"); @@ -663,10 +664,8 @@ static int igt_render_engine_reset_fallback(void *arg) out_rq: i915_gem_request_put(rq); -fini: hang_fini(&h); -unlock: - mutex_unlock(&i915->drm.struct_mutex); +out_backoff: clear_bit(I915_RESET_BACKOFF, &i915->gpu_error.flags); wake_up_all(&i915->gpu_error.reset_queue); @@ -674,6 +673,14 @@ unlock: return -EIO; return err; + +err_request: + i915_gem_request_put(rq); +err_fini: + hang_fini(&h); +err_unlock: + mutex_unlock(&i915->drm.struct_mutex); + goto out_backoff; } int intel_hangcheck_live_selftests(struct drm_i915_private *i915) -- cgit v1.2.3 From 7c3f5317b8c2828ab10e8cf87c8ab5232d1966d0 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Tue, 27 Jun 2017 07:38:54 +0200 Subject: drm/i915: Fix an error checking test 'dma_buf_vmap' returns NULL on error, not an error pointer. Fixes: 6cca22ede8a4 ("drm/i915: Add some mock tests for dmabuf interop") Signed-off-by: Christophe JAILLET Link: http://patchwork.freedesktop.org/patch/msgid/20170627053854.21152-1-christophe.jaillet@wanadoo.fr Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c index d15cc9d3a5cd..89dc25a5a53b 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c @@ -246,9 +246,9 @@ static int igt_dmabuf_export_vmap(void *arg) i915_gem_object_put(obj); ptr = dma_buf_vmap(dmabuf); - if (IS_ERR(ptr)) { - err = PTR_ERR(ptr); - pr_err("dma_buf_vmap failed with err=%d\n", err); + if (!ptr) { + pr_err("dma_buf_vmap failed\n"); + err = -ENOMEM; goto out; } -- cgit v1.2.3 From ceb26569af5bc33a8f47b755fd64f12c81801ce8 Mon Sep 17 00:00:00 2001 From: Sebastian Sanchez Date: Fri, 12 May 2017 09:19:36 -0700 Subject: IB/hfi1: Remove unnecessary initialization from tx request The tx request is unnecessarily initialized in the hot code path with memset(), however, there's no need to do this as most fields are initialized later on. this initialization shows to be costly in the profile. Remove unnecessary initialization from tx request and make sure all variables are initialized properly. Reviewed-by: Mike Marciniszyn Signed-off-by: Sebastian Sanchez Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/user_sdma.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/hfi1/user_sdma.c b/drivers/infiniband/hw/hfi1/user_sdma.c index d55339f5d73b..16fd519216dc 100644 --- a/drivers/infiniband/hw/hfi1/user_sdma.c +++ b/drivers/infiniband/hw/hfi1/user_sdma.c @@ -607,12 +607,19 @@ int hfi1_user_sdma_process_request(struct hfi1_filedata *fd, hfi1_cdbg(SDMA, "[%u:%u:%u] Using req/comp entry %u\n", dd->unit, uctxt->ctxt, fd->subctxt, info.comp_idx); req = pq->reqs + info.comp_idx; - memset(req, 0, sizeof(*req)); req->data_iovs = req_iovcnt(info.ctrl) - 1; /* subtract header vector */ + req->data_len = 0; req->pq = pq; req->cq = cq; req->status = -1; req->ahg_idx = -1; + req->iov_idx = 0; + req->sent = 0; + req->seqnum = 0; + req->seqcomp = 0; + req->seqsubmitted = 0; + req->flags = 0; + req->tids = NULL; INIT_LIST_HEAD(&req->txps); memcpy(&req->info, &info, sizeof(info)); @@ -701,12 +708,14 @@ int hfi1_user_sdma_process_request(struct hfi1_filedata *fd, /* Save all the IO vector structures */ for (i = 0; i < req->data_iovs; i++) { + req->iovs[i].offset = 0; INIT_LIST_HEAD(&req->iovs[i].list); memcpy(&req->iovs[i].iov, iovec + idx++, sizeof(req->iovs[i].iov)); ret = pin_vector_pages(req, &req->iovs[i]); if (ret) { + req->data_iovs = i; req->status = ret; goto free_req; } @@ -749,6 +758,7 @@ int hfi1_user_sdma_process_request(struct hfi1_filedata *fd, } req->tids = tmp; req->n_tids = ntids; + req->tididx = 0; idx++; } -- cgit v1.2.3 From aa560df381f7199fafa4e7f71382de28f0400270 Mon Sep 17 00:00:00 2001 From: Ira Weiny Date: Fri, 12 May 2017 09:19:47 -0700 Subject: IB/hfi1: Remove unused mk_qpn function Leftover function that is not used. Remove it. Reviewed-by: Dennis Dalessandro Signed-off-by: Ira Weiny Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/qp.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/hfi1/qp.c b/drivers/infiniband/hw/hfi1/qp.c index 650305cc0373..e91be05062e6 100644 --- a/drivers/infiniband/hw/hfi1/qp.c +++ b/drivers/infiniband/hw/hfi1/qp.c @@ -73,12 +73,6 @@ static void iowait_wakeup(struct iowait *wait, int reason); static void iowait_sdma_drained(struct iowait *wait); static void qp_pio_drain(struct rvt_qp *qp); -static inline unsigned mk_qpn(struct rvt_qpn_table *qpt, - struct rvt_qpn_map *map, unsigned off) -{ - return (map - qpt->map) * RVT_BITS_PER_PAGE + off; -} - const struct rvt_operation_params hfi1_post_parms[RVT_OPERATION_MAX] = { [IB_WR_RDMA_WRITE] = { .length = sizeof(struct ib_rdma_wr), -- cgit v1.2.3 From 7dafbab3753fcf59bc81748e5b2c5bf04e1c62c7 Mon Sep 17 00:00:00 2001 From: Don Hiatt Date: Fri, 12 May 2017 09:19:55 -0700 Subject: IB/hfi1: Add functions to parse BTH/IB headers Improve code readablity by adding inline functions to read specific BTH/IB fields without knowledge of byte offsets. Reviewed-by: Brian Welty Reviewed-by: Dasaratharaman Chandramouli Reviewed-by: Dennis Dalessandro Signed-off-by: Don Hiatt Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/driver.c | 6 +-- drivers/infiniband/hw/hfi1/rc.c | 8 ++-- drivers/infiniband/hw/hfi1/uc.c | 2 +- drivers/infiniband/hw/hfi1/ud.c | 6 +-- drivers/infiniband/hw/hfi1/verbs.c | 6 +-- include/rdma/ib_hdrs.h | 84 +++++++++++++++++++++++++++++++++++++ include/rdma/ib_verbs.h | 2 + include/rdma/rdmavt_qp.h | 2 +- 8 files changed, 101 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/hfi1/driver.c b/drivers/infiniband/hw/hfi1/driver.c index a50870e455a3..0583479f2576 100644 --- a/drivers/infiniband/hw/hfi1/driver.c +++ b/drivers/infiniband/hw/hfi1/driver.c @@ -286,7 +286,7 @@ static void rcv_hdrerr(struct hfi1_ctxtdata *rcd, struct hfi1_pportdata *ppd, goto drop; } /* Get the destination QP number. */ - qp_num = be32_to_cpu(ohdr->bth[1]) & RVT_QPN_MASK; + qp_num = ib_bth_get_qpn(ohdr); if (lid < be16_to_cpu(IB_MULTICAST_LID_BASE)) { struct rvt_qp *qp; unsigned long flags; @@ -438,7 +438,7 @@ void hfi1_process_ecn_slowpath(struct rvt_qp *qp, struct hfi1_packet *pkt, case IB_QPT_GSI: case IB_QPT_UD: rlid = ib_get_slid(hdr); - rqpn = be32_to_cpu(ohdr->u.ud.deth[1]) & RVT_QPN_MASK; + rqpn = ib_get_sqpn(ohdr); svc_type = IB_CC_SVCTYPE_UD; is_mcast = (dlid > be16_to_cpu(IB_MULTICAST_LID_BASE)) && (dlid != be16_to_cpu(IB_LID_PERMISSIVE)); @@ -461,7 +461,7 @@ void hfi1_process_ecn_slowpath(struct rvt_qp *qp, struct hfi1_packet *pkt, bth1 = be32_to_cpu(ohdr->bth[1]); if (do_cnp && (bth1 & IB_FECN_SMASK)) { - u16 pkey = (u16)be32_to_cpu(ohdr->bth[0]); + u16 pkey = ib_bth_get_pkey(ohdr); return_cnp(ibp, qp, rqpn, pkey, dlid, rlid, sc, grh); } diff --git a/drivers/infiniband/hw/hfi1/rc.c b/drivers/infiniband/hw/hfi1/rc.c index 1080778a1f7c..66e6843aab48 100644 --- a/drivers/infiniband/hw/hfi1/rc.c +++ b/drivers/infiniband/hw/hfi1/rc.c @@ -765,7 +765,7 @@ void hfi1_send_rc_ack(struct hfi1_ctxtdata *rcd, struct rvt_qp *qp, ohdr->u.aeth = rvt_compute_aeth(qp); sc5 = ibp->sl_to_sc[rdma_ah_get_sl(&qp->remote_ah_attr)]; /* set PBC_DC_INFO bit (aka SC[4]) in pbc_flags */ - pbc_flags |= ((!!(sc5 & 0x10)) << PBC_DC_INFO_SHIFT); + pbc_flags |= (ib_is_sc5(sc5) << PBC_DC_INFO_SHIFT); lrh0 |= (sc5 & 0xf) << 12 | (rdma_ah_get_sl(&qp->remote_ah_attr) & 0xf) << 4; hdr.lrh[0] = cpu_to_be16(lrh0); @@ -1009,7 +1009,7 @@ void hfi1_rc_send_complete(struct rvt_qp *qp, struct ib_header *hdr) return; } - psn = be32_to_cpu(ohdr->bth[2]); + psn = ib_bth_get_psn(ohdr); reset_sending_psn(qp, psn); /* @@ -1943,7 +1943,7 @@ void hfi1_rc_rcv(struct hfi1_packet *packet) is_fecn = process_ecn(qp, packet, false); - psn = be32_to_cpu(ohdr->bth[2]); + psn = ib_bth_get_psn(ohdr); opcode = ib_bth_get_opcode(ohdr); /* @@ -2388,7 +2388,7 @@ void hfi1_rc_hdrerr( if (hfi1_ruc_check_hdr(ibp, hdr, has_grh, qp, bth0)) return; - psn = be32_to_cpu(ohdr->bth[2]); + psn = ib_bth_get_psn(ohdr); opcode = ib_bth_get_opcode(ohdr); /* Only deal with RDMA Writes for now */ diff --git a/drivers/infiniband/hw/hfi1/uc.c b/drivers/infiniband/hw/hfi1/uc.c index 5da1e4546543..2a5650f8aee0 100644 --- a/drivers/infiniband/hw/hfi1/uc.c +++ b/drivers/infiniband/hw/hfi1/uc.c @@ -319,7 +319,7 @@ void hfi1_uc_rcv(struct hfi1_packet *packet) process_ecn(qp, packet, true); - psn = be32_to_cpu(ohdr->bth[2]); + psn = ib_bth_get_psn(ohdr); opcode = ib_bth_get_opcode(ohdr); /* Compare the PSN verses the expected PSN. */ diff --git a/drivers/infiniband/hw/hfi1/ud.c b/drivers/infiniband/hw/hfi1/ud.c index 6a4e95cefae5..49fe179ad3ae 100644 --- a/drivers/infiniband/hw/hfi1/ud.c +++ b/drivers/infiniband/hw/hfi1/ud.c @@ -549,7 +549,7 @@ void return_cnp(struct hfi1_ibport *ibp, struct rvt_qp *qp, u32 remote_qpn, hdr.lrh[3] = cpu_to_be16(slid); plen = 2 /* PBC */ + hwords; - pbc_flags |= (!!(sc5 & 0x10)) << PBC_DC_INFO_SHIFT; + pbc_flags |= (ib_is_sc5(sc5) << PBC_DC_INFO_SHIFT); vl = sc_to_vlt(ppd->dd, sc5); pbc = create_pbc(ppd, pbc_flags, qp->srate_mbps, vl, plen); if (ctxt) { @@ -689,8 +689,8 @@ void hfi1_ud_rcv(struct hfi1_packet *packet) u16 slid; u8 extra_bytes; - qkey = be32_to_cpu(ohdr->u.ud.deth[0]); - src_qp = be32_to_cpu(ohdr->u.ud.deth[1]) & RVT_QPN_MASK; + qkey = ib_get_qkey(ohdr); + src_qp = ib_get_sqpn(ohdr); dlid = ib_get_dlid(hdr); bth1 = be32_to_cpu(ohdr->bth[1]); slid = ib_get_slid(hdr); diff --git a/drivers/infiniband/hw/hfi1/verbs.c b/drivers/infiniband/hw/hfi1/verbs.c index 90e7b77d68e8..128d2917a2d9 100644 --- a/drivers/infiniband/hw/hfi1/verbs.c +++ b/drivers/infiniband/hw/hfi1/verbs.c @@ -595,7 +595,7 @@ void hfi1_ib_rcv(struct hfi1_packet *packet) inc_opstats(tlen, &rcd->opstats->stats[opcode]); /* Get the destination QP number. */ - qp_num = be32_to_cpu(packet->ohdr->bth[1]) & RVT_QPN_MASK; + qp_num = ib_bth_get_qpn(packet->ohdr); lid = ib_get_dlid(hdr); if (unlikely((lid >= be16_to_cpu(IB_MULTICAST_LID_BASE)) && (lid != be16_to_cpu(IB_LID_PERMISSIVE)))) { @@ -863,7 +863,7 @@ int hfi1_verbs_send_dma(struct rvt_qp *qp, struct hfi1_pkt_state *ps, /* No vl15 here */ /* set PBC_DC_INFO bit (aka SC[4]) in pbc_flags */ - pbc |= (!!(sc5 & 0x10)) << PBC_DC_INFO_SHIFT; + pbc |= (ib_is_sc5(sc5) << PBC_DC_INFO_SHIFT); if (unlikely(hfi1_dbg_fault_opcode(qp, opcode, false))) pbc = hfi1_fault_tx(qp, opcode, pbc); @@ -999,7 +999,7 @@ int hfi1_verbs_send_pio(struct rvt_qp *qp, struct hfi1_pkt_state *ps, u8 opcode = get_opcode(&tx->phdr.hdr); /* set PBC_DC_INFO bit (aka SC[4]) in pbc_flags */ - pbc |= (!!(sc5 & 0x10)) << PBC_DC_INFO_SHIFT; + pbc |= (ib_is_sc5(sc5) << PBC_DC_INFO_SHIFT); if (unlikely(hfi1_dbg_fault_opcode(qp, opcode, false))) pbc = hfi1_fault_tx(qp, opcode, pbc); pbc = create_pbc(ppd, pbc, qp->srate_mbps, vl, plen); diff --git a/include/rdma/ib_hdrs.h b/include/rdma/ib_hdrs.h index 5519f31f043a..c124d515f7d5 100644 --- a/include/rdma/ib_hdrs.h +++ b/include/rdma/ib_hdrs.h @@ -193,8 +193,12 @@ static inline void put_ib_ateth_compare(u64 val, struct ib_atomic_eth *ateth) #define IB_LNH_MASK 3 #define IB_SC_MASK 0xf #define IB_SC_SHIFT 12 +#define IB_SC5_MASK 0x10 #define IB_SL_MASK 0xf #define IB_SL_SHIFT 4 +#define IB_SL_SHIFT 4 +#define IB_LVER_MASK 0xf +#define IB_LVER_SHIFT 8 static inline u8 ib_get_lnh(struct ib_header *hdr) { @@ -206,6 +210,11 @@ static inline u8 ib_get_sc(struct ib_header *hdr) return ((be16_to_cpu(hdr->lrh[0]) >> IB_SC_SHIFT) & IB_SC_MASK); } +static inline bool ib_is_sc5(u16 sc5) +{ + return !!(sc5 & IB_SC5_MASK); +} + static inline u8 ib_get_sl(struct ib_header *hdr) { return ((be16_to_cpu(hdr->lrh[0]) >> IB_SL_SHIFT) & IB_SL_MASK); @@ -221,6 +230,27 @@ static inline u16 ib_get_slid(struct ib_header *hdr) return (be16_to_cpu(hdr->lrh[3])); } +static inline u8 ib_get_lver(struct ib_header *hdr) +{ + return (u8)((be16_to_cpu(hdr->lrh[0]) >> IB_LVER_SHIFT) & + IB_LVER_MASK); +} + +static inline u16 ib_get_len(struct ib_header *hdr) +{ + return (u16)(be16_to_cpu(hdr->lrh[2])); +} + +static inline u32 ib_get_qkey(struct ib_other_headers *ohdr) +{ + return be32_to_cpu(ohdr->u.ud.deth[0]); +} + +static inline u32 ib_get_sqpn(struct ib_other_headers *ohdr) +{ + return ((be32_to_cpu(ohdr->u.ud.deth[1])) & IB_QPN_MASK); +} + /* * BTH */ @@ -229,6 +259,14 @@ static inline u16 ib_get_slid(struct ib_header *hdr) #define IB_BTH_PAD_MASK 3 #define IB_BTH_PKEY_MASK 0xffff #define IB_BTH_PAD_SHIFT 20 +#define IB_BTH_A_MASK 1 +#define IB_BTH_A_SHIFT 31 +#define IB_BTH_M_MASK 1 +#define IB_BTH_M_SHIFT 22 +#define IB_BTH_SE_MASK 1 +#define IB_BTH_SE_SHIFT 23 +#define IB_BTH_TVER_MASK 0xf +#define IB_BTH_TVER_SHIFT 16 static inline u8 ib_bth_get_pad(struct ib_other_headers *ohdr) { @@ -247,4 +285,50 @@ static inline u8 ib_bth_get_opcode(struct ib_other_headers *ohdr) IB_BTH_OPCODE_MASK); } +static inline u8 ib_bth_get_ackreq(struct ib_other_headers *ohdr) +{ + return (u8)((be32_to_cpu(ohdr->bth[2]) >> IB_BTH_A_SHIFT) & + IB_BTH_A_MASK); +} + +static inline u8 ib_bth_get_migreq(struct ib_other_headers *ohdr) +{ + return (u8)((be32_to_cpu(ohdr->bth[0]) >> IB_BTH_M_SHIFT) & + IB_BTH_M_MASK); +} + +static inline u8 ib_bth_get_se(struct ib_other_headers *ohdr) +{ + return (u8)((be32_to_cpu(ohdr->bth[0]) >> IB_BTH_SE_SHIFT) & + IB_BTH_SE_MASK); +} + +static inline u32 ib_bth_get_psn(struct ib_other_headers *ohdr) +{ + return (u32)(be32_to_cpu(ohdr->bth[2])); +} + +static inline u32 ib_bth_get_qpn(struct ib_other_headers *ohdr) +{ + return (u32)((be32_to_cpu(ohdr->bth[1])) & IB_QPN_MASK); +} + +static inline u8 ib_bth_get_becn(struct ib_other_headers *ohdr) +{ + return (u8)((be32_to_cpu(ohdr->bth[1]) >> IB_BECN_SHIFT) & + IB_BECN_MASK); +} + +static inline u8 ib_bth_get_fecn(struct ib_other_headers *ohdr) +{ + return (u8)((be32_to_cpu(ohdr->bth[1]) >> IB_FECN_SHIFT) & + IB_FECN_MASK); +} + +static inline u8 ib_bth_get_tver(struct ib_other_headers *ohdr) +{ + return (u8)((be32_to_cpu(ohdr->bth[0]) >> IB_BTH_TVER_SHIFT) & + IB_BTH_TVER_MASK); +} + #endif /* IB_HDRS_H */ diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index ba8314ec5768..8f1ce4e27bbd 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -664,6 +664,8 @@ union rdma_network_hdr { }; }; +#define IB_QPN_MASK 0xFFFFFF + enum { IB_MULTICAST_QPN = 0xffffff }; diff --git a/include/rdma/rdmavt_qp.h b/include/rdma/rdmavt_qp.h index be6472e5b06b..13f43b3527a8 100644 --- a/include/rdma/rdmavt_qp.h +++ b/include/rdma/rdmavt_qp.h @@ -396,7 +396,7 @@ struct rvt_srq { #define RVT_QPNMAP_ENTRIES (RVT_QPN_MAX / PAGE_SIZE / BITS_PER_BYTE) #define RVT_BITS_PER_PAGE (PAGE_SIZE * BITS_PER_BYTE) #define RVT_BITS_PER_PAGE_MASK (RVT_BITS_PER_PAGE - 1) -#define RVT_QPN_MASK 0xFFFFFF +#define RVT_QPN_MASK IB_QPN_MASK /* * QPN-map pages start out as NULL, they get allocated upon -- cgit v1.2.3 From 228d2af1b723deedee38f03d144b7d25b39f6f86 Mon Sep 17 00:00:00 2001 From: Don Hiatt Date: Fri, 12 May 2017 09:20:08 -0700 Subject: IB/hfi1: Separate input/output header tracing Calls to trace incoming packets will now receive the packet context as parameter. This enables trace support for future packet types. Header trace output is in the format : which makes parsing easier. input_ibhdr trace before change: -0 [001] d.h. 5904.250925: input_ibhdr: [0000:05:00.0] vl 0 lver 0 sl 0 lnh 2,LRH_BTH dlid 0002 len 18 slid 0001 op 0x64,UD_SEND_ONLY se 0 m 0 pad 0 tver 0 pkey 0xffff f 0 b 0 qpn 0x000001 a 0 psn 0x000001b2 deth qkey 0x80010000 sqpn 0x000001 input_ibhdr trace after change: -0 [001] d.h. 6655.714488: input_ibhdr: [0000:05:00.0] (IB) len:124 sc:0 dlid:0x0001 slid:0x0002 lnh:2,LRH_BTH lver:0 sl:0 age:0 becn:0 fecn:0 l4:0 rc:0 entropy:0 op:0x64,UD_SEND_ONLY se:0 m:0 pad:0 tver:0 pkey:0x7fff f:0 b:0 qpn:0x000001 a:0 psn:0x00000036 hlen:8 deth qkey:0x80010000 sqpn:0x000001 Reviewed-by: Dasaratharaman Chandramouli Reviewed-by: Dennis Dalessandro Signed-off-by: Don Hiatt Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/hfi.h | 49 ----- drivers/infiniband/hw/hfi1/rc.c | 3 +- drivers/infiniband/hw/hfi1/trace.c | 58 +++++- drivers/infiniband/hw/hfi1/trace_ibhdrs.h | 322 ++++++++++++++++++++---------- drivers/infiniband/hw/hfi1/trace_rx.h | 9 + drivers/infiniband/hw/hfi1/verbs.c | 7 +- 6 files changed, 279 insertions(+), 169 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/hfi1/hfi.h b/drivers/infiniband/hw/hfi1/hfi.h index 414a04a481c2..3b76631cbcbd 100644 --- a/drivers/infiniband/hw/hfi1/hfi.h +++ b/drivers/infiniband/hw/hfi1/hfi.h @@ -2086,53 +2086,4 @@ int hfi1_tempsense_rd(struct hfi1_devdata *dd, struct hfi1_temp *temp); #define DD_DEV_ENTRY(dd) __string(dev, dev_name(&(dd)->pcidev->dev)) #define DD_DEV_ASSIGN(dd) __assign_str(dev, dev_name(&(dd)->pcidev->dev)) - -#define packettype_name(etype) { RHF_RCV_TYPE_##etype, #etype } -#define show_packettype(etype) \ -__print_symbolic(etype, \ - packettype_name(EXPECTED), \ - packettype_name(EAGER), \ - packettype_name(IB), \ - packettype_name(ERROR), \ - packettype_name(BYPASS)) - -#define ib_opcode_name(opcode) { IB_OPCODE_##opcode, #opcode } -#define show_ib_opcode(opcode) \ -__print_symbolic(opcode, \ - ib_opcode_name(RC_SEND_FIRST), \ - ib_opcode_name(RC_SEND_MIDDLE), \ - ib_opcode_name(RC_SEND_LAST), \ - ib_opcode_name(RC_SEND_LAST_WITH_IMMEDIATE), \ - ib_opcode_name(RC_SEND_ONLY), \ - ib_opcode_name(RC_SEND_ONLY_WITH_IMMEDIATE), \ - ib_opcode_name(RC_RDMA_WRITE_FIRST), \ - ib_opcode_name(RC_RDMA_WRITE_MIDDLE), \ - ib_opcode_name(RC_RDMA_WRITE_LAST), \ - ib_opcode_name(RC_RDMA_WRITE_LAST_WITH_IMMEDIATE), \ - ib_opcode_name(RC_RDMA_WRITE_ONLY), \ - ib_opcode_name(RC_RDMA_WRITE_ONLY_WITH_IMMEDIATE), \ - ib_opcode_name(RC_RDMA_READ_REQUEST), \ - ib_opcode_name(RC_RDMA_READ_RESPONSE_FIRST), \ - ib_opcode_name(RC_RDMA_READ_RESPONSE_MIDDLE), \ - ib_opcode_name(RC_RDMA_READ_RESPONSE_LAST), \ - ib_opcode_name(RC_RDMA_READ_RESPONSE_ONLY), \ - ib_opcode_name(RC_ACKNOWLEDGE), \ - ib_opcode_name(RC_ATOMIC_ACKNOWLEDGE), \ - ib_opcode_name(RC_COMPARE_SWAP), \ - ib_opcode_name(RC_FETCH_ADD), \ - ib_opcode_name(UC_SEND_FIRST), \ - ib_opcode_name(UC_SEND_MIDDLE), \ - ib_opcode_name(UC_SEND_LAST), \ - ib_opcode_name(UC_SEND_LAST_WITH_IMMEDIATE), \ - ib_opcode_name(UC_SEND_ONLY), \ - ib_opcode_name(UC_SEND_ONLY_WITH_IMMEDIATE), \ - ib_opcode_name(UC_RDMA_WRITE_FIRST), \ - ib_opcode_name(UC_RDMA_WRITE_MIDDLE), \ - ib_opcode_name(UC_RDMA_WRITE_LAST), \ - ib_opcode_name(UC_RDMA_WRITE_LAST_WITH_IMMEDIATE), \ - ib_opcode_name(UC_RDMA_WRITE_ONLY), \ - ib_opcode_name(UC_RDMA_WRITE_ONLY_WITH_IMMEDIATE), \ - ib_opcode_name(UD_SEND_ONLY), \ - ib_opcode_name(UD_SEND_ONLY_WITH_IMMEDIATE), \ - ib_opcode_name(CNP)) #endif /* _HFI1_KERNEL_H */ diff --git a/drivers/infiniband/hw/hfi1/rc.c b/drivers/infiniband/hw/hfi1/rc.c index 66e6843aab48..b443c1e01543 100644 --- a/drivers/infiniband/hw/hfi1/rc.c +++ b/drivers/infiniband/hw/hfi1/rc.c @@ -798,7 +798,8 @@ void hfi1_send_rc_ack(struct hfi1_ctxtdata *rcd, struct rvt_qp *qp, goto queue_ack; } - trace_ack_output_ibhdr(dd_from_ibdev(qp->ibqp.device), &hdr); + trace_ack_output_ibhdr(dd_from_ibdev(qp->ibqp.device), + &hdr, ib_is_sc5(sc5)); /* write the pbc and data */ ppd->dd->pio_inline_send(ppd->dd, pbuf, pbc, &hdr, hwords); diff --git a/drivers/infiniband/hw/hfi1/trace.c b/drivers/infiniband/hw/hfi1/trace.c index eafae487face..b80b74d0c252 100644 --- a/drivers/infiniband/hw/hfi1/trace.c +++ b/drivers/infiniband/hw/hfi1/trace.c @@ -47,7 +47,7 @@ #define CREATE_TRACE_POINTS #include "trace.h" -u8 ibhdr_exhdr_len(struct ib_header *hdr) +u8 hfi1_trace_ib_hdr_len(struct ib_header *hdr) { struct ib_other_headers *ohdr; u8 opcode; @@ -61,13 +61,18 @@ u8 ibhdr_exhdr_len(struct ib_header *hdr) 0 : hdr_len_by_opcode[opcode] - (12 + 8); } -#define IMM_PRN "imm %d" -#define RETH_PRN "reth vaddr 0x%.16llx rkey 0x%.8x dlen 0x%.8x" -#define AETH_PRN "aeth syn 0x%.2x %s msn 0x%.8x" -#define DETH_PRN "deth qkey 0x%.8x sqpn 0x%.6x" -#define IETH_PRN "ieth rkey 0x%.8x" -#define ATOMICACKETH_PRN "origdata %llx" -#define ATOMICETH_PRN "vaddr 0x%llx rkey 0x%.8x sdata %llx cdata %llx" +const char *hfi1_trace_get_packet_str(struct hfi1_packet *packet) +{ + return "IB"; +} + +#define IMM_PRN "imm:%d" +#define RETH_PRN "reth vaddr:0x%.16llx rkey:0x%.8x dlen:0x%.8x" +#define AETH_PRN "aeth syn:0x%.2x %s msn:0x%.8x" +#define DETH_PRN "deth qkey:0x%.8x sqpn:0x%.6x" +#define IETH_PRN "ieth rkey:0x%.8x" +#define ATOMICACKETH_PRN "origdata:%llx" +#define ATOMICETH_PRN "vaddr:0x%llx rkey:0x%.8x sdata:%llx cdata:%llx" #define OP(transport, op) IB_OPCODE_## transport ## _ ## op @@ -84,6 +89,43 @@ static const char *parse_syndrome(u8 syndrome) return ""; } +void hfi1_trace_parse_bth(struct ib_other_headers *ohdr, + u8 *ack, u8 *becn, u8 *fecn, u8 *mig, + u8 *se, u8 *pad, u8 *opcode, u8 *tver, + u16 *pkey, u32 *psn, u32 *qpn) +{ + *ack = ib_bth_get_ackreq(ohdr); + *becn = ib_bth_get_becn(ohdr); + *fecn = ib_bth_get_fecn(ohdr); + *mig = ib_bth_get_migreq(ohdr); + *se = ib_bth_get_se(ohdr); + *pad = ib_bth_get_pad(ohdr); + *opcode = ib_bth_get_opcode(ohdr); + *tver = ib_bth_get_tver(ohdr); + *pkey = ib_bth_get_pkey(ohdr); + *psn = ib_bth_get_psn(ohdr); + *qpn = ib_bth_get_qpn(ohdr); +} + +void hfi1_trace_parse_9b_hdr(struct ib_header *hdr, bool sc5, + struct ib_other_headers **ohdr, + u8 *lnh, u8 *lver, u8 *sl, u8 *sc, + u16 *len, u32 *dlid, u32 *slid) +{ + *lnh = ib_get_lnh(hdr); + *lver = ib_get_lver(hdr); + *sl = ib_get_sl(hdr); + *sc = ib_get_sc(hdr) | (sc5 << 4); + *len = ib_get_len(hdr); + *dlid = ib_get_dlid(hdr); + *slid = ib_get_slid(hdr); + + if (*lnh == HFI1_LRH_BTH) + *ohdr = &hdr->u.oth; + else + *ohdr = &hdr->u.l.oth; +} + const char *parse_everbs_hdrs( struct trace_seq *p, u8 opcode, diff --git a/drivers/infiniband/hw/hfi1/trace_ibhdrs.h b/drivers/infiniband/hw/hfi1/trace_ibhdrs.h index 090f6b506953..0f2d2da057ec 100644 --- a/drivers/infiniband/hw/hfi1/trace_ibhdrs.h +++ b/drivers/infiniband/hw/hfi1/trace_ibhdrs.h @@ -55,8 +55,57 @@ #undef TRACE_SYSTEM #define TRACE_SYSTEM hfi1_ibhdrs -u8 ibhdr_exhdr_len(struct ib_header *hdr); +#define ib_opcode_name(opcode) { IB_OPCODE_##opcode, #opcode } +#define show_ib_opcode(opcode) \ +__print_symbolic(opcode, \ + ib_opcode_name(RC_SEND_FIRST), \ + ib_opcode_name(RC_SEND_MIDDLE), \ + ib_opcode_name(RC_SEND_LAST), \ + ib_opcode_name(RC_SEND_LAST_WITH_IMMEDIATE), \ + ib_opcode_name(RC_SEND_ONLY), \ + ib_opcode_name(RC_SEND_ONLY_WITH_IMMEDIATE), \ + ib_opcode_name(RC_RDMA_WRITE_FIRST), \ + ib_opcode_name(RC_RDMA_WRITE_MIDDLE), \ + ib_opcode_name(RC_RDMA_WRITE_LAST), \ + ib_opcode_name(RC_RDMA_WRITE_LAST_WITH_IMMEDIATE), \ + ib_opcode_name(RC_RDMA_WRITE_ONLY), \ + ib_opcode_name(RC_RDMA_WRITE_ONLY_WITH_IMMEDIATE), \ + ib_opcode_name(RC_RDMA_READ_REQUEST), \ + ib_opcode_name(RC_RDMA_READ_RESPONSE_FIRST), \ + ib_opcode_name(RC_RDMA_READ_RESPONSE_MIDDLE), \ + ib_opcode_name(RC_RDMA_READ_RESPONSE_LAST), \ + ib_opcode_name(RC_RDMA_READ_RESPONSE_ONLY), \ + ib_opcode_name(RC_ACKNOWLEDGE), \ + ib_opcode_name(RC_ATOMIC_ACKNOWLEDGE), \ + ib_opcode_name(RC_COMPARE_SWAP), \ + ib_opcode_name(RC_FETCH_ADD), \ + ib_opcode_name(UC_SEND_FIRST), \ + ib_opcode_name(UC_SEND_MIDDLE), \ + ib_opcode_name(UC_SEND_LAST), \ + ib_opcode_name(UC_SEND_LAST_WITH_IMMEDIATE), \ + ib_opcode_name(UC_SEND_ONLY), \ + ib_opcode_name(UC_SEND_ONLY_WITH_IMMEDIATE), \ + ib_opcode_name(UC_RDMA_WRITE_FIRST), \ + ib_opcode_name(UC_RDMA_WRITE_MIDDLE), \ + ib_opcode_name(UC_RDMA_WRITE_LAST), \ + ib_opcode_name(UC_RDMA_WRITE_LAST_WITH_IMMEDIATE), \ + ib_opcode_name(UC_RDMA_WRITE_ONLY), \ + ib_opcode_name(UC_RDMA_WRITE_ONLY_WITH_IMMEDIATE), \ + ib_opcode_name(UD_SEND_ONLY), \ + ib_opcode_name(UD_SEND_ONLY_WITH_IMMEDIATE), \ + ib_opcode_name(CNP)) + const char *parse_everbs_hdrs(struct trace_seq *p, u8 opcode, void *ehdrs); +u8 hfi1_trace_ib_hdr_len(struct ib_header *hdr); +const char *hfi1_trace_get_packet_str(struct hfi1_packet *packet); +void hfi1_trace_parse_bth(struct ib_other_headers *ohdr, + u8 *ack, u8 *becn, u8 *fecn, u8 *mig, + u8 *se, u8 *pad, u8 *opcode, u8 *tver, + u16 *pkey, u32 *psn, u32 *qpn); +void hfi1_trace_parse_9b_hdr(struct ib_header *hdr, bool sc5, + struct ib_other_headers **ohdr, + u8 *lnh, u8 *lver, u8 *sl, u8 *sc, + u16 *len, u32 *dlid, u32 *slid); #define __parse_ib_ehdrs(op, ehdrs) parse_everbs_hdrs(p, op, ehdrs) @@ -66,139 +115,198 @@ __print_symbolic(lrh, \ lrh_name(LRH_BTH), \ lrh_name(LRH_GRH)) -#define LRH_PRN "vl %d lver %d sl %d lnh %d,%s dlid %.4x len %d slid %.4x" +#define LRH_PRN "len:%d sc:%d dlid:0x%.4x slid:0x%.4x" +#define LRH_9B_PRN "lnh:%d,%s lver:%d sl:%d " #define BTH_PRN \ - "op 0x%.2x,%s se %d m %d pad %d tver %d pkey 0x%.4x " \ - "f %d b %d qpn 0x%.6x a %d psn 0x%.8x" -#define EHDR_PRN "%s" + "op:0x%.2x,%s se:%d m:%d pad:%d tver:%d pkey:0x%.4x " \ + "f:%d b:%d qpn:0x%.6x a:%d psn:0x%.8x" +#define EHDR_PRN "hlen:%d %s" -DECLARE_EVENT_CLASS(hfi1_ibhdr_template, +DECLARE_EVENT_CLASS(hfi1_input_ibhdr_template, TP_PROTO(struct hfi1_devdata *dd, - struct ib_header *hdr), - TP_ARGS(dd, hdr), + struct hfi1_packet *packet, + bool sc5), + TP_ARGS(dd, packet, sc5), TP_STRUCT__entry( DD_DEV_ENTRY(dd) - /* LRH */ - __field(u8, vl) + __field(u8, lnh) __field(u8, lver) __field(u8, sl) + __field(u16, len) + __field(u32, dlid) + __field(u8, sc) + __field(u32, slid) + __field(u8, opcode) + __field(u8, se) + __field(u8, mig) + __field(u8, pad) + __field(u8, tver) + __field(u16, pkey) + __field(u8, fecn) + __field(u8, becn) + __field(u32, qpn) + __field(u8, ack) + __field(u32, psn) + /* extended headers */ + __dynamic_array(u8, ehdrs, + hfi1_trace_ib_hdr_len(packet->hdr)) + ), + TP_fast_assign( + struct ib_other_headers *ohdr; + + DD_DEV_ASSIGN(dd); + + hfi1_trace_parse_9b_hdr(packet->hdr, sc5, + &ohdr, + &__entry->lnh, + &__entry->lver, + &__entry->sl, + &__entry->sc, + &__entry->len, + &__entry->dlid, + &__entry->slid); + + hfi1_trace_parse_bth(ohdr, &__entry->ack, + &__entry->becn, &__entry->fecn, + &__entry->mig, &__entry->se, + &__entry->pad, &__entry->opcode, + &__entry->tver, &__entry->pkey, + &__entry->psn, &__entry->qpn); + /* extended headers */ + memcpy(__get_dynamic_array(ehdrs), &ohdr->u, + __get_dynamic_array_len(ehdrs)); + ), + TP_printk("[%s] (IB) " LRH_PRN " " LRH_9B_PRN " " + BTH_PRN " " EHDR_PRN, + __get_str(dev), + __entry->len, + __entry->sc, + __entry->dlid, + __entry->slid, + __entry->lnh, show_lnh(__entry->lnh), + __entry->lver, + __entry->sl, + /* BTH */ + __entry->opcode, show_ib_opcode(__entry->opcode), + __entry->se, + __entry->mig, + __entry->pad, + __entry->tver, + __entry->pkey, + __entry->fecn, + __entry->becn, + __entry->qpn, + __entry->ack, + __entry->psn, + /* extended headers */ + __get_dynamic_array_len(ehdrs), + __parse_ib_ehdrs( + __entry->opcode, + (void *)__get_dynamic_array(ehdrs)) + ) +); + +DEFINE_EVENT(hfi1_input_ibhdr_template, input_ibhdr, + TP_PROTO(struct hfi1_devdata *dd, + struct hfi1_packet *packet, bool sc5), + TP_ARGS(dd, packet, sc5)); + +DECLARE_EVENT_CLASS(hfi1_output_ibhdr_template, + TP_PROTO(struct hfi1_devdata *dd, + struct ib_header *hdr, + bool sc5), + TP_ARGS(dd, hdr, sc5), + TP_STRUCT__entry( + DD_DEV_ENTRY(dd) __field(u8, lnh) - __field(u16, dlid) + __field(u8, lver) + __field(u8, sl) __field(u16, len) - __field(u16, slid) - /* BTH */ + __field(u32, dlid) + __field(u8, sc) + __field(u32, slid) __field(u8, opcode) __field(u8, se) - __field(u8, m) + __field(u8, mig) __field(u8, pad) __field(u8, tver) __field(u16, pkey) - __field(u8, f) - __field(u8, b) + __field(u8, fecn) + __field(u8, becn) __field(u32, qpn) - __field(u8, a) + __field(u8, ack) __field(u32, psn) /* extended headers */ - __dynamic_array(u8, ehdrs, ibhdr_exhdr_len(hdr)) + __dynamic_array(u8, ehdrs, + hfi1_trace_ib_hdr_len(hdr)) ), - TP_fast_assign( + TP_fast_assign( struct ib_other_headers *ohdr; DD_DEV_ASSIGN(dd); - /* LRH */ - __entry->vl = - (u8)(be16_to_cpu(hdr->lrh[0]) >> 12); - __entry->lver = - (u8)(be16_to_cpu(hdr->lrh[0]) >> 8) & 0xf; - __entry->sl = - (u8)(be16_to_cpu(hdr->lrh[0]) >> 4) & 0xf; - __entry->lnh = - (u8)(be16_to_cpu(hdr->lrh[0]) & 3); - __entry->dlid = - be16_to_cpu(hdr->lrh[1]); - /* allow for larger len */ - __entry->len = - be16_to_cpu(hdr->lrh[2]); - __entry->slid = - be16_to_cpu(hdr->lrh[3]); - /* BTH */ - if (__entry->lnh == HFI1_LRH_BTH) - ohdr = &hdr->u.oth; - else - ohdr = &hdr->u.l.oth; - __entry->opcode = - (be32_to_cpu(ohdr->bth[0]) >> 24) & 0xff; - __entry->se = - (be32_to_cpu(ohdr->bth[0]) >> 23) & 1; - __entry->m = - (be32_to_cpu(ohdr->bth[0]) >> 22) & 1; - __entry->pad = - (be32_to_cpu(ohdr->bth[0]) >> 20) & 3; - __entry->tver = - (be32_to_cpu(ohdr->bth[0]) >> 16) & 0xf; - __entry->pkey = - be32_to_cpu(ohdr->bth[0]) & 0xffff; - __entry->f = - (be32_to_cpu(ohdr->bth[1]) >> IB_FECN_SHIFT) & - IB_FECN_MASK; - __entry->b = - (be32_to_cpu(ohdr->bth[1]) >> IB_BECN_SHIFT) & - IB_BECN_MASK; - __entry->qpn = - be32_to_cpu(ohdr->bth[1]) & RVT_QPN_MASK; - __entry->a = - (be32_to_cpu(ohdr->bth[2]) >> 31) & 1; - /* allow for larger PSN */ - __entry->psn = - be32_to_cpu(ohdr->bth[2]) & 0x7fffffff; + + hfi1_trace_parse_9b_hdr(hdr, sc5, + &ohdr, &__entry->lnh, + &__entry->lver, &__entry->sl, + &__entry->sc, &__entry->len, + &__entry->dlid, &__entry->slid); + + hfi1_trace_parse_bth(ohdr, &__entry->ack, + &__entry->becn, &__entry->fecn, + &__entry->mig, &__entry->se, + &__entry->pad, &__entry->opcode, + &__entry->tver, &__entry->pkey, + &__entry->psn, &__entry->qpn); + /* extended headers */ - memcpy(__get_dynamic_array(ehdrs), &ohdr->u, - ibhdr_exhdr_len(hdr)); - ), - TP_printk("[%s] " LRH_PRN " " BTH_PRN " " EHDR_PRN, - __get_str(dev), - /* LRH */ - __entry->vl, - __entry->lver, - __entry->sl, - __entry->lnh, show_lnh(__entry->lnh), - __entry->dlid, - __entry->len, - __entry->slid, - /* BTH */ - __entry->opcode, show_ib_opcode(__entry->opcode), - __entry->se, - __entry->m, - __entry->pad, - __entry->tver, - __entry->pkey, - __entry->f, - __entry->b, - __entry->qpn, - __entry->a, - __entry->psn, - /* extended headers */ - __parse_ib_ehdrs( - __entry->opcode, - (void *)__get_dynamic_array(ehdrs)) - ) + memcpy(__get_dynamic_array(ehdrs), + &ohdr->u, __get_dynamic_array_len(ehdrs)); + ), + TP_printk("[%s] (IB) " LRH_PRN " " LRH_9B_PRN " " + BTH_PRN " " EHDR_PRN, + __get_str(dev), + __entry->len, + __entry->sc, + __entry->dlid, + __entry->slid, + __entry->lnh, show_lnh(__entry->lnh), + __entry->lver, + __entry->sl, + /* BTH */ + __entry->opcode, show_ib_opcode(__entry->opcode), + __entry->se, + __entry->mig, + __entry->pad, + __entry->tver, + __entry->pkey, + __entry->fecn, + __entry->becn, + __entry->qpn, + __entry->ack, + __entry->psn, + /* extended headers */ + __get_dynamic_array_len(ehdrs), + __parse_ib_ehdrs( + __entry->opcode, + (void *)__get_dynamic_array(ehdrs)) + ) ); -DEFINE_EVENT(hfi1_ibhdr_template, input_ibhdr, - TP_PROTO(struct hfi1_devdata *dd, struct ib_header *hdr), - TP_ARGS(dd, hdr)); +DEFINE_EVENT(hfi1_output_ibhdr_template, pio_output_ibhdr, + TP_PROTO(struct hfi1_devdata *dd, + struct ib_header *hdr, bool sc5), + TP_ARGS(dd, hdr, sc5)); -DEFINE_EVENT(hfi1_ibhdr_template, pio_output_ibhdr, - TP_PROTO(struct hfi1_devdata *dd, struct ib_header *hdr), - TP_ARGS(dd, hdr)); +DEFINE_EVENT(hfi1_output_ibhdr_template, ack_output_ibhdr, + TP_PROTO(struct hfi1_devdata *dd, + struct ib_header *hdr, bool sc5), + TP_ARGS(dd, hdr, sc5)); -DEFINE_EVENT(hfi1_ibhdr_template, ack_output_ibhdr, - TP_PROTO(struct hfi1_devdata *dd, struct ib_header *hdr), - TP_ARGS(dd, hdr)); +DEFINE_EVENT(hfi1_output_ibhdr_template, sdma_output_ibhdr, + TP_PROTO(struct hfi1_devdata *dd, + struct ib_header *hdr, bool sc5), + TP_ARGS(dd, hdr, sc5)); -DEFINE_EVENT(hfi1_ibhdr_template, sdma_output_ibhdr, - TP_PROTO(struct hfi1_devdata *dd, struct ib_header *hdr), - TP_ARGS(dd, hdr)); #endif /* __HFI1_TRACE_IBHDRS_H */ diff --git a/drivers/infiniband/hw/hfi1/trace_rx.h b/drivers/infiniband/hw/hfi1/trace_rx.h index f77e59fb43fe..05fc6d68ffe8 100644 --- a/drivers/infiniband/hw/hfi1/trace_rx.h +++ b/drivers/infiniband/hw/hfi1/trace_rx.h @@ -55,6 +55,15 @@ #undef TRACE_SYSTEM #define TRACE_SYSTEM hfi1_rx +#define packettype_name(etype) { RHF_RCV_TYPE_##etype, #etype } +#define show_packettype(etype) \ +__print_symbolic(etype, \ + packettype_name(EXPECTED), \ + packettype_name(EAGER), \ + packettype_name(IB), \ + packettype_name(ERROR), \ + packettype_name(BYPASS)) + TRACE_EVENT(hfi1_rcvhdr, TP_PROTO(struct hfi1_devdata *dd, u32 ctxt, diff --git a/drivers/infiniband/hw/hfi1/verbs.c b/drivers/infiniband/hw/hfi1/verbs.c index 128d2917a2d9..5f4be35f31b6 100644 --- a/drivers/infiniband/hw/hfi1/verbs.c +++ b/drivers/infiniband/hw/hfi1/verbs.c @@ -589,8 +589,7 @@ void hfi1_ib_rcv(struct hfi1_packet *packet) goto drop; } - trace_input_ibhdr(rcd->dd, hdr); - + trace_input_ibhdr(rcd->dd, packet, !!(packet->rhf & RHF_DC_INFO_SMASK)); opcode = ib_bth_get_opcode(packet->ohdr); inc_opstats(tlen, &rcd->opstats->stats[opcode]); @@ -885,7 +884,7 @@ int hfi1_verbs_send_dma(struct rvt_qp *qp, struct hfi1_pkt_state *ps, return ret; } trace_sdma_output_ibhdr(dd_from_ibdev(qp->ibqp.device), - &ps->s_txreq->phdr.hdr); + &ps->s_txreq->phdr.hdr, ib_is_sc5(sc5)); return ret; bail_ecomm: @@ -1058,7 +1057,7 @@ int hfi1_verbs_send_pio(struct rvt_qp *qp, struct hfi1_pkt_state *ps, } trace_pio_output_ibhdr(dd_from_ibdev(qp->ibqp.device), - &ps->s_txreq->phdr.hdr); + &ps->s_txreq->phdr.hdr, ib_is_sc5(sc5)); pio_bail: if (qp->s_wqe) { -- cgit v1.2.3 From 9039746cdf39dcbf2ddfcc4a68f729cbbbc853df Mon Sep 17 00:00:00 2001 From: Don Hiatt Date: Fri, 12 May 2017 09:20:20 -0700 Subject: IB/hfi1: Setup common IB fields in hfi1_packet struct We move many common IB fields into the hfi1_packet structure and set them up in a single function. This allows us to set the fields in a single place and not deal with them throughout the driver. Reviewed-by: Brian Welty Reviewed-by: Dasaratharaman Chandramouli Reviewed-by: Dennis Dalessandro Signed-off-by: Don Hiatt Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/chip.c | 9 -- drivers/infiniband/hw/hfi1/chip.h | 2 - drivers/infiniband/hw/hfi1/common.h | 1 + drivers/infiniband/hw/hfi1/driver.c | 158 +++++++++++++++++++++++++----------- drivers/infiniband/hw/hfi1/hfi.h | 21 ++++- drivers/infiniband/hw/hfi1/rc.c | 33 +++----- drivers/infiniband/hw/hfi1/ruc.c | 89 ++++++++++---------- drivers/infiniband/hw/hfi1/uc.c | 16 +--- drivers/infiniband/hw/hfi1/ud.c | 23 ++---- drivers/infiniband/hw/hfi1/verbs.c | 89 +++++++++----------- drivers/infiniband/hw/hfi1/verbs.h | 6 +- 11 files changed, 236 insertions(+), 211 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/hfi1/chip.c b/drivers/infiniband/hw/hfi1/chip.c index 2ba00b89df6a..5dbee3c1bd45 100644 --- a/drivers/infiniband/hw/hfi1/chip.c +++ b/drivers/infiniband/hw/hfi1/chip.c @@ -9810,15 +9810,6 @@ void hfi1_clear_tids(struct hfi1_ctxtdata *rcd) hfi1_put_tid(dd, i, PT_INVALID, 0, 0); } -struct ib_header *hfi1_get_msgheader( - struct hfi1_devdata *dd, __le32 *rhf_addr) -{ - u32 offset = rhf_hdrq_offset(rhf_to_cpu(rhf_addr)); - - return (struct ib_header *) - (rhf_addr - dd->rhf_offset + offset); -} - static const char * const ib_cfg_name_strings[] = { "HFI1_IB_CFG_LIDLMC", "HFI1_IB_CFG_LWID_DG_ENB", diff --git a/drivers/infiniband/hw/hfi1/chip.h b/drivers/infiniband/hw/hfi1/chip.h index cbe455d9ab8b..0b4f418ba0ac 100644 --- a/drivers/infiniband/hw/hfi1/chip.h +++ b/drivers/infiniband/hw/hfi1/chip.h @@ -1347,8 +1347,6 @@ enum { u64 get_all_cpu_total(u64 __percpu *cntr); void hfi1_start_cleanup(struct hfi1_devdata *dd); void hfi1_clear_tids(struct hfi1_ctxtdata *rcd); -struct ib_header *hfi1_get_msgheader( - struct hfi1_devdata *dd, __le32 *rhf_addr); void hfi1_init_ctxt(struct send_context *sc); void hfi1_put_tid(struct hfi1_devdata *dd, u32 index, u32 type, unsigned long pa, u16 order); diff --git a/drivers/infiniband/hw/hfi1/common.h b/drivers/infiniband/hw/hfi1/common.h index 995d62c7f9a7..ba9ab971ced9 100644 --- a/drivers/infiniband/hw/hfi1/common.h +++ b/drivers/infiniband/hw/hfi1/common.h @@ -325,6 +325,7 @@ struct diag_pkt { #define HFI1_LRH_BTH 0x0002 /* 1. word of IB LRH - next header: BTH */ /* misc. */ +#define SC15_PACKET 0xF #define SIZE_OF_CRC 1 #define LIM_MGMT_P_KEY 0x7FFF diff --git a/drivers/infiniband/hw/hfi1/driver.c b/drivers/infiniband/hw/hfi1/driver.c index 0583479f2576..2a1022e374a5 100644 --- a/drivers/infiniband/hw/hfi1/driver.c +++ b/drivers/infiniband/hw/hfi1/driver.c @@ -224,6 +224,20 @@ static inline void *get_egrbuf(const struct hfi1_ctxtdata *rcd, u64 rhf, (offset * RCV_BUF_BLOCK_SIZE)); } +static inline void *hfi1_get_header(struct hfi1_devdata *dd, + __le32 *rhf_addr) +{ + u32 offset = rhf_hdrq_offset(rhf_to_cpu(rhf_addr)); + + return (void *)(rhf_addr - dd->rhf_offset + offset); +} + +static inline struct ib_header *hfi1_get_msgheader(struct hfi1_devdata *dd, + __le32 *rhf_addr) +{ + return (struct ib_header *)hfi1_get_header(dd, rhf_addr); +} + /* * Validate and encode the a given RcvArray Buffer size. * The function will check whether the given size falls within @@ -249,7 +263,8 @@ static void rcv_hdrerr(struct hfi1_ctxtdata *rcd, struct hfi1_pportdata *ppd, { struct ib_header *rhdr = packet->hdr; u32 rte = rhf_rcv_type_err(packet->rhf); - int lnh = ib_get_lnh(rhdr); + u8 lnh = ib_get_lnh(rhdr); + bool has_grh = false; struct hfi1_ibport *ibp = rcd_to_iport(rcd); struct hfi1_devdata *dd = ppd->dd; struct rvt_dev_info *rdi = &dd->verbs_dev.rdi; @@ -257,37 +272,42 @@ static void rcv_hdrerr(struct hfi1_ctxtdata *rcd, struct hfi1_pportdata *ppd, if (packet->rhf & (RHF_VCRC_ERR | RHF_ICRC_ERR)) return; + if (lnh == HFI1_LRH_BTH) { + packet->ohdr = &rhdr->u.oth; + } else if (lnh == HFI1_LRH_GRH) { + has_grh = true; + packet->ohdr = &rhdr->u.l.oth; + packet->grh = &rhdr->u.l.grh; + } else { + goto drop; + } + if (packet->rhf & RHF_TID_ERR) { /* For TIDERR and RC QPs preemptively schedule a NAK */ - struct ib_other_headers *ohdr = NULL; u32 tlen = rhf_pkt_len(packet->rhf); /* in bytes */ - u16 lid = ib_get_dlid(rhdr); + u32 dlid = ib_get_dlid(rhdr); u32 qp_num; - u32 rcv_flags = 0; + u32 mlid_base = be16_to_cpu(IB_MULTICAST_LID_BASE); /* Sanity check packet */ if (tlen < 24) goto drop; /* Check for GRH */ - if (lnh == HFI1_LRH_BTH) { - ohdr = &rhdr->u.oth; - } else if (lnh == HFI1_LRH_GRH) { + if (has_grh) { u32 vtf; + struct ib_grh *grh = packet->grh; - ohdr = &rhdr->u.l.oth; - if (rhdr->u.l.grh.next_hdr != IB_GRH_NEXT_HDR) + if (grh->next_hdr != IB_GRH_NEXT_HDR) goto drop; - vtf = be32_to_cpu(rhdr->u.l.grh.version_tclass_flow); + vtf = be32_to_cpu(grh->version_tclass_flow); if ((vtf >> IB_GRH_VERSION_SHIFT) != IB_GRH_VERSION) goto drop; - rcv_flags |= HFI1_HAS_GRH; - } else { - goto drop; } + /* Get the destination QP number. */ - qp_num = ib_bth_get_qpn(ohdr); - if (lid < be16_to_cpu(IB_MULTICAST_LID_BASE)) { + qp_num = ib_bth_get_qpn(packet->ohdr); + if (dlid < mlid_base) { struct rvt_qp *qp; unsigned long flags; @@ -312,11 +332,7 @@ static void rcv_hdrerr(struct hfi1_ctxtdata *rcd, struct hfi1_pportdata *ppd, switch (qp->ibqp.qp_type) { case IB_QPT_RC: - hfi1_rc_hdrerr( - rcd, - rhdr, - rcv_flags, - qp); + hfi1_rc_hdrerr(rcd, packet, qp); break; default: /* For now don't handle any other QP types */ @@ -332,9 +348,8 @@ static void rcv_hdrerr(struct hfi1_ctxtdata *rcd, struct hfi1_pportdata *ppd, switch (rte) { case RHF_RTE_ERROR_OP_CODE_ERR: { - u32 opcode; void *ebuf = NULL; - __be32 *bth = NULL; + u8 opcode; if (rhf_use_egr_bfr(packet->rhf)) ebuf = packet->ebuf; @@ -342,16 +357,7 @@ static void rcv_hdrerr(struct hfi1_ctxtdata *rcd, struct hfi1_pportdata *ppd, if (!ebuf) goto drop; /* this should never happen */ - if (lnh == HFI1_LRH_BTH) - bth = (__be32 *)ebuf; - else if (lnh == HFI1_LRH_GRH) - bth = (__be32 *)((char *)ebuf + sizeof(struct ib_grh)); - else - goto drop; - - opcode = be32_to_cpu(bth[0]) >> 24; - opcode &= 0xff; - + opcode = ib_bth_get_opcode(packet->ohdr); if (opcode == IB_OPCODE_CNP) { /* * Only in pre-B0 h/w is the CNP_OPCODE handled @@ -365,7 +371,7 @@ static void rcv_hdrerr(struct hfi1_ctxtdata *rcd, struct hfi1_pportdata *ppd, sc5 = hfi1_9B_get_sc5(rhdr, packet->rhf); sl = ibp->sc_to_sl[sc5]; - lqpn = be32_to_cpu(bth[1]) & RVT_QPN_MASK; + lqpn = ib_bth_get_qpn(packet->ohdr); rcu_read_lock(); qp = rvt_lookup_qpn(rdi, &ibp->rvp, lqpn); if (!qp) { @@ -415,7 +421,6 @@ static inline void init_packet(struct hfi1_ctxtdata *rcd, packet->rhf = rhf_to_cpu(packet->rhf_addr); packet->rhqoff = rcd->head; packet->numpkt = 0; - packet->rcv_flags = 0; } void hfi1_process_ecn_slowpath(struct rvt_qp *qp, struct hfi1_packet *pkt, @@ -424,15 +429,12 @@ void hfi1_process_ecn_slowpath(struct rvt_qp *qp, struct hfi1_packet *pkt, struct hfi1_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num); struct ib_header *hdr = pkt->hdr; struct ib_other_headers *ohdr = pkt->ohdr; - struct ib_grh *grh = NULL; + struct ib_grh *grh = pkt->grh; u32 rqpn = 0, bth1; u16 rlid, dlid = ib_get_dlid(hdr); u8 sc, svc_type; bool is_mcast = false; - if (pkt->rcv_flags & HFI1_HAS_GRH) - grh = &hdr->u.l.grh; - switch (qp->ibqp.qp_type) { case IB_QPT_SMI: case IB_QPT_GSI: @@ -591,9 +593,10 @@ static void __prescan_rxq(struct hfi1_packet *packet) if (lnh == HFI1_LRH_BTH) { packet->ohdr = &hdr->u.oth; + packet->grh = NULL; } else if (lnh == HFI1_LRH_GRH) { packet->ohdr = &hdr->u.l.oth; - packet->rcv_flags |= HFI1_HAS_GRH; + packet->grh = &hdr->u.l.grh; } else { goto next; /* just in case */ } @@ -698,10 +701,9 @@ static inline int process_rcv_packet(struct hfi1_packet *packet, int thread) { int ret; - packet->hdr = hfi1_get_msgheader(packet->rcd->dd, - packet->rhf_addr); - packet->hlen = (u8 *)packet->rhf_addr - (u8 *)packet->hdr; packet->etype = rhf_rcv_type(packet->rhf); + + packet->hlen = (u8 *)packet->rhf_addr - (u8 *)packet->hdr; /* total length */ packet->tlen = rhf_pkt_len(packet->rhf); /* in bytes */ /* retrieve eager buffer details */ @@ -759,7 +761,7 @@ static inline void process_rcv_update(int last, struct hfi1_packet *packet) packet->etail, 0, 0); packet->updegr = 0; } - packet->rcv_flags = 0; + packet->grh = NULL; } static inline void finish_packet(struct hfi1_packet *packet) @@ -896,12 +898,15 @@ static inline int set_armed_to_active(struct hfi1_ctxtdata *rcd, struct hfi1_devdata *dd) { struct work_struct *lsaw = &rcd->ppd->linkstate_active_work; - struct ib_header *hdr = hfi1_get_msgheader(packet->rcd->dd, - packet->rhf_addr); u8 etype = rhf_rcv_type(packet->rhf); + u8 sc = SC15_PACKET; - if (etype == RHF_RCV_TYPE_IB && - hfi1_9B_get_sc5(hdr, packet->rhf) != 0xf) { + if (etype == RHF_RCV_TYPE_IB) { + struct ib_header *hdr = hfi1_get_msgheader(packet->rcd->dd, + packet->rhf_addr); + sc = hfi1_9B_get_sc5(hdr, packet->rhf); + } + if (sc != SC15_PACKET) { int hwstate = read_logical_state(dd); if (hwstate != LSTATE_ACTIVE) { @@ -1321,6 +1326,58 @@ bail: return ret; } +static inline void hfi1_setup_ib_header(struct hfi1_packet *packet) +{ + packet->hdr = (struct hfi1_ib_message_header *) + hfi1_get_msgheader(packet->rcd->dd, + packet->rhf_addr); + packet->hlen = (u8 *)packet->rhf_addr - (u8 *)packet->hdr; +} + +static int hfi1_setup_9B_packet(struct hfi1_packet *packet) +{ + struct hfi1_ibport *ibp = rcd_to_iport(packet->rcd); + struct ib_header *hdr; + u8 lnh; + + hfi1_setup_ib_header(packet); + hdr = packet->hdr; + + lnh = ib_get_lnh(hdr); + if (lnh == HFI1_LRH_BTH) { + packet->ohdr = &hdr->u.oth; + packet->grh = NULL; + } else if (lnh == HFI1_LRH_GRH) { + u32 vtf; + + packet->ohdr = &hdr->u.l.oth; + packet->grh = &hdr->u.l.grh; + if (packet->grh->next_hdr != IB_GRH_NEXT_HDR) + goto drop; + vtf = be32_to_cpu(packet->grh->version_tclass_flow); + if ((vtf >> IB_GRH_VERSION_SHIFT) != IB_GRH_VERSION) + goto drop; + } else { + goto drop; + } + + /* Query commonly used fields from packet header */ + packet->opcode = ib_bth_get_opcode(packet->ohdr); + packet->slid = ib_get_slid(hdr); + packet->dlid = ib_get_dlid(hdr); + packet->sl = ib_get_sl(hdr); + packet->sc = hfi1_9B_get_sc5(hdr, packet->rhf); + packet->pad = ib_bth_get_pad(packet->ohdr); + packet->extra_byte = 0; + packet->fecn = ib_bth_get_fecn(packet->ohdr); + packet->becn = ib_bth_get_becn(packet->ohdr); + + return 0; +drop: + ibp->rvp.n_pkt_drops++; + return -EINVAL; +} + void handle_eflags(struct hfi1_packet *packet) { struct hfi1_ctxtdata *rcd = packet->rcd; @@ -1351,6 +1408,9 @@ int process_receive_ib(struct hfi1_packet *packet) if (unlikely(hfi1_dbg_fault_packet(packet))) return RHF_RCV_CONTINUE; + if (hfi1_setup_9B_packet(packet)) + return RHF_RCV_CONTINUE; + trace_hfi1_rcvhdr(packet->rcd->ppd->dd, packet->rcd->ctxt, rhf_err_flags(packet->rhf), @@ -1422,6 +1482,7 @@ int process_receive_error(struct hfi1_packet *packet) rhf_rcv_type_err(packet->rhf) == 3)) return RHF_RCV_CONTINUE; + hfi1_setup_ib_header(packet); handle_eflags(packet); if (unlikely(rhf_err_flags(packet->rhf))) @@ -1435,6 +1496,8 @@ int kdeth_process_expected(struct hfi1_packet *packet) { if (unlikely(hfi1_dbg_fault_packet(packet))) return RHF_RCV_CONTINUE; + + hfi1_setup_ib_header(packet); if (unlikely(rhf_err_flags(packet->rhf))) handle_eflags(packet); @@ -1445,6 +1508,7 @@ int kdeth_process_expected(struct hfi1_packet *packet) int kdeth_process_eager(struct hfi1_packet *packet) { + hfi1_setup_ib_header(packet); if (unlikely(rhf_err_flags(packet->rhf))) handle_eflags(packet); if (unlikely(hfi1_dbg_fault_packet(packet))) diff --git a/drivers/infiniband/hw/hfi1/hfi.h b/drivers/infiniband/hw/hfi1/hfi.h index 3b76631cbcbd..9c6c73448461 100644 --- a/drivers/infiniband/hw/hfi1/hfi.h +++ b/drivers/infiniband/hw/hfi1/hfi.h @@ -356,17 +356,26 @@ struct hfi1_packet { __le32 *rhf_addr; struct rvt_qp *qp; struct ib_other_headers *ohdr; + struct ib_grh *grh; u64 rhf; u32 maxcnt; u32 rhqoff; + u32 dlid; + u32 slid; u16 tlen; s16 etail; u8 hlen; u8 numpkt; u8 rsize; u8 updegr; - u8 rcv_flags; u8 etype; + u8 extra_byte; + u8 pad; + u8 sc; + u8 sl; + u8 opcode; + bool becn; + bool fecn; }; struct rvt_sge_state; @@ -2086,4 +2095,14 @@ int hfi1_tempsense_rd(struct hfi1_devdata *dd, struct hfi1_temp *temp); #define DD_DEV_ENTRY(dd) __string(dev, dev_name(&(dd)->pcidev->dev)) #define DD_DEV_ASSIGN(dd) __assign_str(dev, dev_name(&(dd)->pcidev->dev)) + +/* + * hfi1_check_mcast- Check if the given lid is + * in the IB multicast range. + */ +static inline bool hfi1_check_mcast(u16 lid) +{ + return ((lid >= be16_to_cpu(IB_MULTICAST_LID_BASE)) && + (lid != be16_to_cpu(IB_LID_PERMISSIVE))); +} #endif /* _HFI1_KERNEL_H */ diff --git a/drivers/infiniband/hw/hfi1/rc.c b/drivers/infiniband/hw/hfi1/rc.c index b443c1e01543..baa67bf0772b 100644 --- a/drivers/infiniband/hw/hfi1/rc.c +++ b/drivers/infiniband/hw/hfi1/rc.c @@ -1916,17 +1916,16 @@ void process_becn(struct hfi1_pportdata *ppd, u8 sl, u16 rlid, u32 lqpn, void hfi1_rc_rcv(struct hfi1_packet *packet) { struct hfi1_ctxtdata *rcd = packet->rcd; - struct ib_header *hdr = packet->hdr; - u32 rcv_flags = packet->rcv_flags; void *data = packet->ebuf; u32 tlen = packet->tlen; struct rvt_qp *qp = packet->qp; struct hfi1_ibport *ibp = rcd_to_iport(rcd); struct ib_other_headers *ohdr = packet->ohdr; - u32 bth0, opcode; + u32 bth0; + u32 opcode = packet->opcode; u32 hdrsize = packet->hlen; u32 psn; - u32 pad; + u32 pad = packet->pad; struct ib_wc wc; u32 pmtu = qp->pmtu; int diff; @@ -1938,14 +1937,13 @@ void hfi1_rc_rcv(struct hfi1_packet *packet) u32 rkey; lockdep_assert_held(&qp->r_lock); + bth0 = be32_to_cpu(ohdr->bth[0]); - if (hfi1_ruc_check_hdr(ibp, hdr, rcv_flags & HFI1_HAS_GRH, qp, bth0)) + if (hfi1_ruc_check_hdr(ibp, packet)) return; is_fecn = process_ecn(qp, packet, false); - psn = ib_bth_get_psn(ohdr); - opcode = ib_bth_get_opcode(ohdr); /* * Process responses (ACKs) before anything else. Note that the @@ -2075,8 +2073,6 @@ no_immediate_data: wc.wc_flags = 0; wc.ex.imm_data = 0; send_last: - /* Get the number of bytes the message was padded by. */ - pad = ib_bth_get_pad(ohdr); /* Check for invalid length. */ /* LAST len should be >= 1 */ if (unlikely(tlen < (hdrsize + pad + 4))) @@ -2369,28 +2365,19 @@ send_ack: void hfi1_rc_hdrerr( struct hfi1_ctxtdata *rcd, - struct ib_header *hdr, - u32 rcv_flags, + struct hfi1_packet *packet, struct rvt_qp *qp) { - int has_grh = rcv_flags & HFI1_HAS_GRH; - struct ib_other_headers *ohdr; struct hfi1_ibport *ibp = rcd_to_iport(rcd); int diff; u32 opcode; - u32 psn, bth0; - - /* Check for GRH */ - ohdr = &hdr->u.oth; - if (has_grh) - ohdr = &hdr->u.l.oth; + u32 psn; - bth0 = be32_to_cpu(ohdr->bth[0]); - if (hfi1_ruc_check_hdr(ibp, hdr, has_grh, qp, bth0)) + if (hfi1_ruc_check_hdr(ibp, packet)) return; - psn = ib_bth_get_psn(ohdr); - opcode = ib_bth_get_opcode(ohdr); + psn = ib_bth_get_psn(packet->ohdr); + opcode = ib_bth_get_opcode(packet->ohdr); /* Only deal with RDMA Writes for now */ if (opcode < IB_OPCODE_RC_RDMA_READ_RESPONSE_FIRST) { diff --git a/drivers/infiniband/hw/hfi1/ruc.c b/drivers/infiniband/hw/hfi1/ruc.c index 3a17daba28a9..9cc9c7be9dd4 100644 --- a/drivers/infiniband/hw/hfi1/ruc.c +++ b/drivers/infiniband/hw/hfi1/ruc.c @@ -214,100 +214,95 @@ static int gid_ok(union ib_gid *gid, __be64 gid_prefix, __be64 id) * * The s_lock will be acquired around the hfi1_migrate_qp() call. */ -int hfi1_ruc_check_hdr(struct hfi1_ibport *ibp, struct ib_header *hdr, - int has_grh, struct rvt_qp *qp, u32 bth0) +int hfi1_ruc_check_hdr(struct hfi1_ibport *ibp, struct hfi1_packet *packet) { __be64 guid; unsigned long flags; + struct rvt_qp *qp = packet->qp; u8 sc5 = ibp->sl_to_sc[rdma_ah_get_sl(&qp->remote_ah_attr)]; - - if (qp->s_mig_state == IB_MIG_ARMED && (bth0 & IB_BTH_MIG_REQ)) { - if (!has_grh) { + u32 dlid = packet->dlid; + u32 slid = packet->slid; + u32 sl = packet->sl; + int migrated; + u32 bth0, bth1; + + bth0 = be32_to_cpu(packet->ohdr->bth[0]); + bth1 = be32_to_cpu(packet->ohdr->bth[1]); + migrated = bth0 & IB_BTH_MIG_REQ; + + if (qp->s_mig_state == IB_MIG_ARMED && migrated) { + if (!packet->grh) { if (rdma_ah_get_ah_flags(&qp->alt_ah_attr) & IB_AH_GRH) - goto err; + return 1; } else { const struct ib_global_route *grh; if (!(rdma_ah_get_ah_flags(&qp->alt_ah_attr) & IB_AH_GRH)) - goto err; + return 1; grh = rdma_ah_read_grh(&qp->alt_ah_attr); guid = get_sguid(ibp, grh->sgid_index); - if (!gid_ok(&hdr->u.l.grh.dgid, ibp->rvp.gid_prefix, + if (!gid_ok(&packet->grh->dgid, ibp->rvp.gid_prefix, guid)) - goto err; + return 1; if (!gid_ok( - &hdr->u.l.grh.sgid, + &packet->grh->sgid, grh->dgid.global.subnet_prefix, grh->dgid.global.interface_id)) - goto err; + return 1; } - if (unlikely(rcv_pkey_check(ppd_from_ibp(ibp), (u16)bth0, sc5, - ib_get_slid(hdr)))) { - hfi1_bad_pqkey(ibp, OPA_TRAP_BAD_P_KEY, - (u16)bth0, - ib_get_sl(hdr), - 0, qp->ibqp.qp_num, - ib_get_slid(hdr), - ib_get_dlid(hdr)); - goto err; + if (unlikely(rcv_pkey_check(ppd_from_ibp(ibp), (u16)bth0, + sc5, slid))) { + hfi1_bad_pqkey(ibp, OPA_TRAP_BAD_P_KEY, (u16)bth0, sl, + 0, qp->ibqp.qp_num, slid, dlid); + return 1; } /* Validate the SLID. See Ch. 9.6.1.5 and 17.2.8 */ - if (ib_get_slid(hdr) != - rdma_ah_get_dlid(&qp->alt_ah_attr) || + if (slid != rdma_ah_get_dlid(&qp->alt_ah_attr) || ppd_from_ibp(ibp)->port != rdma_ah_get_port_num(&qp->alt_ah_attr)) - goto err; + return 1; spin_lock_irqsave(&qp->s_lock, flags); hfi1_migrate_qp(qp); spin_unlock_irqrestore(&qp->s_lock, flags); } else { - if (!has_grh) { + if (!packet->grh) { if (rdma_ah_get_ah_flags(&qp->remote_ah_attr) & IB_AH_GRH) - goto err; + return 1; } else { const struct ib_global_route *grh; if (!(rdma_ah_get_ah_flags(&qp->remote_ah_attr) & IB_AH_GRH)) - goto err; + return 1; grh = rdma_ah_read_grh(&qp->remote_ah_attr); guid = get_sguid(ibp, grh->sgid_index); - if (!gid_ok(&hdr->u.l.grh.dgid, ibp->rvp.gid_prefix, + if (!gid_ok(&packet->grh->dgid, ibp->rvp.gid_prefix, guid)) - goto err; + return 1; if (!gid_ok( - &hdr->u.l.grh.sgid, + &packet->grh->sgid, grh->dgid.global.subnet_prefix, grh->dgid.global.interface_id)) - goto err; + return 1; } - if (unlikely(rcv_pkey_check(ppd_from_ibp(ibp), (u16)bth0, sc5, - ib_get_slid(hdr)))) { - hfi1_bad_pqkey(ibp, OPA_TRAP_BAD_P_KEY, - (u16)bth0, - ib_get_sl(hdr), - 0, qp->ibqp.qp_num, - ib_get_slid(hdr), - ib_get_dlid(hdr)); - goto err; + if (unlikely(rcv_pkey_check(ppd_from_ibp(ibp), (u16)bth0, + sc5, slid))) { + hfi1_bad_pqkey(ibp, OPA_TRAP_BAD_P_KEY, (u16)bth0, sl, + 0, qp->ibqp.qp_num, slid, dlid); + return 1; } /* Validate the SLID. See Ch. 9.6.1.5 */ - if (ib_get_slid(hdr) != - rdma_ah_get_dlid(&qp->remote_ah_attr) || + if ((slid != rdma_ah_get_dlid(&qp->remote_ah_attr)) || ppd_from_ibp(ibp)->port != qp->port_num) - goto err; - if (qp->s_mig_state == IB_MIG_REARM && - !(bth0 & IB_BTH_MIG_REQ)) + return 1; + if (qp->s_mig_state == IB_MIG_REARM && !migrated) qp->s_mig_state = IB_MIG_ARMED; } return 0; - -err: - return 1; } /** diff --git a/drivers/infiniband/hw/hfi1/uc.c b/drivers/infiniband/hw/hfi1/uc.c index 2a5650f8aee0..76c2451a53d7 100644 --- a/drivers/infiniband/hw/hfi1/uc.c +++ b/drivers/infiniband/hw/hfi1/uc.c @@ -297,31 +297,25 @@ bail_no_tx: void hfi1_uc_rcv(struct hfi1_packet *packet) { struct hfi1_ibport *ibp = rcd_to_iport(packet->rcd); - struct ib_header *hdr = packet->hdr; - u32 rcv_flags = packet->rcv_flags; void *data = packet->ebuf; u32 tlen = packet->tlen; struct rvt_qp *qp = packet->qp; struct ib_other_headers *ohdr = packet->ohdr; - u32 bth0, opcode; + u32 opcode = packet->opcode; u32 hdrsize = packet->hlen; u32 psn; - u32 pad; + u32 pad = packet->pad; struct ib_wc wc; u32 pmtu = qp->pmtu; struct ib_reth *reth; - int has_grh = rcv_flags & HFI1_HAS_GRH; int ret; - bth0 = be32_to_cpu(ohdr->bth[0]); - if (hfi1_ruc_check_hdr(ibp, hdr, has_grh, qp, bth0)) + if (hfi1_ruc_check_hdr(ibp, packet)) return; process_ecn(qp, packet, true); psn = ib_bth_get_psn(ohdr); - opcode = ib_bth_get_opcode(ohdr); - /* Compare the PSN verses the expected PSN. */ if (unlikely(cmp_psn(psn, qp->r_psn) != 0)) { /* @@ -432,8 +426,6 @@ no_immediate_data: wc.ex.imm_data = 0; wc.wc_flags = 0; send_last: - /* Get the number of bytes the message was padded by. */ - pad = ib_bth_get_pad(ohdr); /* Check for invalid length. */ /* LAST len should be >= 1 */ if (unlikely(tlen < (hdrsize + pad + 4))) @@ -527,8 +519,6 @@ rdma_first: rdma_last_imm: wc.wc_flags = IB_WC_WITH_IMM; - /* Get the number of bytes the message was padded by. */ - pad = ib_bth_get_pad(ohdr); /* Check for invalid length. */ /* LAST len should be >= 1 */ if (unlikely(tlen < (hdrsize + pad + 4))) diff --git a/drivers/infiniband/hw/hfi1/ud.c b/drivers/infiniband/hw/hfi1/ud.c index 49fe179ad3ae..c995aa58c36a 100644 --- a/drivers/infiniband/hw/hfi1/ud.c +++ b/drivers/infiniband/hw/hfi1/ud.c @@ -668,36 +668,31 @@ static int opa_smp_check(struct hfi1_ibport *ibp, u16 pkey, u8 sc5, void hfi1_ud_rcv(struct hfi1_packet *packet) { struct ib_other_headers *ohdr = packet->ohdr; - int opcode; u32 hdrsize = packet->hlen; struct ib_wc wc; u32 qkey; u32 src_qp; - u16 dlid, pkey; + u16 pkey; int mgmt_pkey_idx = -1; struct hfi1_ibport *ibp = rcd_to_iport(packet->rcd); struct hfi1_pportdata *ppd = ppd_from_ibp(ibp); struct ib_header *hdr = packet->hdr; - u32 rcv_flags = packet->rcv_flags; void *data = packet->ebuf; u32 tlen = packet->tlen; struct rvt_qp *qp = packet->qp; - bool has_grh = rcv_flags & HFI1_HAS_GRH; u8 sc5 = hfi1_9B_get_sc5(hdr, packet->rhf); u32 bth1; - u8 sl_from_sc, sl; - u16 slid; - u8 extra_bytes; + u8 sl_from_sc; + u8 extra_bytes = packet->pad; + u8 opcode = packet->opcode; + u8 sl = packet->sl; + u32 dlid = packet->dlid; + u32 slid = packet->slid; + bth1 = be32_to_cpu(ohdr->bth[1]); qkey = ib_get_qkey(ohdr); src_qp = ib_get_sqpn(ohdr); - dlid = ib_get_dlid(hdr); - bth1 = be32_to_cpu(ohdr->bth[1]); - slid = ib_get_slid(hdr); pkey = ib_bth_get_pkey(ohdr); - opcode = ib_bth_get_opcode(ohdr); - sl = ib_get_sl(hdr); - extra_bytes = ib_bth_get_pad(ohdr); extra_bytes += (SIZE_OF_CRC << 2); sl_from_sc = ibp->sc_to_sl[sc5]; @@ -811,7 +806,7 @@ void hfi1_ud_rcv(struct hfi1_packet *packet) qp->r_flags |= RVT_R_REUSE_SGE; goto drop; } - if (has_grh) { + if (packet->grh) { hfi1_copy_sge(&qp->r_sge, &hdr->u.l.grh, sizeof(struct ib_grh), true, false); wc.wc_flags |= IB_WC_GRH; diff --git a/drivers/infiniband/hw/hfi1/verbs.c b/drivers/infiniband/hw/hfi1/verbs.c index 5f4be35f31b6..af54d3f4696a 100644 --- a/drivers/infiniband/hw/hfi1/verbs.c +++ b/drivers/infiniband/hw/hfi1/verbs.c @@ -508,13 +508,14 @@ again: /* * Make sure the QP is ready and able to accept the given opcode. */ -static inline opcode_handler qp_ok(int opcode, struct hfi1_packet *packet) +static inline opcode_handler qp_ok(struct hfi1_packet *packet) { if (!(ib_rvt_state_ops[packet->qp->state] & RVT_PROCESS_RECV_OK)) return NULL; - if (((opcode & RVT_OPCODE_QP_MASK) == packet->qp->allowed_ops) || - (opcode == IB_OPCODE_CNP)) - return opcode_handler_tbl[opcode]; + if (((packet->opcode & RVT_OPCODE_QP_MASK) == + packet->qp->allowed_ops) || + (packet->opcode == IB_OPCODE_CNP)) + return opcode_handler_tbl[packet->opcode]; return NULL; } @@ -548,68 +549,34 @@ static u64 hfi1_fault_tx(struct rvt_qp *qp, u8 opcode, u64 pbc) return pbc; } -/** - * hfi1_ib_rcv - process an incoming packet - * @packet: data packet information - * - * This is called to process an incoming packet at interrupt level. - * - * Tlen is the length of the header + data + CRC in bytes. - */ -void hfi1_ib_rcv(struct hfi1_packet *packet) +static inline void hfi1_handle_packet(struct hfi1_packet *packet, + bool is_mcast) { + u32 qp_num; struct hfi1_ctxtdata *rcd = packet->rcd; - struct ib_header *hdr = packet->hdr; - u32 tlen = packet->tlen; struct hfi1_pportdata *ppd = rcd->ppd; struct hfi1_ibport *ibp = rcd_to_iport(rcd); struct rvt_dev_info *rdi = &ppd->dd->verbs_dev.rdi; opcode_handler packet_handler; unsigned long flags; - u32 qp_num; - int lnh; - u8 opcode; - u16 lid; - - /* Check for GRH */ - lnh = ib_get_lnh(hdr); - if (lnh == HFI1_LRH_BTH) { - packet->ohdr = &hdr->u.oth; - } else if (lnh == HFI1_LRH_GRH) { - u32 vtf; - - packet->ohdr = &hdr->u.l.oth; - if (hdr->u.l.grh.next_hdr != IB_GRH_NEXT_HDR) - goto drop; - vtf = be32_to_cpu(hdr->u.l.grh.version_tclass_flow); - if ((vtf >> IB_GRH_VERSION_SHIFT) != IB_GRH_VERSION) - goto drop; - packet->rcv_flags |= HFI1_HAS_GRH; - } else { - goto drop; - } - trace_input_ibhdr(rcd->dd, packet, !!(packet->rhf & RHF_DC_INFO_SMASK)); - opcode = ib_bth_get_opcode(packet->ohdr); - inc_opstats(tlen, &rcd->opstats->stats[opcode]); + inc_opstats(packet->tlen, &rcd->opstats->stats[packet->opcode]); - /* Get the destination QP number. */ - qp_num = ib_bth_get_qpn(packet->ohdr); - lid = ib_get_dlid(hdr); - if (unlikely((lid >= be16_to_cpu(IB_MULTICAST_LID_BASE)) && - (lid != be16_to_cpu(IB_LID_PERMISSIVE)))) { + if (unlikely(is_mcast)) { struct rvt_mcast *mcast; struct rvt_mcast_qp *p; - if (lnh != HFI1_LRH_GRH) + if (!packet->grh) goto drop; - mcast = rvt_mcast_find(&ibp->rvp, &hdr->u.l.grh.dgid, lid); + mcast = rvt_mcast_find(&ibp->rvp, + &packet->grh->dgid, + packet->dlid); if (!mcast) goto drop; list_for_each_entry_rcu(p, &mcast->qp_list, list) { packet->qp = p->qp; spin_lock_irqsave(&packet->qp->r_lock, flags); - packet_handler = qp_ok(opcode, packet); + packet_handler = qp_ok(packet); if (likely(packet_handler)) packet_handler(packet); else @@ -623,19 +590,21 @@ void hfi1_ib_rcv(struct hfi1_packet *packet) if (atomic_dec_return(&mcast->refcount) <= 1) wake_up(&mcast->wait); } else { + /* Get the destination QP number. */ + qp_num = ib_bth_get_qpn(packet->ohdr); rcu_read_lock(); packet->qp = rvt_lookup_qpn(rdi, &ibp->rvp, qp_num); if (!packet->qp) { rcu_read_unlock(); goto drop; } - if (unlikely(hfi1_dbg_fault_opcode(packet->qp, opcode, + if (unlikely(hfi1_dbg_fault_opcode(packet->qp, packet->opcode, true))) { rcu_read_unlock(); goto drop; } spin_lock_irqsave(&packet->qp->r_lock, flags); - packet_handler = qp_ok(opcode, packet); + packet_handler = qp_ok(packet); if (likely(packet_handler)) packet_handler(packet); else @@ -644,11 +613,29 @@ void hfi1_ib_rcv(struct hfi1_packet *packet) rcu_read_unlock(); } return; - drop: ibp->rvp.n_pkt_drops++; } +/** + * hfi1_ib_rcv - process an incoming packet + * @packet: data packet information + * + * This is called to process an incoming packet at interrupt level. + */ +void hfi1_ib_rcv(struct hfi1_packet *packet) +{ + struct hfi1_ctxtdata *rcd = packet->rcd; + bool is_mcast = false; + + if (unlikely(hfi1_check_mcast(packet->dlid))) + is_mcast = true; + + trace_input_ibhdr(rcd->dd, packet, + !!(packet->rhf & RHF_DC_INFO_SMASK)); + hfi1_handle_packet(packet, is_mcast); +} + /* * This is called from a timer to check for QPs * which need kernel memory in order to send a packet. diff --git a/drivers/infiniband/hw/hfi1/verbs.h b/drivers/infiniband/hw/hfi1/verbs.h index cd635d0c1d3b..17b38cd5f654 100644 --- a/drivers/infiniband/hw/hfi1/verbs.h +++ b/drivers/infiniband/hw/hfi1/verbs.h @@ -307,8 +307,7 @@ void hfi1_rc_rcv(struct hfi1_packet *packet); void hfi1_rc_hdrerr( struct hfi1_ctxtdata *rcd, - struct ib_header *hdr, - u32 rcv_flags, + struct hfi1_packet *packet, struct rvt_qp *qp); u8 ah_to_sc(struct ib_device *ibdev, struct rdma_ah_attr *ah_attr); @@ -346,8 +345,7 @@ static inline u8 get_opcode(struct ib_header *h) return be32_to_cpu(h->u.l.oth.bth[0]) >> 24; } -int hfi1_ruc_check_hdr(struct hfi1_ibport *ibp, struct ib_header *hdr, - int has_grh, struct rvt_qp *qp, u32 bth0); +int hfi1_ruc_check_hdr(struct hfi1_ibport *ibp, struct hfi1_packet *packet); u32 hfi1_make_grh(struct hfi1_ibport *ibp, struct ib_grh *hdr, const struct ib_global_route *grh, u32 hwords, u32 nwords); -- cgit v1.2.3 From 14fe13fcd3afb96b06809f280b586be1c998332c Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Fri, 12 May 2017 09:20:31 -0700 Subject: IB/rdmavt: Compress adjacent SGEs in rvt_lkey_ok() SGEs that are contiguous needlessly consume driver dependent TX resources. The lkey validation logic is enhanced to compress the SGE that ends up in the send wqe when consecutive addresses are detected. The lkey validation API used to return 1 (success) or 0 (fail). The return value is now an -errno, 0 (compressed), or 1 (uncompressed). A additional argument is added to pass the last SQE for the compression. Loopback callers always pass a NULL to last_sge since the optimization is of little benefit in that situation. Reviewed-by: Dennis Dalessandro Signed-off-by: Brian Welty Signed-off-by: Venkata Sandeep Dhanalakota Signed-off-by: Mike Marciniszyn Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/ruc.c | 2 +- drivers/infiniband/hw/qib/qib_ruc.c | 2 +- drivers/infiniband/sw/rdmavt/mr.c | 51 +++++++++++++++++++++++---- drivers/infiniband/sw/rdmavt/qp.c | 23 ++++++------ drivers/infiniband/sw/rdmavt/trace_mr.h | 62 +++++++++++++++++++++++++++++++++ drivers/infiniband/sw/rdmavt/trace_tx.h | 11 +++--- include/rdma/rdma_vt.h | 3 +- 7 files changed, 130 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/hfi1/ruc.c b/drivers/infiniband/hw/hfi1/ruc.c index 9cc9c7be9dd4..476fe5da2992 100644 --- a/drivers/infiniband/hw/hfi1/ruc.c +++ b/drivers/infiniband/hw/hfi1/ruc.c @@ -75,7 +75,7 @@ static int init_sge(struct rvt_qp *qp, struct rvt_rwqe *wqe) continue; /* Check LKEY */ if (!rvt_lkey_ok(rkt, pd, j ? &ss->sg_list[j - 1] : &ss->sge, - &wqe->sg_list[i], IB_ACCESS_LOCAL_WRITE)) + NULL, &wqe->sg_list[i], IB_ACCESS_LOCAL_WRITE)) goto bad_lkey; qp->r_len += wqe->sg_list[i].length; j++; diff --git a/drivers/infiniband/hw/qib/qib_ruc.c b/drivers/infiniband/hw/qib/qib_ruc.c index bd09de7c6e56..88d84cbf7e5a 100644 --- a/drivers/infiniband/hw/qib/qib_ruc.c +++ b/drivers/infiniband/hw/qib/qib_ruc.c @@ -59,7 +59,7 @@ static int qib_init_sge(struct rvt_qp *qp, struct rvt_rwqe *wqe) continue; /* Check LKEY */ if (!rvt_lkey_ok(rkt, pd, j ? &ss->sg_list[j - 1] : &ss->sge, - &wqe->sg_list[i], IB_ACCESS_LOCAL_WRITE)) + NULL, &wqe->sg_list[i], IB_ACCESS_LOCAL_WRITE)) goto bad_lkey; qp->r_len += wqe->sg_list[i].length; j++; diff --git a/drivers/infiniband/sw/rdmavt/mr.c b/drivers/infiniband/sw/rdmavt/mr.c index aa5f9ea318e4..ea95672d9675 100644 --- a/drivers/infiniband/sw/rdmavt/mr.c +++ b/drivers/infiniband/sw/rdmavt/mr.c @@ -777,24 +777,55 @@ out: return ret; } +/** + * rvt_sge_adjacent - is isge compressible + * @isge: outgoing internal SGE + * @last_sge: last outgoing SGE written + * @sge: SGE to check + * + * If adjacent will update last_sge to add length. + * + * Return: true if isge is adjacent to last sge + */ +static inline bool rvt_sge_adjacent(struct rvt_sge *isge, + struct rvt_sge *last_sge, + struct ib_sge *sge) +{ + if (last_sge && sge->lkey == last_sge->mr->lkey && + ((uint64_t)(last_sge->vaddr + last_sge->length) == sge->addr)) { + if (sge->lkey) { + if (unlikely((sge->addr - last_sge->mr->user_base + + sge->length > last_sge->mr->length))) + return false; /* overrun, caller will catch */ + } else { + last_sge->length += sge->length; + } + last_sge->sge_length += sge->length; + trace_rvt_sge_adjacent(last_sge, sge); + return true; + } + return false; +} + /** * rvt_lkey_ok - check IB SGE for validity and initialize * @rkt: table containing lkey to check SGE against * @pd: protection domain * @isge: outgoing internal SGE + * @last_sge: last outgoing SGE written * @sge: SGE to check * @acc: access flags * * Check the IB SGE for validity and initialize our internal version * of it. * - * Return: 1 if valid and successful, otherwise returns 0. - * - * increments the reference count upon success + * Increments the reference count when a new sge is stored. * + * Return: 0 if compressed, 1 if added , otherwise returns -errno. */ int rvt_lkey_ok(struct rvt_lkey_table *rkt, struct rvt_pd *pd, - struct rvt_sge *isge, struct ib_sge *sge, int acc) + struct rvt_sge *isge, struct rvt_sge *last_sge, + struct ib_sge *sge, int acc) { struct rvt_mregion *mr; unsigned n, m; @@ -804,12 +835,14 @@ int rvt_lkey_ok(struct rvt_lkey_table *rkt, struct rvt_pd *pd, * We use LKEY == zero for kernel virtual addresses * (see rvt_get_dma_mr() and dma_virt_ops). */ - rcu_read_lock(); if (sge->lkey == 0) { struct rvt_dev_info *dev = ib_to_rvt(pd->ibpd.device); if (pd->user) - goto bail; + return -EINVAL; + if (rvt_sge_adjacent(isge, last_sge, sge)) + return 0; + rcu_read_lock(); mr = rcu_dereference(dev->dma_mr); if (!mr) goto bail; @@ -824,6 +857,9 @@ int rvt_lkey_ok(struct rvt_lkey_table *rkt, struct rvt_pd *pd, isge->n = 0; goto ok; } + if (rvt_sge_adjacent(isge, last_sge, sge)) + return 0; + rcu_read_lock(); mr = rcu_dereference(rkt->table[sge->lkey >> rkt->shift]); if (!mr) goto bail; @@ -874,12 +910,13 @@ int rvt_lkey_ok(struct rvt_lkey_table *rkt, struct rvt_pd *pd, isge->m = m; isge->n = n; ok: + trace_rvt_sge_new(isge, sge); return 1; bail_unref: rvt_put_mr(mr); bail: rcu_read_unlock(); - return 0; + return -EINVAL; } EXPORT_SYMBOL(rvt_lkey_ok); diff --git a/drivers/infiniband/sw/rdmavt/qp.c b/drivers/infiniband/sw/rdmavt/qp.c index 727e81cc2c8f..a3dd1e536860 100644 --- a/drivers/infiniband/sw/rdmavt/qp.c +++ b/drivers/infiniband/sw/rdmavt/qp.c @@ -1646,7 +1646,7 @@ static int rvt_post_one_wr(struct rvt_qp *qp, struct rvt_pd *pd; struct rvt_dev_info *rdi = ib_to_rvt(qp->ibqp.device); u8 log_pmtu; - int ret; + int ret, incr; size_t cplen; bool reserved_op; int local_ops_delayed = 0; @@ -1719,22 +1719,23 @@ static int rvt_post_one_wr(struct rvt_qp *qp, wqe->length = 0; j = 0; if (wr->num_sge) { + struct rvt_sge *last_sge = NULL; + acc = wr->opcode >= IB_WR_RDMA_READ ? IB_ACCESS_LOCAL_WRITE : 0; for (i = 0; i < wr->num_sge; i++) { u32 length = wr->sg_list[i].length; - int ok; if (length == 0) continue; - ok = rvt_lkey_ok(rkt, pd, &wqe->sg_list[j], - &wr->sg_list[i], acc); - if (!ok) { - ret = -EINVAL; - goto bail_inval_free; - } + incr = rvt_lkey_ok(rkt, pd, &wqe->sg_list[j], last_sge, + &wr->sg_list[i], acc); + if (unlikely(incr < 0)) + goto bail_lkey_error; wqe->length += length; - j++; + if (incr) + last_sge = &wqe->sg_list[j]; + j += incr; } wqe->wr.num_sge = j; } @@ -1781,12 +1782,14 @@ static int rvt_post_one_wr(struct rvt_qp *qp, wqe->wr.send_flags &= ~RVT_SEND_RESERVE_USED; qp->s_avail--; } - trace_rvt_post_one_wr(qp, wqe); + trace_rvt_post_one_wr(qp, wqe, wr->num_sge); smp_wmb(); /* see request builders */ qp->s_head = next; return 0; +bail_lkey_error: + ret = incr; bail_inval_free: /* release mr holds */ while (j) { diff --git a/drivers/infiniband/sw/rdmavt/trace_mr.h b/drivers/infiniband/sw/rdmavt/trace_mr.h index 3318a6c36373..976e482930a3 100644 --- a/drivers/infiniband/sw/rdmavt/trace_mr.h +++ b/drivers/infiniband/sw/rdmavt/trace_mr.h @@ -103,6 +103,68 @@ DEFINE_EVENT( TP_PROTO(struct rvt_mregion *mr, u16 m, u16 n, void *v, size_t len), TP_ARGS(mr, m, n, v, len)); +DECLARE_EVENT_CLASS( + rvt_sge_template, + TP_PROTO(struct rvt_sge *sge, struct ib_sge *isge), + TP_ARGS(sge, isge), + TP_STRUCT__entry( + RDI_DEV_ENTRY(ib_to_rvt(sge->mr->pd->device)) + __field(struct rvt_mregion *, mr) + __field(struct rvt_sge *, sge) + __field(struct ib_sge *, isge) + __field(void *, vaddr) + __field(u64, ivaddr) + __field(u32, lkey) + __field(u32, sge_length) + __field(u32, length) + __field(u32, ilength) + __field(int, user) + __field(u16, m) + __field(u16, n) + ), + TP_fast_assign( + RDI_DEV_ASSIGN(ib_to_rvt(sge->mr->pd->device)); + __entry->mr = sge->mr; + __entry->sge = sge; + __entry->isge = isge; + __entry->vaddr = sge->vaddr; + __entry->ivaddr = isge->addr; + __entry->lkey = sge->mr->lkey; + __entry->sge_length = sge->sge_length; + __entry->length = sge->length; + __entry->ilength = isge->length; + __entry->m = sge->m; + __entry->n = sge->m; + __entry->user = ibpd_to_rvtpd(sge->mr->pd)->user; + ), + TP_printk( + "[%s] mr %p sge %p isge %p vaddr %p ivaddr %llx lkey %x sge_length %u length %u ilength %u m %u n %u user %u", + __get_str(dev), + __entry->mr, + __entry->sge, + __entry->isge, + __entry->vaddr, + __entry->ivaddr, + __entry->lkey, + __entry->sge_length, + __entry->length, + __entry->ilength, + __entry->m, + __entry->n, + __entry->user + ) +); + +DEFINE_EVENT( + rvt_sge_template, rvt_sge_adjacent, + TP_PROTO(struct rvt_sge *sge, struct ib_sge *isge), + TP_ARGS(sge, isge)); + +DEFINE_EVENT( + rvt_sge_template, rvt_sge_new, + TP_PROTO(struct rvt_sge *sge, struct ib_sge *isge), + TP_ARGS(sge, isge)); + #endif /* __RVT_TRACE_MR_H */ #undef TRACE_INCLUDE_PATH diff --git a/drivers/infiniband/sw/rdmavt/trace_tx.h b/drivers/infiniband/sw/rdmavt/trace_tx.h index a613a2223751..0ef25fc49f25 100644 --- a/drivers/infiniband/sw/rdmavt/trace_tx.h +++ b/drivers/infiniband/sw/rdmavt/trace_tx.h @@ -84,12 +84,12 @@ __print_symbolic(opcode, \ wr_opcode_name(RESERVED10)) #define POS_PRN \ -"[%s] wqe %p wr_id %llx send_flags %x qpn %x qpt %u psn %x lpsn %x ssn %x length %u opcode 0x%.2x,%s size %u avail %u head %u last %u pid %u num_sge %u" +"[%s] wqe %p wr_id %llx send_flags %x qpn %x qpt %u psn %x lpsn %x ssn %x length %u opcode 0x%.2x,%s size %u avail %u head %u last %u pid %u num_sge %u wr_num_sge %u" TRACE_EVENT( rvt_post_one_wr, - TP_PROTO(struct rvt_qp *qp, struct rvt_swqe *wqe), - TP_ARGS(qp, wqe), + TP_PROTO(struct rvt_qp *qp, struct rvt_swqe *wqe, int wr_num_sge), + TP_ARGS(qp, wqe, wr_num_sge), TP_STRUCT__entry( RDI_DEV_ENTRY(ib_to_rvt(qp->ibqp.device)) __field(u64, wr_id) @@ -108,6 +108,7 @@ TRACE_EVENT( __field(int, send_flags) __field(pid_t, pid) __field(int, num_sge) + __field(int, wr_num_sge) ), TP_fast_assign( RDI_DEV_ASSIGN(ib_to_rvt(qp->ibqp.device)) @@ -127,6 +128,7 @@ TRACE_EVENT( __entry->ssn = wqe->ssn; __entry->send_flags = wqe->wr.send_flags; __entry->num_sge = wqe->wr.num_sge; + __entry->wr_num_sge = wr_num_sge; ), TP_printk( POS_PRN, @@ -146,7 +148,8 @@ TRACE_EVENT( __entry->head, __entry->last, __entry->pid, - __entry->num_sge + __entry->num_sge, + __entry->wr_num_sge ) ); diff --git a/include/rdma/rdma_vt.h b/include/rdma/rdma_vt.h index 4878aaf7bdff..d0b9f91e5f4d 100644 --- a/include/rdma/rdma_vt.h +++ b/include/rdma/rdma_vt.h @@ -515,7 +515,8 @@ int rvt_invalidate_rkey(struct rvt_qp *qp, u32 rkey); int rvt_rkey_ok(struct rvt_qp *qp, struct rvt_sge *sge, u32 len, u64 vaddr, u32 rkey, int acc); int rvt_lkey_ok(struct rvt_lkey_table *rkt, struct rvt_pd *pd, - struct rvt_sge *isge, struct ib_sge *sge, int acc); + struct rvt_sge *isge, struct rvt_sge *last_sge, + struct ib_sge *sge, int acc); struct rvt_mcast *rvt_mcast_find(struct rvt_ibport *ibp, union ib_gid *mgid, u16 lid); -- cgit v1.2.3 From 7be85676f1d13c77a7e0c72e04903bfd39580d4f Mon Sep 17 00:00:00 2001 From: Sebastian Sanchez Date: Fri, 26 May 2017 05:35:12 -0700 Subject: IB/hfi1: Don't remove RB entry when not needed. An RB tree is used for the SDMA pinning cache. Cache entries are extracted and reinserted from the tree in case the address range for it changes. However, if the address range for the entry doesn't change, deleting the entry from the RB tree is not necessary. This affects performance since the tree needs to be rebalanced for each insertion, and this happens in the hot path. Optimize RB search by not removing entries when it's not needed. Reviewed-by: Mike Marciniszyn Reviewed-by: Mitko Haralanov Signed-off-by: Sebastian Sanchez Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/mmu_rb.c | 14 ++++++++++---- drivers/infiniband/hw/hfi1/mmu_rb.h | 5 +++-- drivers/infiniband/hw/hfi1/user_sdma.c | 23 ++++++++++++++++------- 3 files changed, 29 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/hfi1/mmu_rb.c b/drivers/infiniband/hw/hfi1/mmu_rb.c index ccbf52c8ff6f..d41fd87a39f2 100644 --- a/drivers/infiniband/hw/hfi1/mmu_rb.c +++ b/drivers/infiniband/hw/hfi1/mmu_rb.c @@ -217,21 +217,27 @@ static struct mmu_rb_node *__mmu_rb_search(struct mmu_rb_handler *handler, return node; } -struct mmu_rb_node *hfi1_mmu_rb_extract(struct mmu_rb_handler *handler, - unsigned long addr, unsigned long len) +bool hfi1_mmu_rb_remove_unless_exact(struct mmu_rb_handler *handler, + unsigned long addr, unsigned long len, + struct mmu_rb_node **rb_node) { struct mmu_rb_node *node; unsigned long flags; + bool ret = false; spin_lock_irqsave(&handler->lock, flags); node = __mmu_rb_search(handler, addr, len); if (node) { + if (node->addr == addr && node->len == len) + goto unlock; __mmu_int_rb_remove(node, &handler->root); list_del(&node->list); /* remove from LRU list */ + ret = true; } +unlock: spin_unlock_irqrestore(&handler->lock, flags); - - return node; + *rb_node = node; + return ret; } void hfi1_mmu_rb_evict(struct mmu_rb_handler *handler, void *evict_arg) diff --git a/drivers/infiniband/hw/hfi1/mmu_rb.h b/drivers/infiniband/hw/hfi1/mmu_rb.h index 754f6ebf13fb..f04cec1e99d1 100644 --- a/drivers/infiniband/hw/hfi1/mmu_rb.h +++ b/drivers/infiniband/hw/hfi1/mmu_rb.h @@ -81,7 +81,8 @@ int hfi1_mmu_rb_insert(struct mmu_rb_handler *handler, void hfi1_mmu_rb_evict(struct mmu_rb_handler *handler, void *evict_arg); void hfi1_mmu_rb_remove(struct mmu_rb_handler *handler, struct mmu_rb_node *mnode); -struct mmu_rb_node *hfi1_mmu_rb_extract(struct mmu_rb_handler *handler, - unsigned long addr, unsigned long len); +bool hfi1_mmu_rb_remove_unless_exact(struct mmu_rb_handler *handler, + unsigned long addr, unsigned long len, + struct mmu_rb_node **rb_node); #endif /* _HFI1_MMU_RB_H */ diff --git a/drivers/infiniband/hw/hfi1/user_sdma.c b/drivers/infiniband/hw/hfi1/user_sdma.c index 16fd519216dc..79450cf2a3d5 100644 --- a/drivers/infiniband/hw/hfi1/user_sdma.c +++ b/drivers/infiniband/hw/hfi1/user_sdma.c @@ -1165,14 +1165,23 @@ static int pin_vector_pages(struct user_sdma_request *req, struct hfi1_user_sdma_pkt_q *pq = req->pq; struct sdma_mmu_node *node = NULL; struct mmu_rb_node *rb_node; - - rb_node = hfi1_mmu_rb_extract(pq->handler, - (unsigned long)iovec->iov.iov_base, - iovec->iov.iov_len); - if (rb_node) + bool extracted; + + extracted = + hfi1_mmu_rb_remove_unless_exact(pq->handler, + (unsigned long) + iovec->iov.iov_base, + iovec->iov.iov_len, &rb_node); + if (rb_node) { node = container_of(rb_node, struct sdma_mmu_node, rb); - else - rb_node = NULL; + if (!extracted) { + atomic_inc(&node->refcount); + iovec->pages = node->pages; + iovec->npages = node->npages; + iovec->node = node; + return 0; + } + } if (!node) { node = kzalloc(sizeof(*node), GFP_KERNEL); -- cgit v1.2.3 From e3304b7cc4f14d365f46d6847a35563ae8b017f7 Mon Sep 17 00:00:00 2001 From: Sebastian Sanchez Date: Fri, 26 May 2017 05:35:18 -0700 Subject: IB/hfi1: Optimize cachelines for user SDMA request structure The current user SDMA request structure layout has holes. The cachelines can be reduced to improve cacheline trading. Separate fields in the following categories: mostly read, writable and shared with interrupt. Reviewed-by: Mike Marciniszyn Signed-off-by: Sebastian Sanchez Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/user_sdma.c | 106 ++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 48 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/hfi1/user_sdma.c b/drivers/infiniband/hw/hfi1/user_sdma.c index 79450cf2a3d5..92517cebb4c7 100644 --- a/drivers/infiniband/hw/hfi1/user_sdma.c +++ b/drivers/infiniband/hw/hfi1/user_sdma.c @@ -117,6 +117,7 @@ MODULE_PARM_DESC(sdma_comp_size, "Size of User SDMA completion ring. Default: 12 #define AHG_KDETH_INTR_SHIFT 12 #define AHG_KDETH_SH_SHIFT 13 +#define AHG_KDETH_ARRAY_SIZE 9 #define PBC2LRH(x) ((((x) & 0xfff) << 2) - 4) #define LRH2PBC(x) ((((x) >> 2) + 1) & 0xfff) @@ -204,25 +205,42 @@ struct evict_data { }; struct user_sdma_request { - struct sdma_req_info info; - struct hfi1_user_sdma_pkt_q *pq; - struct hfi1_user_sdma_comp_q *cq; /* This is the original header from user space */ struct hfi1_pkt_header hdr; + + /* Read mostly fields */ + struct hfi1_user_sdma_pkt_q *pq ____cacheline_aligned_in_smp; + struct hfi1_user_sdma_comp_q *cq; /* * Pointer to the SDMA engine for this request. * Since different request could be on different VLs, * each request will need it's own engine pointer. */ struct sdma_engine *sde; - s8 ahg_idx; - u32 ahg[9]; + struct sdma_req_info info; + /* TID array values copied from the tid_iov vector */ + u32 *tids; + /* total length of the data in the request */ + u32 data_len; + /* number of elements copied to the tids array */ + u16 n_tids; /* - * KDETH.Offset (Eager) field - * We need to remember the initial value so the headers - * can be updated properly. + * We copy the iovs for this request (based on + * info.iovcnt). These are only the data vectors */ - u32 koffset; + u8 data_iovs; + s8 ahg_idx; + + /* Writeable fields shared with interrupt */ + u64 seqcomp ____cacheline_aligned_in_smp; + u64 seqsubmitted; + unsigned long flags; + /* status of the last txreq completed */ + int status; + + /* Send side fields */ + struct list_head txps ____cacheline_aligned_in_smp; + u64 seqnum; /* * KDETH.OFFSET (TID) field * The offset can cover multiple packets, depending on the @@ -230,29 +248,19 @@ struct user_sdma_request { */ u32 tidoffset; /* - * We copy the iovs for this request (based on - * info.iovcnt). These are only the data vectors + * KDETH.Offset (Eager) field + * We need to remember the initial value so the headers + * can be updated properly. */ - unsigned data_iovs; - /* total length of the data in the request */ - u32 data_len; + u32 koffset; + u32 sent; + /* TID index copied from the tid_iov vector */ + u16 tididx; /* progress index moving along the iovs array */ - unsigned iov_idx; + u8 iov_idx; + struct user_sdma_iovec iovs[MAX_VECTORS_PER_REQ]; - /* number of elements copied to the tids array */ - u16 n_tids; - /* TID array values copied from the tid_iov vector */ - u32 *tids; - u16 tididx; - u32 sent; - u64 seqnum; - u64 seqcomp; - u64 seqsubmitted; - struct list_head txps; - unsigned long flags; - /* status of the last txreq completed */ - int status; -}; +} ____cacheline_aligned_in_smp; /* * A single txreq could span up to 3 physical pages when the MTU @@ -1034,11 +1042,6 @@ static int user_sdma_send_pkts(struct user_sdma_request *req, unsigned maxpkts) datalen); if (changes < 0) goto free_tx; - sdma_txinit_ahg(&tx->txreq, - SDMA_TXREQ_F_USE_AHG, - datalen, req->ahg_idx, changes, - req->ahg, sizeof(req->hdr), - user_sdma_txreq_cb); } } else { ret = sdma_txinit(&tx->txreq, 0, sizeof(req->hdr) + @@ -1442,21 +1445,22 @@ done: } static int set_txreq_header_ahg(struct user_sdma_request *req, - struct user_sdma_txreq *tx, u32 len) + struct user_sdma_txreq *tx, u32 datalen) { + u32 ahg[AHG_KDETH_ARRAY_SIZE]; int diff = 0; u8 omfactor; /* KDETH.OM */ struct hfi1_user_sdma_pkt_q *pq = req->pq; struct hfi1_pkt_header *hdr = &req->hdr; u16 pbclen = le16_to_cpu(hdr->pbc[0]); - u32 val32, tidval = 0, lrhlen = get_lrh_len(*hdr, pad_len(len)); + u32 val32, tidval = 0, lrhlen = get_lrh_len(*hdr, pad_len(datalen)); if (PBC2LRH(pbclen) != lrhlen) { /* PBC.PbcLengthDWs */ - AHG_HEADER_SET(req->ahg, diff, 0, 0, 12, + AHG_HEADER_SET(ahg, diff, 0, 0, 12, cpu_to_le16(LRH2PBC(lrhlen))); /* LRH.PktLen (we need the full 16 bits due to byte swap) */ - AHG_HEADER_SET(req->ahg, diff, 3, 0, 16, + AHG_HEADER_SET(ahg, diff, 3, 0, 16, cpu_to_be16(lrhlen >> 2)); } @@ -1468,13 +1472,12 @@ static int set_txreq_header_ahg(struct user_sdma_request *req, (HFI1_CAP_IS_KSET(EXTENDED_PSN) ? 0x7fffffff : 0xffffff); if (unlikely(tx->flags & TXREQ_FLAGS_REQ_ACK)) val32 |= 1UL << 31; - AHG_HEADER_SET(req->ahg, diff, 6, 0, 16, cpu_to_be16(val32 >> 16)); - AHG_HEADER_SET(req->ahg, diff, 6, 16, 16, cpu_to_be16(val32 & 0xffff)); + AHG_HEADER_SET(ahg, diff, 6, 0, 16, cpu_to_be16(val32 >> 16)); + AHG_HEADER_SET(ahg, diff, 6, 16, 16, cpu_to_be16(val32 & 0xffff)); /* KDETH.Offset */ - AHG_HEADER_SET(req->ahg, diff, 15, 0, 16, + AHG_HEADER_SET(ahg, diff, 15, 0, 16, cpu_to_le16(req->koffset & 0xffff)); - AHG_HEADER_SET(req->ahg, diff, 15, 16, 16, - cpu_to_le16(req->koffset >> 16)); + AHG_HEADER_SET(ahg, diff, 15, 16, 16, cpu_to_le16(req->koffset >> 16)); if (req_opcode(req->info.ctrl) == EXPECTED) { __le16 val; @@ -1492,9 +1495,8 @@ static int set_txreq_header_ahg(struct user_sdma_request *req, * we have to check again. */ if (++req->tididx > req->n_tids - 1 || - !req->tids[req->tididx]) { + !req->tids[req->tididx]) return -EINVAL; - } tidval = req->tids[req->tididx]; } omfactor = ((EXP_TID_GET(tidval, LEN) * @@ -1502,7 +1504,7 @@ static int set_txreq_header_ahg(struct user_sdma_request *req, KDETH_OM_MAX_SIZE) ? KDETH_OM_LARGE_SHIFT : KDETH_OM_SMALL_SHIFT; /* KDETH.OM and KDETH.OFFSET (TID) */ - AHG_HEADER_SET(req->ahg, diff, 7, 0, 16, + AHG_HEADER_SET(ahg, diff, 7, 0, 16, ((!!(omfactor - KDETH_OM_SMALL_SHIFT)) << 15 | ((req->tidoffset >> omfactor) & 0x7fff))); @@ -1522,12 +1524,20 @@ static int set_txreq_header_ahg(struct user_sdma_request *req, AHG_KDETH_INTR_SHIFT)); } - AHG_HEADER_SET(req->ahg, diff, 7, 16, 14, val); + AHG_HEADER_SET(ahg, diff, 7, 16, 14, val); } + if (diff < 0) + return diff; trace_hfi1_sdma_user_header_ahg(pq->dd, pq->ctxt, pq->subctxt, req->info.comp_idx, req->sde->this_idx, - req->ahg_idx, req->ahg, diff, tidval); + req->ahg_idx, ahg, diff, tidval); + sdma_txinit_ahg(&tx->txreq, + SDMA_TXREQ_F_USE_AHG, + datalen, req->ahg_idx, diff, + ahg, sizeof(req->hdr), + user_sdma_txreq_cb); + return diff; } -- cgit v1.2.3 From 721c462123b4b53745c1ccd99619b16e8f4e091b Mon Sep 17 00:00:00 2001 From: "Michael J. Ruhl" Date: Fri, 26 May 2017 05:35:25 -0700 Subject: IB/hfi1: Name function prototype parameters for affinity module To improve the readability of function prototypes, give the parameters names in the affinity module. Reviewed-by: Sebastian Sanchez Signed-off-by: Michael J. Ruhl Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/affinity.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/hfi1/affinity.h b/drivers/infiniband/hw/hfi1/affinity.h index e78c7aa094e0..2a1e374169c0 100644 --- a/drivers/infiniband/hw/hfi1/affinity.h +++ b/drivers/infiniband/hw/hfi1/affinity.h @@ -1,5 +1,5 @@ /* - * Copyright(c) 2015, 2016 Intel Corporation. + * Copyright(c) 2015 - 2017 Intel Corporation. * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. @@ -75,24 +75,26 @@ struct hfi1_msix_entry; /* Initialize non-HT cpu cores mask */ void init_real_cpu_mask(void); /* Initialize driver affinity data */ -int hfi1_dev_affinity_init(struct hfi1_devdata *); +int hfi1_dev_affinity_init(struct hfi1_devdata *dd); /* * Set IRQ affinity to a CPU. The function will determine the * CPU and set the affinity to it. */ -int hfi1_get_irq_affinity(struct hfi1_devdata *, struct hfi1_msix_entry *); +int hfi1_get_irq_affinity(struct hfi1_devdata *dd, + struct hfi1_msix_entry *msix); /* * Remove the IRQ's CPU affinity. This function also updates * any internal CPU tracking data */ -void hfi1_put_irq_affinity(struct hfi1_devdata *, struct hfi1_msix_entry *); +void hfi1_put_irq_affinity(struct hfi1_devdata *dd, + struct hfi1_msix_entry *msix); /* * Determine a CPU affinity for a user process, if the process does not * have an affinity set yet. */ -int hfi1_get_proc_affinity(int); +int hfi1_get_proc_affinity(int node); /* Release a CPU used by a user process. */ -void hfi1_put_proc_affinity(int); +void hfi1_put_proc_affinity(int cpu); struct hfi1_affinity_node { int node; -- cgit v1.2.3 From bb7dde8784913c06ccd1456bed6dcc5ebd0b3c24 Mon Sep 17 00:00:00 2001 From: "Michael J. Ruhl" Date: Fri, 26 May 2017 05:35:31 -0700 Subject: IB/hfi1: Replace deprecated pci functions with new API pci_enable_msix_range() and pci_disable_msix() have been deprecated. Updating to the new pci_alloc_irq_vectors() interface. Reviewed-by: Sebastian Sanchez Signed-off-by: Michael J. Ruhl Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/affinity.c | 18 +++--- drivers/infiniband/hw/hfi1/chip.c | 105 +++++++++++++++++----------------- drivers/infiniband/hw/hfi1/hfi.h | 6 +- drivers/infiniband/hw/hfi1/pcie.c | 80 ++++++-------------------- 4 files changed, 78 insertions(+), 131 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/hfi1/affinity.c b/drivers/infiniband/hw/hfi1/affinity.c index e2cd2cd3b28a..a97055dd4fbd 100644 --- a/drivers/infiniband/hw/hfi1/affinity.c +++ b/drivers/infiniband/hw/hfi1/affinity.c @@ -1,5 +1,5 @@ /* - * Copyright(c) 2015, 2016 Intel Corporation. + * Copyright(c) 2015 - 2017 Intel Corporation. * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. @@ -335,10 +335,10 @@ static void hfi1_update_sdma_affinity(struct hfi1_msix_entry *msix, int cpu) sde->cpu = cpu; cpumask_clear(&msix->mask); cpumask_set_cpu(cpu, &msix->mask); - dd_dev_dbg(dd, "IRQ vector: %u, type %s engine %u -> cpu: %d\n", - msix->msix.vector, irq_type_names[msix->type], + dd_dev_dbg(dd, "IRQ: %u, type %s engine %u -> cpu: %d\n", + msix->irq, irq_type_names[msix->type], sde->this_idx, cpu); - irq_set_affinity_hint(msix->msix.vector, &msix->mask); + irq_set_affinity_hint(msix->irq, &msix->mask); /* * Set the new cpu in the hfi1_affinity_node and clean @@ -387,7 +387,7 @@ static void hfi1_setup_sdma_notifier(struct hfi1_msix_entry *msix) { struct irq_affinity_notify *notify = &msix->notify; - notify->irq = msix->msix.vector; + notify->irq = msix->irq; notify->notify = hfi1_irq_notifier_notify; notify->release = hfi1_irq_notifier_release; @@ -472,10 +472,10 @@ static int get_irq_affinity(struct hfi1_devdata *dd, } cpumask_set_cpu(cpu, &msix->mask); - dd_dev_info(dd, "IRQ vector: %u, type %s %s -> cpu: %d\n", - msix->msix.vector, irq_type_names[msix->type], + dd_dev_info(dd, "IRQ: %u, type %s %s -> cpu: %d\n", + msix->irq, irq_type_names[msix->type], extra, cpu); - irq_set_affinity_hint(msix->msix.vector, &msix->mask); + irq_set_affinity_hint(msix->irq, &msix->mask); if (msix->type == IRQ_SDMA) { sde->cpu = cpu; @@ -533,7 +533,7 @@ void hfi1_put_irq_affinity(struct hfi1_devdata *dd, } } - irq_set_affinity_hint(msix->msix.vector, NULL); + irq_set_affinity_hint(msix->irq, NULL); cpumask_clear(&msix->mask); mutex_unlock(&node_affinity.lock); } diff --git a/drivers/infiniband/hw/hfi1/chip.c b/drivers/infiniband/hw/hfi1/chip.c index 5dbee3c1bd45..9118618d28e5 100644 --- a/drivers/infiniband/hw/hfi1/chip.c +++ b/drivers/infiniband/hw/hfi1/chip.c @@ -12800,30 +12800,24 @@ static void clean_up_interrupts(struct hfi1_devdata *dd) for (i = 0; i < dd->num_msix_entries; i++, me++) { if (!me->arg) /* => no irq, no affinity */ continue; - hfi1_put_irq_affinity(dd, &dd->msix_entries[i]); - free_irq(me->msix.vector, me->arg); + hfi1_put_irq_affinity(dd, me); + free_irq(me->irq, me->arg); } + + /* clean structures */ + kfree(dd->msix_entries); + dd->msix_entries = NULL; + dd->num_msix_entries = 0; } else { /* INTx */ if (dd->requested_intx_irq) { free_irq(dd->pcidev->irq, dd); dd->requested_intx_irq = 0; } - } - - /* turn off interrupts */ - if (dd->num_msix_entries) { - /* MSI-X */ - pci_disable_msix(dd->pcidev); - } else { - /* INTx */ disable_intx(dd->pcidev); } - /* clean structures */ - kfree(dd->msix_entries); - dd->msix_entries = NULL; - dd->num_msix_entries = 0; + pci_free_irq_vectors(dd->pcidev); } /* @@ -12972,13 +12966,21 @@ static int request_msix_irqs(struct hfi1_devdata *dd) continue; /* make sure the name is terminated */ me->name[sizeof(me->name) - 1] = 0; + me->irq = pci_irq_vector(dd->pcidev, i); + /* + * On err return me->irq. Don't need to clear this + * because 'arg' has not been set, and cleanup will + * do the right thing. + */ + if (me->irq < 0) + return me->irq; - ret = request_threaded_irq(me->msix.vector, handler, thread, 0, + ret = request_threaded_irq(me->irq, handler, thread, 0, me->name, arg); if (ret) { dd_dev_err(dd, - "unable to allocate %s interrupt, vector %d, index %d, err %d\n", - err_info, me->msix.vector, idx, ret); + "unable to allocate %s interrupt, irq %d, index %d, err %d\n", + err_info, me->irq, idx, ret); return ret; } /* @@ -12989,8 +12991,7 @@ static int request_msix_irqs(struct hfi1_devdata *dd) ret = hfi1_get_irq_affinity(dd, me); if (ret) - dd_dev_err(dd, - "unable to pin IRQ %d\n", ret); + dd_dev_err(dd, "unable to pin IRQ %d\n", ret); } return ret; @@ -13009,7 +13010,7 @@ void hfi1_vnic_synchronize_irq(struct hfi1_devdata *dd) struct hfi1_ctxtdata *rcd = dd->vnic.ctxt[i]; struct hfi1_msix_entry *me = &dd->msix_entries[rcd->msix_intr]; - synchronize_irq(me->msix.vector); + synchronize_irq(me->irq); } } @@ -13022,7 +13023,7 @@ void hfi1_reset_vnic_msix_info(struct hfi1_ctxtdata *rcd) return; hfi1_put_irq_affinity(dd, me); - free_irq(me->msix.vector, me->arg); + free_irq(me->irq, me->arg); me->arg = NULL; } @@ -13050,14 +13051,19 @@ void hfi1_set_vnic_msix_info(struct hfi1_ctxtdata *rcd) DRIVER_NAME "_%d kctxt%d", dd->unit, idx); me->name[sizeof(me->name) - 1] = 0; me->type = IRQ_RCVCTXT; - + me->irq = pci_irq_vector(dd->pcidev, rcd->msix_intr); + if (me->irq < 0) { + dd_dev_err(dd, "vnic irq vector request (idx %d) fail %d\n", + idx, me->irq); + return; + } remap_intr(dd, IS_RCVAVAIL_START + idx, rcd->msix_intr); - ret = request_threaded_irq(me->msix.vector, receive_context_interrupt, + ret = request_threaded_irq(me->irq, receive_context_interrupt, receive_context_thread, 0, me->name, arg); if (ret) { - dd_dev_err(dd, "vnic irq request (vector %d, idx %d) fail %d\n", - me->msix.vector, idx, ret); + dd_dev_err(dd, "vnic irq request (irq %d, idx %d) fail %d\n", + me->irq, idx, ret); return; } /* @@ -13070,7 +13076,7 @@ void hfi1_set_vnic_msix_info(struct hfi1_ctxtdata *rcd) if (ret) { dd_dev_err(dd, "unable to pin IRQ %d\n", ret); - free_irq(me->msix.vector, me->arg); + free_irq(me->irq, me->arg); } } @@ -13093,9 +13099,8 @@ static void reset_interrupts(struct hfi1_devdata *dd) static int set_up_interrupts(struct hfi1_devdata *dd) { - struct hfi1_msix_entry *entries; - u32 total, request; - int i, ret; + u32 total; + int ret, request; int single_interrupt = 0; /* we expect to have all the interrupts */ /* @@ -13107,39 +13112,31 @@ static int set_up_interrupts(struct hfi1_devdata *dd) */ total = 1 + dd->num_sdma + dd->n_krcv_queues + HFI1_NUM_VNIC_CTXT; - entries = kcalloc(total, sizeof(*entries), GFP_KERNEL); - if (!entries) { - ret = -ENOMEM; - goto fail; - } - /* 1-1 MSI-X entry assignment */ - for (i = 0; i < total; i++) - entries[i].msix.entry = i; - /* ask for MSI-X interrupts */ - request = total; - request_msix(dd, &request, entries); - - if (request == 0) { + request = request_msix(dd, total); + if (request < 0) { + ret = request; + goto fail; + } else if (request == 0) { /* using INTx */ /* dd->num_msix_entries already zero */ - kfree(entries); single_interrupt = 1; dd_dev_err(dd, "MSI-X failed, using INTx interrupts\n"); + } else if (request < total) { + /* using MSI-X, with reduced interrupts */ + dd_dev_err(dd, "reduced interrupt found, wanted %u, got %u\n", + total, request); + ret = -EINVAL; + goto fail; } else { - /* using MSI-X */ - dd->num_msix_entries = request; - dd->msix_entries = entries; - - if (request != total) { - /* using MSI-X, with reduced interrupts */ - dd_dev_err( - dd, - "cannot handle reduced interrupt case, want %u, got %u\n", - total, request); - ret = -EINVAL; + dd->msix_entries = kcalloc(total, sizeof(*dd->msix_entries), + GFP_KERNEL); + if (!dd->msix_entries) { + ret = -ENOMEM; goto fail; } + /* using MSI-X */ + dd->num_msix_entries = total; dd_dev_info(dd, "%u MSI-X interrupts allocated\n", total); } diff --git a/drivers/infiniband/hw/hfi1/hfi.h b/drivers/infiniband/hw/hfi1/hfi.h index 9c6c73448461..8f74cf6d6c9a 100644 --- a/drivers/infiniband/hw/hfi1/hfi.h +++ b/drivers/infiniband/hw/hfi1/hfi.h @@ -521,7 +521,7 @@ static inline void incr_cntr32(u32 *cntr) #define MAX_NAME_SIZE 64 struct hfi1_msix_entry { enum irq_type type; - struct msix_entry msix; + int irq; void *arg; char name[MAX_NAME_SIZE]; cpumask_t mask; @@ -1838,9 +1838,7 @@ void hfi1_pcie_cleanup(struct pci_dev *pdev); int hfi1_pcie_ddinit(struct hfi1_devdata *dd, struct pci_dev *pdev); void hfi1_pcie_ddcleanup(struct hfi1_devdata *); int pcie_speeds(struct hfi1_devdata *dd); -void request_msix(struct hfi1_devdata *dd, u32 *nent, - struct hfi1_msix_entry *entry); -void hfi1_enable_intx(struct pci_dev *pdev); +int request_msix(struct hfi1_devdata *dd, u32 msireq); void restore_pci_variables(struct hfi1_devdata *dd); int do_pcie_gen3_transition(struct hfi1_devdata *dd); int parse_platform_config(struct hfi1_devdata *dd); diff --git a/drivers/infiniband/hw/hfi1/pcie.c b/drivers/infiniband/hw/hfi1/pcie.c index 6a9f6f9819e1..f01841b51946 100644 --- a/drivers/infiniband/hw/hfi1/pcie.c +++ b/drivers/infiniband/hw/hfi1/pcie.c @@ -1,5 +1,5 @@ /* - * Copyright(c) 2015, 2016 Intel Corporation. + * Copyright(c) 2015 - 2017 Intel Corporation. * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. @@ -240,50 +240,6 @@ void hfi1_pcie_ddcleanup(struct hfi1_devdata *dd) iounmap(dd->piobase); } -static void msix_setup(struct hfi1_devdata *dd, int pos, u32 *msixcnt, - struct hfi1_msix_entry *hfi1_msix_entry) -{ - int ret; - int nvec = *msixcnt; - struct msix_entry *msix_entry; - int i; - - /* - * We can't pass hfi1_msix_entry array to msix_setup - * so use a dummy msix_entry array and copy the allocated - * irq back to the hfi1_msix_entry array. - */ - msix_entry = kmalloc_array(nvec, sizeof(*msix_entry), GFP_KERNEL); - if (!msix_entry) { - ret = -ENOMEM; - goto do_intx; - } - - for (i = 0; i < nvec; i++) - msix_entry[i] = hfi1_msix_entry[i].msix; - - ret = pci_enable_msix_range(dd->pcidev, msix_entry, 1, nvec); - if (ret < 0) - goto free_msix_entry; - nvec = ret; - - for (i = 0; i < nvec; i++) - hfi1_msix_entry[i].msix = msix_entry[i]; - - kfree(msix_entry); - *msixcnt = nvec; - return; - -free_msix_entry: - kfree(msix_entry); - -do_intx: - dd_dev_err(dd, "pci_enable_msix_range %d vectors failed: %d, falling back to INTx\n", - nvec, ret); - *msixcnt = 0; - hfi1_enable_intx(dd->pcidev); -} - /* return the PCIe link speed from the given link status */ static u32 extract_speed(u16 linkstat) { @@ -364,33 +320,29 @@ int pcie_speeds(struct hfi1_devdata *dd) } /* - * Returns in *nent: - * - actual number of interrupts allocated + * Returns: + * - actual number of interrupts allocated or * - 0 if fell back to INTx. + * - error */ -void request_msix(struct hfi1_devdata *dd, u32 *nent, - struct hfi1_msix_entry *entry) +int request_msix(struct hfi1_devdata *dd, u32 msireq) { - int pos; + int nvec; - pos = dd->pcidev->msix_cap; - if (*nent && pos) { - msix_setup(dd, pos, nent, entry); - /* did it, either MSI-X or INTx */ - } else { - *nent = 0; - hfi1_enable_intx(dd->pcidev); + nvec = pci_alloc_irq_vectors(dd->pcidev, 1, msireq, + PCI_IRQ_MSIX | PCI_IRQ_LEGACY); + if (nvec < 0) { + dd_dev_err(dd, "pci_alloc_irq_vectors() failed: %d\n", nvec); + return nvec; } tune_pcie_caps(dd); -} -void hfi1_enable_intx(struct pci_dev *pdev) -{ - /* first, turn on INTx */ - pci_intx(pdev, 1); - /* then turn off MSI-X */ - pci_disable_msix(pdev); + /* check for legacy IRQ */ + if (nvec == 1 && !dd->pcidev->msix_enabled) + return 0; + + return nvec; } /* restore command and BARs after a reset has wiped them out */ -- cgit v1.2.3 From cb49366f3616fdf197893c24a5b2677b8c26ce29 Mon Sep 17 00:00:00 2001 From: "Vishwanathapura, Niranjana" Date: Thu, 1 Jun 2017 17:04:02 -0700 Subject: IB/core,rdmavt,hfi1,opa-vnic: Send OPA cap_mask3 in trap Provide the ability for IB clients to modify the OPA specific capability mask and include this mask in the subsequent trap data. Reviewed-by: Niranjana Vishwanathapura Signed-off-by: Michael N. Henry Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/mad.c | 7 ++----- drivers/infiniband/hw/hfi1/mad.h | 2 +- drivers/infiniband/hw/hfi1/verbs.c | 6 +++++- drivers/infiniband/sw/rdmavt/vt.c | 9 +++++++-- drivers/infiniband/ulp/opa_vnic/opa_vnic_vema.c | 27 ++++++++++++++++++++++++- include/rdma/ib_verbs.h | 3 ++- include/rdma/rdma_vt.h | 1 + 7 files changed, 44 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/hfi1/mad.c b/drivers/infiniband/hw/hfi1/mad.c index 5977673a52d4..70831ad621b0 100644 --- a/drivers/infiniband/hw/hfi1/mad.c +++ b/drivers/infiniband/hw/hfi1/mad.c @@ -260,6 +260,7 @@ void hfi1_cap_mask_chg(struct rvt_dev_info *rdi, u8 port_num) data.issuer_lid = cpu_to_be32(lid); data.ntc_144.lid = data.issuer_lid; data.ntc_144.new_cap_mask = cpu_to_be32(ibp->rvp.port_cap_flags); + data.ntc_144.cap_mask3 = cpu_to_be16(ibp->rvp.port_cap3_flags); send_trap(ibp, &data, sizeof(data)); } @@ -704,11 +705,7 @@ static int __subn_get_opa_portinfo(struct opa_smp *smp, u32 am, u8 *data, buffer_units |= (dd->vl15_init << 11) & OPA_PI_MASK_BUF_UNIT_VL15_INIT; pi->buffer_units = cpu_to_be32(buffer_units); - pi->opa_cap_mask = cpu_to_be16(OPA_CAP_MASK3_IsSharedSpaceSupported | - OPA_CAP_MASK3_IsEthOnFabricSupported); - /* Driver does not support mcast/collective configuration */ - pi->opa_cap_mask &= - cpu_to_be16(~OPA_CAP_MASK3_IsAddrRangeConfigSupported); + pi->opa_cap_mask = cpu_to_be16(ibp->rvp.port_cap3_flags); pi->collectivemask_multicastmask = ((HFI1_COLLECTIVE_NR & 0x7) << 3 | (HFI1_MCAST_NR & 0x7)); diff --git a/drivers/infiniband/hw/hfi1/mad.h b/drivers/infiniband/hw/hfi1/mad.h index 5aa3fd1be653..a4e2506bd5ca 100644 --- a/drivers/infiniband/hw/hfi1/mad.h +++ b/drivers/infiniband/hw/hfi1/mad.h @@ -115,7 +115,7 @@ struct opa_mad_notice_attr { __be32 lid; /* LID where change occurred */ __be32 new_cap_mask; /* new capability mask */ __be16 reserved2; - __be16 cap_mask; + __be16 cap_mask3; __be16 change_flags; /* low 4 bits only */ } __packed ntc_144; diff --git a/drivers/infiniband/hw/hfi1/verbs.c b/drivers/infiniband/hw/hfi1/verbs.c index af54d3f4696a..2d7759f0c6b4 100644 --- a/drivers/infiniband/hw/hfi1/verbs.c +++ b/drivers/infiniband/hw/hfi1/verbs.c @@ -1537,9 +1537,13 @@ static void init_ibport(struct hfi1_pportdata *ppd) /* Set the prefix to the default value (see ch. 4.1.1) */ ibp->rvp.gid_prefix = IB_DEFAULT_GID_PREFIX; ibp->rvp.sm_lid = 0; - /* Below should only set bits defined in OPA PortInfo.CapabilityMask */ + /* + * Below should only set bits defined in OPA PortInfo.CapabilityMask + * and PortInfo.CapabilityMask3 + */ ibp->rvp.port_cap_flags = IB_PORT_AUTO_MIGR_SUP | IB_PORT_CAP_MASK_NOTICE_SUP; + ibp->rvp.port_cap3_flags = OPA_CAP_MASK3_IsSharedSpaceSupported; ibp->rvp.pma_counter_select[0] = IB_PMA_PORT_XMIT_DATA; ibp->rvp.pma_counter_select[1] = IB_PMA_PORT_RCV_DATA; ibp->rvp.pma_counter_select[2] = IB_PMA_PORT_XMIT_PKTS; diff --git a/drivers/infiniband/sw/rdmavt/vt.c b/drivers/infiniband/sw/rdmavt/vt.c index 0d7c6bb551d9..64bdd442078a 100644 --- a/drivers/infiniband/sw/rdmavt/vt.c +++ b/drivers/infiniband/sw/rdmavt/vt.c @@ -202,8 +202,13 @@ static int rvt_modify_port(struct ib_device *ibdev, u8 port_num, return -EINVAL; rvp = rdi->ports[port_index]; - rvp->port_cap_flags |= props->set_port_cap_mask; - rvp->port_cap_flags &= ~props->clr_port_cap_mask; + if (port_modify_mask & IB_PORT_OPA_MASK_CHG) { + rvp->port_cap3_flags |= props->set_port_cap_mask; + rvp->port_cap3_flags &= ~props->clr_port_cap_mask; + } else { + rvp->port_cap_flags |= props->set_port_cap_mask; + rvp->port_cap_flags &= ~props->clr_port_cap_mask; + } if (props->set_port_cap_mask || props->clr_port_cap_mask) rdi->driver_f.cap_mask_chg(rdi, port_num); diff --git a/drivers/infiniband/ulp/opa_vnic/opa_vnic_vema.c b/drivers/infiniband/ulp/opa_vnic/opa_vnic_vema.c index 875694f9a7f9..32cdd7a35415 100644 --- a/drivers/infiniband/ulp/opa_vnic/opa_vnic_vema.c +++ b/drivers/infiniband/ulp/opa_vnic/opa_vnic_vema.c @@ -52,7 +52,9 @@ #include #include -#include +#include +#include +#include #include "opa_vnic_internal.h" @@ -979,6 +981,27 @@ static int vema_register(struct opa_vnic_ctrl_port *cport) return 0; } +/** + * opa_vnic_ctrl_config_dev -- This function sends a trap to the EM + * by way of ib_modify_port to indicate support for ethernet on the + * fabric. + * @cport: pointer to control port + * @en: enable or disable ethernet on fabric support + */ +static void opa_vnic_ctrl_config_dev(struct opa_vnic_ctrl_port *cport, bool en) +{ + struct ib_port_modify pm = { 0 }; + int i; + + if (en) + pm.set_port_cap_mask = OPA_CAP_MASK3_IsEthOnFabricSupported; + else + pm.clr_port_cap_mask = OPA_CAP_MASK3_IsEthOnFabricSupported; + + for (i = 1; i <= cport->num_ports; i++) + ib_modify_port(cport->ibdev, i, IB_PORT_OPA_MASK_CHG, &pm); +} + /** * opa_vnic_vema_add_one -- Handle new ib device * @device: ib device pointer @@ -1007,6 +1030,7 @@ static void opa_vnic_vema_add_one(struct ib_device *device) c_info("VNIC client initialized\n"); ib_set_client_data(device, &opa_vnic_client, cport); + opa_vnic_ctrl_config_dev(cport, true); } /** @@ -1025,6 +1049,7 @@ static void opa_vnic_vema_rem_one(struct ib_device *device, return; c_info("removing VNIC client\n"); + opa_vnic_ctrl_config_dev(cport, false); vema_unregister(cport); kfree(cport); } diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index 8f1ce4e27bbd..9d4d2a74c95e 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -577,7 +577,8 @@ struct ib_device_modify { enum ib_port_modify_flags { IB_PORT_SHUTDOWN = 1, IB_PORT_INIT_TYPE = (1<<2), - IB_PORT_RESET_QKEY_CNTR = (1<<3) + IB_PORT_RESET_QKEY_CNTR = (1<<3), + IB_PORT_OPA_MASK_CHG = (1<<4) }; struct ib_port_modify { diff --git a/include/rdma/rdma_vt.h b/include/rdma/rdma_vt.h index d0b9f91e5f4d..0f18ffd98dd7 100644 --- a/include/rdma/rdma_vt.h +++ b/include/rdma/rdma_vt.h @@ -75,6 +75,7 @@ struct rvt_ibport { __be64 mkey; u64 tid; u32 port_cap_flags; + u16 port_cap3_flags; u32 pma_sample_start; u32 pma_sample_interval; __be16 pma_counter_select[5]; -- cgit v1.2.3 From b888429c202197916c8c549811a2dd62f090280d Mon Sep 17 00:00:00 2001 From: Sebastian Sanchez Date: Fri, 26 May 2017 05:35:44 -0700 Subject: IB/hfi1: Remove atomic SDMA_REQ_SEND_DONE bit operation The atomic SDMA_REQ_SEND_DONE bit is set by the process-level code, and then the same process-level code uses the bit to test that all packets have been submitted incurring a costly atomic read. Use a bool type with a READ_ONCE/WRITE_ONCE pairing for this bit, and use the same condition that is used to set the bit to test that all packets have been submitted. Reviewed-by: Mike Marciniszyn Signed-off-by: Sebastian Sanchez Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/user_sdma.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/hfi1/user_sdma.c b/drivers/infiniband/hw/hfi1/user_sdma.c index 92517cebb4c7..6fb70f0064a6 100644 --- a/drivers/infiniband/hw/hfi1/user_sdma.c +++ b/drivers/infiniband/hw/hfi1/user_sdma.c @@ -154,10 +154,8 @@ MODULE_PARM_DESC(sdma_comp_size, "Size of User SDMA completion ring. Default: 12 #define TXREQ_FLAGS_REQ_DISABLE_SH BIT(1) /* Disable header suppression */ /* SDMA request flag bits */ -#define SDMA_REQ_FOR_THREAD 1 -#define SDMA_REQ_SEND_DONE 2 -#define SDMA_REQ_HAS_ERROR 3 -#define SDMA_REQ_DONE_ERROR 4 +#define SDMA_REQ_HAS_ERROR 1 +#define SDMA_REQ_DONE_ERROR 2 #define SDMA_PKT_Q_INACTIVE BIT(0) #define SDMA_PKT_Q_ACTIVE BIT(1) @@ -258,6 +256,7 @@ struct user_sdma_request { u16 tididx; /* progress index moving along the iovs array */ u8 iov_idx; + u8 done; struct user_sdma_iovec iovs[MAX_VECTORS_PER_REQ]; } ____cacheline_aligned_in_smp; @@ -628,6 +627,7 @@ int hfi1_user_sdma_process_request(struct hfi1_filedata *fd, req->seqsubmitted = 0; req->flags = 0; req->tids = NULL; + req->done = 0; INIT_LIST_HEAD(&req->txps); memcpy(&req->info, &info, sizeof(info)); @@ -809,7 +809,7 @@ int hfi1_user_sdma_process_request(struct hfi1_filedata *fd, * request have been submitted to the SDMA engine. However, it * will not wait for send completions. */ - while (!test_bit(SDMA_REQ_SEND_DONE, &req->flags)) { + while (req->seqsubmitted != req->info.npkts) { ret = user_sdma_send_pkts(req, pcount); if (ret < 0) { if (ret != -EBUSY) { @@ -1118,7 +1118,7 @@ dosend: ret = sdma_send_txlist(req->sde, &pq->busy, &req->txps, &count); req->seqsubmitted += count; if (req->seqsubmitted == req->info.npkts) { - set_bit(SDMA_REQ_SEND_DONE, &req->flags); + WRITE_ONCE(req->done, 1); /* * The txreq has already been submitted to the HW queue * so we can free the AHG entry now. Corruption will not @@ -1585,7 +1585,7 @@ static void user_sdma_txreq_cb(struct sdma_txreq *txreq, int status) if (status != SDMA_TXREQ_S_OK) req->status = status; if (req->seqcomp == (ACCESS_ONCE(req->seqsubmitted) - 1) && - (test_bit(SDMA_REQ_SEND_DONE, &req->flags) || + (READ_ONCE(req->done) || test_bit(SDMA_REQ_DONE_ERROR, &req->flags))) { user_sdma_free_request(req, false); pq_update(pq); -- cgit v1.2.3 From e9c48ebd0cb4d31bbaf60ddec2a2fa40227b8cb5 Mon Sep 17 00:00:00 2001 From: Sebastian Sanchez Date: Fri, 26 May 2017 05:35:50 -0700 Subject: IB/hfi1: Remove atomic SDMA_REQ_HAS_ERROR bit operation Atomic bit tests are used to single errors and the completion of request submissions. These operations don't need to be atomic and show to be expensive on the profile. Replace each atomic bit operation with a bool type and a READ_ONCE/WRITE_ONCE pairing. Reviewed-by: Mike Marciniszyn Signed-off-by: Sebastian Sanchez Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/user_sdma.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/hfi1/user_sdma.c b/drivers/infiniband/hw/hfi1/user_sdma.c index 6fb70f0064a6..fcadbb9978ca 100644 --- a/drivers/infiniband/hw/hfi1/user_sdma.c +++ b/drivers/infiniband/hw/hfi1/user_sdma.c @@ -153,10 +153,6 @@ MODULE_PARM_DESC(sdma_comp_size, "Size of User SDMA completion ring. Default: 12 #define TXREQ_FLAGS_REQ_ACK BIT(0) /* Set the ACK bit in the header */ #define TXREQ_FLAGS_REQ_DISABLE_SH BIT(1) /* Disable header suppression */ -/* SDMA request flag bits */ -#define SDMA_REQ_HAS_ERROR 1 -#define SDMA_REQ_DONE_ERROR 2 - #define SDMA_PKT_Q_INACTIVE BIT(0) #define SDMA_PKT_Q_ACTIVE BIT(1) #define SDMA_PKT_Q_DEFERRED BIT(2) @@ -232,7 +228,6 @@ struct user_sdma_request { /* Writeable fields shared with interrupt */ u64 seqcomp ____cacheline_aligned_in_smp; u64 seqsubmitted; - unsigned long flags; /* status of the last txreq completed */ int status; @@ -257,6 +252,7 @@ struct user_sdma_request { /* progress index moving along the iovs array */ u8 iov_idx; u8 done; + u8 has_error; struct user_sdma_iovec iovs[MAX_VECTORS_PER_REQ]; } ____cacheline_aligned_in_smp; @@ -625,9 +621,9 @@ int hfi1_user_sdma_process_request(struct hfi1_filedata *fd, req->seqnum = 0; req->seqcomp = 0; req->seqsubmitted = 0; - req->flags = 0; req->tids = NULL; req->done = 0; + req->has_error = 0; INIT_LIST_HEAD(&req->txps); memcpy(&req->info, &info, sizeof(info)); @@ -814,7 +810,7 @@ int hfi1_user_sdma_process_request(struct hfi1_filedata *fd, if (ret < 0) { if (ret != -EBUSY) { req->status = ret; - set_bit(SDMA_REQ_DONE_ERROR, &req->flags); + WRITE_ONCE(req->has_error, 1); if (ACCESS_ONCE(req->seqcomp) == req->seqsubmitted - 1) goto free_req; @@ -916,10 +912,8 @@ static int user_sdma_send_pkts(struct user_sdma_request *req, unsigned maxpkts) pq = req->pq; /* If tx completion has reported an error, we are done. */ - if (test_bit(SDMA_REQ_HAS_ERROR, &req->flags)) { - set_bit(SDMA_REQ_DONE_ERROR, &req->flags); + if (READ_ONCE(req->has_error)) return -EFAULT; - } /* * Check if we might have sent the entire request already @@ -942,10 +936,8 @@ static int user_sdma_send_pkts(struct user_sdma_request *req, unsigned maxpkts) * with errors. If so, we are not going to process any * more packets from this request. */ - if (test_bit(SDMA_REQ_HAS_ERROR, &req->flags)) { - set_bit(SDMA_REQ_DONE_ERROR, &req->flags); + if (READ_ONCE(req->has_error)) return -EFAULT; - } tx = kmem_cache_alloc(pq->txreq_cache, GFP_KERNEL); if (!tx) @@ -1566,7 +1558,7 @@ static void user_sdma_txreq_cb(struct sdma_txreq *txreq, int status) if (status != SDMA_TXREQ_S_OK) { SDMA_DBG(req, "SDMA completion with error %d", status); - set_bit(SDMA_REQ_HAS_ERROR, &req->flags); + WRITE_ONCE(req->has_error, 1); } req->seqcomp = tx->seqnum; @@ -1586,7 +1578,7 @@ static void user_sdma_txreq_cb(struct sdma_txreq *txreq, int status) req->status = status; if (req->seqcomp == (ACCESS_ONCE(req->seqsubmitted) - 1) && (READ_ONCE(req->done) || - test_bit(SDMA_REQ_DONE_ERROR, &req->flags))) { + READ_ONCE(req->has_error))) { user_sdma_free_request(req, false); pq_update(pq); set_comp_state(pq, cq, idx, ERROR, req->status); -- cgit v1.2.3 From b4e9e2f0fc87b876a4e2162733c1940e861785b1 Mon Sep 17 00:00:00 2001 From: Sebastian Sanchez Date: Fri, 26 May 2017 05:35:57 -0700 Subject: IB/hfi1: Reclassify type of messages printed for platform config logic Reclassify messages printed out to /var/log/messages into warnings and errors to facilitate debugging in the future for issues related to the platform config logic. Reviewed-by: Mike Marciniszyn Signed-off-by: Sebastian Sanchez Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/platform.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/hfi1/platform.c b/drivers/infiniband/hw/hfi1/platform.c index 838fe84e285a..cbda9b189216 100644 --- a/drivers/infiniband/hw/hfi1/platform.c +++ b/drivers/infiniband/hw/hfi1/platform.c @@ -242,7 +242,7 @@ static int qual_power(struct hfi1_pportdata *ppd) if (ppd->offline_disabled_reason == HFI1_ODR_MASK(OPA_LINKDOWN_REASON_POWER_POLICY)) { - dd_dev_info( + dd_dev_err( ppd->dd, "%s: Port disabled due to system power restrictions\n", __func__); @@ -268,7 +268,7 @@ static int qual_bitrate(struct hfi1_pportdata *ppd) if (ppd->offline_disabled_reason == HFI1_ODR_MASK(OPA_LINKDOWN_REASON_LINKSPEED_POLICY)) { - dd_dev_info( + dd_dev_err( ppd->dd, "%s: Cable failed bitrate check, disabling port\n", __func__); @@ -709,15 +709,15 @@ static void apply_tunings( ret = load_8051_config(ppd->dd, DC_HOST_COMM_SETTINGS, GENERAL_CONFIG, config_data); if (ret != HCMD_SUCCESS) - dd_dev_info(ppd->dd, - "%s: Failed set ext device config params\n", - __func__); + dd_dev_err(ppd->dd, + "%s: Failed set ext device config params\n", + __func__); } if (tx_preset_index == OPA_INVALID_INDEX) { if (ppd->port_type == PORT_TYPE_QSFP && limiting_active) - dd_dev_info(ppd->dd, "%s: Invalid Tx preset index\n", - __func__); + dd_dev_err(ppd->dd, "%s: Invalid Tx preset index\n", + __func__); return; } @@ -900,7 +900,7 @@ static int tune_qsfp(struct hfi1_pportdata *ppd, case 0xD: /* fallthrough */ case 0xF: default: - dd_dev_info(ppd->dd, "%s: Unknown/unsupported cable\n", + dd_dev_warn(ppd->dd, "%s: Unknown/unsupported cable\n", __func__); break; } @@ -942,7 +942,7 @@ void tune_serdes(struct hfi1_pportdata *ppd) case PORT_TYPE_DISCONNECTED: ppd->offline_disabled_reason = HFI1_ODR_MASK(OPA_LINKDOWN_REASON_DISCONNECTED); - dd_dev_info(dd, "%s: Port disconnected, disabling port\n", + dd_dev_warn(dd, "%s: Port disconnected, disabling port\n", __func__); goto bail; case PORT_TYPE_FIXED: @@ -1027,7 +1027,7 @@ void tune_serdes(struct hfi1_pportdata *ppd) } break; default: - dd_dev_info(ppd->dd, "%s: Unknown port type\n", __func__); + dd_dev_warn(ppd->dd, "%s: Unknown port type\n", __func__); ppd->port_type = PORT_TYPE_UNKNOWN; tuning_method = OPA_UNKNOWN_TUNING; total_atten = 0; -- cgit v1.2.3 From 90dba23e1e30af72dbf4379842a5161e811b26b8 Mon Sep 17 00:00:00 2001 From: Ira Weiny Date: Fri, 26 May 2017 05:36:04 -0700 Subject: IB/hfi1: Fix up sdma_init function comment sdma_init does not take a number of sdma engine parameters, rather it initializes all of the sdma engines. Signed-off-by: Ira Weiny Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/sdma.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/hfi1/sdma.c b/drivers/infiniband/hw/hfi1/sdma.c index bfd0d5187e9b..d82ff57214c5 100644 --- a/drivers/infiniband/hw/hfi1/sdma.c +++ b/drivers/infiniband/hw/hfi1/sdma.c @@ -1340,10 +1340,8 @@ static void sdma_clean(struct hfi1_devdata *dd, size_t num_engines) * @dd: hfi1_devdata * @port: port number (currently only zero) * - * sdma_init initializes the specified number of engines. - * - * The code initializes each sde, its csrs. Interrupts - * are not required to be enabled. + * Initializes each sde and its csrs. + * Interrupts are not required to be enabled. * * Returns: * 0 - success, -errno on failure -- cgit v1.2.3 From b2f8a04e77bad520d52b7f321ca776b33c947ad0 Mon Sep 17 00:00:00 2001 From: Dennis Dalessandro Date: Mon, 29 May 2017 17:17:28 -0700 Subject: IB/rdmavt: Remove duplicated functions The free_qpn() function from the hfi1/qib driver which was the basis for rdmavt_free_qpn() function was accidentally left in the code. Remove it. Reviewed-by: Michael J. Ruhl Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/sw/rdmavt/qp.c | 37 ++++++++++++++----------------------- 1 file changed, 14 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/sw/rdmavt/qp.c b/drivers/infiniband/sw/rdmavt/qp.c index a3dd1e536860..a372afbbfbef 100644 --- a/drivers/infiniband/sw/rdmavt/qp.c +++ b/drivers/infiniband/sw/rdmavt/qp.c @@ -422,15 +422,6 @@ bail: return ret; } -static void free_qpn(struct rvt_qpn_table *qpt, u32 qpn) -{ - struct rvt_qpn_map *map; - - map = qpt->map + qpn / RVT_BITS_PER_PAGE; - if (map->page) - clear_bit(qpn & RVT_BITS_PER_PAGE_MASK, map->page); -} - /** * rvt_clear_mr_refs - Drop help mr refs * @qp: rvt qp data structure @@ -646,6 +637,19 @@ static void rvt_reset_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp, lockdep_assert_held(&qp->s_lock); } +/** rvt_free_qpn - Free a qpn from the bit map + * @qpt: QP table + * @qpn: queue pair number to free + */ +static void rvt_free_qpn(struct rvt_qpn_table *qpt, u32 qpn) +{ + struct rvt_qpn_map *map; + + map = qpt->map + qpn / RVT_BITS_PER_PAGE; + if (map->page) + clear_bit(qpn & RVT_BITS_PER_PAGE_MASK, map->page); +} + /** * rvt_create_qp - create a queue pair for a device * @ibpd: the protection domain who's device we create the queue pair for @@ -936,7 +940,7 @@ bail_ip: kref_put(&qp->ip->ref, rvt_release_mmap_info); bail_qpn: - free_qpn(&rdi->qp_dev->qpn_table, qp->ibqp.qp_num); + rvt_free_qpn(&rdi->qp_dev->qpn_table, qp->ibqp.qp_num); bail_rq_wq: if (!qp->ip) @@ -1325,19 +1329,6 @@ inval: return -EINVAL; } -/** rvt_free_qpn - Free a qpn from the bit map - * @qpt: QP table - * @qpn: queue pair number to free - */ -static void rvt_free_qpn(struct rvt_qpn_table *qpt, u32 qpn) -{ - struct rvt_qpn_map *map; - - map = qpt->map + qpn / RVT_BITS_PER_PAGE; - if (map->page) - clear_bit(qpn & RVT_BITS_PER_PAGE_MASK, map->page); -} - /** * rvt_destroy_qp - destroy a queue pair * @ibqp: the queue pair to destroy -- cgit v1.2.3 From bc54f6714c3a5d1f7ac6e7e5a5f7c390b1a01285 Mon Sep 17 00:00:00 2001 From: Dennis Dalessandro Date: Mon, 29 May 2017 17:18:14 -0700 Subject: IB/hfi1: Ensure dd->gi_mask can not be overflowed As the code stands today the array access in remap_intr() is OK. To future proof the code though we should explicitly check to ensure the index value is not outside of the valid range. This is not a straight forward calculation so err on the side of caution. Reviewed-by: Michael J. Ruhl Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/chip.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/hfi1/chip.c b/drivers/infiniband/hw/hfi1/chip.c index 9118618d28e5..d6af715c35bf 100644 --- a/drivers/infiniband/hw/hfi1/chip.c +++ b/drivers/infiniband/hw/hfi1/chip.c @@ -12832,7 +12832,12 @@ static void remap_intr(struct hfi1_devdata *dd, int isrc, int msix_intr) /* clear from the handled mask of the general interrupt */ m = isrc / 64; n = isrc % 64; - dd->gi_mask[m] &= ~((u64)1 << n); + if (likely(m < CCE_NUM_INT_CSRS)) { + dd->gi_mask[m] &= ~((u64)1 << n); + } else { + dd_dev_err(dd, "remap interrupt err\n"); + return; + } /* direct the chip source to the given MSI-X interrupt */ m = isrc / 8; -- cgit v1.2.3 From 67838e64fa63415fe4e0da7149bcb123ed9f5612 Mon Sep 17 00:00:00 2001 From: Dennis Dalessandro Date: Mon, 29 May 2017 17:18:46 -0700 Subject: IB/hfi1: Fix spelling mistake in linkdown reason Spell receive correctly in OPA_LINKDOWN_REASON_RCV_ERROR Reviewed-by: Michael J. Ruhl Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/chip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/hfi1/chip.c b/drivers/infiniband/hw/hfi1/chip.c index d6af715c35bf..99c29ddcca35 100644 --- a/drivers/infiniband/hw/hfi1/chip.c +++ b/drivers/infiniband/hw/hfi1/chip.c @@ -6906,7 +6906,7 @@ static void reset_neighbor_info(struct hfi1_pportdata *ppd) static const char * const link_down_reason_strs[] = { [OPA_LINKDOWN_REASON_NONE] = "None", - [OPA_LINKDOWN_REASON_RCV_ERROR_0] = "Recive error 0", + [OPA_LINKDOWN_REASON_RCV_ERROR_0] = "Receive error 0", [OPA_LINKDOWN_REASON_BAD_PKT_LEN] = "Bad packet length", [OPA_LINKDOWN_REASON_PKT_TOO_LONG] = "Packet too long", [OPA_LINKDOWN_REASON_PKT_TOO_SHORT] = "Packet too short", -- cgit v1.2.3 From 6c31e5283cb06b81a13cc88da2f2ad3db594a935 Mon Sep 17 00:00:00 2001 From: Dennis Dalessandro Date: Mon, 29 May 2017 17:19:21 -0700 Subject: IB/hfi1: Use QPN mask to avoid overflow Ensure we can't come up with an array size that is bigger than the array by applying the QPN mask before the divide in the free_qpn function. Reviewed-by: Michael J. Ruhl Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/sw/rdmavt/qp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/sw/rdmavt/qp.c b/drivers/infiniband/sw/rdmavt/qp.c index a372afbbfbef..2ce0928dddd6 100644 --- a/drivers/infiniband/sw/rdmavt/qp.c +++ b/drivers/infiniband/sw/rdmavt/qp.c @@ -645,7 +645,7 @@ static void rvt_free_qpn(struct rvt_qpn_table *qpt, u32 qpn) { struct rvt_qpn_map *map; - map = qpt->map + qpn / RVT_BITS_PER_PAGE; + map = qpt->map + (qpn & RVT_QPN_MASK) / RVT_BITS_PER_PAGE; if (map->page) clear_bit(qpn & RVT_BITS_PER_PAGE_MASK, map->page); } -- cgit v1.2.3 From 52d86e72c515ebd4fb0d329470aa50698e28fb36 Mon Sep 17 00:00:00 2001 From: Dennis Dalessandro Date: Mon, 29 May 2017 17:19:46 -0700 Subject: IB/hfi1: Remove subtraction of uninitialized value In process_receive_packet the packet header field is used to calculate the length of the packet. However this is not necessarily setup. In fact only if the ECN prescan is enabled will the packet header be valid at this point. The code works as is because we do not do anything with the packet length at this point in the packet processing. The length and header are setup correctly in hfi1_setup_ib_header which is called by the following sequence: process_receive_packet() -> rhf_receieve_function_map[]() --> process_receive_ib() ---> hfi1_setup_9B_packet() ----> hfi1_setup_ib_header() Reviewed-by: Mike Marciniszyn Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/driver.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/hfi1/driver.c b/drivers/infiniband/hw/hfi1/driver.c index 2a1022e374a5..9e59430bc55c 100644 --- a/drivers/infiniband/hw/hfi1/driver.c +++ b/drivers/infiniband/hw/hfi1/driver.c @@ -703,7 +703,6 @@ static inline int process_rcv_packet(struct hfi1_packet *packet, int thread) packet->etype = rhf_rcv_type(packet->rhf); - packet->hlen = (u8 *)packet->rhf_addr - (u8 *)packet->hdr; /* total length */ packet->tlen = rhf_pkt_len(packet->rhf); /* in bytes */ /* retrieve eager buffer details */ -- cgit v1.2.3 From f1685179820bb7f9d9c4f5d0ac9bfb269529a919 Mon Sep 17 00:00:00 2001 From: Neel Desai Date: Mon, 29 May 2017 17:20:27 -0700 Subject: IB/hfi1: Add error checking for buffer overrun in OPA aggregate Improve safety of code by checking the size of the data buffer and prevent buffer overrun Reviewed-by: Dennis Dalessandro Reviewed-by: Brian Welty Signed-off-by: Neel Desai Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/mad.c | 296 ++++++++++++++++++++++++--------------- 1 file changed, 185 insertions(+), 111 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/hfi1/mad.c b/drivers/infiniband/hw/hfi1/mad.c index 70831ad621b0..b180dff5f2e9 100644 --- a/drivers/infiniband/hw/hfi1/mad.c +++ b/drivers/infiniband/hw/hfi1/mad.c @@ -59,6 +59,14 @@ #define OPA_LINK_WIDTH_RESET_OLD 0x0fff #define OPA_LINK_WIDTH_RESET 0xffff +static int smp_length_check(u32 data_size, u32 request_len) +{ + if (unlikely(request_len < data_size)) + return -EINVAL; + + return 0; +} + static int reply(struct ib_mad_hdr *smp) { /* @@ -308,11 +316,11 @@ void hfi1_node_desc_chg(struct hfi1_ibport *ibp) static int __subn_get_opa_nodedesc(struct opa_smp *smp, u32 am, u8 *data, struct ib_device *ibdev, - u8 port, u32 *resp_len) + u8 port, u32 *resp_len, u32 max_len) { struct opa_node_description *nd; - if (am) { + if (am || smp_length_check(sizeof(*nd), max_len)) { smp->status |= IB_SMP_INVALID_FIELD; return reply((struct ib_mad_hdr *)smp); } @@ -329,7 +337,7 @@ static int __subn_get_opa_nodedesc(struct opa_smp *smp, u32 am, static int __subn_get_opa_nodeinfo(struct opa_smp *smp, u32 am, u8 *data, struct ib_device *ibdev, u8 port, - u32 *resp_len) + u32 *resp_len, u32 max_len) { struct opa_node_info *ni; struct hfi1_devdata *dd = dd_from_ibdev(ibdev); @@ -339,6 +347,7 @@ static int __subn_get_opa_nodeinfo(struct opa_smp *smp, u32 am, u8 *data, /* GUID 0 is illegal */ if (am || pidx >= dd->num_pports || ibdev->node_guid == 0 || + smp_length_check(sizeof(*ni), max_len) || get_sguid(to_iport(ibdev, port), HFI1_PORT_GUID_INDEX) == 0) { smp->status |= IB_SMP_INVALID_FIELD; return reply((struct ib_mad_hdr *)smp); @@ -520,7 +529,7 @@ void read_ltp_rtt(struct hfi1_devdata *dd) static int __subn_get_opa_portinfo(struct opa_smp *smp, u32 am, u8 *data, struct ib_device *ibdev, u8 port, - u32 *resp_len) + u32 *resp_len, u32 max_len) { int i; struct hfi1_devdata *dd; @@ -536,7 +545,7 @@ static int __subn_get_opa_portinfo(struct opa_smp *smp, u32 am, u8 *data, u32 buffer_units; u64 tmp = 0; - if (num_ports != 1) { + if (num_ports != 1 || smp_length_check(sizeof(*pi), max_len)) { smp->status |= IB_SMP_INVALID_FIELD; return reply((struct ib_mad_hdr *)smp); } @@ -745,7 +754,7 @@ static int get_pkeys(struct hfi1_devdata *dd, u8 port, u16 *pkeys) static int __subn_get_opa_pkeytable(struct opa_smp *smp, u32 am, u8 *data, struct ib_device *ibdev, u8 port, - u32 *resp_len) + u32 *resp_len, u32 max_len) { struct hfi1_devdata *dd = dd_from_ibdev(ibdev); u32 n_blocks_req = OPA_AM_NBLK(am); @@ -768,6 +777,11 @@ static int __subn_get_opa_pkeytable(struct opa_smp *smp, u32 am, u8 *data, size = (n_blocks_req * OPA_PARTITION_TABLE_BLK_SIZE) * sizeof(u16); + if (smp_length_check(size, max_len)) { + smp->status |= IB_SMP_INVALID_FIELD; + return reply((struct ib_mad_hdr *)smp); + } + if (start_block + n_blocks_req > n_blocks_avail || n_blocks_req > OPA_NUM_PKEY_BLOCKS_PER_SMP) { pr_warn("OPA Get PKey AM Invalid : s 0x%x; req 0x%x; " @@ -1071,7 +1085,7 @@ static int set_port_states(struct hfi1_pportdata *ppd, struct opa_smp *smp, */ static int __subn_set_opa_portinfo(struct opa_smp *smp, u32 am, u8 *data, struct ib_device *ibdev, u8 port, - u32 *resp_len) + u32 *resp_len, u32 max_len) { struct opa_port_info *pi = (struct opa_port_info *)data; struct ib_event event; @@ -1092,7 +1106,8 @@ static int __subn_set_opa_portinfo(struct opa_smp *smp, u32 am, u8 *data, int ret, i, invalid = 0, call_set_mtu = 0; int call_link_downgrade_policy = 0; - if (num_ports != 1) { + if (num_ports != 1 || + smp_length_check(sizeof(*pi), max_len)) { smp->status |= IB_SMP_INVALID_FIELD; return reply((struct ib_mad_hdr *)smp); } @@ -1343,7 +1358,8 @@ static int __subn_set_opa_portinfo(struct opa_smp *smp, u32 am, u8 *data, if (ret) return ret; - ret = __subn_get_opa_portinfo(smp, am, data, ibdev, port, resp_len); + ret = __subn_get_opa_portinfo(smp, am, data, ibdev, port, resp_len, + max_len); /* restore re-reg bit per o14-12.2.1 */ pi->clientrereg_subnettimeout |= clientrereg; @@ -1360,7 +1376,8 @@ static int __subn_set_opa_portinfo(struct opa_smp *smp, u32 am, u8 *data, return ret; get_only: - return __subn_get_opa_portinfo(smp, am, data, ibdev, port, resp_len); + return __subn_get_opa_portinfo(smp, am, data, ibdev, port, resp_len, + max_len); } /** @@ -1421,7 +1438,7 @@ static int set_pkeys(struct hfi1_devdata *dd, u8 port, u16 *pkeys) static int __subn_set_opa_pkeytable(struct opa_smp *smp, u32 am, u8 *data, struct ib_device *ibdev, u8 port, - u32 *resp_len) + u32 *resp_len, u32 max_len) { struct hfi1_devdata *dd = dd_from_ibdev(ibdev); u32 n_blocks_sent = OPA_AM_NBLK(am); @@ -1431,6 +1448,7 @@ static int __subn_set_opa_pkeytable(struct opa_smp *smp, u32 am, u8 *data, int i; u16 n_blocks_avail; unsigned npkeys = hfi1_get_npkeys(dd); + u32 size = 0; if (n_blocks_sent == 0) { pr_warn("OPA Get PKey AM Invalid : P = %d; B = 0x%x; N = 0x%x\n", @@ -1441,6 +1459,13 @@ static int __subn_set_opa_pkeytable(struct opa_smp *smp, u32 am, u8 *data, n_blocks_avail = (u16)(npkeys / OPA_PARTITION_TABLE_BLK_SIZE) + 1; + size = sizeof(u16) * (n_blocks_sent * OPA_PARTITION_TABLE_BLK_SIZE); + + if (smp_length_check(size, max_len)) { + smp->status |= IB_SMP_INVALID_FIELD; + return reply((struct ib_mad_hdr *)smp); + } + if (start_block + n_blocks_sent > n_blocks_avail || n_blocks_sent > OPA_NUM_PKEY_BLOCKS_PER_SMP) { pr_warn("OPA Set PKey AM Invalid : s 0x%x; req 0x%x; avail 0x%x; blk/smp 0x%lx\n", @@ -1458,7 +1483,8 @@ static int __subn_set_opa_pkeytable(struct opa_smp *smp, u32 am, u8 *data, return reply((struct ib_mad_hdr *)smp); } - return __subn_get_opa_pkeytable(smp, am, data, ibdev, port, resp_len); + return __subn_get_opa_pkeytable(smp, am, data, ibdev, port, resp_len, + max_len); } #define ILLEGAL_VL 12 @@ -1519,14 +1545,14 @@ static int get_sc2vlt_tables(struct hfi1_devdata *dd, void *data) static int __subn_get_opa_sl_to_sc(struct opa_smp *smp, u32 am, u8 *data, struct ib_device *ibdev, u8 port, - u32 *resp_len) + u32 *resp_len, u32 max_len) { struct hfi1_ibport *ibp = to_iport(ibdev, port); u8 *p = data; size_t size = ARRAY_SIZE(ibp->sl_to_sc); /* == 32 */ unsigned i; - if (am) { + if (am || smp_length_check(size, max_len)) { smp->status |= IB_SMP_INVALID_FIELD; return reply((struct ib_mad_hdr *)smp); } @@ -1542,14 +1568,15 @@ static int __subn_get_opa_sl_to_sc(struct opa_smp *smp, u32 am, u8 *data, static int __subn_set_opa_sl_to_sc(struct opa_smp *smp, u32 am, u8 *data, struct ib_device *ibdev, u8 port, - u32 *resp_len) + u32 *resp_len, u32 max_len) { struct hfi1_ibport *ibp = to_iport(ibdev, port); u8 *p = data; + size_t size = ARRAY_SIZE(ibp->sl_to_sc); int i; u8 sc; - if (am) { + if (am || smp_length_check(size, max_len)) { smp->status |= IB_SMP_INVALID_FIELD; return reply((struct ib_mad_hdr *)smp); } @@ -1564,19 +1591,20 @@ static int __subn_set_opa_sl_to_sc(struct opa_smp *smp, u32 am, u8 *data, } } - return __subn_get_opa_sl_to_sc(smp, am, data, ibdev, port, resp_len); + return __subn_get_opa_sl_to_sc(smp, am, data, ibdev, port, resp_len, + max_len); } static int __subn_get_opa_sc_to_sl(struct opa_smp *smp, u32 am, u8 *data, struct ib_device *ibdev, u8 port, - u32 *resp_len) + u32 *resp_len, u32 max_len) { struct hfi1_ibport *ibp = to_iport(ibdev, port); u8 *p = data; size_t size = ARRAY_SIZE(ibp->sc_to_sl); /* == 32 */ unsigned i; - if (am) { + if (am || smp_length_check(size, max_len)) { smp->status |= IB_SMP_INVALID_FIELD; return reply((struct ib_mad_hdr *)smp); } @@ -1592,13 +1620,14 @@ static int __subn_get_opa_sc_to_sl(struct opa_smp *smp, u32 am, u8 *data, static int __subn_set_opa_sc_to_sl(struct opa_smp *smp, u32 am, u8 *data, struct ib_device *ibdev, u8 port, - u32 *resp_len) + u32 *resp_len, u32 max_len) { struct hfi1_ibport *ibp = to_iport(ibdev, port); + size_t size = ARRAY_SIZE(ibp->sc_to_sl); u8 *p = data; int i; - if (am) { + if (am || smp_length_check(size, max_len)) { smp->status |= IB_SMP_INVALID_FIELD; return reply((struct ib_mad_hdr *)smp); } @@ -1606,19 +1635,20 @@ static int __subn_set_opa_sc_to_sl(struct opa_smp *smp, u32 am, u8 *data, for (i = 0; i < ARRAY_SIZE(ibp->sc_to_sl); i++) ibp->sc_to_sl[i] = *p++; - return __subn_get_opa_sc_to_sl(smp, am, data, ibdev, port, resp_len); + return __subn_get_opa_sc_to_sl(smp, am, data, ibdev, port, resp_len, + max_len); } static int __subn_get_opa_sc_to_vlt(struct opa_smp *smp, u32 am, u8 *data, struct ib_device *ibdev, u8 port, - u32 *resp_len) + u32 *resp_len, u32 max_len) { u32 n_blocks = OPA_AM_NBLK(am); struct hfi1_devdata *dd = dd_from_ibdev(ibdev); void *vp = (void *)data; size_t size = 4 * sizeof(u64); - if (n_blocks != 1) { + if (n_blocks != 1 || smp_length_check(size, max_len)) { smp->status |= IB_SMP_INVALID_FIELD; return reply((struct ib_mad_hdr *)smp); } @@ -1633,7 +1663,7 @@ static int __subn_get_opa_sc_to_vlt(struct opa_smp *smp, u32 am, u8 *data, static int __subn_set_opa_sc_to_vlt(struct opa_smp *smp, u32 am, u8 *data, struct ib_device *ibdev, u8 port, - u32 *resp_len) + u32 *resp_len, u32 max_len) { u32 n_blocks = OPA_AM_NBLK(am); int async_update = OPA_AM_ASYNC(am); @@ -1641,8 +1671,15 @@ static int __subn_set_opa_sc_to_vlt(struct opa_smp *smp, u32 am, u8 *data, void *vp = (void *)data; struct hfi1_pportdata *ppd; int lstate; + /* + * set_sc2vlt_tables writes the information contained in *data + * to four 64-bit registers SendSC2VLt[0-3]. We need to make + * sure *max_len is not greater than the total size of the four + * SendSC2VLt[0-3] registers. + */ + size_t size = 4 * sizeof(u64); - if (n_blocks != 1 || async_update) { + if (n_blocks != 1 || async_update || smp_length_check(size, max_len)) { smp->status |= IB_SMP_INVALID_FIELD; return reply((struct ib_mad_hdr *)smp); } @@ -1662,27 +1699,28 @@ static int __subn_set_opa_sc_to_vlt(struct opa_smp *smp, u32 am, u8 *data, set_sc2vlt_tables(dd, vp); - return __subn_get_opa_sc_to_vlt(smp, am, data, ibdev, port, resp_len); + return __subn_get_opa_sc_to_vlt(smp, am, data, ibdev, port, resp_len, + max_len); } static int __subn_get_opa_sc_to_vlnt(struct opa_smp *smp, u32 am, u8 *data, struct ib_device *ibdev, u8 port, - u32 *resp_len) + u32 *resp_len, u32 max_len) { u32 n_blocks = OPA_AM_NPORT(am); struct hfi1_devdata *dd = dd_from_ibdev(ibdev); struct hfi1_pportdata *ppd; void *vp = (void *)data; - int size; + int size = sizeof(struct sc2vlnt); - if (n_blocks != 1) { + if (n_blocks != 1 || smp_length_check(size, max_len)) { smp->status |= IB_SMP_INVALID_FIELD; return reply((struct ib_mad_hdr *)smp); } ppd = dd->pport + (port - 1); - size = fm_get_table(ppd, FM_TBL_SC2VLNT, vp); + fm_get_table(ppd, FM_TBL_SC2VLNT, vp); if (resp_len) *resp_len += size; @@ -1692,15 +1730,16 @@ static int __subn_get_opa_sc_to_vlnt(struct opa_smp *smp, u32 am, u8 *data, static int __subn_set_opa_sc_to_vlnt(struct opa_smp *smp, u32 am, u8 *data, struct ib_device *ibdev, u8 port, - u32 *resp_len) + u32 *resp_len, u32 max_len) { u32 n_blocks = OPA_AM_NPORT(am); struct hfi1_devdata *dd = dd_from_ibdev(ibdev); struct hfi1_pportdata *ppd; void *vp = (void *)data; int lstate; + int size = sizeof(struct sc2vlnt); - if (n_blocks != 1) { + if (n_blocks != 1 || smp_length_check(size, max_len)) { smp->status |= IB_SMP_INVALID_FIELD; return reply((struct ib_mad_hdr *)smp); } @@ -1718,12 +1757,12 @@ static int __subn_set_opa_sc_to_vlnt(struct opa_smp *smp, u32 am, u8 *data, fm_set_table(ppd, FM_TBL_SC2VLNT, vp); return __subn_get_opa_sc_to_vlnt(smp, am, data, ibdev, port, - resp_len); + resp_len, max_len); } static int __subn_get_opa_psi(struct opa_smp *smp, u32 am, u8 *data, struct ib_device *ibdev, u8 port, - u32 *resp_len) + u32 *resp_len, u32 max_len) { u32 nports = OPA_AM_NPORT(am); u32 start_of_sm_config = OPA_AM_START_SM_CFG(am); @@ -1732,7 +1771,7 @@ static int __subn_get_opa_psi(struct opa_smp *smp, u32 am, u8 *data, struct hfi1_pportdata *ppd; struct opa_port_state_info *psi = (struct opa_port_state_info *)data; - if (nports != 1) { + if (nports != 1 || smp_length_check(sizeof(*psi), max_len)) { smp->status |= IB_SMP_INVALID_FIELD; return reply((struct ib_mad_hdr *)smp); } @@ -1765,7 +1804,7 @@ static int __subn_get_opa_psi(struct opa_smp *smp, u32 am, u8 *data, static int __subn_set_opa_psi(struct opa_smp *smp, u32 am, u8 *data, struct ib_device *ibdev, u8 port, - u32 *resp_len) + u32 *resp_len, u32 max_len) { u32 nports = OPA_AM_NPORT(am); u32 start_of_sm_config = OPA_AM_START_SM_CFG(am); @@ -1776,7 +1815,7 @@ static int __subn_set_opa_psi(struct opa_smp *smp, u32 am, u8 *data, struct opa_port_state_info *psi = (struct opa_port_state_info *)data; int ret, invalid = 0; - if (nports != 1) { + if (nports != 1 || smp_length_check(sizeof(*psi), max_len)) { smp->status |= IB_SMP_INVALID_FIELD; return reply((struct ib_mad_hdr *)smp); } @@ -1806,19 +1845,21 @@ static int __subn_set_opa_psi(struct opa_smp *smp, u32 am, u8 *data, if (invalid) smp->status |= IB_SMP_INVALID_FIELD; - return __subn_get_opa_psi(smp, am, data, ibdev, port, resp_len); + return __subn_get_opa_psi(smp, am, data, ibdev, port, resp_len, + max_len); } static int __subn_get_opa_cable_info(struct opa_smp *smp, u32 am, u8 *data, struct ib_device *ibdev, u8 port, - u32 *resp_len) + u32 *resp_len, u32 max_len) { struct hfi1_devdata *dd = dd_from_ibdev(ibdev); u32 addr = OPA_AM_CI_ADDR(am); u32 len = OPA_AM_CI_LEN(am) + 1; int ret; - if (dd->pport->port_type != PORT_TYPE_QSFP) { + if (dd->pport->port_type != PORT_TYPE_QSFP || + smp_length_check(len, max_len)) { smp->status |= IB_SMP_INVALID_FIELD; return reply((struct ib_mad_hdr *)smp); } @@ -1861,21 +1902,22 @@ static int __subn_get_opa_cable_info(struct opa_smp *smp, u32 am, u8 *data, } static int __subn_get_opa_bct(struct opa_smp *smp, u32 am, u8 *data, - struct ib_device *ibdev, u8 port, u32 *resp_len) + struct ib_device *ibdev, u8 port, u32 *resp_len, + u32 max_len) { u32 num_ports = OPA_AM_NPORT(am); struct hfi1_devdata *dd = dd_from_ibdev(ibdev); struct hfi1_pportdata *ppd; struct buffer_control *p = (struct buffer_control *)data; - int size; + int size = sizeof(struct buffer_control); - if (num_ports != 1) { + if (num_ports != 1 || smp_length_check(size, max_len)) { smp->status |= IB_SMP_INVALID_FIELD; return reply((struct ib_mad_hdr *)smp); } ppd = dd->pport + (port - 1); - size = fm_get_table(ppd, FM_TBL_BUFFER_CONTROL, p); + fm_get_table(ppd, FM_TBL_BUFFER_CONTROL, p); trace_bct_get(dd, p); if (resp_len) *resp_len += size; @@ -1884,14 +1926,15 @@ static int __subn_get_opa_bct(struct opa_smp *smp, u32 am, u8 *data, } static int __subn_set_opa_bct(struct opa_smp *smp, u32 am, u8 *data, - struct ib_device *ibdev, u8 port, u32 *resp_len) + struct ib_device *ibdev, u8 port, u32 *resp_len, + u32 max_len) { u32 num_ports = OPA_AM_NPORT(am); struct hfi1_devdata *dd = dd_from_ibdev(ibdev); struct hfi1_pportdata *ppd; struct buffer_control *p = (struct buffer_control *)data; - if (num_ports != 1) { + if (num_ports != 1 || smp_length_check(sizeof(*p), max_len)) { smp->status |= IB_SMP_INVALID_FIELD; return reply((struct ib_mad_hdr *)smp); } @@ -1902,41 +1945,43 @@ static int __subn_set_opa_bct(struct opa_smp *smp, u32 am, u8 *data, return reply((struct ib_mad_hdr *)smp); } - return __subn_get_opa_bct(smp, am, data, ibdev, port, resp_len); + return __subn_get_opa_bct(smp, am, data, ibdev, port, resp_len, + max_len); } static int __subn_get_opa_vl_arb(struct opa_smp *smp, u32 am, u8 *data, struct ib_device *ibdev, u8 port, - u32 *resp_len) + u32 *resp_len, u32 max_len) { struct hfi1_pportdata *ppd = ppd_from_ibp(to_iport(ibdev, port)); u32 num_ports = OPA_AM_NPORT(am); u8 section = (am & 0x00ff0000) >> 16; u8 *p = data; - int size = 0; + int size = 256; - if (num_ports != 1) { + if (num_ports != 1 || smp_length_check(size, max_len)) { smp->status |= IB_SMP_INVALID_FIELD; return reply((struct ib_mad_hdr *)smp); } switch (section) { case OPA_VLARB_LOW_ELEMENTS: - size = fm_get_table(ppd, FM_TBL_VL_LOW_ARB, p); + fm_get_table(ppd, FM_TBL_VL_LOW_ARB, p); break; case OPA_VLARB_HIGH_ELEMENTS: - size = fm_get_table(ppd, FM_TBL_VL_HIGH_ARB, p); + fm_get_table(ppd, FM_TBL_VL_HIGH_ARB, p); break; case OPA_VLARB_PREEMPT_ELEMENTS: - size = fm_get_table(ppd, FM_TBL_VL_PREEMPT_ELEMS, p); + fm_get_table(ppd, FM_TBL_VL_PREEMPT_ELEMS, p); break; case OPA_VLARB_PREEMPT_MATRIX: - size = fm_get_table(ppd, FM_TBL_VL_PREEMPT_MATRIX, p); + fm_get_table(ppd, FM_TBL_VL_PREEMPT_MATRIX, p); break; default: pr_warn("OPA SubnGet(VL Arb) AM Invalid : 0x%x\n", be32_to_cpu(smp->attr_mod)); smp->status |= IB_SMP_INVALID_FIELD; + size = 0; break; } @@ -1948,14 +1993,15 @@ static int __subn_get_opa_vl_arb(struct opa_smp *smp, u32 am, u8 *data, static int __subn_set_opa_vl_arb(struct opa_smp *smp, u32 am, u8 *data, struct ib_device *ibdev, u8 port, - u32 *resp_len) + u32 *resp_len, u32 max_len) { struct hfi1_pportdata *ppd = ppd_from_ibp(to_iport(ibdev, port)); u32 num_ports = OPA_AM_NPORT(am); u8 section = (am & 0x00ff0000) >> 16; u8 *p = data; + int size = 256; - if (num_ports != 1) { + if (num_ports != 1 || smp_length_check(size, max_len)) { smp->status |= IB_SMP_INVALID_FIELD; return reply((struct ib_mad_hdr *)smp); } @@ -1983,7 +2029,8 @@ static int __subn_set_opa_vl_arb(struct opa_smp *smp, u32 am, u8 *data, break; } - return __subn_get_opa_vl_arb(smp, am, data, ibdev, port, resp_len); + return __subn_get_opa_vl_arb(smp, am, data, ibdev, port, resp_len, + max_len); } struct opa_pma_mad { @@ -3279,13 +3326,18 @@ struct opa_congestion_info_attr { static int __subn_get_opa_cong_info(struct opa_smp *smp, u32 am, u8 *data, struct ib_device *ibdev, u8 port, - u32 *resp_len) + u32 *resp_len, u32 max_len) { struct opa_congestion_info_attr *p = (struct opa_congestion_info_attr *)data; struct hfi1_ibport *ibp = to_iport(ibdev, port); struct hfi1_pportdata *ppd = ppd_from_ibp(ibp); + if (smp_length_check(sizeof(*p), max_len)) { + smp->status |= IB_SMP_INVALID_FIELD; + return reply((struct ib_mad_hdr *)smp); + } + p->congestion_info = 0; p->control_table_cap = ppd->cc_max_table_entries; p->congestion_log_length = OPA_CONG_LOG_ELEMS; @@ -3298,7 +3350,7 @@ static int __subn_get_opa_cong_info(struct opa_smp *smp, u32 am, u8 *data, static int __subn_get_opa_cong_setting(struct opa_smp *smp, u32 am, u8 *data, struct ib_device *ibdev, - u8 port, u32 *resp_len) + u8 port, u32 *resp_len, u32 max_len) { int i; struct opa_congestion_setting_attr *p = @@ -3308,6 +3360,11 @@ static int __subn_get_opa_cong_setting(struct opa_smp *smp, u32 am, struct opa_congestion_setting_entry_shadow *entries; struct cc_state *cc_state; + if (smp_length_check(sizeof(*p), max_len)) { + smp->status |= IB_SMP_INVALID_FIELD; + return reply((struct ib_mad_hdr *)smp); + } + rcu_read_lock(); cc_state = get_cc_state(ppd); @@ -3382,7 +3439,7 @@ static void apply_cc_state(struct hfi1_pportdata *ppd) static int __subn_set_opa_cong_setting(struct opa_smp *smp, u32 am, u8 *data, struct ib_device *ibdev, u8 port, - u32 *resp_len) + u32 *resp_len, u32 max_len) { struct opa_congestion_setting_attr *p = (struct opa_congestion_setting_attr *)data; @@ -3391,6 +3448,11 @@ static int __subn_set_opa_cong_setting(struct opa_smp *smp, u32 am, u8 *data, struct opa_congestion_setting_entry_shadow *entries; int i; + if (smp_length_check(sizeof(*p), max_len)) { + smp->status |= IB_SMP_INVALID_FIELD; + return reply((struct ib_mad_hdr *)smp); + } + /* * Save details from packet into the ppd. Hold the cc_state_lock so * our information is consistent with anyone trying to apply the state. @@ -3412,12 +3474,12 @@ static int __subn_set_opa_cong_setting(struct opa_smp *smp, u32 am, u8 *data, apply_cc_state(ppd); return __subn_get_opa_cong_setting(smp, am, data, ibdev, port, - resp_len); + resp_len, max_len); } static int __subn_get_opa_hfi1_cong_log(struct opa_smp *smp, u32 am, u8 *data, struct ib_device *ibdev, - u8 port, u32 *resp_len) + u8 port, u32 *resp_len, u32 max_len) { struct hfi1_ibport *ibp = to_iport(ibdev, port); struct hfi1_pportdata *ppd = ppd_from_ibp(ibp); @@ -3425,7 +3487,7 @@ static int __subn_get_opa_hfi1_cong_log(struct opa_smp *smp, u32 am, s64 ts; int i; - if (am != 0) { + if (am || smp_length_check(sizeof(*cong_log), max_len)) { smp->status |= IB_SMP_INVALID_FIELD; return reply((struct ib_mad_hdr *)smp); } @@ -3483,7 +3545,7 @@ static int __subn_get_opa_hfi1_cong_log(struct opa_smp *smp, u32 am, static int __subn_get_opa_cc_table(struct opa_smp *smp, u32 am, u8 *data, struct ib_device *ibdev, u8 port, - u32 *resp_len) + u32 *resp_len, u32 max_len) { struct ib_cc_table_attr *cc_table_attr = (struct ib_cc_table_attr *)data; @@ -3495,9 +3557,10 @@ static int __subn_get_opa_cc_table(struct opa_smp *smp, u32 am, u8 *data, int i, j; u32 sentry, eentry; struct cc_state *cc_state; + u32 size = sizeof(u16) * (IB_CCT_ENTRIES * n_blocks + 1); /* sanity check n_blocks, start_block */ - if (n_blocks == 0 || + if (n_blocks == 0 || smp_length_check(size, max_len) || start_block + n_blocks > ppd->cc_max_table_entries) { smp->status |= IB_SMP_INVALID_FIELD; return reply((struct ib_mad_hdr *)smp); @@ -3527,14 +3590,14 @@ static int __subn_get_opa_cc_table(struct opa_smp *smp, u32 am, u8 *data, rcu_read_unlock(); if (resp_len) - *resp_len += sizeof(u16) * (IB_CCT_ENTRIES * n_blocks + 1); + *resp_len += size; return reply((struct ib_mad_hdr *)smp); } static int __subn_set_opa_cc_table(struct opa_smp *smp, u32 am, u8 *data, struct ib_device *ibdev, u8 port, - u32 *resp_len) + u32 *resp_len, u32 max_len) { struct ib_cc_table_attr *p = (struct ib_cc_table_attr *)data; struct hfi1_ibport *ibp = to_iport(ibdev, port); @@ -3545,9 +3608,10 @@ static int __subn_set_opa_cc_table(struct opa_smp *smp, u32 am, u8 *data, int i, j; u32 sentry, eentry; u16 ccti_limit; + u32 size = sizeof(u16) * (IB_CCT_ENTRIES * n_blocks + 1); /* sanity check n_blocks, start_block */ - if (n_blocks == 0 || + if (n_blocks == 0 || smp_length_check(size, max_len) || start_block + n_blocks > ppd->cc_max_table_entries) { smp->status |= IB_SMP_INVALID_FIELD; return reply((struct ib_mad_hdr *)smp); @@ -3578,7 +3642,8 @@ static int __subn_set_opa_cc_table(struct opa_smp *smp, u32 am, u8 *data, /* now apply the information */ apply_cc_state(ppd); - return __subn_get_opa_cc_table(smp, am, data, ibdev, port, resp_len); + return __subn_get_opa_cc_table(smp, am, data, ibdev, port, resp_len, + max_len); } struct opa_led_info { @@ -3591,7 +3656,7 @@ struct opa_led_info { static int __subn_get_opa_led_info(struct opa_smp *smp, u32 am, u8 *data, struct ib_device *ibdev, u8 port, - u32 *resp_len) + u32 *resp_len, u32 max_len) { struct hfi1_devdata *dd = dd_from_ibdev(ibdev); struct hfi1_pportdata *ppd = dd->pport; @@ -3599,7 +3664,7 @@ static int __subn_get_opa_led_info(struct opa_smp *smp, u32 am, u8 *data, u32 nport = OPA_AM_NPORT(am); u32 is_beaconing_active; - if (nport != 1) { + if (nport != 1 || smp_length_check(sizeof(*p), max_len)) { smp->status |= IB_SMP_INVALID_FIELD; return reply((struct ib_mad_hdr *)smp); } @@ -3621,14 +3686,14 @@ static int __subn_get_opa_led_info(struct opa_smp *smp, u32 am, u8 *data, static int __subn_set_opa_led_info(struct opa_smp *smp, u32 am, u8 *data, struct ib_device *ibdev, u8 port, - u32 *resp_len) + u32 *resp_len, u32 max_len) { struct hfi1_devdata *dd = dd_from_ibdev(ibdev); struct opa_led_info *p = (struct opa_led_info *)data; u32 nport = OPA_AM_NPORT(am); int on = !!(be32_to_cpu(p->rsvd_led_mask) & OPA_LED_MASK); - if (nport != 1) { + if (nport != 1 || smp_length_check(sizeof(*p), max_len)) { smp->status |= IB_SMP_INVALID_FIELD; return reply((struct ib_mad_hdr *)smp); } @@ -3638,12 +3703,13 @@ static int __subn_set_opa_led_info(struct opa_smp *smp, u32 am, u8 *data, else shutdown_led_override(dd->pport); - return __subn_get_opa_led_info(smp, am, data, ibdev, port, resp_len); + return __subn_get_opa_led_info(smp, am, data, ibdev, port, resp_len, + max_len); } static int subn_get_opa_sma(__be16 attr_id, struct opa_smp *smp, u32 am, u8 *data, struct ib_device *ibdev, u8 port, - u32 *resp_len) + u32 *resp_len, u32 max_len) { int ret; struct hfi1_ibport *ibp = to_iport(ibdev, port); @@ -3651,71 +3717,71 @@ static int subn_get_opa_sma(__be16 attr_id, struct opa_smp *smp, u32 am, switch (attr_id) { case IB_SMP_ATTR_NODE_DESC: ret = __subn_get_opa_nodedesc(smp, am, data, ibdev, port, - resp_len); + resp_len, max_len); break; case IB_SMP_ATTR_NODE_INFO: ret = __subn_get_opa_nodeinfo(smp, am, data, ibdev, port, - resp_len); + resp_len, max_len); break; case IB_SMP_ATTR_PORT_INFO: ret = __subn_get_opa_portinfo(smp, am, data, ibdev, port, - resp_len); + resp_len, max_len); break; case IB_SMP_ATTR_PKEY_TABLE: ret = __subn_get_opa_pkeytable(smp, am, data, ibdev, port, - resp_len); + resp_len, max_len); break; case OPA_ATTRIB_ID_SL_TO_SC_MAP: ret = __subn_get_opa_sl_to_sc(smp, am, data, ibdev, port, - resp_len); + resp_len, max_len); break; case OPA_ATTRIB_ID_SC_TO_SL_MAP: ret = __subn_get_opa_sc_to_sl(smp, am, data, ibdev, port, - resp_len); + resp_len, max_len); break; case OPA_ATTRIB_ID_SC_TO_VLT_MAP: ret = __subn_get_opa_sc_to_vlt(smp, am, data, ibdev, port, - resp_len); + resp_len, max_len); break; case OPA_ATTRIB_ID_SC_TO_VLNT_MAP: ret = __subn_get_opa_sc_to_vlnt(smp, am, data, ibdev, port, - resp_len); + resp_len, max_len); break; case OPA_ATTRIB_ID_PORT_STATE_INFO: ret = __subn_get_opa_psi(smp, am, data, ibdev, port, - resp_len); + resp_len, max_len); break; case OPA_ATTRIB_ID_BUFFER_CONTROL_TABLE: ret = __subn_get_opa_bct(smp, am, data, ibdev, port, - resp_len); + resp_len, max_len); break; case OPA_ATTRIB_ID_CABLE_INFO: ret = __subn_get_opa_cable_info(smp, am, data, ibdev, port, - resp_len); + resp_len, max_len); break; case IB_SMP_ATTR_VL_ARB_TABLE: ret = __subn_get_opa_vl_arb(smp, am, data, ibdev, port, - resp_len); + resp_len, max_len); break; case OPA_ATTRIB_ID_CONGESTION_INFO: ret = __subn_get_opa_cong_info(smp, am, data, ibdev, port, - resp_len); + resp_len, max_len); break; case OPA_ATTRIB_ID_HFI_CONGESTION_SETTING: ret = __subn_get_opa_cong_setting(smp, am, data, ibdev, - port, resp_len); + port, resp_len, max_len); break; case OPA_ATTRIB_ID_HFI_CONGESTION_LOG: ret = __subn_get_opa_hfi1_cong_log(smp, am, data, ibdev, - port, resp_len); + port, resp_len, max_len); break; case OPA_ATTRIB_ID_CONGESTION_CONTROL_TABLE: ret = __subn_get_opa_cc_table(smp, am, data, ibdev, port, - resp_len); + resp_len, max_len); break; case IB_SMP_ATTR_LED_INFO: ret = __subn_get_opa_led_info(smp, am, data, ibdev, port, - resp_len); + resp_len, max_len); break; case IB_SMP_ATTR_SM_INFO: if (ibp->rvp.port_cap_flags & IB_PORT_SM_DISABLED) @@ -3733,7 +3799,7 @@ static int subn_get_opa_sma(__be16 attr_id, struct opa_smp *smp, u32 am, static int subn_set_opa_sma(__be16 attr_id, struct opa_smp *smp, u32 am, u8 *data, struct ib_device *ibdev, u8 port, - u32 *resp_len) + u32 *resp_len, u32 max_len) { int ret; struct hfi1_ibport *ibp = to_iport(ibdev, port); @@ -3741,51 +3807,51 @@ static int subn_set_opa_sma(__be16 attr_id, struct opa_smp *smp, u32 am, switch (attr_id) { case IB_SMP_ATTR_PORT_INFO: ret = __subn_set_opa_portinfo(smp, am, data, ibdev, port, - resp_len); + resp_len, max_len); break; case IB_SMP_ATTR_PKEY_TABLE: ret = __subn_set_opa_pkeytable(smp, am, data, ibdev, port, - resp_len); + resp_len, max_len); break; case OPA_ATTRIB_ID_SL_TO_SC_MAP: ret = __subn_set_opa_sl_to_sc(smp, am, data, ibdev, port, - resp_len); + resp_len, max_len); break; case OPA_ATTRIB_ID_SC_TO_SL_MAP: ret = __subn_set_opa_sc_to_sl(smp, am, data, ibdev, port, - resp_len); + resp_len, max_len); break; case OPA_ATTRIB_ID_SC_TO_VLT_MAP: ret = __subn_set_opa_sc_to_vlt(smp, am, data, ibdev, port, - resp_len); + resp_len, max_len); break; case OPA_ATTRIB_ID_SC_TO_VLNT_MAP: ret = __subn_set_opa_sc_to_vlnt(smp, am, data, ibdev, port, - resp_len); + resp_len, max_len); break; case OPA_ATTRIB_ID_PORT_STATE_INFO: ret = __subn_set_opa_psi(smp, am, data, ibdev, port, - resp_len); + resp_len, max_len); break; case OPA_ATTRIB_ID_BUFFER_CONTROL_TABLE: ret = __subn_set_opa_bct(smp, am, data, ibdev, port, - resp_len); + resp_len, max_len); break; case IB_SMP_ATTR_VL_ARB_TABLE: ret = __subn_set_opa_vl_arb(smp, am, data, ibdev, port, - resp_len); + resp_len, max_len); break; case OPA_ATTRIB_ID_HFI_CONGESTION_SETTING: ret = __subn_set_opa_cong_setting(smp, am, data, ibdev, - port, resp_len); + port, resp_len, max_len); break; case OPA_ATTRIB_ID_CONGESTION_CONTROL_TABLE: ret = __subn_set_opa_cc_table(smp, am, data, ibdev, port, - resp_len); + resp_len, max_len); break; case IB_SMP_ATTR_LED_INFO: ret = __subn_set_opa_led_info(smp, am, data, ibdev, port, - resp_len); + resp_len, max_len); break; case IB_SMP_ATTR_SM_INFO: if (ibp->rvp.port_cap_flags & IB_PORT_SM_DISABLED) @@ -3841,7 +3907,10 @@ static int subn_get_opa_aggregate(struct opa_smp *smp, memset(next_smp + sizeof(*agg), 0, agg_data_len); (void)subn_get_opa_sma(agg->attr_id, smp, am, agg->data, - ibdev, port, NULL); + ibdev, port, NULL, (u32)agg_data_len); + + if (smp->status & IB_SMP_INVALID_FIELD) + break; if (smp->status & ~IB_SMP_DIRECTION) { set_aggr_error(agg); return reply((struct ib_mad_hdr *)smp); @@ -3884,7 +3953,9 @@ static int subn_set_opa_aggregate(struct opa_smp *smp, } (void)subn_set_opa_sma(agg->attr_id, smp, am, agg->data, - ibdev, port, NULL); + ibdev, port, NULL, (u32)agg_data_len); + if (smp->status & IB_SMP_INVALID_FIELD) + break; if (smp->status & ~IB_SMP_DIRECTION) { set_aggr_error(agg); return reply((struct ib_mad_hdr *)smp); @@ -3994,12 +4065,13 @@ static int process_subn_opa(struct ib_device *ibdev, int mad_flags, struct opa_smp *smp = (struct opa_smp *)out_mad; struct hfi1_ibport *ibp = to_iport(ibdev, port); u8 *data; - u32 am; + u32 am, data_size; __be16 attr_id; int ret; *out_mad = *in_mad; data = opa_get_smp_data(smp); + data_size = (u32)opa_get_smp_data_size(smp); am = be32_to_cpu(smp->attr_mod); attr_id = smp->attr_id; @@ -4043,7 +4115,8 @@ static int process_subn_opa(struct ib_device *ibdev, int mad_flags, default: clear_opa_smp_data(smp); ret = subn_get_opa_sma(attr_id, smp, am, data, - ibdev, port, resp_len); + ibdev, port, resp_len, + data_size); break; case OPA_ATTRIB_ID_AGGREGATE: ret = subn_get_opa_aggregate(smp, ibdev, port, @@ -4055,7 +4128,8 @@ static int process_subn_opa(struct ib_device *ibdev, int mad_flags, switch (attr_id) { default: ret = subn_set_opa_sma(attr_id, smp, am, data, - ibdev, port, resp_len); + ibdev, port, resp_len, + data_size); break; case OPA_ATTRIB_ID_AGGREGATE: ret = subn_set_opa_aggregate(smp, ibdev, port, -- cgit v1.2.3 From d54389836ac63cb517bf863b9f6c22626c6aec26 Mon Sep 17 00:00:00 2001 From: Tadeusz Struk Date: Mon, 29 May 2017 17:20:53 -0700 Subject: IB/core: Allow QP state transition from reset to error Playing with IP-O-IB interface can trigger a warning message: "ib0: Failed to modify QP to ERROR state" to be logged. This happens when the QP is in IB_QPS_RESET state and the stack is trying to transition it to IB_QPS_ERR state in ipoib_ib_dev_stop(). According to the IB spec, Table 91 - "QP State Transition Properties" it looks like the transition from reset to error is valid: Transition: Any State to Error Required Attributes: None Optional Attributes: None allowed Actions: Queue processing is stopped. Work Requests pending or in process are completed in error, when possible. This patch allows the transition and quiets the message. Reviewed-by: Dennis Dalessandro Signed-off-by: Tadeusz Struk Signed-off-by: Dennis Dalessandro Reviewed-by: Leon Romanovsky Signed-off-by: Doug Ledford --- drivers/infiniband/core/verbs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c index 4792f5209ac2..b822bedeb4a5 100644 --- a/drivers/infiniband/core/verbs.c +++ b/drivers/infiniband/core/verbs.c @@ -872,6 +872,7 @@ static const struct { } qp_state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = { [IB_QPS_RESET] = { [IB_QPS_RESET] = { .valid = 1 }, + [IB_QPS_ERR] = { .valid = 1 }, [IB_QPS_INIT] = { .valid = 1, .req_param = { -- cgit v1.2.3 From bec7c79cd8f764ba84c8ec6d8c402b8a7cd3a54f Mon Sep 17 00:00:00 2001 From: "Byczkowski, Jakub" Date: Mon, 29 May 2017 17:21:32 -0700 Subject: IB/hfi1: Modify handling of physical link state by Host Driver Ensure states returned to the Fabric Manager are consistent with the OPA specification by caching the physical state along with the logical state. Reviewed-by: Stuart Summers Reviewed-by: Ira Weiny Reviewed-by: Andrzej Kotlowski Signed-off-by: Jakub Byczkowski Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/chip.c | 102 +++++++++++++++++++++++++----------- drivers/infiniband/hw/hfi1/chip.h | 2 +- drivers/infiniband/hw/hfi1/driver.c | 8 +-- drivers/infiniband/hw/hfi1/hfi.h | 18 ++++++- drivers/infiniband/hw/hfi1/mad.c | 6 +-- drivers/infiniband/hw/hfi1/verbs.c | 2 +- 6 files changed, 97 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/hfi1/chip.c b/drivers/infiniband/hw/hfi1/chip.c index 99c29ddcca35..3fae98d079e4 100644 --- a/drivers/infiniband/hw/hfi1/chip.c +++ b/drivers/infiniband/hw/hfi1/chip.c @@ -1066,6 +1066,8 @@ static int thermal_init(struct hfi1_devdata *dd); static int wait_logical_linkstate(struct hfi1_pportdata *ppd, u32 state, int msecs); +static int wait_physical_linkstate(struct hfi1_pportdata *ppd, u32 state, + int msecs); static void read_planned_down_reason_code(struct hfi1_devdata *dd, u8 *pdrrc); static void read_link_down_reason(struct hfi1_devdata *dd, u8 *ldr); static void handle_temp_err(struct hfi1_devdata *dd); @@ -10028,28 +10030,6 @@ static void set_lidlmc(struct hfi1_pportdata *ppd) sdma_update_lmc(dd, mask, ppd->lid); } -static int wait_phy_linkstate(struct hfi1_devdata *dd, u32 state, u32 msecs) -{ - unsigned long timeout; - u32 curr_state; - - timeout = jiffies + msecs_to_jiffies(msecs); - while (1) { - curr_state = read_physical_state(dd); - if (curr_state == state) - break; - if (time_after(jiffies, timeout)) { - dd_dev_err(dd, - "timeout waiting for phy link state 0x%x, current state is 0x%x\n", - state, curr_state); - return -ETIMEDOUT; - } - usleep_range(1950, 2050); /* sleep 2ms-ish */ - } - - return 0; -} - static const char *state_completed_string(u32 completed) { static const char * const state_completed[] = { @@ -10283,7 +10263,7 @@ static int goto_offline(struct hfi1_pportdata *ppd, u8 rem_reason) if (do_wait) { /* it can take a while for the link to go down */ - ret = wait_phy_linkstate(dd, PLS_OFFLINE, 10000); + ret = wait_physical_linkstate(ppd, PLS_OFFLINE, 10000); if (ret < 0) return ret; } @@ -10536,6 +10516,19 @@ int set_link_state(struct hfi1_pportdata *ppd, u32 state) goto unexpected; } + /* + * Wait for Link_Up physical state. + * Physical and Logical states should already be + * be transitioned to LinkUp and LinkInit respectively. + */ + ret = wait_physical_linkstate(ppd, PLS_LINKUP, 1000); + if (ret) { + dd_dev_err(dd, + "%s: physical state did not change to LINK-UP\n", + __func__); + break; + } + ret = wait_logical_linkstate(ppd, IB_PORT_INIT, 1000); if (ret) { dd_dev_err(dd, @@ -10649,6 +10642,8 @@ int set_link_state(struct hfi1_pportdata *ppd, u32 state) */ if (ret) goto_offline(ppd, 0); + else + cache_physical_state(ppd); break; case HLS_DN_DISABLE: /* link is disabled */ @@ -10673,6 +10668,13 @@ int set_link_state(struct hfi1_pportdata *ppd, u32 state) ret = -EINVAL; break; } + ret = wait_physical_linkstate(ppd, PLS_DISABLED, 10000); + if (ret) { + dd_dev_err(dd, + "%s: physical state did not change to DISABLED\n", + __func__); + break; + } dc_shutdown(dd); } ppd->host_link_state = HLS_DN_DISABLE; @@ -10690,6 +10692,7 @@ int set_link_state(struct hfi1_pportdata *ppd, u32 state) if (ppd->host_link_state != HLS_DN_POLL) goto unexpected; ppd->host_link_state = HLS_VERIFY_CAP; + cache_physical_state(ppd); break; case HLS_GOING_UP: if (ppd->host_link_state != HLS_VERIFY_CAP) @@ -12663,21 +12666,56 @@ static int wait_logical_linkstate(struct hfi1_pportdata *ppd, u32 state, return -ETIMEDOUT; } -u8 hfi1_ibphys_portstate(struct hfi1_pportdata *ppd) +/* + * Read the physical hardware link state and set the driver's cached value + * of it. + */ +void cache_physical_state(struct hfi1_pportdata *ppd) { - u32 pstate; + u32 read_pstate; u32 ib_pstate; - pstate = read_physical_state(ppd->dd); - ib_pstate = chip_to_opa_pstate(ppd->dd, pstate); - if (ppd->last_pstate != ib_pstate) { + read_pstate = read_physical_state(ppd->dd); + ib_pstate = chip_to_opa_pstate(ppd->dd, read_pstate); + /* check if OPA pstate changed */ + if (chip_to_opa_pstate(ppd->dd, ppd->pstate) != ib_pstate) { dd_dev_info(ppd->dd, "%s: physical state changed to %s (0x%x), phy 0x%x\n", __func__, opa_pstate_name(ib_pstate), ib_pstate, - pstate); - ppd->last_pstate = ib_pstate; + read_pstate); + } + ppd->pstate = read_pstate; +} + +/* + * wait_physical_linkstate - wait for an physical link state change to occur + * @ppd: port device + * @state: the state to wait for + * @msecs: the number of milliseconds to wait + * + * Wait up to msecs milliseconds for physical link state change to occur. + * Returns 0 if state reached, otherwise -ETIMEDOUT. + */ +static int wait_physical_linkstate(struct hfi1_pportdata *ppd, u32 state, + int msecs) +{ + unsigned long timeout; + + timeout = jiffies + msecs_to_jiffies(msecs); + while (1) { + cache_physical_state(ppd); + if (ppd->pstate == state) + break; + if (time_after(jiffies, timeout)) { + dd_dev_err(ppd->dd, + "timeout waiting for phy link state 0x%x, current state is 0x%x\n", + state, ppd->pstate); + return -ETIMEDOUT; + } + usleep_range(1950, 2050); /* sleep 2ms-ish */ } - return ib_pstate; + + return 0; } #define CLEAR_STATIC_RATE_CONTROL_SMASK(r) \ @@ -14781,7 +14819,7 @@ struct hfi1_devdata *hfi1_init_dd(struct pci_dev *pdev, /* start in offline */ ppd->host_link_state = HLS_DN_OFFLINE; init_vl_arb_caches(ppd); - ppd->last_pstate = 0xff; /* invalid value */ + ppd->pstate = PLS_OFFLINE; } dd->link_default = HLS_DN_POLL; diff --git a/drivers/infiniband/hw/hfi1/chip.h b/drivers/infiniband/hw/hfi1/chip.h index 0b4f418ba0ac..3dab3156ba4a 100644 --- a/drivers/infiniband/hw/hfi1/chip.h +++ b/drivers/infiniband/hw/hfi1/chip.h @@ -744,6 +744,7 @@ int is_bx(struct hfi1_devdata *dd); u32 read_physical_state(struct hfi1_devdata *dd); u32 chip_to_opa_pstate(struct hfi1_devdata *dd, u32 chip_pstate); u32 get_logical_state(struct hfi1_pportdata *ppd); +void cache_physical_state(struct hfi1_pportdata *ppd); const char *opa_lstate_name(u32 lstate); const char *opa_pstate_name(u32 pstate); u32 driver_physical_state(struct hfi1_pportdata *ppd); @@ -1354,7 +1355,6 @@ void hfi1_quiet_serdes(struct hfi1_pportdata *ppd); void hfi1_rcvctrl(struct hfi1_devdata *dd, unsigned int op, int ctxt); u32 hfi1_read_cntrs(struct hfi1_devdata *dd, char **namep, u64 **cntrp); u32 hfi1_read_portcntrs(struct hfi1_pportdata *ppd, char **namep, u64 **cntrp); -u8 hfi1_ibphys_portstate(struct hfi1_pportdata *ppd); int hfi1_get_ib_cfg(struct hfi1_pportdata *ppd, int which); int hfi1_set_ib_cfg(struct hfi1_pportdata *ppd, int which, u32 val); int hfi1_set_ctxt_jkey(struct hfi1_devdata *dd, unsigned ctxt, u16 jkey); diff --git a/drivers/infiniband/hw/hfi1/driver.c b/drivers/infiniband/hw/hfi1/driver.c index 9e59430bc55c..e64e9e28c936 100644 --- a/drivers/infiniband/hw/hfi1/driver.c +++ b/drivers/infiniband/hw/hfi1/driver.c @@ -906,10 +906,12 @@ static inline int set_armed_to_active(struct hfi1_ctxtdata *rcd, sc = hfi1_9B_get_sc5(hdr, packet->rhf); } if (sc != SC15_PACKET) { - int hwstate = read_logical_state(dd); + int hwstate = driver_lstate(rcd->ppd); - if (hwstate != LSTATE_ACTIVE) { - dd_dev_info(dd, "Unexpected link state %d\n", hwstate); + if (hwstate != IB_PORT_ACTIVE) { + dd_dev_info(dd, + "Unexpected link state %s\n", + opa_lstate_name(hwstate)); return 0; } diff --git a/drivers/infiniband/hw/hfi1/hfi.h b/drivers/infiniband/hw/hfi1/hfi.h index 8f74cf6d6c9a..bca781c3b5ac 100644 --- a/drivers/infiniband/hw/hfi1/hfi.h +++ b/drivers/infiniband/hw/hfi1/hfi.h @@ -663,7 +663,7 @@ struct hfi1_pportdata { u8 link_enabled; /* link enabled? */ u8 linkinit_reason; u8 local_tx_rate; /* rate given to 8051 firmware */ - u8 last_pstate; /* info only */ + u8 pstate; /* info only */ u8 qsfp_retry_count; /* placeholders for IB MAD packet settings */ @@ -1330,6 +1330,22 @@ static inline u32 driver_lstate(struct hfi1_pportdata *ppd) return ppd->lstate; } +/* return the driver's idea of the physical OPA port state */ +static inline u32 driver_pstate(struct hfi1_pportdata *ppd) +{ + /* + * The driver does some processing from the time the physical + * link state is at LINKUP to the time the SM can be notified + * as such. Return IB_PORTPHYSSTATE_TRAINING until the software + * state is ready. + */ + if (ppd->pstate == PLS_LINKUP && + !(ppd->host_link_state & HLS_UP)) + return IB_PORTPHYSSTATE_TRAINING; + else + return chip_to_opa_pstate(ppd->dd, ppd->pstate); +} + void receive_interrupt_work(struct work_struct *work); /* extract service channel from header and rhf */ diff --git a/drivers/infiniband/hw/hfi1/mad.c b/drivers/infiniband/hw/hfi1/mad.c index b180dff5f2e9..c8daf633212d 100644 --- a/drivers/infiniband/hw/hfi1/mad.c +++ b/drivers/infiniband/hw/hfi1/mad.c @@ -113,7 +113,7 @@ static void send_trap(struct hfi1_ibport *ibp, void *data, unsigned len) return; /* o14-3.2.1 */ - if (ppd_from_ibp(ibp)->lstate != IB_PORT_ACTIVE) + if (driver_lstate(ppd_from_ibp(ibp)) != IB_PORT_ACTIVE) return; /* o14-2 */ @@ -615,7 +615,7 @@ static int __subn_get_opa_portinfo(struct opa_smp *smp, u32 am, u8 *data, ppd->offline_disabled_reason; pi->port_states.portphysstate_portstate = - (hfi1_ibphys_portstate(ppd) << 4) | state; + (driver_pstate(ppd) << 4) | state; pi->mkeyprotect_lmc = (ibp->rvp.mkeyprot << 6) | ppd->lmc; @@ -1791,7 +1791,7 @@ static int __subn_get_opa_psi(struct opa_smp *smp, u32 am, u8 *data, ppd->offline_disabled_reason; psi->port_states.portphysstate_portstate = - (hfi1_ibphys_portstate(ppd) << 4) | (lstate & 0xf); + (driver_pstate(ppd) << 4) | (lstate & 0xf); psi->link_width_downgrade_tx_active = cpu_to_be16(ppd->link_width_downgrade_tx_active); psi->link_width_downgrade_rx_active = diff --git a/drivers/infiniband/hw/hfi1/verbs.c b/drivers/infiniband/hw/hfi1/verbs.c index 2d7759f0c6b4..5b53faf47042 100644 --- a/drivers/infiniband/hw/hfi1/verbs.c +++ b/drivers/infiniband/hw/hfi1/verbs.c @@ -1354,7 +1354,7 @@ static int query_port(struct rvt_dev_info *rdi, u8 port_num, props->lmc = ppd->lmc; /* OPA logical states match IB logical states */ props->state = driver_lstate(ppd); - props->phys_state = hfi1_ibphys_portstate(ppd); + props->phys_state = driver_pstate(ppd); props->gid_tbl_len = HFI1_GUIDS_PER_PORT; props->active_width = (u8)opa_width_to_ib(ppd->link_width_active); /* see rate_show() in ib core/sysfs.c */ -- cgit v1.2.3 From 13d84914db56c1afd1c9bf4f41e9bf91f061a7dd Mon Sep 17 00:00:00 2001 From: Dennis Dalessandro Date: Mon, 29 May 2017 17:22:01 -0700 Subject: IB/hfi1,qib: Do not send QKey trap for UD qps According to IBTA spec a QKey violation should not result in a bad qkey trap being triggered for UD queue pairs. Also since it is a silent error we do not increment the q_key violation or the dropped packet counters. Reviewed-by: Mike Marciniszyn Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/mad.c | 14 ++++-------- drivers/infiniband/hw/hfi1/ruc.c | 8 +++---- drivers/infiniband/hw/hfi1/ud.c | 37 ++++++++++-------------------- drivers/infiniband/hw/hfi1/verbs.h | 4 ++-- drivers/infiniband/hw/qib/qib_mad.c | 13 ++++------- drivers/infiniband/hw/qib/qib_ruc.c | 20 ++++++++-------- drivers/infiniband/hw/qib/qib_ud.c | 43 ++++++++++++----------------------- drivers/infiniband/hw/qib/qib_verbs.h | 4 ++-- 8 files changed, 54 insertions(+), 89 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/hfi1/mad.c b/drivers/infiniband/hw/hfi1/mad.c index c8daf633212d..a081a98d728a 100644 --- a/drivers/infiniband/hw/hfi1/mad.c +++ b/drivers/infiniband/hw/hfi1/mad.c @@ -180,10 +180,10 @@ static void send_trap(struct hfi1_ibport *ibp, void *data, unsigned len) } /* - * Send a bad [PQ]_Key trap (ch. 14.3.8). + * Send a bad P_Key trap (ch. 14.3.8). */ -void hfi1_bad_pqkey(struct hfi1_ibport *ibp, __be16 trap_num, u32 key, u32 sl, - u32 qp1, u32 qp2, u16 lid1, u16 lid2) +void hfi1_bad_pkey(struct hfi1_ibport *ibp, u32 key, u32 sl, + u32 qp1, u32 qp2, u16 lid1, u16 lid2) { struct opa_mad_notice_attr data; u32 lid = ppd_from_ibp(ibp)->lid; @@ -191,17 +191,13 @@ void hfi1_bad_pqkey(struct hfi1_ibport *ibp, __be16 trap_num, u32 key, u32 sl, u32 _lid2 = lid2; memset(&data, 0, sizeof(data)); - - if (trap_num == OPA_TRAP_BAD_P_KEY) - ibp->rvp.pkey_violations++; - else - ibp->rvp.qkey_violations++; ibp->rvp.n_pkt_drops++; + ibp->rvp.pkey_violations++; /* Send violation trap */ data.generic_type = IB_NOTICE_TYPE_SECURITY; data.prod_type_lsb = IB_NOTICE_PROD_CA; - data.trap_num = trap_num; + data.trap_num = OPA_TRAP_BAD_P_KEY; data.issuer_lid = cpu_to_be32(lid); data.ntc_257_258.lid1 = cpu_to_be32(_lid1); data.ntc_257_258.lid2 = cpu_to_be32(_lid2); diff --git a/drivers/infiniband/hw/hfi1/ruc.c b/drivers/infiniband/hw/hfi1/ruc.c index 476fe5da2992..9cf506a9a796 100644 --- a/drivers/infiniband/hw/hfi1/ruc.c +++ b/drivers/infiniband/hw/hfi1/ruc.c @@ -254,8 +254,8 @@ int hfi1_ruc_check_hdr(struct hfi1_ibport *ibp, struct hfi1_packet *packet) } if (unlikely(rcv_pkey_check(ppd_from_ibp(ibp), (u16)bth0, sc5, slid))) { - hfi1_bad_pqkey(ibp, OPA_TRAP_BAD_P_KEY, (u16)bth0, sl, - 0, qp->ibqp.qp_num, slid, dlid); + hfi1_bad_pkey(ibp, (u16)bth0, sl, + 0, qp->ibqp.qp_num, slid, dlid); return 1; } /* Validate the SLID. See Ch. 9.6.1.5 and 17.2.8 */ @@ -290,8 +290,8 @@ int hfi1_ruc_check_hdr(struct hfi1_ibport *ibp, struct hfi1_packet *packet) } if (unlikely(rcv_pkey_check(ppd_from_ibp(ibp), (u16)bth0, sc5, slid))) { - hfi1_bad_pqkey(ibp, OPA_TRAP_BAD_P_KEY, (u16)bth0, sl, - 0, qp->ibqp.qp_num, slid, dlid); + hfi1_bad_pkey(ibp, (u16)bth0, sl, + 0, qp->ibqp.qp_num, slid, dlid); return 1; } /* Validate the SLID. See Ch. 9.6.1.5 */ diff --git a/drivers/infiniband/hw/hfi1/ud.c b/drivers/infiniband/hw/hfi1/ud.c index c995aa58c36a..6bf7a1b08491 100644 --- a/drivers/infiniband/hw/hfi1/ud.c +++ b/drivers/infiniband/hw/hfi1/ud.c @@ -110,10 +110,10 @@ static void ud_loopback(struct rvt_qp *sqp, struct rvt_swqe *swqe) ((1 << ppd->lmc) - 1)); if (unlikely(ingress_pkey_check(ppd, pkey, sc5, qp->s_pkey_index, slid))) { - hfi1_bad_pqkey(ibp, OPA_TRAP_BAD_P_KEY, pkey, - rdma_ah_get_sl(ah_attr), - sqp->ibqp.qp_num, qp->ibqp.qp_num, - slid, rdma_ah_get_dlid(ah_attr)); + hfi1_bad_pkey(ibp, pkey, + rdma_ah_get_sl(ah_attr), + sqp->ibqp.qp_num, qp->ibqp.qp_num, + slid, rdma_ah_get_dlid(ah_attr)); goto drop; } } @@ -128,18 +128,8 @@ static void ud_loopback(struct rvt_qp *sqp, struct rvt_swqe *swqe) qkey = (int)swqe->ud_wr.remote_qkey < 0 ? sqp->qkey : swqe->ud_wr.remote_qkey; - if (unlikely(qkey != qp->qkey)) { - u16 lid; - - lid = ppd->lid | (rdma_ah_get_path_bits(ah_attr) & - ((1 << ppd->lmc) - 1)); - hfi1_bad_pqkey(ibp, OPA_TRAP_BAD_Q_KEY, qkey, - rdma_ah_get_sl(ah_attr), - sqp->ibqp.qp_num, qp->ibqp.qp_num, - lid, - rdma_ah_get_dlid(ah_attr)); - goto drop; - } + if (unlikely(qkey != qp->qkey)) + goto drop; /* silently drop per IBTA spec */ } /* @@ -722,10 +712,10 @@ void hfi1_ud_rcv(struct hfi1_packet *packet) * for invalid pkeys is optional according to * IB spec (release 1.3, section 10.9.4) */ - hfi1_bad_pqkey(ibp, OPA_TRAP_BAD_P_KEY, - pkey, sl, - src_qp, qp->ibqp.qp_num, - slid, dlid); + hfi1_bad_pkey(ibp, + pkey, sl, + src_qp, qp->ibqp.qp_num, + slid, dlid); return; } } else { @@ -734,12 +724,9 @@ void hfi1_ud_rcv(struct hfi1_packet *packet) if (mgmt_pkey_idx < 0) goto drop; } - if (unlikely(qkey != qp->qkey)) { - hfi1_bad_pqkey(ibp, OPA_TRAP_BAD_Q_KEY, qkey, sl, - src_qp, qp->ibqp.qp_num, - slid, dlid); + if (unlikely(qkey != qp->qkey)) /* Silent drop */ return; - } + /* Drop invalid MAD packets (see 13.5.3.1). */ if (unlikely(qp->ibqp.qp_num == 1 && (tlen > 2048 || (sc5 == 0xF)))) diff --git a/drivers/infiniband/hw/hfi1/verbs.h b/drivers/infiniband/hw/hfi1/verbs.h index 17b38cd5f654..fdf1e1fb880c 100644 --- a/drivers/infiniband/hw/hfi1/verbs.h +++ b/drivers/infiniband/hw/hfi1/verbs.h @@ -236,8 +236,8 @@ static inline int hfi1_send_ok(struct rvt_qp *qp) /* * This must be called with s_lock held. */ -void hfi1_bad_pqkey(struct hfi1_ibport *ibp, __be16 trap_num, u32 key, u32 sl, - u32 qp1, u32 qp2, u16 lid1, u16 lid2); +void hfi1_bad_pkey(struct hfi1_ibport *ibp, u32 key, u32 sl, + u32 qp1, u32 qp2, u16 lid1, u16 lid2); void hfi1_cap_mask_chg(struct rvt_dev_info *rdi, u8 port_num); void hfi1_sys_guid_chg(struct hfi1_ibport *ibp); void hfi1_node_desc_chg(struct hfi1_ibport *ibp); diff --git a/drivers/infiniband/hw/qib/qib_mad.c b/drivers/infiniband/hw/qib/qib_mad.c index da295e0392ed..a4a7f2a76f24 100644 --- a/drivers/infiniband/hw/qib/qib_mad.c +++ b/drivers/infiniband/hw/qib/qib_mad.c @@ -134,24 +134,21 @@ static void qib_send_trap(struct qib_ibport *ibp, void *data, unsigned len) } /* - * Send a bad [PQ]_Key trap (ch. 14.3.8). + * Send a bad P_Key trap (ch. 14.3.8). */ -void qib_bad_pqkey(struct qib_ibport *ibp, __be16 trap_num, u32 key, u32 sl, - u32 qp1, u32 qp2, __be16 lid1, __be16 lid2) +void qib_bad_pkey(struct qib_ibport *ibp, u32 key, u32 sl, + u32 qp1, u32 qp2, __be16 lid1, __be16 lid2) { struct ib_mad_notice_attr data; - if (trap_num == IB_NOTICE_TRAP_BAD_PKEY) - ibp->rvp.pkey_violations++; - else - ibp->rvp.qkey_violations++; ibp->rvp.n_pkt_drops++; + ibp->rvp.pkey_violations++; /* Send violation trap */ data.generic_type = IB_NOTICE_TYPE_SECURITY; data.prod_type_msb = 0; data.prod_type_lsb = IB_NOTICE_PROD_CA; - data.trap_num = trap_num; + data.trap_num = IB_NOTICE_TRAP_BAD_PKEY; data.issuer_lid = cpu_to_be16(ppd_from_ibp(ibp)->lid); data.toggle_count = 0; memset(&data.details, 0, sizeof(data.details)); diff --git a/drivers/infiniband/hw/qib/qib_ruc.c b/drivers/infiniband/hw/qib/qib_ruc.c index 88d84cbf7e5a..28528459a052 100644 --- a/drivers/infiniband/hw/qib/qib_ruc.c +++ b/drivers/infiniband/hw/qib/qib_ruc.c @@ -256,11 +256,11 @@ int qib_ruc_check_hdr(struct qib_ibport *ibp, struct ib_header *hdr, } if (!qib_pkey_ok((u16)bth0, qib_get_pkey(ibp, qp->s_alt_pkey_index))) { - qib_bad_pqkey(ibp, IB_NOTICE_TRAP_BAD_PKEY, - (u16)bth0, - (be16_to_cpu(hdr->lrh[0]) >> 4) & 0xF, - 0, qp->ibqp.qp_num, - hdr->lrh[3], hdr->lrh[1]); + qib_bad_pkey(ibp, + (u16)bth0, + (be16_to_cpu(hdr->lrh[0]) >> 4) & 0xF, + 0, qp->ibqp.qp_num, + hdr->lrh[3], hdr->lrh[1]); goto err; } /* Validate the SLID. See Ch. 9.6.1.5 and 17.2.8 */ @@ -295,11 +295,11 @@ int qib_ruc_check_hdr(struct qib_ibport *ibp, struct ib_header *hdr, } if (!qib_pkey_ok((u16)bth0, qib_get_pkey(ibp, qp->s_pkey_index))) { - qib_bad_pqkey(ibp, IB_NOTICE_TRAP_BAD_PKEY, - (u16)bth0, - (be16_to_cpu(hdr->lrh[0]) >> 4) & 0xF, - 0, qp->ibqp.qp_num, - hdr->lrh[3], hdr->lrh[1]); + qib_bad_pkey(ibp, + (u16)bth0, + (be16_to_cpu(hdr->lrh[0]) >> 4) & 0xF, + 0, qp->ibqp.qp_num, + hdr->lrh[3], hdr->lrh[1]); goto err; } /* Validate the SLID. See Ch. 9.6.1.5 */ diff --git a/drivers/infiniband/hw/qib/qib_ud.c b/drivers/infiniband/hw/qib/qib_ud.c index 341a123ee95c..be4907453ac4 100644 --- a/drivers/infiniband/hw/qib/qib_ud.c +++ b/drivers/infiniband/hw/qib/qib_ud.c @@ -66,8 +66,7 @@ static void qib_ud_loopback(struct rvt_qp *sqp, struct rvt_swqe *swqe) qp = rvt_lookup_qpn(rdi, &ibp->rvp, swqe->ud_wr.remote_qpn); if (!qp) { ibp->rvp.n_pkt_drops++; - rcu_read_unlock(); - return; + goto drop; } sqptype = sqp->ibqp.qp_type == IB_QPT_GSI ? @@ -94,11 +93,11 @@ static void qib_ud_loopback(struct rvt_qp *sqp, struct rvt_swqe *swqe) if (unlikely(!qib_pkey_ok(pkey1, pkey2))) { lid = ppd->lid | (rdma_ah_get_path_bits(ah_attr) & ((1 << ppd->lmc) - 1)); - qib_bad_pqkey(ibp, IB_NOTICE_TRAP_BAD_PKEY, pkey1, - rdma_ah_get_sl(ah_attr), - sqp->ibqp.qp_num, qp->ibqp.qp_num, - cpu_to_be16(lid), - cpu_to_be16(rdma_ah_get_dlid(ah_attr))); + qib_bad_pkey(ibp, pkey1, + rdma_ah_get_sl(ah_attr), + sqp->ibqp.qp_num, qp->ibqp.qp_num, + cpu_to_be16(lid), + cpu_to_be16(rdma_ah_get_dlid(ah_attr))); goto drop; } } @@ -113,18 +112,8 @@ static void qib_ud_loopback(struct rvt_qp *sqp, struct rvt_swqe *swqe) qkey = (int)swqe->ud_wr.remote_qkey < 0 ? sqp->qkey : swqe->ud_wr.remote_qkey; - if (unlikely(qkey != qp->qkey)) { - u16 lid; - - lid = ppd->lid | (rdma_ah_get_path_bits(ah_attr) & - ((1 << ppd->lmc) - 1)); - qib_bad_pqkey(ibp, IB_NOTICE_TRAP_BAD_QKEY, qkey, - rdma_ah_get_sl(ah_attr), - sqp->ibqp.qp_num, qp->ibqp.qp_num, - cpu_to_be16(lid), - cpu_to_be16(rdma_ah_get_dlid(ah_attr))); + if (unlikely(qkey != qp->qkey)) goto drop; - } } /* @@ -487,22 +476,18 @@ void qib_ud_rcv(struct qib_ibport *ibp, struct ib_header *hdr, pkey1 = be32_to_cpu(ohdr->bth[0]); pkey2 = qib_get_pkey(ibp, qp->s_pkey_index); if (unlikely(!qib_pkey_ok(pkey1, pkey2))) { - qib_bad_pqkey(ibp, IB_NOTICE_TRAP_BAD_PKEY, - pkey1, - (be16_to_cpu(hdr->lrh[0]) >> 4) & + qib_bad_pkey(ibp, + pkey1, + (be16_to_cpu(hdr->lrh[0]) >> 4) & 0xF, - src_qp, qp->ibqp.qp_num, - hdr->lrh[3], hdr->lrh[1]); + src_qp, qp->ibqp.qp_num, + hdr->lrh[3], hdr->lrh[1]); return; } } - if (unlikely(qkey != qp->qkey)) { - qib_bad_pqkey(ibp, IB_NOTICE_TRAP_BAD_QKEY, qkey, - (be16_to_cpu(hdr->lrh[0]) >> 4) & 0xF, - src_qp, qp->ibqp.qp_num, - hdr->lrh[3], hdr->lrh[1]); + if (unlikely(qkey != qp->qkey)) return; - } + /* Drop invalid MAD packets (see 13.5.3.1). */ if (unlikely(qp->ibqp.qp_num == 1 && (tlen != 256 || diff --git a/drivers/infiniband/hw/qib/qib_verbs.h b/drivers/infiniband/hw/qib/qib_verbs.h index da0db5485ddc..33d5691a9b2d 100644 --- a/drivers/infiniband/hw/qib/qib_verbs.h +++ b/drivers/infiniband/hw/qib/qib_verbs.h @@ -241,8 +241,8 @@ static inline int qib_pkey_ok(u16 pkey1, u16 pkey2) return p1 && p1 == p2 && ((__s16)pkey1 < 0 || (__s16)pkey2 < 0); } -void qib_bad_pqkey(struct qib_ibport *ibp, __be16 trap_num, u32 key, u32 sl, - u32 qp1, u32 qp2, __be16 lid1, __be16 lid2); +void qib_bad_pkey(struct qib_ibport *ibp, u32 key, u32 sl, + u32 qp1, u32 qp2, __be16 lid1, __be16 lid2); void qib_cap_mask_chg(struct rvt_dev_info *rdi, u8 port_num); void qib_sys_guid_chg(struct qib_ibport *ibp); void qib_node_desc_chg(struct qib_ibport *ibp); -- cgit v1.2.3 From ddbf2efff4ad85135b9fd1cb53b10069a160bd58 Mon Sep 17 00:00:00 2001 From: Bartlomiej Dudek Date: Fri, 9 Jun 2017 15:59:26 -0700 Subject: IB/hfi1: Fix DC 8051 host info flag array Fix info array of host message flags by adding entry for link width downgrade and reverse values for BC SMA and BC PWR_MSG messages Reviewed-by: Jakub Byczkowski Signed-off-by: Bartlomiej Dudek Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/chip.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/hfi1/chip.c b/drivers/infiniband/hw/hfi1/chip.c index 3fae98d079e4..ebcb2c405c5f 100644 --- a/drivers/infiniband/hw/hfi1/chip.c +++ b/drivers/infiniband/hw/hfi1/chip.c @@ -1012,14 +1012,15 @@ static struct flag_table dc8051_info_err_flags[] = { */ static struct flag_table dc8051_info_host_msg_flags[] = { FLAG_ENTRY0("Host request done", 0x0001), - FLAG_ENTRY0("BC SMA message", 0x0002), - FLAG_ENTRY0("BC PWR_MGM message", 0x0004), + FLAG_ENTRY0("BC PWR_MGM message", 0x0002), + FLAG_ENTRY0("BC SMA message", 0x0004), FLAG_ENTRY0("BC Unknown message (BCC)", 0x0008), FLAG_ENTRY0("BC Unknown message (LCB)", 0x0010), FLAG_ENTRY0("External device config request", 0x0020), FLAG_ENTRY0("VerifyCap all frames received", 0x0040), FLAG_ENTRY0("LinkUp achieved", 0x0080), FLAG_ENTRY0("Link going down", 0x0100), + FLAG_ENTRY0("Link width downgraded", 0x0200), }; static u32 encoded_size(u32 size); -- cgit v1.2.3 From 702265fc0002497fd0ddaae4a5bec00a8a40da3e Mon Sep 17 00:00:00 2001 From: Jan Sokolowski Date: Fri, 9 Jun 2017 15:59:33 -0700 Subject: IB/hfi1: Set proper logging levels on QSFP cable error events Change QSFP cable error events logging levels from info to error. Reviewed-by: Jakub Byczkowski Reviewed-by: Dennis Dalessandro Signed-off-by: Jan Sokolowski Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/chip.c | 64 +++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/hfi1/chip.c b/drivers/infiniband/hw/hfi1/chip.c index ebcb2c405c5f..b8ee0e27dae6 100644 --- a/drivers/infiniband/hw/hfi1/chip.c +++ b/drivers/infiniband/hw/hfi1/chip.c @@ -9376,13 +9376,13 @@ static int handle_qsfp_error_conditions(struct hfi1_pportdata *ppd, if ((qsfp_interrupt_status[0] & QSFP_HIGH_TEMP_ALARM) || (qsfp_interrupt_status[0] & QSFP_HIGH_TEMP_WARNING)) - dd_dev_info(dd, "%s: QSFP cable temperature too high\n", - __func__); + dd_dev_err(dd, "%s: QSFP cable temperature too high\n", + __func__); if ((qsfp_interrupt_status[0] & QSFP_LOW_TEMP_ALARM) || (qsfp_interrupt_status[0] & QSFP_LOW_TEMP_WARNING)) - dd_dev_info(dd, "%s: QSFP cable temperature too low\n", - __func__); + dd_dev_err(dd, "%s: QSFP cable temperature too low\n", + __func__); /* * The remaining alarms/warnings don't matter if the link is down. @@ -9392,75 +9392,75 @@ static int handle_qsfp_error_conditions(struct hfi1_pportdata *ppd, if ((qsfp_interrupt_status[1] & QSFP_HIGH_VCC_ALARM) || (qsfp_interrupt_status[1] & QSFP_HIGH_VCC_WARNING)) - dd_dev_info(dd, "%s: QSFP supply voltage too high\n", - __func__); + dd_dev_err(dd, "%s: QSFP supply voltage too high\n", + __func__); if ((qsfp_interrupt_status[1] & QSFP_LOW_VCC_ALARM) || (qsfp_interrupt_status[1] & QSFP_LOW_VCC_WARNING)) - dd_dev_info(dd, "%s: QSFP supply voltage too low\n", - __func__); + dd_dev_err(dd, "%s: QSFP supply voltage too low\n", + __func__); /* Byte 2 is vendor specific */ if ((qsfp_interrupt_status[3] & QSFP_HIGH_POWER_ALARM) || (qsfp_interrupt_status[3] & QSFP_HIGH_POWER_WARNING)) - dd_dev_info(dd, "%s: Cable RX channel 1/2 power too high\n", - __func__); + dd_dev_err(dd, "%s: Cable RX channel 1/2 power too high\n", + __func__); if ((qsfp_interrupt_status[3] & QSFP_LOW_POWER_ALARM) || (qsfp_interrupt_status[3] & QSFP_LOW_POWER_WARNING)) - dd_dev_info(dd, "%s: Cable RX channel 1/2 power too low\n", - __func__); + dd_dev_err(dd, "%s: Cable RX channel 1/2 power too low\n", + __func__); if ((qsfp_interrupt_status[4] & QSFP_HIGH_POWER_ALARM) || (qsfp_interrupt_status[4] & QSFP_HIGH_POWER_WARNING)) - dd_dev_info(dd, "%s: Cable RX channel 3/4 power too high\n", - __func__); + dd_dev_err(dd, "%s: Cable RX channel 3/4 power too high\n", + __func__); if ((qsfp_interrupt_status[4] & QSFP_LOW_POWER_ALARM) || (qsfp_interrupt_status[4] & QSFP_LOW_POWER_WARNING)) - dd_dev_info(dd, "%s: Cable RX channel 3/4 power too low\n", - __func__); + dd_dev_err(dd, "%s: Cable RX channel 3/4 power too low\n", + __func__); if ((qsfp_interrupt_status[5] & QSFP_HIGH_BIAS_ALARM) || (qsfp_interrupt_status[5] & QSFP_HIGH_BIAS_WARNING)) - dd_dev_info(dd, "%s: Cable TX channel 1/2 bias too high\n", - __func__); + dd_dev_err(dd, "%s: Cable TX channel 1/2 bias too high\n", + __func__); if ((qsfp_interrupt_status[5] & QSFP_LOW_BIAS_ALARM) || (qsfp_interrupt_status[5] & QSFP_LOW_BIAS_WARNING)) - dd_dev_info(dd, "%s: Cable TX channel 1/2 bias too low\n", - __func__); + dd_dev_err(dd, "%s: Cable TX channel 1/2 bias too low\n", + __func__); if ((qsfp_interrupt_status[6] & QSFP_HIGH_BIAS_ALARM) || (qsfp_interrupt_status[6] & QSFP_HIGH_BIAS_WARNING)) - dd_dev_info(dd, "%s: Cable TX channel 3/4 bias too high\n", - __func__); + dd_dev_err(dd, "%s: Cable TX channel 3/4 bias too high\n", + __func__); if ((qsfp_interrupt_status[6] & QSFP_LOW_BIAS_ALARM) || (qsfp_interrupt_status[6] & QSFP_LOW_BIAS_WARNING)) - dd_dev_info(dd, "%s: Cable TX channel 3/4 bias too low\n", - __func__); + dd_dev_err(dd, "%s: Cable TX channel 3/4 bias too low\n", + __func__); if ((qsfp_interrupt_status[7] & QSFP_HIGH_POWER_ALARM) || (qsfp_interrupt_status[7] & QSFP_HIGH_POWER_WARNING)) - dd_dev_info(dd, "%s: Cable TX channel 1/2 power too high\n", - __func__); + dd_dev_err(dd, "%s: Cable TX channel 1/2 power too high\n", + __func__); if ((qsfp_interrupt_status[7] & QSFP_LOW_POWER_ALARM) || (qsfp_interrupt_status[7] & QSFP_LOW_POWER_WARNING)) - dd_dev_info(dd, "%s: Cable TX channel 1/2 power too low\n", - __func__); + dd_dev_err(dd, "%s: Cable TX channel 1/2 power too low\n", + __func__); if ((qsfp_interrupt_status[8] & QSFP_HIGH_POWER_ALARM) || (qsfp_interrupt_status[8] & QSFP_HIGH_POWER_WARNING)) - dd_dev_info(dd, "%s: Cable TX channel 3/4 power too high\n", - __func__); + dd_dev_err(dd, "%s: Cable TX channel 3/4 power too high\n", + __func__); if ((qsfp_interrupt_status[8] & QSFP_LOW_POWER_ALARM) || (qsfp_interrupt_status[8] & QSFP_LOW_POWER_WARNING)) - dd_dev_info(dd, "%s: Cable TX channel 3/4 power too low\n", - __func__); + dd_dev_err(dd, "%s: Cable TX channel 3/4 power too low\n", + __func__); /* Bytes 9-10 and 11-12 are reserved */ /* Bytes 13-15 are vendor specific */ -- cgit v1.2.3 From 9c1a99c3882beb9e88ed41d914e75bab2d593926 Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Fri, 9 Jun 2017 15:59:40 -0700 Subject: IB/hfi1: Create common expected receive verbs/PSM code Declarations and code in common between verbs and PSM are now moved to exp_rcv.[ch]. Reviewed-by: Michael J. Ruhl Reviewed-by: Mitko Haralanov Reviewed-by: Ashutosh Dixit Signed-off-by: Mike Marciniszyn Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/Makefile | 2 +- drivers/infiniband/hw/hfi1/exp_rcv.c | 118 +++++++++++++++++++ drivers/infiniband/hw/hfi1/exp_rcv.h | 187 ++++++++++++++++++++++++++++++ drivers/infiniband/hw/hfi1/file_ops.c | 4 +- drivers/infiniband/hw/hfi1/user_exp_rcv.c | 121 ------------------- drivers/infiniband/hw/hfi1/user_exp_rcv.h | 23 +--- drivers/infiniband/hw/hfi1/user_sdma.c | 38 ------ 7 files changed, 309 insertions(+), 184 deletions(-) create mode 100644 drivers/infiniband/hw/hfi1/exp_rcv.c create mode 100644 drivers/infiniband/hw/hfi1/exp_rcv.h (limited to 'drivers') diff --git a/drivers/infiniband/hw/hfi1/Makefile b/drivers/infiniband/hw/hfi1/Makefile index 88085f65432e..66d538c033b0 100644 --- a/drivers/infiniband/hw/hfi1/Makefile +++ b/drivers/infiniband/hw/hfi1/Makefile @@ -8,7 +8,7 @@ obj-$(CONFIG_INFINIBAND_HFI1) += hfi1.o hfi1-y := affinity.o chip.o device.o driver.o efivar.o \ - eprom.o file_ops.o firmware.o \ + eprom.o exp_rcv.o file_ops.o firmware.o \ init.o intr.o mad.o mmu_rb.o pcie.o pio.o pio_copy.o platform.o \ qp.o qsfp.o rc.o ruc.o sdma.o sysfs.o trace.o \ uc.o ud.o user_exp_rcv.o user_pages.o user_sdma.o verbs.o \ diff --git a/drivers/infiniband/hw/hfi1/exp_rcv.c b/drivers/infiniband/hw/hfi1/exp_rcv.c new file mode 100644 index 000000000000..08d13ed1b574 --- /dev/null +++ b/drivers/infiniband/hw/hfi1/exp_rcv.c @@ -0,0 +1,118 @@ +/* + * Copyright(c) 2017 Intel Corporation. + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License 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. + * + * BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "exp_rcv.h" +#include "trace.h" + +/** + * exp_tid_group_init - initialize exp_tid_set + * @set - the set + */ +void hfi1_exp_tid_group_init(struct exp_tid_set *set) +{ + INIT_LIST_HEAD(&set->list); + set->count = 0; +} + +/** + * alloc_ctxt_rcv_groups - initialize expected receive groups + * @rcd - the context to add the groupings to + */ +int hfi1_alloc_ctxt_rcv_groups(struct hfi1_ctxtdata *rcd) +{ + struct hfi1_devdata *dd = rcd->dd; + u32 tidbase; + struct tid_group *grp; + int i; + + hfi1_exp_tid_group_init(&rcd->tid_group_list); + hfi1_exp_tid_group_init(&rcd->tid_used_list); + hfi1_exp_tid_group_init(&rcd->tid_full_list); + + tidbase = rcd->expected_base; + for (i = 0; i < rcd->expected_count / + dd->rcv_entries.group_size; i++) { + grp = kzalloc(sizeof(*grp), GFP_KERNEL); + if (!grp) + goto bail; + grp->size = dd->rcv_entries.group_size; + grp->base = tidbase; + tid_group_add_tail(grp, &rcd->tid_group_list); + tidbase += dd->rcv_entries.group_size; + } + + return 0; +bail: + hfi1_free_ctxt_rcv_groups(rcd); + return -ENOMEM; +} + +/** + * free_ctxt_rcv_groups - free expected receive groups + * @rcd - the context to free + * + * The routine dismantles the expect receive linked + * list and clears any tids associated with the receive + * context. + * + * This should only be called for kernel contexts and the + * a base user context. + */ +void hfi1_free_ctxt_rcv_groups(struct hfi1_ctxtdata *rcd) +{ + struct tid_group *grp, *gptr; + + WARN_ON(!EXP_TID_SET_EMPTY(rcd->tid_full_list)); + WARN_ON(!EXP_TID_SET_EMPTY(rcd->tid_used_list)); + + list_for_each_entry_safe(grp, gptr, &rcd->tid_group_list.list, list) { + tid_group_remove(grp, &rcd->tid_group_list); + kfree(grp); + } + + hfi1_clear_tids(rcd); +} diff --git a/drivers/infiniband/hw/hfi1/exp_rcv.h b/drivers/infiniband/hw/hfi1/exp_rcv.h new file mode 100644 index 000000000000..c7d02bcddded --- /dev/null +++ b/drivers/infiniband/hw/hfi1/exp_rcv.h @@ -0,0 +1,187 @@ +#ifndef _HFI1_EXP_RCV_H +#define _HFI1_EXP_RCV_H +/* + * Copyright(c) 2017 Intel Corporation. + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License 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. + * + * BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "hfi.h" + +#define EXP_TID_SET_EMPTY(set) (set.count == 0 && list_empty(&set.list)) + +#define EXP_TID_TIDLEN_MASK 0x7FFULL +#define EXP_TID_TIDLEN_SHIFT 0 +#define EXP_TID_TIDCTRL_MASK 0x3ULL +#define EXP_TID_TIDCTRL_SHIFT 20 +#define EXP_TID_TIDIDX_MASK 0x3FFULL +#define EXP_TID_TIDIDX_SHIFT 22 +#define EXP_TID_GET(tid, field) \ + (((tid) >> EXP_TID_TID##field##_SHIFT) & EXP_TID_TID##field##_MASK) + +#define EXP_TID_SET(field, value) \ + (((value) & EXP_TID_TID##field##_MASK) << \ + EXP_TID_TID##field##_SHIFT) +#define EXP_TID_CLEAR(tid, field) ({ \ + (tid) &= ~(EXP_TID_TID##field##_MASK << \ + EXP_TID_TID##field##_SHIFT); \ + }) +#define EXP_TID_RESET(tid, field, value) do { \ + EXP_TID_CLEAR(tid, field); \ + (tid) |= EXP_TID_SET(field, (value)); \ + } while (0) + +/* + * Define fields in the KDETH header so we can update the header + * template. + */ +#define KDETH_OFFSET_SHIFT 0 +#define KDETH_OFFSET_MASK 0x7fff +#define KDETH_OM_SHIFT 15 +#define KDETH_OM_MASK 0x1 +#define KDETH_TID_SHIFT 16 +#define KDETH_TID_MASK 0x3ff +#define KDETH_TIDCTRL_SHIFT 26 +#define KDETH_TIDCTRL_MASK 0x3 +#define KDETH_INTR_SHIFT 28 +#define KDETH_INTR_MASK 0x1 +#define KDETH_SH_SHIFT 29 +#define KDETH_SH_MASK 0x1 +#define KDETH_KVER_SHIFT 30 +#define KDETH_KVER_MASK 0x3 +#define KDETH_JKEY_SHIFT 0x0 +#define KDETH_JKEY_MASK 0xff +#define KDETH_HCRC_UPPER_SHIFT 16 +#define KDETH_HCRC_UPPER_MASK 0xff +#define KDETH_HCRC_LOWER_SHIFT 24 +#define KDETH_HCRC_LOWER_MASK 0xff + +#define KDETH_GET(val, field) \ + (((le32_to_cpu((val))) >> KDETH_##field##_SHIFT) & KDETH_##field##_MASK) +#define KDETH_SET(dw, field, val) do { \ + u32 dwval = le32_to_cpu(dw); \ + dwval &= ~(KDETH_##field##_MASK << KDETH_##field##_SHIFT); \ + dwval |= (((val) & KDETH_##field##_MASK) << \ + KDETH_##field##_SHIFT); \ + dw = cpu_to_le32(dwval); \ + } while (0) + +#define KDETH_RESET(dw, field, val) ({ dw = 0; KDETH_SET(dw, field, val); }) + +/* KDETH OM multipliers and switch over point */ +#define KDETH_OM_SMALL 4 +#define KDETH_OM_SMALL_SHIFT 2 +#define KDETH_OM_LARGE 64 +#define KDETH_OM_LARGE_SHIFT 6 +#define KDETH_OM_MAX_SIZE (1 << ((KDETH_OM_LARGE / KDETH_OM_SMALL) + 1)) + +struct tid_group { + struct list_head list; + u32 base; + u8 size; + u8 used; + u8 map; +}; + +/* + * Write an "empty" RcvArray entry. + * This function exists so the TID registaration code can use it + * to write to unused/unneeded entries and still take advantage + * of the WC performance improvements. The HFI will ignore this + * write to the RcvArray entry. + */ +static inline void rcv_array_wc_fill(struct hfi1_devdata *dd, u32 index) +{ + /* + * Doing the WC fill writes only makes sense if the device is + * present and the RcvArray has been mapped as WC memory. + */ + if ((dd->flags & HFI1_PRESENT) && dd->rcvarray_wc) + writeq(0, dd->rcvarray_wc + (index * 8)); +} + +static inline void tid_group_add_tail(struct tid_group *grp, + struct exp_tid_set *set) +{ + list_add_tail(&grp->list, &set->list); + set->count++; +} + +static inline void tid_group_remove(struct tid_group *grp, + struct exp_tid_set *set) +{ + list_del_init(&grp->list); + set->count--; +} + +static inline void tid_group_move(struct tid_group *group, + struct exp_tid_set *s1, + struct exp_tid_set *s2) +{ + tid_group_remove(group, s1); + tid_group_add_tail(group, s2); +} + +static inline struct tid_group *tid_group_pop(struct exp_tid_set *set) +{ + struct tid_group *grp = + list_first_entry(&set->list, struct tid_group, list); + list_del_init(&grp->list); + set->count--; + return grp; +} + +static inline u32 rcventry2tidinfo(u32 rcventry) +{ + u32 pair = rcventry & ~0x1; + + return EXP_TID_SET(IDX, pair >> 1) | + EXP_TID_SET(CTRL, 1 << (rcventry - pair)); +} + +int hfi1_alloc_ctxt_rcv_groups(struct hfi1_ctxtdata *rcd); +void hfi1_free_ctxt_rcv_groups(struct hfi1_ctxtdata *rcd); +void hfi1_exp_tid_group_init(struct exp_tid_set *set); + +#endif /* _HFI1_EXP_RCV_H */ diff --git a/drivers/infiniband/hw/hfi1/file_ops.c b/drivers/infiniband/hw/hfi1/file_ops.c index 3158128d57e8..2dd8758f0644 100644 --- a/drivers/infiniband/hw/hfi1/file_ops.c +++ b/drivers/infiniband/hw/hfi1/file_ops.c @@ -804,7 +804,7 @@ static int hfi1_file_close(struct inode *inode, struct file *fp) dd->rcd[uctxt->ctxt] = NULL; - hfi1_user_exp_rcv_grp_free(uctxt); + hfi1_free_ctxt_rcv_groups(uctxt); hfi1_clear_ctxt_pkey(dd, uctxt); uctxt->rcvwait_to = 0; @@ -1260,7 +1260,7 @@ static int setup_base_ctxt(struct hfi1_filedata *fd) if (ret) goto setup_failed; - ret = hfi1_user_exp_rcv_grp_init(fd); + ret = hfi1_alloc_ctxt_rcv_groups(uctxt); if (ret) goto setup_failed; diff --git a/drivers/infiniband/hw/hfi1/user_exp_rcv.c b/drivers/infiniband/hw/hfi1/user_exp_rcv.c index a8f0aa4722f6..6318e6ca1b18 100644 --- a/drivers/infiniband/hw/hfi1/user_exp_rcv.c +++ b/drivers/infiniband/hw/hfi1/user_exp_rcv.c @@ -51,14 +51,6 @@ #include "trace.h" #include "mmu_rb.h" -struct tid_group { - struct list_head list; - u32 base; - u8 size; - u8 used; - u8 map; -}; - struct tid_rb_node { struct mmu_rb_node mmu; unsigned long phys; @@ -75,8 +67,6 @@ struct tid_pageset { u16 count; }; -#define EXP_TID_SET_EMPTY(set) (set.count == 0 && list_empty(&set.list)) - #define num_user_pages(vaddr, len) \ (1 + (((((unsigned long)(vaddr) + \ (unsigned long)(len) - 1) & PAGE_MASK) - \ @@ -109,88 +99,6 @@ static struct mmu_rb_ops tid_rb_ops = { .invalidate = tid_rb_invalidate }; -static inline u32 rcventry2tidinfo(u32 rcventry) -{ - u32 pair = rcventry & ~0x1; - - return EXP_TID_SET(IDX, pair >> 1) | - EXP_TID_SET(CTRL, 1 << (rcventry - pair)); -} - -static inline void exp_tid_group_init(struct exp_tid_set *set) -{ - INIT_LIST_HEAD(&set->list); - set->count = 0; -} - -static inline void tid_group_remove(struct tid_group *grp, - struct exp_tid_set *set) -{ - list_del_init(&grp->list); - set->count--; -} - -static inline void tid_group_add_tail(struct tid_group *grp, - struct exp_tid_set *set) -{ - list_add_tail(&grp->list, &set->list); - set->count++; -} - -static inline struct tid_group *tid_group_pop(struct exp_tid_set *set) -{ - struct tid_group *grp = - list_first_entry(&set->list, struct tid_group, list); - list_del_init(&grp->list); - set->count--; - return grp; -} - -static inline void tid_group_move(struct tid_group *group, - struct exp_tid_set *s1, - struct exp_tid_set *s2) -{ - tid_group_remove(group, s1); - tid_group_add_tail(group, s2); -} - -int hfi1_user_exp_rcv_grp_init(struct hfi1_filedata *fd) -{ - struct hfi1_ctxtdata *uctxt = fd->uctxt; - struct hfi1_devdata *dd = fd->dd; - u32 tidbase; - u32 i; - struct tid_group *grp, *gptr; - - exp_tid_group_init(&uctxt->tid_group_list); - exp_tid_group_init(&uctxt->tid_used_list); - exp_tid_group_init(&uctxt->tid_full_list); - - tidbase = uctxt->expected_base; - for (i = 0; i < uctxt->expected_count / - dd->rcv_entries.group_size; i++) { - grp = kzalloc(sizeof(*grp), GFP_KERNEL); - if (!grp) - goto grp_failed; - - grp->size = dd->rcv_entries.group_size; - grp->base = tidbase; - tid_group_add_tail(grp, &uctxt->tid_group_list); - tidbase += dd->rcv_entries.group_size; - } - - return 0; - -grp_failed: - list_for_each_entry_safe(grp, gptr, &uctxt->tid_group_list.list, - list) { - list_del_init(&grp->list); - kfree(grp); - } - - return -ENOMEM; -} - /* * Initialize context and file private data needed for Expected * receive caching. This needs to be done after the context has @@ -266,18 +174,6 @@ int hfi1_user_exp_rcv_init(struct hfi1_filedata *fd) return ret; } -void hfi1_user_exp_rcv_grp_free(struct hfi1_ctxtdata *uctxt) -{ - struct tid_group *grp, *gptr; - - list_for_each_entry_safe(grp, gptr, &uctxt->tid_group_list.list, - list) { - list_del_init(&grp->list); - kfree(grp); - } - hfi1_clear_tids(uctxt); -} - void hfi1_user_exp_rcv_free(struct hfi1_filedata *fd) { struct hfi1_ctxtdata *uctxt = fd->uctxt; @@ -302,23 +198,6 @@ void hfi1_user_exp_rcv_free(struct hfi1_filedata *fd) fd->entry_to_rb = NULL; } -/* - * Write an "empty" RcvArray entry. - * This function exists so the TID registaration code can use it - * to write to unused/unneeded entries and still take advantage - * of the WC performance improvements. The HFI will ignore this - * write to the RcvArray entry. - */ -static inline void rcv_array_wc_fill(struct hfi1_devdata *dd, u32 index) -{ - /* - * Doing the WC fill writes only makes sense if the device is - * present and the RcvArray has been mapped as WC memory. - */ - if ((dd->flags & HFI1_PRESENT) && dd->rcvarray_wc) - writeq(0, dd->rcvarray_wc + (index * 8)); -} - /* * RcvArray entry allocation for Expected Receives is done by the * following algorithm: diff --git a/drivers/infiniband/hw/hfi1/user_exp_rcv.h b/drivers/infiniband/hw/hfi1/user_exp_rcv.h index 5250c897298d..1bdc61be53cb 100644 --- a/drivers/infiniband/hw/hfi1/user_exp_rcv.h +++ b/drivers/infiniband/hw/hfi1/user_exp_rcv.h @@ -49,29 +49,8 @@ #include "hfi.h" -#define EXP_TID_TIDLEN_MASK 0x7FFULL -#define EXP_TID_TIDLEN_SHIFT 0 -#define EXP_TID_TIDCTRL_MASK 0x3ULL -#define EXP_TID_TIDCTRL_SHIFT 20 -#define EXP_TID_TIDIDX_MASK 0x3FFULL -#define EXP_TID_TIDIDX_SHIFT 22 -#define EXP_TID_GET(tid, field) \ - (((tid) >> EXP_TID_TID##field##_SHIFT) & EXP_TID_TID##field##_MASK) +#include "exp_rcv.h" -#define EXP_TID_SET(field, value) \ - (((value) & EXP_TID_TID##field##_MASK) << \ - EXP_TID_TID##field##_SHIFT) -#define EXP_TID_CLEAR(tid, field) ({ \ - (tid) &= ~(EXP_TID_TID##field##_MASK << \ - EXP_TID_TID##field##_SHIFT); \ - }) -#define EXP_TID_RESET(tid, field, value) do { \ - EXP_TID_CLEAR(tid, field); \ - (tid) |= EXP_TID_SET(field, (value)); \ - } while (0) - -void hfi1_user_exp_rcv_grp_free(struct hfi1_ctxtdata *uctxt); -int hfi1_user_exp_rcv_grp_init(struct hfi1_filedata *fd); int hfi1_user_exp_rcv_init(struct hfi1_filedata *fd); void hfi1_user_exp_rcv_free(struct hfi1_filedata *fd); int hfi1_user_exp_rcv_setup(struct hfi1_filedata *fd, diff --git a/drivers/infiniband/hw/hfi1/user_sdma.c b/drivers/infiniband/hw/hfi1/user_sdma.c index fcadbb9978ca..8f7cfdd9e9ec 100644 --- a/drivers/infiniband/hw/hfi1/user_sdma.c +++ b/drivers/infiniband/hw/hfi1/user_sdma.c @@ -94,27 +94,6 @@ MODULE_PARM_DESC(sdma_comp_size, "Size of User SDMA completion ring. Default: 12 /* Number of BTH.PSN bits used for sequence number in expected rcvs */ #define BTH_SEQ_MASK 0x7ffull -/* - * Define fields in the KDETH header so we can update the header - * template. - */ -#define KDETH_OFFSET_SHIFT 0 -#define KDETH_OFFSET_MASK 0x7fff -#define KDETH_OM_SHIFT 15 -#define KDETH_OM_MASK 0x1 -#define KDETH_TID_SHIFT 16 -#define KDETH_TID_MASK 0x3ff -#define KDETH_TIDCTRL_SHIFT 26 -#define KDETH_TIDCTRL_MASK 0x3 -#define KDETH_INTR_SHIFT 28 -#define KDETH_INTR_MASK 0x1 -#define KDETH_SH_SHIFT 29 -#define KDETH_SH_MASK 0x1 -#define KDETH_HCRC_UPPER_SHIFT 16 -#define KDETH_HCRC_UPPER_MASK 0xff -#define KDETH_HCRC_LOWER_SHIFT 24 -#define KDETH_HCRC_LOWER_MASK 0xff - #define AHG_KDETH_INTR_SHIFT 12 #define AHG_KDETH_SH_SHIFT 13 #define AHG_KDETH_ARRAY_SIZE 9 @@ -122,16 +101,6 @@ MODULE_PARM_DESC(sdma_comp_size, "Size of User SDMA completion ring. Default: 12 #define PBC2LRH(x) ((((x) & 0xfff) << 2) - 4) #define LRH2PBC(x) ((((x) >> 2) + 1) & 0xfff) -#define KDETH_GET(val, field) \ - (((le32_to_cpu((val))) >> KDETH_##field##_SHIFT) & KDETH_##field##_MASK) -#define KDETH_SET(dw, field, val) do { \ - u32 dwval = le32_to_cpu(dw); \ - dwval &= ~(KDETH_##field##_MASK << KDETH_##field##_SHIFT); \ - dwval |= (((val) & KDETH_##field##_MASK) << \ - KDETH_##field##_SHIFT); \ - dw = cpu_to_le32(dwval); \ - } while (0) - #define AHG_HEADER_SET(arr, idx, dw, bit, width, value) \ do { \ if ((idx) < ARRAY_SIZE((arr))) \ @@ -142,13 +111,6 @@ MODULE_PARM_DESC(sdma_comp_size, "Size of User SDMA completion ring. Default: 12 return -ERANGE; \ } while (0) -/* KDETH OM multipliers and switch over point */ -#define KDETH_OM_SMALL 4 -#define KDETH_OM_SMALL_SHIFT 2 -#define KDETH_OM_LARGE 64 -#define KDETH_OM_LARGE_SHIFT 6 -#define KDETH_OM_MAX_SIZE (1 << ((KDETH_OM_LARGE / KDETH_OM_SMALL) + 1)) - /* Tx request flag bits */ #define TXREQ_FLAGS_REQ_ACK BIT(0) /* Set the ACK bit in the header */ #define TXREQ_FLAGS_REQ_DISABLE_SH BIT(1) /* Disable header suppression */ -- cgit v1.2.3 From f5114440c5491d4737b061c3a77195088bbaca52 Mon Sep 17 00:00:00 2001 From: Jan Sokolowski Date: Fri, 9 Jun 2017 15:59:46 -0700 Subject: IB/hfi1: Remove reading platform configuration from EFI variable Currently, platform configuration can be read from EFI variable for discrete cards. It will happen when reading from EPROM fails. EFI variables should not be queried for platform configuration in any scenario. Reviewed-by: Jakub Byczkowski Signed-off-by: Jan Sokolowski Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/platform.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/hfi1/platform.c b/drivers/infiniband/hw/hfi1/platform.c index cbda9b189216..41307e474525 100644 --- a/drivers/infiniband/hw/hfi1/platform.c +++ b/drivers/infiniband/hw/hfi1/platform.c @@ -136,7 +136,6 @@ static void save_platform_config_fields(struct hfi1_devdata *dd) void get_platform_config(struct hfi1_devdata *dd) { int ret = 0; - unsigned long size = 0; u8 *temp_platform_config = NULL; u32 esize; @@ -160,15 +159,6 @@ void get_platform_config(struct hfi1_devdata *dd) dd->platform_config.size = esize; return; } - /* fail, try EFI variable */ - - ret = read_hfi1_efi_var(dd, "configuration", &size, - (void **)&temp_platform_config); - if (!ret) { - dd->platform_config.data = temp_platform_config; - dd->platform_config.size = size; - return; - } } dd_dev_err(dd, "%s: Failed to get platform config, falling back to sub-optimal default file\n", -- cgit v1.2.3 From f523984fb85d16e098aac94642cc16803a4cc61f Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Fri, 9 Jun 2017 15:59:53 -0700 Subject: IB/hfi1: Use a template for tid reg/unreg This is the preferred way to add a duplicate trace call. Reviewed-by: Dennis Dalessandro Signed-off-by: Mike Marciniszyn Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/trace_rx.h | 46 ++++++++++------------------------- 1 file changed, 13 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/hfi1/trace_rx.h b/drivers/infiniband/hw/hfi1/trace_rx.h index 05fc6d68ffe8..7af593827d37 100644 --- a/drivers/infiniband/hw/hfi1/trace_rx.h +++ b/drivers/infiniband/hw/hfi1/trace_rx.h @@ -138,7 +138,8 @@ TRACE_EVENT(hfi1_receive_interrupt, ) ); -TRACE_EVENT(hfi1_exp_tid_reg, +DECLARE_EVENT_CLASS( + hfi1_exp_tid_reg_unreg, TP_PROTO(unsigned int ctxt, u16 subctxt, u32 rarr, u32 npages, unsigned long va, unsigned long pa, dma_addr_t dma), @@ -172,38 +173,17 @@ TRACE_EVENT(hfi1_exp_tid_reg, ) ); -TRACE_EVENT(hfi1_exp_tid_unreg, - TP_PROTO(unsigned int ctxt, u16 subctxt, u32 rarr, u32 npages, - unsigned long va, unsigned long pa, dma_addr_t dma), - TP_ARGS(ctxt, subctxt, rarr, npages, va, pa, dma), - TP_STRUCT__entry( - __field(unsigned int, ctxt) - __field(u16, subctxt) - __field(u32, rarr) - __field(u32, npages) - __field(unsigned long, va) - __field(unsigned long, pa) - __field(dma_addr_t, dma) - ), - TP_fast_assign( - __entry->ctxt = ctxt; - __entry->subctxt = subctxt; - __entry->rarr = rarr; - __entry->npages = npages; - __entry->va = va; - __entry->pa = pa; - __entry->dma = dma; - ), - TP_printk("[%u:%u] entry:%u, %u pages @ 0x%lx, va:0x%lx dma:0x%llx", - __entry->ctxt, - __entry->subctxt, - __entry->rarr, - __entry->npages, - __entry->pa, - __entry->va, - __entry->dma - ) - ); +DEFINE_EVENT( + hfi1_exp_tid_reg_unreg, hfi1_exp_tid_unreg, + TP_PROTO(unsigned int ctxt, u16 subctxt, u32 rarr, u32 npages, + unsigned long va, unsigned long pa, dma_addr_t dma), + TP_ARGS(ctxt, subctxt, rarr, npages, va, pa, dma)); + +DEFINE_EVENT( + hfi1_exp_tid_reg_unreg, hfi1_exp_tid_reg, + TP_PROTO(unsigned int ctxt, u16 subctxt, u32 rarr, u32 npages, + unsigned long va, unsigned long pa, dma_addr_t dma), + TP_ARGS(ctxt, subctxt, rarr, npages, va, pa, dma)); TRACE_EVENT(hfi1_exp_tid_inval, TP_PROTO(unsigned int ctxt, u16 subctxt, unsigned long va, u32 rarr, -- cgit v1.2.3 From 8cb1021b806bda3f5fda6f3699e1f98df14245df Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Fri, 9 Jun 2017 15:59:59 -0700 Subject: IB/hfi1: Add traces for TID operations This patch adds a trace for putting a TID and for writing the RcvArray CSR. The CSR access template can be easily extended for additional CSR readq/writeq calls. Reviewed-by: Ashutosh Dixit Signed-off-by: Mike Marciniszyn Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/chip.c | 16 ++------------- drivers/infiniband/hw/hfi1/trace_misc.h | 20 +++++++++++++++++++ drivers/infiniband/hw/hfi1/trace_rx.h | 35 +++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/hfi1/chip.c b/drivers/infiniband/hw/hfi1/chip.c index b8ee0e27dae6..937350d9deab 100644 --- a/drivers/infiniband/hw/hfi1/chip.c +++ b/drivers/infiniband/hw/hfi1/chip.c @@ -9745,17 +9745,6 @@ static inline int init_cpu_counters(struct hfi1_devdata *dd) return 0; } -static const char * const pt_names[] = { - "expected", - "eager", - "invalid" -}; - -static const char *pt_name(u32 type) -{ - return type >= ARRAY_SIZE(pt_names) ? "unknown" : pt_names[type]; -} - /* * index is the index into the receive array */ @@ -9777,15 +9766,14 @@ void hfi1_put_tid(struct hfi1_devdata *dd, u32 index, type, index); goto done; } - - hfi1_cdbg(TID, "type %s, index 0x%x, pa 0x%lx, bsize 0x%lx", - pt_name(type), index, pa, (unsigned long)order); + trace_hfi1_put_tid(dd, index, type, pa, order); #define RT_ADDR_SHIFT 12 /* 4KB kernel address boundary */ reg = RCV_ARRAY_RT_WRITE_ENABLE_SMASK | (u64)order << RCV_ARRAY_RT_BUF_SIZE_SHIFT | ((pa >> RT_ADDR_SHIFT) & RCV_ARRAY_RT_ADDR_MASK) << RCV_ARRAY_RT_ADDR_SHIFT; + trace_hfi1_write_rcvarray(base + (index * 8), reg); writeq(reg, base + (index * 8)); if (type == PT_EAGER) diff --git a/drivers/infiniband/hw/hfi1/trace_misc.h b/drivers/infiniband/hw/hfi1/trace_misc.h index deac77ddaeab..8db2253523ff 100644 --- a/drivers/infiniband/hw/hfi1/trace_misc.h +++ b/drivers/infiniband/hw/hfi1/trace_misc.h @@ -72,6 +72,26 @@ TRACE_EVENT(hfi1_interrupt, __entry->src) ); +DECLARE_EVENT_CLASS( + hfi1_csr_template, + TP_PROTO(void __iomem *addr, u64 value), + TP_ARGS(addr, value), + TP_STRUCT__entry( + __field(void __iomem *, addr) + __field(u64, value) + ), + TP_fast_assign( + __entry->addr = addr; + __entry->value = value; + ), + TP_printk("addr %p value %llx", __entry->addr, __entry->value) +); + +DEFINE_EVENT( + hfi1_csr_template, hfi1_write_rcvarray, + TP_PROTO(void __iomem *addr, u64 value), + TP_ARGS(addr, value)); + #ifdef CONFIG_FAULT_INJECTION TRACE_EVENT(hfi1_fault_opcode, TP_PROTO(struct rvt_qp *qp, u8 opcode), diff --git a/drivers/infiniband/hw/hfi1/trace_rx.h b/drivers/infiniband/hw/hfi1/trace_rx.h index 7af593827d37..84929578cfe6 100644 --- a/drivers/infiniband/hw/hfi1/trace_rx.h +++ b/drivers/infiniband/hw/hfi1/trace_rx.h @@ -52,6 +52,13 @@ #include "hfi.h" +#define tidtype_name(type) { PT_##type, #type } +#define show_tidtype(type) \ +__print_symbolic(type, \ + tidtype_name(EXPECTED), \ + tidtype_name(EAGER), \ + tidtype_name(INVALID)) \ + #undef TRACE_SYSTEM #define TRACE_SYSTEM hfi1_rx @@ -185,6 +192,34 @@ DEFINE_EVENT( unsigned long va, unsigned long pa, dma_addr_t dma), TP_ARGS(ctxt, subctxt, rarr, npages, va, pa, dma)); +TRACE_EVENT( + hfi1_put_tid, + TP_PROTO(struct hfi1_devdata *dd, + u32 index, u32 type, unsigned long pa, u16 order), + TP_ARGS(dd, index, type, pa, order), + TP_STRUCT__entry( + DD_DEV_ENTRY(dd) + __field(unsigned long, pa); + __field(u32, index); + __field(u32, type); + __field(u16, order); + ), + TP_fast_assign( + DD_DEV_ASSIGN(dd); + __entry->pa = pa; + __entry->index = index; + __entry->type = type; + __entry->order = order; + ), + TP_printk("[%s] type %s pa %lx index %u order %u", + __get_str(dev), + show_tidtype(__entry->type), + __entry->pa, + __entry->index, + __entry->order + ) +); + TRACE_EVENT(hfi1_exp_tid_inval, TP_PROTO(unsigned int ctxt, u16 subctxt, unsigned long va, u32 rarr, u32 npages, dma_addr_t dma), -- cgit v1.2.3 From 581d01aaaca1fbb9df83cf3337c77e85215dcc5b Mon Sep 17 00:00:00 2001 From: "Michael J. Ruhl" Date: Fri, 9 Jun 2017 16:00:06 -0700 Subject: IB/qib: Replace deprecated pci functions with new API pci_enable_msix_range() and pci_disable_msix() have been deprecated. Updating to the new pci_alloc_irq_vectors() interface. Reviewed-by: Sebastian Sanchez Reviewed-by: Mike Marciniszyn Signed-off-by: Michael J. Ruhl Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/qib/qib.h | 8 +- drivers/infiniband/hw/qib/qib_iba6120.c | 6 +- drivers/infiniband/hw/qib/qib_iba7220.c | 7 +- drivers/infiniband/hw/qib/qib_iba7322.c | 48 +++++----- drivers/infiniband/hw/qib/qib_pcie.c | 149 +++++++++++++------------------- 5 files changed, 98 insertions(+), 120 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/qib/qib.h b/drivers/infiniband/hw/qib/qib.h index a3e21a25cea5..f9e1c69603a5 100644 --- a/drivers/infiniband/hw/qib/qib.h +++ b/drivers/infiniband/hw/qib/qib.h @@ -1,7 +1,7 @@ #ifndef _QIB_KERNEL_H #define _QIB_KERNEL_H /* - * Copyright (c) 2012, 2013 Intel Corporation. All rights reserved. + * Copyright (c) 2012 - 2017 Intel Corporation. All rights reserved. * Copyright (c) 2006 - 2012 QLogic Corporation. All rights reserved. * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. * @@ -443,7 +443,7 @@ struct qib_irq_notify; #endif struct qib_msix_entry { - struct msix_entry msix; + int irq; void *arg; #ifdef CONFIG_INFINIBAND_QIB_DCA int dca; @@ -1433,9 +1433,9 @@ int qib_pcie_init(struct pci_dev *, const struct pci_device_id *); int qib_pcie_ddinit(struct qib_devdata *, struct pci_dev *, const struct pci_device_id *); void qib_pcie_ddcleanup(struct qib_devdata *); -int qib_pcie_params(struct qib_devdata *, u32, u32 *, struct qib_msix_entry *); +int qib_pcie_params(struct qib_devdata *dd, u32 minw, u32 *nent); int qib_reinit_intr(struct qib_devdata *); -void qib_enable_intx(struct pci_dev *); +void qib_enable_intx(struct qib_devdata *dd); void qib_nomsi(struct qib_devdata *); void qib_nomsix(struct qib_devdata *); void qib_pcie_getcmd(struct qib_devdata *, u16 *, u8 *, u8 *); diff --git a/drivers/infiniband/hw/qib/qib_iba6120.c b/drivers/infiniband/hw/qib/qib_iba6120.c index e423b71e6ea0..46045fc28fa0 100644 --- a/drivers/infiniband/hw/qib/qib_iba6120.c +++ b/drivers/infiniband/hw/qib/qib_iba6120.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 Intel Corporation. All rights reserved. + * Copyright (c) 2013 - 2017 Intel Corporation. All rights reserved. * Copyright (c) 2006, 2007, 2008, 2009, 2010 QLogic Corporation. * All rights reserved. * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. @@ -1838,7 +1838,7 @@ static int qib_6120_setup_reset(struct qib_devdata *dd) bail: if (ret) { - if (qib_pcie_params(dd, dd->lbus_width, NULL, NULL)) + if (qib_pcie_params(dd, dd->lbus_width, NULL)) qib_dev_err(dd, "Reset failed to setup PCIe or interrupts; continuing anyway\n"); /* clear the reset error, init error/hwerror mask */ @@ -3562,7 +3562,7 @@ struct qib_devdata *qib_init_iba6120_funcs(struct pci_dev *pdev, if (qib_mini_init) goto bail; - if (qib_pcie_params(dd, 8, NULL, NULL)) + if (qib_pcie_params(dd, 8, NULL)) qib_dev_err(dd, "Failed to setup PCIe or interrupts; continuing anyway\n"); dd->cspec->irq = pdev->irq; /* save IRQ */ diff --git a/drivers/infiniband/hw/qib/qib_iba7220.c b/drivers/infiniband/hw/qib/qib_iba7220.c index c3679c48e61c..49cd6e3beb72 100644 --- a/drivers/infiniband/hw/qib/qib_iba7220.c +++ b/drivers/infiniband/hw/qib/qib_iba7220.c @@ -1,4 +1,5 @@ /* + * Copyright (c) 2011 - 2017 Intel Corporation. All rights reserved. * Copyright (c) 2006, 2007, 2008, 2009, 2010 QLogic Corporation. * All rights reserved. * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. @@ -2148,7 +2149,7 @@ static int qib_setup_7220_reset(struct qib_devdata *dd) bail: if (ret) { - if (qib_pcie_params(dd, dd->lbus_width, NULL, NULL)) + if (qib_pcie_params(dd, dd->lbus_width, NULL)) qib_dev_err(dd, "Reset failed to setup PCIe or interrupts; continuing anyway\n"); @@ -3309,7 +3310,7 @@ static int qib_7220_intr_fallback(struct qib_devdata *dd) qib_devinfo(dd->pcidev, "MSI interrupt not detected, trying INTx interrupts\n"); qib_7220_free_irq(dd); - qib_enable_intx(dd->pcidev); + qib_enable_intx(dd); /* * Some newer kernels require free_irq before disable_msi, * and irq can be changed during disable and INTx enable @@ -4619,7 +4620,7 @@ struct qib_devdata *qib_init_iba7220_funcs(struct pci_dev *pdev, minwidth = 8; /* x8 capable boards */ break; } - if (qib_pcie_params(dd, minwidth, NULL, NULL)) + if (qib_pcie_params(dd, minwidth, NULL)) qib_dev_err(dd, "Failed to setup PCIe or interrupts; continuing anyway\n"); diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c index bb2439fff8fa..2653064ce9e9 100644 --- a/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/drivers/infiniband/hw/qib/qib_iba7322.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Intel Corporation. All rights reserved. + * Copyright (c) 2012 - 2017 Intel Corporation. All rights reserved. * Copyright (c) 2008 - 2012 QLogic Corporation. All rights reserved. * * This software is available to you under a choice of one of two @@ -2841,10 +2841,10 @@ static void qib_7322_nomsix(struct qib_devdata *dd) reset_dca_notifier(dd, &dd->cspec->msix_entries[i]); #endif irq_set_affinity_hint( - dd->cspec->msix_entries[i].msix.vector, NULL); + dd->cspec->msix_entries[i].irq, NULL); free_cpumask_var(dd->cspec->msix_entries[i].mask); - free_irq(dd->cspec->msix_entries[i].msix.vector, - dd->cspec->msix_entries[i].arg); + free_irq(dd->cspec->msix_entries[i].irq, + dd->cspec->msix_entries[i].arg); } qib_nomsix(dd); } @@ -3336,9 +3336,9 @@ static void reset_dca_notifier(struct qib_devdata *dd, struct qib_msix_entry *m) qib_devinfo(dd->pcidev, "Disabling notifier on HCA %d irq %d\n", dd->unit, - m->msix.vector); + m->irq); irq_set_affinity_notifier( - m->msix.vector, + m->irq, NULL); m->notifier = NULL; } @@ -3354,7 +3354,7 @@ static void setup_dca_notifier(struct qib_devdata *dd, struct qib_msix_entry *m) int ret; m->notifier = n; - n->notify.irq = m->msix.vector; + n->notify.irq = m->irq; n->notify.notify = qib_irq_notifier_notify; n->notify.release = qib_irq_notifier_release; n->arg = m->arg; @@ -3500,10 +3500,21 @@ try_intx: - 1, QIB_DRV_NAME "%d (kctx)", dd->unit); } - ret = request_irq( - dd->cspec->msix_entries[msixnum].msix.vector, - handler, 0, dd->cspec->msix_entries[msixnum].name, - arg); + + dd->cspec->msix_entries[msixnum].irq = pci_irq_vector( + dd->pcidev, msixnum); + if (dd->cspec->msix_entries[msixnum].irq < 0) { + qib_dev_err(dd, + "Couldn't get MSIx irq (vec=%d): %d\n", + msixnum, + dd->cspec->msix_entries[msixnum].irq); + qib_7322_nomsix(dd); + goto try_intx; + } + ret = request_irq(dd->cspec->msix_entries[msixnum].irq, + handler, 0, + dd->cspec->msix_entries[msixnum].name, + arg); if (ret) { /* * Shouldn't happen since the enable said we could @@ -3512,7 +3523,7 @@ try_intx: qib_dev_err(dd, "Couldn't setup MSIx interrupt (vec=%d, irq=%d): %d\n", msixnum, - dd->cspec->msix_entries[msixnum].msix.vector, + dd->cspec->msix_entries[msixnum].irq, ret); qib_7322_nomsix(dd); goto try_intx; @@ -3548,7 +3559,7 @@ try_intx: dd->cspec->msix_entries[msixnum].mask); } irq_set_affinity_hint( - dd->cspec->msix_entries[msixnum].msix.vector, + dd->cspec->msix_entries[msixnum].irq, dd->cspec->msix_entries[msixnum].mask); } msixnum++; @@ -3744,7 +3755,6 @@ static int qib_do_7322_reset(struct qib_devdata *dd) if (msix_entries) { /* restore the MSIx vector address and data if saved above */ for (i = 0; i < msix_entries; i++) { - dd->cspec->msix_entries[i].msix.entry = i; if (!msix_vecsave || !msix_vecsave[2 * i]) continue; qib_write_kreg(dd, 2 * i + @@ -3762,8 +3772,7 @@ static int qib_do_7322_reset(struct qib_devdata *dd) write_7322_initregs(dd); if (qib_pcie_params(dd, dd->lbus_width, - &dd->cspec->num_msix_entries, - dd->cspec->msix_entries)) + &dd->cspec->num_msix_entries)) qib_dev_err(dd, "Reset failed to setup PCIe or interrupts; continuing anyway\n"); @@ -5195,7 +5204,7 @@ static int qib_7322_intr_fallback(struct qib_devdata *dd) qib_devinfo(dd->pcidev, "MSIx interrupt not detected, trying INTx interrupts\n"); qib_7322_nomsix(dd); - qib_enable_intx(dd->pcidev); + qib_enable_intx(dd); qib_setup_7322_interrupt(dd, 0); return 1; } @@ -7327,10 +7336,7 @@ struct qib_devdata *qib_init_iba7322_funcs(struct pci_dev *pdev, if (!dd->cspec->msix_entries) tabsize = 0; - for (i = 0; i < tabsize; i++) - dd->cspec->msix_entries[i].msix.entry = i; - - if (qib_pcie_params(dd, 8, &tabsize, dd->cspec->msix_entries)) + if (qib_pcie_params(dd, 8, &tabsize)) qib_dev_err(dd, "Failed to setup PCIe or interrupts; continuing anyway\n"); /* may be less than we wanted, if not enough available */ diff --git a/drivers/infiniband/hw/qib/qib_pcie.c b/drivers/infiniband/hw/qib/qib_pcie.c index c379b8342a09..d90403e31a9d 100644 --- a/drivers/infiniband/hw/qib/qib_pcie.c +++ b/drivers/infiniband/hw/qib/qib_pcie.c @@ -1,4 +1,5 @@ /* + * Copyright (c) 2010 - 2017 Intel Corporation. All rights reserved. * Copyright (c) 2008, 2009 QLogic Corporation. All rights reserved. * * This software is available to you under a choice of one of two @@ -187,112 +188,84 @@ void qib_pcie_ddcleanup(struct qib_devdata *dd) pci_set_drvdata(dd->pcidev, NULL); } -static void qib_msix_setup(struct qib_devdata *dd, int pos, u32 *msixcnt, - struct qib_msix_entry *qib_msix_entry) -{ - int ret; - int nvec = *msixcnt; - struct msix_entry *msix_entry; - int i; - - ret = pci_msix_vec_count(dd->pcidev); - if (ret < 0) - goto do_intx; - - nvec = min(nvec, ret); - - /* We can't pass qib_msix_entry array to qib_msix_setup - * so use a dummy msix_entry array and copy the allocated - * irq back to the qib_msix_entry array. */ - msix_entry = kcalloc(nvec, sizeof(*msix_entry), GFP_KERNEL); - if (!msix_entry) - goto do_intx; - - for (i = 0; i < nvec; i++) - msix_entry[i] = qib_msix_entry[i].msix; - - ret = pci_enable_msix_range(dd->pcidev, msix_entry, 1, nvec); - if (ret < 0) - goto free_msix_entry; - else - nvec = ret; - - for (i = 0; i < nvec; i++) - qib_msix_entry[i].msix = msix_entry[i]; - - kfree(msix_entry); - *msixcnt = nvec; - return; - -free_msix_entry: - kfree(msix_entry); - -do_intx: - qib_dev_err( - dd, - "pci_enable_msix_range %d vectors failed: %d, falling back to INTx\n", - nvec, ret); - *msixcnt = 0; - qib_enable_intx(dd->pcidev); -} - /** * We save the msi lo and hi values, so we can restore them after * chip reset (the kernel PCI infrastructure doesn't yet handle that * correctly. */ -static int qib_msi_setup(struct qib_devdata *dd, int pos) +static void qib_msi_setup(struct qib_devdata *dd, int pos) { struct pci_dev *pdev = dd->pcidev; u16 control; - int ret; - ret = pci_enable_msi(pdev); - if (ret) - qib_dev_err(dd, - "pci_enable_msi failed: %d, interrupts may not work\n", - ret); - /* continue even if it fails, we may still be OK... */ - - pci_read_config_dword(pdev, pos + PCI_MSI_ADDRESS_LO, - &dd->msi_lo); - pci_read_config_dword(pdev, pos + PCI_MSI_ADDRESS_HI, - &dd->msi_hi); + pci_read_config_dword(pdev, pos + PCI_MSI_ADDRESS_LO, &dd->msi_lo); + pci_read_config_dword(pdev, pos + PCI_MSI_ADDRESS_HI, &dd->msi_hi); pci_read_config_word(pdev, pos + PCI_MSI_FLAGS, &control); + /* now save the data (vector) info */ - pci_read_config_word(pdev, pos + ((control & PCI_MSI_FLAGS_64BIT) - ? 12 : 8), + pci_read_config_word(pdev, + pos + ((control & PCI_MSI_FLAGS_64BIT) ? 12 : 8), &dd->msi_data); - return ret; } -int qib_pcie_params(struct qib_devdata *dd, u32 minw, u32 *nent, - struct qib_msix_entry *entry) +static int qib_allocate_irqs(struct qib_devdata *dd, u32 maxvec) +{ + unsigned int flags = PCI_IRQ_LEGACY; + + /* Check our capabilities */ + if (dd->pcidev->msix_cap) { + flags |= PCI_IRQ_MSIX; + } else { + if (dd->pcidev->msi_cap) { + flags |= PCI_IRQ_MSI; + /* Get msi_lo and msi_hi */ + qib_msi_setup(dd, dd->pcidev->msi_cap); + } + } + + if (!(flags & (PCI_IRQ_MSIX | PCI_IRQ_MSI))) + qib_dev_err(dd, "No PCI MSI or MSIx capability!\n"); + + return pci_alloc_irq_vectors(dd->pcidev, 1, maxvec, flags); +} + +int qib_pcie_params(struct qib_devdata *dd, u32 minw, u32 *nent) { u16 linkstat, speed; - int pos = 0, ret = 1; + int nvec; + int maxvec; + int ret = 0; if (!pci_is_pcie(dd->pcidev)) { qib_dev_err(dd, "Can't find PCI Express capability!\n"); /* set up something... */ dd->lbus_width = 1; dd->lbus_speed = 2500; /* Gen1, 2.5GHz */ + ret = -1; goto bail; } - pos = dd->pcidev->msix_cap; - if (nent && *nent && pos) { - qib_msix_setup(dd, pos, nent, entry); - ret = 0; /* did it, either MSIx or INTx */ - } else { - pos = dd->pcidev->msi_cap; - if (pos) - ret = qib_msi_setup(dd, pos); - else - qib_dev_err(dd, "No PCI MSI or MSIx capability!\n"); + maxvec = (nent && *nent) ? *nent : 1; + nvec = qib_allocate_irqs(dd, maxvec); + if (nvec < 0) { + ret = nvec; + goto bail; + } + + /* + * If nent exists, make sure to record how many vectors were allocated + */ + if (nent) { + *nent = nvec; + + /* + * If we requested (nent) MSIX, but msix_enabled is not set, + * pci_alloc_irq_vectors() enabled INTx. + */ + if (!dd->pcidev->msix_enabled) + qib_dev_err(dd, + "no msix vectors allocated, using INTx\n"); } - if (!pos) - qib_enable_intx(dd->pcidev); pcie_capability_read_word(dd->pcidev, PCI_EXP_LNKSTA, &linkstat); /* @@ -379,7 +352,7 @@ int qib_reinit_intr(struct qib_devdata *dd) ret = 1; bail: if (!ret && (dd->flags & QIB_HAS_INTX)) { - qib_enable_intx(dd->pcidev); + qib_enable_intx(dd); ret = 1; } @@ -397,7 +370,7 @@ bail: void qib_nomsi(struct qib_devdata *dd) { dd->msi_lo = 0; - pci_disable_msi(dd->pcidev); + pci_free_irq_vectors(dd->pcidev); } /* @@ -405,23 +378,21 @@ void qib_nomsi(struct qib_devdata *dd) */ void qib_nomsix(struct qib_devdata *dd) { - pci_disable_msix(dd->pcidev); + pci_free_irq_vectors(dd->pcidev); } /* * Similar to pci_intx(pdev, 1), except that we make sure * msi(x) is off. */ -void qib_enable_intx(struct pci_dev *pdev) +void qib_enable_intx(struct qib_devdata *dd) { u16 cw, new; int pos; + struct pci_dev *pdev = dd->pcidev; - /* first, turn on INTx */ - pci_read_config_word(pdev, PCI_COMMAND, &cw); - new = cw & ~PCI_COMMAND_INTX_DISABLE; - if (new != cw) - pci_write_config_word(pdev, PCI_COMMAND, new); + if (pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_LEGACY) < 0) + qib_dev_err(dd, "Failed to enable INTx\n"); pos = pdev->msi_cap; if (pos) { -- cgit v1.2.3 From fe4e74eeb24286c730672e776ac4c2c3caa19137 Mon Sep 17 00:00:00 2001 From: "Michael J. Ruhl" Date: Fri, 9 Jun 2017 16:00:12 -0700 Subject: IB/hfi1: Initialize TID lists to avoid crash on cleanup The expected receive lists (tid_xxx_list) are not initialized until late in the receive context initialization. If an error happens before the initialization, a NULL pointer access will occur during cleanup. Initialized the lists sooner rather than later to avoid this Oops: IP: unlock_exp_tids.isra.11+0x26/0xd0 [hfi1] RIP: 0010:unlock_exp_tids.isra.11+0x26/0xd0 [hfi1] Call Trace: hfi1_user_exp_rcv_free+0x79/0xb0 [hfi1] hfi1_file_close+0x87/0x360 [hfi1] __fput+0xe7/0x210 ____fput+0xe/0x10 Reviewed-by: Mike Marciniszyn Reviewed-by: Sebastian Sanchez Signed-off-by: Michael J. Ruhl Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/exp_rcv.c | 4 ---- drivers/infiniband/hw/hfi1/init.c | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/hfi1/exp_rcv.c b/drivers/infiniband/hw/hfi1/exp_rcv.c index 08d13ed1b574..0af91675acc6 100644 --- a/drivers/infiniband/hw/hfi1/exp_rcv.c +++ b/drivers/infiniband/hw/hfi1/exp_rcv.c @@ -69,10 +69,6 @@ int hfi1_alloc_ctxt_rcv_groups(struct hfi1_ctxtdata *rcd) struct tid_group *grp; int i; - hfi1_exp_tid_group_init(&rcd->tid_group_list); - hfi1_exp_tid_group_init(&rcd->tid_used_list); - hfi1_exp_tid_group_init(&rcd->tid_full_list); - tidbase = rcd->expected_base; for (i = 0; i < rcd->expected_count / dd->rcv_entries.group_size; i++) { diff --git a/drivers/infiniband/hw/hfi1/init.c b/drivers/infiniband/hw/hfi1/init.c index 4a11d4da4c92..a00308ccf016 100644 --- a/drivers/infiniband/hw/hfi1/init.c +++ b/drivers/infiniband/hw/hfi1/init.c @@ -67,6 +67,7 @@ #include "aspm.h" #include "affinity.h" #include "vnic.h" +#include "exp_rcv.h" #undef pr_fmt #define pr_fmt(fmt) DRIVER_NAME ": " fmt @@ -221,6 +222,9 @@ struct hfi1_ctxtdata *hfi1_create_ctxtdata(struct hfi1_pportdata *ppd, u32 ctxt, hfi1_cdbg(PROC, "setting up context %u\n", ctxt); INIT_LIST_HEAD(&rcd->qp_wait_list); + hfi1_exp_tid_group_init(&rcd->tid_group_list); + hfi1_exp_tid_group_init(&rcd->tid_used_list); + hfi1_exp_tid_group_init(&rcd->tid_full_list); rcd->ppd = ppd; rcd->dd = dd; __set_bit(0, rcd->in_use_ctxts); -- cgit v1.2.3 From f683c80ca68e087b55c6f9ab6ca6beb88ebc6d69 Mon Sep 17 00:00:00 2001 From: "Michael J. Ruhl" Date: Fri, 9 Jun 2017 16:00:19 -0700 Subject: IB/hfi1: Resolve kernel panics by reference counting receive contexts Base receive contexts can be used by sub contexts. Because of this, resources for the context cannot be completely freed until all sub contexts are done using the base context. Introduce a reference count so that the base receive context can be freed only when all sub contexts are done with it. Use the provided function call for setting default send context integrity rather than the manual method. The cleanup path does not set all variables back to NULL after freeing resources. Since the clean up code can get called more than once, (e.g. during context close and on the error path), it is necessary to make sure that all the variables are NULLed. Possible crash are: BUG: unable to handle kernel paging request at 0000000001908900 IP: read_csr+0x24/0x30 [hfi1] RIP: 0010:read_csr+0x24/0x30 [hfi1] Call Trace: sc_disable+0x40/0x110 [hfi1] hfi1_file_close+0x16f/0x360 [hfi1] __fput+0xe7/0x210 ____fput+0xe/0x10 or kernel BUG at mm/slub.c:3877! RIP: 0010:kfree+0x14f/0x170 Call Trace: hfi1_free_ctxtdata+0x19a/0x2b0 [hfi1] ? hfi1_user_exp_rcv_grp_free+0x73/0x80 [hfi1] hfi1_file_close+0x20f/0x360 [hfi1] __fput+0xe7/0x210 ____fput+0xe/0x10 Fixes: Commit 62239fc6e554 ("IB/hfi1: Clean up on context initialization failure") Reviewed-by: Mike Marciniszyn Reviewed-by: Sebastian Sanchez Signed-off-by: Michael J. Ruhl Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/file_ops.c | 39 +++++++++++++++-------- drivers/infiniband/hw/hfi1/hfi.h | 11 +++---- drivers/infiniband/hw/hfi1/init.c | 58 ++++++++++++++++++++++++++++------ drivers/infiniband/hw/hfi1/vnic_main.c | 11 ++++--- 4 files changed, 85 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/hfi1/file_ops.c b/drivers/infiniband/hw/hfi1/file_ops.c index 2dd8758f0644..bbf80b1dd9d9 100644 --- a/drivers/infiniband/hw/hfi1/file_ops.c +++ b/drivers/infiniband/hw/hfi1/file_ops.c @@ -774,6 +774,8 @@ static int hfi1_file_close(struct inode *inode, struct file *fp) *ev = 0; __clear_bit(fdata->subctxt, uctxt->in_use_ctxts); + fdata->uctxt = NULL; + hfi1_rcd_put(uctxt); /* fdata reference */ if (!bitmap_empty(uctxt->in_use_ctxts, HFI1_MAX_SHARED_CTXTS)) { mutex_unlock(&hfi1_mutex); goto done; @@ -794,16 +796,15 @@ static int hfi1_file_close(struct inode *inode, struct file *fp) /* Clear the context's J_KEY */ hfi1_clear_ctxt_jkey(dd, uctxt->ctxt); /* - * Reset context integrity checks to default. - * (writes to CSRs probably belong in chip.c) + * If a send context is allocated, reset context integrity + * checks to default and disable the send context. */ - write_kctxt_csr(dd, uctxt->sc->hw_context, SEND_CTXT_CHECK_ENABLE, - hfi1_pkt_default_send_ctxt_mask(dd, uctxt->sc->type)); - sc_disable(uctxt->sc); + if (uctxt->sc) { + set_pio_integrity(uctxt->sc); + sc_disable(uctxt->sc); + } spin_unlock_irqrestore(&dd->uctxt_lock, flags); - dd->rcd[uctxt->ctxt] = NULL; - hfi1_free_ctxt_rcv_groups(uctxt); hfi1_clear_ctxt_pkey(dd, uctxt); @@ -816,8 +817,11 @@ static int hfi1_file_close(struct inode *inode, struct file *fp) hfi1_stats.sps_ctxts--; if (++dd->freectxts == dd->num_user_contexts) aspm_enable_all(dd); + + /* _rcd_put() should be done after releasing mutex */ + dd->rcd[uctxt->ctxt] = NULL; mutex_unlock(&hfi1_mutex); - hfi1_free_ctxtdata(dd, uctxt); + hfi1_rcd_put(uctxt); /* dd reference */ done: mmdrop(fdata->mm); kobject_put(&dd->kobj); @@ -887,16 +891,17 @@ static int assign_ctxt(struct hfi1_filedata *fd, struct hfi1_user_info *uinfo) ret = wait_event_interruptible(fd->uctxt->wait, !test_bit( HFI1_CTXT_BASE_UNINIT, &fd->uctxt->event_flags)); - if (test_bit(HFI1_CTXT_BASE_FAILED, &fd->uctxt->event_flags)) { - clear_bit(fd->subctxt, fd->uctxt->in_use_ctxts); - return -ENOMEM; - } + if (test_bit(HFI1_CTXT_BASE_FAILED, &fd->uctxt->event_flags)) + ret = -ENOMEM; + /* The only thing a sub context needs is the user_xxx stuff */ if (!ret) ret = init_user_ctxt(fd); - if (ret) + if (ret) { clear_bit(fd->subctxt, fd->uctxt->in_use_ctxts); + hfi1_rcd_put(fd->uctxt); + } } else if (!ret) { ret = setup_base_ctxt(fd); if (fd->uctxt->subctxt_cnt) { @@ -961,6 +966,8 @@ static int find_sub_ctxt(struct hfi1_filedata *fd, fd->uctxt = uctxt; fd->subctxt = subctxt; + + hfi1_rcd_get(uctxt); __set_bit(fd->subctxt, uctxt->in_use_ctxts); return 1; @@ -1069,11 +1076,14 @@ static int allocate_ctxt(struct hfi1_filedata *fd, struct hfi1_devdata *dd, aspm_disable_all(dd); fd->uctxt = uctxt; + /* Count the reference for the fd */ + hfi1_rcd_get(uctxt); + return 0; ctxdata_free: dd->rcd[ctxt] = NULL; - hfi1_free_ctxtdata(dd, uctxt); + hfi1_rcd_put(uctxt); return ret; } @@ -1273,6 +1283,7 @@ static int setup_base_ctxt(struct hfi1_filedata *fd) return 0; setup_failed: + /* Call _free_ctxtdata, not _rcd_put(). We still need the context. */ hfi1_free_ctxtdata(dd, uctxt); return ret; } diff --git a/drivers/infiniband/hw/hfi1/hfi.h b/drivers/infiniband/hw/hfi1/hfi.h index bca781c3b5ac..1a33a5087734 100644 --- a/drivers/infiniband/hw/hfi1/hfi.h +++ b/drivers/infiniband/hw/hfi1/hfi.h @@ -213,11 +213,9 @@ struct hfi1_ctxtdata { /* dynamic receive available interrupt timeout */ u32 rcvavail_timeout; - /* - * number of opens (including slave sub-contexts) on this instance - * (ignoring forks, dup, etc. for now) - */ - int cnt; + /* Reference count the base context usage */ + struct kref kref; + /* Device context index */ unsigned ctxt; /* @@ -1291,7 +1289,8 @@ struct hfi1_ctxtdata *hfi1_create_ctxtdata(struct hfi1_pportdata *ppd, u32 ctxt, void hfi1_init_pportdata(struct pci_dev *pdev, struct hfi1_pportdata *ppd, struct hfi1_devdata *dd, u8 hw_pidx, u8 port); void hfi1_free_ctxtdata(struct hfi1_devdata *dd, struct hfi1_ctxtdata *rcd); - +int hfi1_rcd_put(struct hfi1_ctxtdata *rcd); +void hfi1_rcd_get(struct hfi1_ctxtdata *rcd); int handle_receive_interrupt(struct hfi1_ctxtdata *rcd, int thread); int handle_receive_interrupt_nodma_rtail(struct hfi1_ctxtdata *rcd, int thread); int handle_receive_interrupt_dma_rtail(struct hfi1_ctxtdata *rcd, int thread); diff --git a/drivers/infiniband/hw/hfi1/init.c b/drivers/infiniband/hw/hfi1/init.c index a00308ccf016..dfdb4126ca05 100644 --- a/drivers/infiniband/hw/hfi1/init.c +++ b/drivers/infiniband/hw/hfi1/init.c @@ -191,15 +191,45 @@ int hfi1_create_ctxts(struct hfi1_devdata *dd) nomem: ret = -ENOMEM; - if (dd->rcd) { - for (i = 0; i < dd->num_rcv_contexts; ++i) - hfi1_free_ctxtdata(dd, dd->rcd[i]); - } + for (i = 0; dd->rcd && i < dd->first_dyn_alloc_ctxt; ++i) + hfi1_rcd_put(dd->rcd[i]); + + /* All the contexts should be freed, free the array */ kfree(dd->rcd); dd->rcd = NULL; return ret; } +/* + * Helper routines for the receive context reference count (rcd and uctxt) + */ +static void hfi1_rcd_init(struct hfi1_ctxtdata *rcd) +{ + kref_init(&rcd->kref); +} + +static void hfi1_rcd_free(struct kref *kref) +{ + struct hfi1_ctxtdata *rcd = + container_of(kref, struct hfi1_ctxtdata, kref); + + hfi1_free_ctxtdata(rcd->dd, rcd); + kfree(rcd); +} + +int hfi1_rcd_put(struct hfi1_ctxtdata *rcd) +{ + if (rcd) + return kref_put(&rcd->kref, hfi1_rcd_free); + + return 0; +} + +void hfi1_rcd_get(struct hfi1_ctxtdata *rcd) +{ + kref_get(&rcd->kref); +} + /* * Common code for user and kernel context setup. */ @@ -332,6 +362,8 @@ struct hfi1_ctxtdata *hfi1_create_ctxtdata(struct hfi1_pportdata *ppd, u32 ctxt, if (!rcd->opstats) goto bail; } + + hfi1_rcd_init(rcd); } return rcd; bail: @@ -931,14 +963,11 @@ static void shutdown_device(struct hfi1_devdata *dd) * @rcd: the ctxtdata structure * * free up any allocated data for a context - * This should not touch anything that would affect a simultaneous - * re-allocation of context data, because it is called after hfi1_mutex - * is released (and can be called from reinit as well). * It should never change any chip state, or global driver state. */ void hfi1_free_ctxtdata(struct hfi1_devdata *dd, struct hfi1_ctxtdata *rcd) { - unsigned e; + u32 e; if (!rcd) return; @@ -957,6 +986,7 @@ void hfi1_free_ctxtdata(struct hfi1_devdata *dd, struct hfi1_ctxtdata *rcd) /* all the RcvArray entries should have been cleared by now */ kfree(rcd->egrbufs.rcvtids); + rcd->egrbufs.rcvtids = NULL; for (e = 0; e < rcd->egrbufs.alloced; e++) { if (rcd->egrbufs.buffers[e].dma) @@ -966,13 +996,21 @@ void hfi1_free_ctxtdata(struct hfi1_devdata *dd, struct hfi1_ctxtdata *rcd) rcd->egrbufs.buffers[e].dma); } kfree(rcd->egrbufs.buffers); + rcd->egrbufs.alloced = 0; + rcd->egrbufs.buffers = NULL; sc_free(rcd->sc); + rcd->sc = NULL; + vfree(rcd->subctxt_uregbase); vfree(rcd->subctxt_rcvegrbuf); vfree(rcd->subctxt_rcvhdr_base); kfree(rcd->opstats); - kfree(rcd); + + rcd->subctxt_uregbase = NULL; + rcd->subctxt_rcvegrbuf = NULL; + rcd->subctxt_rcvhdr_base = NULL; + rcd->opstats = NULL; } /* @@ -1366,7 +1404,7 @@ static void cleanup_device_data(struct hfi1_devdata *dd) tmp[ctxt] = NULL; /* debugging paranoia */ if (rcd) { hfi1_clear_tids(rcd); - hfi1_free_ctxtdata(dd, rcd); + hfi1_rcd_put(rcd); } } kfree(tmp); diff --git a/drivers/infiniband/hw/hfi1/vnic_main.c b/drivers/infiniband/hw/hfi1/vnic_main.c index b601c2929f8f..950c1b4df442 100644 --- a/drivers/infiniband/hw/hfi1/vnic_main.c +++ b/drivers/infiniband/hw/hfi1/vnic_main.c @@ -156,11 +156,11 @@ static int allocate_vnic_ctxt(struct hfi1_devdata *dd, return ret; bail: /* - * hfi1_free_ctxtdata() also releases send_context - * structure if uctxt->sc is not null + * hfi1_rcd_put() will call hfi1_free_ctxtdata(), which will + * release send_context structure if uctxt->sc is not null */ dd->rcd[uctxt->ctxt] = NULL; - hfi1_free_ctxtdata(dd, uctxt); + hfi1_rcd_put(uctxt); dd_dev_dbg(dd, "vnic allocation failed. rc %d\n", ret); return ret; } @@ -208,7 +208,7 @@ static void deallocate_vnic_ctxt(struct hfi1_devdata *dd, hfi1_clear_ctxt_pkey(dd, uctxt); hfi1_stats.sps_ctxts--; - hfi1_free_ctxtdata(dd, uctxt); + hfi1_rcd_put(uctxt); } void hfi1_vnic_setup(struct hfi1_devdata *dd) @@ -751,6 +751,7 @@ static int hfi1_vnic_init(struct hfi1_vnic_vport_info *vinfo) rc = hfi1_vnic_allot_ctxt(dd, &dd->vnic.ctxt[i]); if (rc) break; + hfi1_rcd_get(dd->vnic.ctxt[i]); dd->vnic.ctxt[i]->vnic_q_idx = i; } @@ -762,6 +763,7 @@ static int hfi1_vnic_init(struct hfi1_vnic_vport_info *vinfo) */ while (i-- > dd->vnic.num_ctxt) { deallocate_vnic_ctxt(dd, dd->vnic.ctxt[i]); + hfi1_rcd_put(dd->vnic.ctxt[i]); dd->vnic.ctxt[i] = NULL; } goto alloc_fail; @@ -791,6 +793,7 @@ static void hfi1_vnic_deinit(struct hfi1_vnic_vport_info *vinfo) if (--dd->vnic.num_vports == 0) { for (i = 0; i < dd->vnic.num_ctxt; i++) { deallocate_vnic_ctxt(dd, dd->vnic.ctxt[i]); + hfi1_rcd_put(dd->vnic.ctxt[i]); dd->vnic.ctxt[i] = NULL; } hfi1_deinit_vnic_rsm(dd); -- cgit v1.2.3 From bc5214ee29220251e5507882696ded5ca183b169 Mon Sep 17 00:00:00 2001 From: Jan Sokolowski Date: Fri, 9 Jun 2017 16:00:26 -0700 Subject: IB/hfi1: Handle missing magic values in config file Driver does not check whether proper configuration file exist in EPROM, and treats empty partition as possible valid configuration, preventing fallback to default firmware. Change EPROM read function to treat missing magic number as read error. Reviewed-by: Jakub Byczkowski Signed-off-by: Jan Sokolowski Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/eprom.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/hfi1/eprom.c b/drivers/infiniband/hw/hfi1/eprom.c index 26da124c88e2..d46b17107901 100644 --- a/drivers/infiniband/hw/hfi1/eprom.c +++ b/drivers/infiniband/hw/hfi1/eprom.c @@ -250,7 +250,6 @@ static int read_partition_platform_config(struct hfi1_devdata *dd, void **data, { void *buffer; void *p; - u32 length; int ret; buffer = kmalloc(P1_SIZE, GFP_KERNEL); @@ -265,13 +264,13 @@ static int read_partition_platform_config(struct hfi1_devdata *dd, void **data, /* scan for image magic that may trail the actual data */ p = strnstr(buffer, IMAGE_TRAIL_MAGIC, P1_SIZE); - if (p) - length = p - buffer; - else - length = P1_SIZE; + if (!p) { + kfree(buffer); + return -ENOENT; + } *data = buffer; - *size = length; + *size = p - buffer; return 0; } -- cgit v1.2.3 From 330c422a8ee88d77407f65494f3bbf141a8d9453 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 20 Jun 2017 13:57:06 -0400 Subject: drm/core: Fail atomic IOCTL with no CRTC state but with signaling. Problem : While running IGT kms_atomic_transition test suite i encountered a hang in drmHandleEvent immediately following an atomic_commit. After dumping the atomic state I relized that in this case there was not even one CRTC attached to the state and only disabled planes. This probably due to a commit which hadn't changed any property which would require attaching crtc state. This means drmHandleEvent will never wake up from read since without CRTC in atomic state the event fd will not be signaled. Fix: Protect against this issue by failing atomic_commit early in drm_mode_atomic_commit where such probelm can be identified. v2: Fix typos and extra newlines. Change-Id: I3ee28ffae35fd1e8bfe553146c44da53da02e6f8 Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Acked-by: Daniel Vetter Reviewed-by: Maarten Lankhorst Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1497981426-27203-1-git-send-email-Andrey.Grodzovsky@amd.com --- drivers/gpu/drm/drm_atomic.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index c0f336d23f9c..095e87278a88 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -2039,7 +2039,7 @@ static int prepare_crtc_signaling(struct drm_device *dev, { struct drm_crtc *crtc; struct drm_crtc_state *crtc_state; - int i, ret; + int i, c = 0, ret; if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) return 0; @@ -2100,8 +2100,17 @@ static int prepare_crtc_signaling(struct drm_device *dev, crtc_state->event->base.fence = fence; } + + c++; } + /* + * Having this flag means user mode pends on event which will never + * reach due to lack of at least one CRTC for signaling + */ + if (c == 0 && (arg->flags & DRM_MODE_PAGE_FLIP_EVENT)) + return -EINVAL; + return 0; } -- cgit v1.2.3 From 9cd90018ebd5b4f484300f2a5af804317d3428a1 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 27 Jun 2017 16:25:10 +0100 Subject: drm/i915: Cancel pending execlists irq handler upon idling Due to the slight asynchronicity in handling the execlists interrupts (i.e. we defer the work to a handler that may consume more than one interrupt event), when the engine is idle we may still have an irq tasklet queued (especially when it has been deferred to a ksoftirqd). At the beginning of the tasklet, we assert that we do hold a device wakeref for the access we are about to perform. This assumes that when we idle and release the GT wakeref, all execlists work has been completed (since the elsp tracking says the hw is idle). However, there may still be a tasklet queued, so as we mark the engine idle, also cancel any pending tasklet. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20170627152510.28589-1-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/intel_engine_cs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 3b46c1f7b88b..49e875c46c96 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -1328,6 +1328,7 @@ void intel_engines_mark_idle(struct drm_i915_private *i915) for_each_engine(engine, i915, id) { intel_engine_disarm_breadcrumbs(engine); i915_gem_batch_pool_fini(&engine->batch_pool); + tasklet_kill(&engine->irq_tasklet); engine->no_priolist = false; } } -- cgit v1.2.3 From c544815a212f15dd787f0783720518178346f7d7 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 28 Jun 2017 11:11:41 +0200 Subject: drm/hdlcd: remove drm_vblank_cleanup, rise of the zoombies edition This was accidentally restored in commit de5cc8155cd250a31da67dea49aff7637ce98887 Author: Liviu Dudau Date: Tue Jun 6 15:05:21 2017 +0100 drm/arm: hdlcd: Set the CRTC's port before binding the encoder Fixes: de5cc8155cd2 ("drm/arm: hdlcd: Set the CRTC's port before binding the encoder.") Cc: Liviu Dudau Cc: Brian Starkey Cc: Mali DP Maintainers Acked-by: Liviu Dudau Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170628091141.14539-1-daniel.vetter@ffwll.ch --- drivers/gpu/drm/arm/hdlcd_drv.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c index d3da87fbd85a..90bd97bf0013 100644 --- a/drivers/gpu/drm/arm/hdlcd_drv.c +++ b/drivers/gpu/drm/arm/hdlcd_drv.c @@ -343,7 +343,6 @@ err_register: } err_fbdev: drm_kms_helper_poll_fini(drm); - drm_vblank_cleanup(drm); err_vblank: pm_runtime_disable(drm->dev); err_pm_active: @@ -375,7 +374,6 @@ static void hdlcd_drm_unbind(struct device *dev) component_unbind_all(dev, drm); of_node_put(hdlcd->crtc.port); hdlcd->crtc.port = NULL; - drm_vblank_cleanup(drm); pm_runtime_get_sync(drm->dev); drm_irq_uninstall(drm); pm_runtime_put_sync(drm->dev); -- cgit v1.2.3 From b4164d66c4a2adf7beac7cd5e3f8cc5d06723d57 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 26 Jun 2017 18:19:49 +0200 Subject: drm/vblank: Unexport drm_vblank_cleanup There's no reason for drivers to call this, and all the ones I've removed looked very fishy: - Proper quiescenting of the vblank machinery should be done by calling drm_crtc_vblank_off(), which is best done by shutting down the entire display engine with drm_atomic_helper_shutdown. - Releasing of allocated memory is done by the core already, it calls drm_vblank_cleanup as a fallback. - drm_vblank_cleanup also has checks for drivers which forget to clean up vblank interrupts. This essentially reverts commit e77cef9c2d87db835ad9d70cde4a9b00b0ca2262 Author: Jerome Glisse Date: Thu Jan 7 15:39:13 2010 +0100 drm: Avoid calling vblank function is vblank wasn't initialized which was done to fix a bug in radeon code with msi interrupts: commit 003e69f9862bcda89a75c27750efdbc17ac02945 Author: Jerome Glisse Date: Thu Jan 7 15:39:14 2010 +0100 drm/radeon/kms: Don't try to enable IRQ if we have no handler installed Afaict from digging around in old code, this was needed to avoid blowing up in the ums fallback, and has stopped serving it's purpose long ago - if irq init fails, the driver fails to load, and there's really no way to blow up anymore. Long story short, this was most likely a small ums compat/fallback hack that became a thing of it's own and got cargo-cult duplicated all over the drm codebase for essentially no gain at all. v2: Mention that for drivers with a ->release callback cleanup is handled by drm_dev_fini() (Thierry). Cc: Thierry Reding Acked-by: Thierry Reding Cc: Jerome Glisse Reviewed-by: Sean Paul Acked-by: Alex Deucher Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170626161949.25629-2-daniel.vetter@ffwll.ch --- drivers/gpu/drm/drm_internal.h | 1 + drivers/gpu/drm/drm_vblank.c | 19 ++----------------- include/drm/drm_vblank.h | 1 - 3 files changed, 3 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index f89371e920e6..068b685608cf 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h @@ -57,6 +57,7 @@ int drm_gem_name_info(struct seq_file *m, void *data); /* drm_vblank.c */ extern unsigned int drm_timestamp_monotonic; void drm_vblank_disable_and_save(struct drm_device *dev, unsigned int pipe); +void drm_vblank_cleanup(struct drm_device *dev); /* IOCTLS */ int drm_wait_vblank_ioctl(struct drm_device *dev, void *data, diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index 7e3f59182571..05d043e9219f 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -394,19 +394,6 @@ static void vblank_disable_fn(unsigned long arg) spin_unlock_irqrestore(&dev->vbl_lock, irqflags); } -/** - * drm_vblank_cleanup - cleanup vblank support - * @dev: DRM device - * - * This function cleans up any resources allocated in drm_vblank_init(). It is - * called by the DRM core when @dev is finalized. - * - * Drivers can call drm_vblank_cleanup() if they need to quiescent the vblank - * interrupt in their unload code. But in general this should be handled by - * disabling all active &drm_crtc through e.g. drm_atomic_helper_shutdown, which - * should end up calling drm_crtc_vblank_off(). - * - */ void drm_vblank_cleanup(struct drm_device *dev) { unsigned int pipe; @@ -428,7 +415,6 @@ void drm_vblank_cleanup(struct drm_device *dev) dev->num_crtcs = 0; } -EXPORT_SYMBOL(drm_vblank_cleanup); /** * drm_vblank_init - initialize vblank support @@ -436,9 +422,8 @@ EXPORT_SYMBOL(drm_vblank_cleanup); * @num_crtcs: number of CRTCs supported by @dev * * This function initializes vblank support for @num_crtcs display pipelines. - * Drivers do not need to call drm_vblank_cleanup(), cleanup is already handled - * by the DRM core, or through calling drm_dev_fini() for drivers with a - * &drm_driver.release callback. + * Cleanup is handled by the DRM core, or through calling drm_dev_fini() for + * drivers with a &drm_driver.release callback. * * Returns: * Zero on success or a negative error code on failure. diff --git a/include/drm/drm_vblank.h b/include/drm/drm_vblank.h index 4ceef128582f..7fba9efe4951 100644 --- a/include/drm/drm_vblank.h +++ b/include/drm/drm_vblank.h @@ -168,7 +168,6 @@ void drm_crtc_wait_one_vblank(struct drm_crtc *crtc); void drm_crtc_vblank_off(struct drm_crtc *crtc); void drm_crtc_vblank_reset(struct drm_crtc *crtc); void drm_crtc_vblank_on(struct drm_crtc *crtc); -void drm_vblank_cleanup(struct drm_device *dev); u32 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc); bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, -- cgit v1.2.3 From f3f63e6b5683ffb83eebc40f9768356a7beab6dc Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 28 Jun 2017 00:16:14 +0300 Subject: drm: arcpgu: Remove CRTC .commit() helper operation The CRTC helper .commit() operation is legacy code, the atomic helpers prefer the .enable() operation. As the arcpgu driver implements the .enable() operation, .commit() is never used and can be removed. Signed-off-by: Laurent Pinchart Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170627211621.27767-1-laurent.pinchart+renesas@ideasonboard.com --- drivers/gpu/drm/arc/arcpgu_crtc.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c index 611af74a31c0..51745608e09d 100644 --- a/drivers/gpu/drm/arc/arcpgu_crtc.c +++ b/drivers/gpu/drm/arc/arcpgu_crtc.c @@ -164,7 +164,6 @@ static const struct drm_crtc_helper_funcs arc_pgu_crtc_helper_funcs = { .enable = arc_pgu_crtc_enable, .disable = arc_pgu_crtc_disable, .prepare = arc_pgu_crtc_disable, - .commit = arc_pgu_crtc_enable, .atomic_begin = arc_pgu_crtc_atomic_begin, }; -- cgit v1.2.3 From b35954722c5e753d3e7170d71b0058c9fd2620e3 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 28 Jun 2017 00:16:15 +0300 Subject: drm: arcpgu: Remove CRTC .prepare() helper operation The CRTC helper .prepare() operation is legacy code, the atomic helpers prefer the .disable() operation. As the arcpgu driver implements the .disable() and .prepare() operations identicallly, .prepare() can be removed. Signed-off-by: Laurent Pinchart Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170627211621.27767-2-laurent.pinchart+renesas@ideasonboard.com --- drivers/gpu/drm/arc/arcpgu_crtc.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c index 51745608e09d..1f306781c9d5 100644 --- a/drivers/gpu/drm/arc/arcpgu_crtc.c +++ b/drivers/gpu/drm/arc/arcpgu_crtc.c @@ -163,7 +163,6 @@ static const struct drm_crtc_helper_funcs arc_pgu_crtc_helper_funcs = { .mode_set_nofb = arc_pgu_crtc_mode_set_nofb, .enable = arc_pgu_crtc_enable, .disable = arc_pgu_crtc_disable, - .prepare = arc_pgu_crtc_disable, .atomic_begin = arc_pgu_crtc_atomic_begin, }; -- cgit v1.2.3 From 4889b35d7fa1d211ff8246fae514800e07fb0099 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 28 Jun 2017 00:16:16 +0300 Subject: drm: qxl: Remove unused CRTC .dpms() helper operation The CRTC .dpms() helper operation is called by the atomic helpers only when no .prepare(), .atomic_disable() or .disable() operation is provided. As the qxl driver provides a .disable() operation, the .dpms() operation is unused and can be removed. Signed-off-by: Laurent Pinchart Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170627211621.27767-3-laurent.pinchart+renesas@ideasonboard.com --- drivers/gpu/drm/qxl/qxl_display.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 72dcaab84bba..19ba336ce096 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -378,10 +378,6 @@ qxl_framebuffer_init(struct drm_device *dev, return 0; } -static void qxl_crtc_dpms(struct drm_crtc *crtc, int mode) -{ -} - static bool qxl_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) @@ -467,7 +463,6 @@ static void qxl_crtc_disable(struct drm_crtc *crtc) } static const struct drm_crtc_helper_funcs qxl_crtc_helper_funcs = { - .dpms = qxl_crtc_dpms, .disable = qxl_crtc_disable, .mode_fixup = qxl_crtc_mode_fixup, .mode_set_nofb = qxl_mode_set_nofb, -- cgit v1.2.3 From 641164f23614ec3bcd551323e61a6e2707898d34 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 28 Jun 2017 00:16:17 +0300 Subject: drm: qxl: Replace CRTC .commit() helper operation with .enable() The CRTC helper .commit() operation is legacy code, the atomic helpers prefer the .enable() operation. Replace the .commit() helper operation with .enable() in the driver. Signed-off-by: Laurent Pinchart Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170627211621.27767-4-laurent.pinchart+renesas@ideasonboard.com --- drivers/gpu/drm/qxl/qxl_display.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 19ba336ce096..7ede5f131a5c 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -447,7 +447,7 @@ static void qxl_mode_set_nofb(struct drm_crtc *crtc) } -static void qxl_crtc_commit(struct drm_crtc *crtc) +static void qxl_crtc_enable(struct drm_crtc *crtc) { DRM_DEBUG("\n"); } @@ -466,7 +466,7 @@ static const struct drm_crtc_helper_funcs qxl_crtc_helper_funcs = { .disable = qxl_crtc_disable, .mode_fixup = qxl_crtc_mode_fixup, .mode_set_nofb = qxl_mode_set_nofb, - .commit = qxl_crtc_commit, + .enable = qxl_crtc_enable, .atomic_flush = qxl_crtc_atomic_flush, }; -- cgit v1.2.3 From 4e004f644bc40b3d51653e91cc58af7c6b102f56 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 28 Jun 2017 00:16:18 +0300 Subject: drm: vmwgfx: Remove unneeded CRTC .prepare() helper operation The CRTC .prepare() helper operation is part of the legacy helpers and is deprecated in favour of the .disable() helper operation. As the vmwgfx driver provides a .disable() helper operation, and as the .prepare() helper operation implementation is empty, we can remove it. Signed-off-by: Laurent Pinchart Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170627211621.27767-5-laurent.pinchart+renesas@ideasonboard.com --- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 449ed4fba0f2..639e16703b80 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -202,18 +202,6 @@ static void vmw_ldu_crtc_mode_set_nofb(struct drm_crtc *crtc) { } -/** - * vmw_ldu_crtc_helper_prepare - Noop - * - * @crtc: CRTC associated with the new screen - * - * Prepares the CRTC for a mode set, but we don't need to do anything here. - * - */ -static void vmw_ldu_crtc_helper_prepare(struct drm_crtc *crtc) -{ -} - /** * vmw_ldu_crtc_helper_commit - Noop * @@ -388,7 +376,6 @@ drm_plane_helper_funcs vmw_ldu_primary_plane_helper_funcs = { }; static const struct drm_crtc_helper_funcs vmw_ldu_crtc_helper_funcs = { - .prepare = vmw_ldu_crtc_helper_prepare, .commit = vmw_ldu_crtc_helper_commit, .disable = vmw_ldu_crtc_helper_disable, .mode_set_nofb = vmw_ldu_crtc_mode_set_nofb, -- cgit v1.2.3 From 4177b51e1949468c74a54dde99c775f5746fa11e Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 28 Jun 2017 00:16:19 +0300 Subject: drm: vmwgfx: Replace CRTC .commit() helper operation with .enable() The CRTC helper .commit() operation is legacy code, the atomic helpers prefer the .enable() operation. Replace the .commit() helper operation with .enable() in the driver. Signed-off-by: Laurent Pinchart Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170627211621.27767-6-laurent.pinchart+renesas@ideasonboard.com --- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 6 +++--- drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 6 +++--- drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 639e16703b80..f8acd3a15523 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -203,7 +203,7 @@ static void vmw_ldu_crtc_mode_set_nofb(struct drm_crtc *crtc) } /** - * vmw_ldu_crtc_helper_commit - Noop + * vmw_ldu_crtc_helper_enable - Noop * * @crtc: CRTC associated with the new screen * @@ -212,7 +212,7 @@ static void vmw_ldu_crtc_mode_set_nofb(struct drm_crtc *crtc) * but since for LDU the display plane is closely tied to the * CRTC, it makes more sense to do those at plane update time. */ -static void vmw_ldu_crtc_helper_commit(struct drm_crtc *crtc) +static void vmw_ldu_crtc_helper_enable(struct drm_crtc *crtc) { } @@ -376,7 +376,7 @@ drm_plane_helper_funcs vmw_ldu_primary_plane_helper_funcs = { }; static const struct drm_crtc_helper_funcs vmw_ldu_crtc_helper_funcs = { - .commit = vmw_ldu_crtc_helper_commit, + .enable = vmw_ldu_crtc_helper_enable, .disable = vmw_ldu_crtc_helper_disable, .mode_set_nofb = vmw_ldu_crtc_mode_set_nofb, .atomic_check = vmw_du_crtc_atomic_check, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index 3b917c9b0c21..1cb826c503bf 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c @@ -270,13 +270,13 @@ static void vmw_sou_crtc_helper_prepare(struct drm_crtc *crtc) } /** - * vmw_sou_crtc_helper_commit - Noop + * vmw_sou_crtc_helper_enable - Noop * * @crtc: CRTC associated with the new screen * * This is called after a mode set has been completed. */ -static void vmw_sou_crtc_helper_commit(struct drm_crtc *crtc) +static void vmw_sou_crtc_helper_enable(struct drm_crtc *crtc) { } @@ -573,7 +573,7 @@ drm_plane_helper_funcs vmw_sou_primary_plane_helper_funcs = { static const struct drm_crtc_helper_funcs vmw_sou_crtc_helper_funcs = { .prepare = vmw_sou_crtc_helper_prepare, - .commit = vmw_sou_crtc_helper_commit, + .enable = vmw_sou_crtc_helper_enable, .disable = vmw_sou_crtc_helper_disable, .mode_set_nofb = vmw_sou_crtc_mode_set_nofb, .atomic_check = vmw_du_crtc_atomic_check, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c index 6aecba6cd5e2..4eb93b47d6db 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c @@ -412,7 +412,7 @@ static void vmw_stdu_crtc_helper_prepare(struct drm_crtc *crtc) } -static void vmw_stdu_crtc_helper_commit(struct drm_crtc *crtc) +static void vmw_stdu_crtc_helper_enable(struct drm_crtc *crtc) { struct vmw_private *dev_priv; struct vmw_screen_target_display_unit *stdu; @@ -1415,7 +1415,7 @@ drm_plane_helper_funcs vmw_stdu_primary_plane_helper_funcs = { static const struct drm_crtc_helper_funcs vmw_stdu_crtc_helper_funcs = { .prepare = vmw_stdu_crtc_helper_prepare, - .commit = vmw_stdu_crtc_helper_commit, + .enable = vmw_stdu_crtc_helper_enable, .disable = vmw_stdu_crtc_helper_disable, .mode_set_nofb = vmw_stdu_crtc_mode_set_nofb, .atomic_check = vmw_du_crtc_atomic_check, -- cgit v1.2.3 From 13f8458f9a4522bcb7d1856dd8b329ff5d90f887 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 27 Jun 2017 18:37:31 +0100 Subject: drm/i915: Drop flushing of the object free list/worker from i915_gem_suspend i915_gem_suspend() is called from all of our finalization paths (suspend, hibernate, unload). i915_gem_drain_freed_objects() adds an arbitrary delay as it uses an rcu_barrier() to ensure that there are no more freed objects in flight, and this delay causes a large amount of variability in suspend timings. For S3 suspend, we do not need to free pages as doing so does not impact at all upon the system in its suspended state, unlike S4 hibernation where we do want the hibernation image to be as small as possible. Therefore we can forgo waiting inside i915_gem_suspend(), so long as we ensure that we do cleanup before unload (see i915_gem_load_cleanup()) and prefer to reap our objects prior to hibernation (see i915_gem_freeze()). Removing the rcu_barrier() from i915_gem_suspend() improves S3 latency by about 30ms on Skylake (ymmv). Reported-by: David Weinehall Signed-off-by: Chris Wilson Cc: David Weinehall Link: http://patchwork.freedesktop.org/patch/msgid/20170627173731.11566-1-chris@chris-wilson.co.uk Tested-by: David Weinehall Reviewed-by: David Weinehall --- drivers/gpu/drm/i915/i915_gem.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 36d838677982..f38c84e485ab 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4597,8 +4597,6 @@ int i915_gem_suspend(struct drm_i915_private *dev_priv) while (flush_delayed_work(&dev_priv->gt.idle_work)) ; - i915_gem_drain_freed_objects(dev_priv); - /* Assert that we sucessfully flushed all the work and * reset the GPU back to its idle, low power state. */ -- cgit v1.2.3 From 7b92c1bd0540b64f54d98331d67e57266f9343c4 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 28 Jun 2017 13:35:48 +0100 Subject: drm/i915: Avoid keeping waitboost active for signaling threads MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Once a client has requested a waitboost, we keep that waitboost active until all clients are no longer waiting. This is because we don't distinguish which waiter deserves the boost. However, with the advent of fence signaling, the signaler threads appear as waiters to the RPS interrupt handler. So instead of using a single boolean to track when to keep the waitboost active, use a counter of all outstanding waitboosted requests. At this point, I have removed all vestiges of the rate limiting on clients. Whilst this means that compositors should remain more fluid, it also means that boosts are more prevalent. See commit b29c19b64528 ("drm/i915: Boost RPS frequency for CPU stalls") for a longer discussion on the pros and cons of both approaches. A drawback of this implementation is that it requires constant request submission to keep the waitboost trimmed (as it is now cancelled when the request is completed). This will be fine for a busy system, but near idle the boosts may be kept for longer than desired (effectively tens of vblanks worstcase) and there is a reliance on rc6 instead. v2: Remove defunct rps.client_lock Reported-by: Michał Winiarski Signed-off-by: Chris Wilson Cc: Michał Winiarski Reviewed-by: Michał Winiarski Link: http://patchwork.freedesktop.org/patch/msgid/20170628123548.9236-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_debugfs.c | 12 +++---- drivers/gpu/drm/i915/i915_drv.h | 10 ++---- drivers/gpu/drm/i915/i915_gem.c | 25 +-------------- drivers/gpu/drm/i915/i915_gem_request.c | 7 +++- drivers/gpu/drm/i915/i915_gem_request.h | 2 ++ drivers/gpu/drm/i915/i915_irq.c | 18 ++--------- drivers/gpu/drm/i915/intel_drv.h | 5 ++- drivers/gpu/drm/i915/intel_pm.c | 57 +++++++++++++-------------------- 8 files changed, 45 insertions(+), 91 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index f7aa6cbe3a2e..580bd4f4a49e 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2327,6 +2327,8 @@ static int i915_rps_boost_info(struct seq_file *m, void *data) seq_printf(m, "GPU busy? %s [%d requests]\n", yesno(dev_priv->gt.awake), dev_priv->gt.active_requests); seq_printf(m, "CPU waiting? %d\n", count_irq_waiters(dev_priv)); + seq_printf(m, "Boosts outstanding? %d\n", + atomic_read(&dev_priv->rps.num_waiters)); seq_printf(m, "Frequency requested %d\n", intel_gpu_freq(dev_priv, dev_priv->rps.cur_freq)); seq_printf(m, " min hard:%d, soft:%d; max soft:%d, hard:%d\n", @@ -2340,22 +2342,20 @@ static int i915_rps_boost_info(struct seq_file *m, void *data) intel_gpu_freq(dev_priv, dev_priv->rps.boost_freq)); mutex_lock(&dev->filelist_mutex); - spin_lock(&dev_priv->rps.client_lock); list_for_each_entry_reverse(file, &dev->filelist, lhead) { struct drm_i915_file_private *file_priv = file->driver_priv; struct task_struct *task; rcu_read_lock(); task = pid_task(file->pid, PIDTYPE_PID); - seq_printf(m, "%s [%d]: %d boosts%s\n", + seq_printf(m, "%s [%d]: %d boosts\n", task ? task->comm : "", task ? task->pid : -1, - file_priv->rps.boosts, - list_empty(&file_priv->rps.link) ? "" : ", active"); + atomic_read(&file_priv->rps.boosts)); rcu_read_unlock(); } - seq_printf(m, "Kernel (anonymous) boosts: %d\n", dev_priv->rps.boosts); - spin_unlock(&dev_priv->rps.client_lock); + seq_printf(m, "Kernel (anonymous) boosts: %d\n", + atomic_read(&dev_priv->rps.boosts)); mutex_unlock(&dev->filelist_mutex); if (INTEL_GEN(dev_priv) >= 6 && diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 5524e6fc9476..ddb5ee8e0535 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -584,8 +584,7 @@ struct drm_i915_file_private { struct idr context_idr; struct intel_rps_client { - struct list_head link; - unsigned boosts; + atomic_t boosts; } rps; unsigned int bsd_engine; @@ -1302,13 +1301,10 @@ struct intel_gen6_power_mgmt { int last_adj; enum { LOW_POWER, BETWEEN, HIGH_POWER } power; - spinlock_t client_lock; - struct list_head clients; - bool client_boost; - bool enabled; struct delayed_work autoenable_work; - unsigned boosts; + atomic_t num_waiters; + atomic_t boosts; /* manual wa residency calculations */ struct intel_rps_ei ei; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index f38c84e485ab..1b2dfa8bdeef 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -388,7 +388,7 @@ i915_gem_object_wait_fence(struct dma_fence *fence, */ if (rps) { if (INTEL_GEN(rq->i915) >= 6) - gen6_rps_boost(rq->i915, rps, rq->emitted_jiffies); + gen6_rps_boost(rq, rps); else rps = NULL; } @@ -399,22 +399,6 @@ out: if (flags & I915_WAIT_LOCKED && i915_gem_request_completed(rq)) i915_gem_request_retire_upto(rq); - if (rps && i915_gem_request_global_seqno(rq) == intel_engine_last_submit(rq->engine)) { - /* The GPU is now idle and this client has stalled. - * Since no other client has submitted a request in the - * meantime, assume that this client is the only one - * supplying work to the GPU but is unable to keep that - * work supplied because it is waiting. Since the GPU is - * then never kept fully busy, RPS autoclocking will - * keep the clocks relatively low, causing further delays. - * Compensate by giving the synchronous client credit for - * a waitboost next time. - */ - spin_lock(&rq->i915->rps.client_lock); - list_del_init(&rps->link); - spin_unlock(&rq->i915->rps.client_lock); - } - return timeout; } @@ -5053,12 +5037,6 @@ void i915_gem_release(struct drm_device *dev, struct drm_file *file) list_for_each_entry(request, &file_priv->mm.request_list, client_link) request->file_priv = NULL; spin_unlock(&file_priv->mm.lock); - - if (!list_empty(&file_priv->rps.link)) { - spin_lock(&to_i915(dev)->rps.client_lock); - list_del(&file_priv->rps.link); - spin_unlock(&to_i915(dev)->rps.client_lock); - } } int i915_gem_open(struct drm_i915_private *i915, struct drm_file *file) @@ -5075,7 +5053,6 @@ int i915_gem_open(struct drm_i915_private *i915, struct drm_file *file) file->driver_priv = file_priv; file_priv->dev_priv = i915; file_priv->file = file; - INIT_LIST_HEAD(&file_priv->rps.link); spin_lock_init(&file_priv->mm.lock); INIT_LIST_HEAD(&file_priv->mm.request_list); diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 8c59c79cbd8b..483af8921060 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -384,7 +384,11 @@ static void i915_gem_request_retire(struct drm_i915_gem_request *request) engine->context_unpin(engine, engine->last_retired_context); engine->last_retired_context = request->ctx; - dma_fence_signal(&request->fence); + spin_lock_irq(&request->lock); + if (request->waitboost) + atomic_dec(&request->i915->rps.num_waiters); + dma_fence_signal_locked(&request->fence); + spin_unlock_irq(&request->lock); i915_priotree_fini(request->i915, &request->priotree); i915_gem_request_put(request); @@ -639,6 +643,7 @@ i915_gem_request_alloc(struct intel_engine_cs *engine, req->file_priv = NULL; req->batch = NULL; req->capture_list = NULL; + req->waitboost = false; /* * Reserve space in the ring buffer for all the commands required to diff --git a/drivers/gpu/drm/i915/i915_gem_request.h b/drivers/gpu/drm/i915/i915_gem_request.h index 7b7c84369d78..604e131470a1 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.h +++ b/drivers/gpu/drm/i915/i915_gem_request.h @@ -184,6 +184,8 @@ struct drm_i915_gem_request { /** Time at which this request was emitted, in jiffies. */ unsigned long emitted_jiffies; + bool waitboost; + /** engine->request_list entry for this request */ struct list_head link; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index e4934d5adc9e..1d33cea01a1b 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1091,18 +1091,6 @@ static u32 vlv_wa_c0_ei(struct drm_i915_private *dev_priv, u32 pm_iir) return events; } -static bool any_waiters(struct drm_i915_private *dev_priv) -{ - struct intel_engine_cs *engine; - enum intel_engine_id id; - - for_each_engine(engine, dev_priv, id) - if (intel_engine_has_waiter(engine)) - return true; - - return false; -} - static void gen6_pm_rps_work(struct work_struct *work) { struct drm_i915_private *dev_priv = @@ -1114,7 +1102,7 @@ static void gen6_pm_rps_work(struct work_struct *work) spin_lock_irq(&dev_priv->irq_lock); if (dev_priv->rps.interrupts_enabled) { pm_iir = fetch_and_zero(&dev_priv->rps.pm_iir); - client_boost = fetch_and_zero(&dev_priv->rps.client_boost); + client_boost = atomic_read(&dev_priv->rps.num_waiters); } spin_unlock_irq(&dev_priv->irq_lock); @@ -1131,7 +1119,7 @@ static void gen6_pm_rps_work(struct work_struct *work) new_delay = dev_priv->rps.cur_freq; min = dev_priv->rps.min_freq_softlimit; max = dev_priv->rps.max_freq_softlimit; - if (client_boost || any_waiters(dev_priv)) + if (client_boost) max = dev_priv->rps.max_freq; if (client_boost && new_delay < dev_priv->rps.boost_freq) { new_delay = dev_priv->rps.boost_freq; @@ -1144,7 +1132,7 @@ static void gen6_pm_rps_work(struct work_struct *work) if (new_delay >= dev_priv->rps.max_freq_softlimit) adj = 0; - } else if (client_boost || any_waiters(dev_priv)) { + } else if (client_boost) { adj = 0; } else if (pm_iir & GEN6_PM_RP_DOWN_TIMEOUT) { if (dev_priv->rps.cur_freq > dev_priv->rps.efficient_freq) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 4d3982bb596a..f73474a22b6b 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1869,9 +1869,8 @@ void intel_suspend_gt_powersave(struct drm_i915_private *dev_priv); void gen6_rps_busy(struct drm_i915_private *dev_priv); void gen6_rps_reset_ei(struct drm_i915_private *dev_priv); void gen6_rps_idle(struct drm_i915_private *dev_priv); -void gen6_rps_boost(struct drm_i915_private *dev_priv, - struct intel_rps_client *rps, - unsigned long submitted); +void gen6_rps_boost(struct drm_i915_gem_request *rq, + struct intel_rps_client *rps); void intel_queue_rps_boost_for_request(struct drm_i915_gem_request *req); void g4x_wm_get_hw_state(struct drm_device *dev); void vlv_wm_get_hw_state(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 48ea0fca1f72..c3fcadfa0ae7 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6126,47 +6126,35 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv) gen6_sanitize_rps_pm_mask(dev_priv, ~0)); } mutex_unlock(&dev_priv->rps.hw_lock); - - spin_lock(&dev_priv->rps.client_lock); - while (!list_empty(&dev_priv->rps.clients)) - list_del_init(dev_priv->rps.clients.next); - spin_unlock(&dev_priv->rps.client_lock); } -void gen6_rps_boost(struct drm_i915_private *dev_priv, - struct intel_rps_client *rps, - unsigned long submitted) +void gen6_rps_boost(struct drm_i915_gem_request *rq, + struct intel_rps_client *rps) { + struct drm_i915_private *i915 = rq->i915; + bool boost; + /* This is intentionally racy! We peek at the state here, then * validate inside the RPS worker. */ - if (!(dev_priv->gt.awake && - dev_priv->rps.enabled && - dev_priv->rps.cur_freq < dev_priv->rps.boost_freq)) + if (!i915->rps.enabled) return; - /* Force a RPS boost (and don't count it against the client) if - * the GPU is severely congested. - */ - if (rps && time_after(jiffies, submitted + DRM_I915_THROTTLE_JIFFIES)) - rps = NULL; - - spin_lock(&dev_priv->rps.client_lock); - if (rps == NULL || list_empty(&rps->link)) { - spin_lock_irq(&dev_priv->irq_lock); - if (dev_priv->rps.interrupts_enabled) { - dev_priv->rps.client_boost = true; - schedule_work(&dev_priv->rps.work); - } - spin_unlock_irq(&dev_priv->irq_lock); - - if (rps != NULL) { - list_add(&rps->link, &dev_priv->rps.clients); - rps->boosts++; - } else - dev_priv->rps.boosts++; + boost = false; + spin_lock_irq(&rq->lock); + if (!rq->waitboost && !i915_gem_request_completed(rq)) { + atomic_inc(&i915->rps.num_waiters); + rq->waitboost = true; + boost = true; } - spin_unlock(&dev_priv->rps.client_lock); + spin_unlock_irq(&rq->lock); + if (!boost) + return; + + if (READ_ONCE(i915->rps.cur_freq) < i915->rps.boost_freq) + schedule_work(&i915->rps.work); + + atomic_inc(rps ? &rps->boosts : &i915->rps.boosts); } int intel_set_rps(struct drm_i915_private *dev_priv, u8 val) @@ -9113,7 +9101,7 @@ static void __intel_rps_boost_work(struct work_struct *work) struct drm_i915_gem_request *req = boost->req; if (!i915_gem_request_completed(req)) - gen6_rps_boost(req->i915, NULL, req->emitted_jiffies); + gen6_rps_boost(req, NULL); i915_gem_request_put(req); kfree(boost); @@ -9142,11 +9130,10 @@ void intel_queue_rps_boost_for_request(struct drm_i915_gem_request *req) void intel_pm_setup(struct drm_i915_private *dev_priv) { mutex_init(&dev_priv->rps.hw_lock); - spin_lock_init(&dev_priv->rps.client_lock); INIT_DELAYED_WORK(&dev_priv->rps.autoenable_work, __intel_autoenable_gt_powersave); - INIT_LIST_HEAD(&dev_priv->rps.clients); + atomic_set(&dev_priv->rps.num_waiters, 0); dev_priv->pm.suspended = false; atomic_set(&dev_priv->pm.wakeref_count, 0); -- cgit v1.2.3 From faa8b0b7534aabdc8095eb05310f04eff4024b36 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 28 Jun 2017 15:41:01 +0300 Subject: drm/gma500: remove an unneeded NULL check "connector" is the list iterator and it can't be NULL. It causes a static checker warning because we dereference the iterator to get the next item in the list. Let's remove this check. Signed-off-by: Dan Carpenter Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170628124100.3pw2gyitsfopaib5@mwanda --- drivers/gpu/drm/gma500/mdfld_intel_display.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/gma500/mdfld_intel_display.c b/drivers/gpu/drm/gma500/mdfld_intel_display.c index 63c6e08600ae..531e4450c000 100644 --- a/drivers/gpu/drm/gma500/mdfld_intel_display.c +++ b/drivers/gpu/drm/gma500/mdfld_intel_display.c @@ -737,11 +737,7 @@ static int mdfld_crtc_mode_set(struct drm_crtc *crtc, sizeof(struct drm_display_mode)); list_for_each_entry(connector, &mode_config->connector_list, head) { - if (!connector) - continue; - encoder = connector->encoder; - if (!encoder) continue; -- cgit v1.2.3 From 886015a0ad43c7fc034b23ea4614ba39162f9ddd Mon Sep 17 00:00:00 2001 From: Gabriel Krisman Bertazi Date: Wed, 28 Jun 2017 18:06:05 -0300 Subject: drm/i915: reintroduce VLV/CHV PFI programming power domain workaround MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are still cases on these platforms where an attempt is made to configure the CDCLK while the power domain is off, like when coming back from a suspend. So the workaround below is still needed. This effectively reverts commit 63ff30442519 ("drm/i915: Nuke the VLV/CHV PFI programming power domain workaround"). Cc: stable@vger.kernel.org Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=101517 Suggested-by: Ville Syrjälä Signed-off-by: Gabriel Krisman Bertazi Link: http://patchwork.freedesktop.org/patch/msgid/20170628210605.4994-1-krisman@collabora.co.uk Reviewed-by: Ville Syrjälä Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_cdclk.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c index b8914db7d2e1..1241e5891b29 100644 --- a/drivers/gpu/drm/i915/intel_cdclk.c +++ b/drivers/gpu/drm/i915/intel_cdclk.c @@ -491,6 +491,14 @@ static void vlv_set_cdclk(struct drm_i915_private *dev_priv, int cdclk = cdclk_state->cdclk; u32 val, cmd; + /* There are cases where we can end up here with power domains + * off and a CDCLK frequency other than the minimum, like when + * issuing a modeset without actually changing any display after + * a system suspend. So grab the PIPE-A domain, which covers + * the HW blocks needed for the following programming. + */ + intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A); + if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */ cmd = 2; else if (cdclk == 266667) @@ -549,6 +557,8 @@ static void vlv_set_cdclk(struct drm_i915_private *dev_priv, intel_update_cdclk(dev_priv); vlv_program_pfi_credits(dev_priv); + + intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A); } static void chv_set_cdclk(struct drm_i915_private *dev_priv, @@ -568,6 +578,14 @@ static void chv_set_cdclk(struct drm_i915_private *dev_priv, return; } + /* There are cases where we can end up here with power domains + * off and a CDCLK frequency other than the minimum, like when + * issuing a modeset without actually changing any display after + * a system suspend. So grab the PIPE-A domain, which covers + * the HW blocks needed for the following programming. + */ + intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A); + /* * Specs are full of misinformation, but testing on actual * hardware has shown that we just need to write the desired @@ -590,6 +608,8 @@ static void chv_set_cdclk(struct drm_i915_private *dev_priv, intel_update_cdclk(dev_priv); vlv_program_pfi_credits(dev_priv); + + intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A); } static int bdw_calc_cdclk(int max_pixclk) -- cgit v1.2.3 From 4d470f7359c4bf22518baa30700ad45649371a22 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 29 Jun 2017 16:04:25 +0100 Subject: drm/i915: Avoid undefined behaviour of "u32 >> 32" When computing a hash for looking up relocation target handles in an execbuf, we start with a large size for the hashtable and proceed to halve it until the allocation succeeds. The final attempt is with an order of 0 (i.e. a single element). This means that we then pass bits=0 to hash_32() which then computes "hash >> (32 - 0)" to lookup the single element. Right shifting a value by the width of the operand is undefined, so limit the smallest hash table we use to order 1. v2: Keep the retry allocation flag for the final pass Fixes: 4ff4b44cbb70 ("drm/i915: Store a direct lookup from object handle to vma") Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20170629150425.27508-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 38 +++++++++++++++++++----------- 1 file changed, 24 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index ec33b358fba9..929f275e67aa 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -288,20 +288,26 @@ static int eb_create(struct i915_execbuffer *eb) * direct lookup. */ do { + unsigned int flags; + + /* While we can still reduce the allocation size, don't + * raise a warning and allow the allocation to fail. + * On the last pass though, we want to try as hard + * as possible to perform the allocation and warn + * if it fails. + */ + flags = GFP_TEMPORARY; + if (size > 1) + flags |= __GFP_NORETRY | __GFP_NOWARN; + eb->buckets = kzalloc(sizeof(struct hlist_head) << size, - GFP_TEMPORARY | - __GFP_NORETRY | - __GFP_NOWARN); + flags); if (eb->buckets) break; } while (--size); - if (unlikely(!eb->buckets)) { - eb->buckets = kzalloc(sizeof(struct hlist_head), - GFP_TEMPORARY); - if (unlikely(!eb->buckets)) - return -ENOMEM; - } + if (unlikely(!size)) + return -ENOMEM; eb->lut_size = size; } else { @@ -452,7 +458,7 @@ eb_add_vma(struct i915_execbuffer *eb, return err; } - if (eb->lut_size >= 0) { + if (eb->lut_size > 0) { vma->exec_handle = entry->handle; hlist_add_head(&vma->exec_node, &eb->buckets[hash_32(entry->handle, @@ -895,7 +901,7 @@ static void eb_release_vmas(const struct i915_execbuffer *eb) static void eb_reset_vmas(const struct i915_execbuffer *eb) { eb_release_vmas(eb); - if (eb->lut_size >= 0) + if (eb->lut_size > 0) memset(eb->buckets, 0, sizeof(struct hlist_head) << eb->lut_size); } @@ -904,7 +910,7 @@ static void eb_destroy(const struct i915_execbuffer *eb) { GEM_BUG_ON(eb->reloc_cache.rq); - if (eb->lut_size >= 0) + if (eb->lut_size > 0) kfree(eb->buckets); } @@ -2180,8 +2186,11 @@ i915_gem_do_execbuffer(struct drm_device *dev, } } - if (eb_create(&eb)) - return -ENOMEM; + err = eb_create(&eb); + if (err) + goto err_out_fence; + + GEM_BUG_ON(!eb.lut_size); err = eb_select_context(&eb); if (unlikely(err)) @@ -2341,6 +2350,7 @@ err_rpm: i915_gem_context_put(eb.ctx); err_destroy: eb_destroy(&eb); +err_out_fence: if (out_fence_fd != -1) put_unused_fd(out_fence_fd); err_in_fence: -- cgit v1.2.3 From 98eed3d1ade53596e1c8785e049f03da4480a820 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Mon, 19 Jun 2017 14:21:47 -0700 Subject: drm/i915/cfl: Fix Workarounds. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During the review of Coffee Lake workarounds Mika pointed out that WaDisableKillLogic and GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC should be removed from CFL and with that I should carry the rv-b. However when doing the v2 I removed another Workaround that should remain because although not mentioned by spec the history of hangs around it advocates on its favor. On some follow-up patches I continued operating on the wrong workardound, but Ville noticed that, so here is the fix for the current CFL code that is upstream already. Fixes: 46c26662d2f ("drm/i915/cfl: Introduce Coffee Lake workarounds.") Cc: Ville Syrjälä Cc: Dhinakaran Pandiyan Cc: Mika Kuoppala Signed-off-by: Rodrigo Vivi Reviewed-by: Dhinakaran Pandiyan --- drivers/gpu/drm/i915/intel_engine_cs.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 49e875c46c96..a55cd72aeeff 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -809,9 +809,10 @@ static int gen9_init_workarounds(struct intel_engine_cs *engine) I915_WRITE(BDW_SCRATCH1, I915_READ(BDW_SCRATCH1) | GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE); - /* WaDisableKillLogic:bxt,skl,kbl,cfl */ - I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | - ECOCHK_DIS_TLB); + /* WaDisableKillLogic:bxt,skl,kbl */ + if (!IS_COFFEELAKE(dev_priv)) + I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | + ECOCHK_DIS_TLB); /* WaClearFlowControlGpgpuContextSave:skl,bxt,kbl,glk,cfl */ /* WaDisablePartialInstShootdown:skl,bxt,kbl,glk,cfl */ @@ -882,10 +883,9 @@ static int gen9_init_workarounds(struct intel_engine_cs *engine) WA_SET_BIT_MASKED(HDC_CHICKEN0, HDC_FORCE_NON_COHERENT); - /* WaDisableHDCInvalidation:skl,bxt,kbl */ - if (!IS_COFFEELAKE(dev_priv)) - I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | - BDW_DISABLE_HDC_INVALIDATION); + /* WaDisableHDCInvalidation:skl,bxt,kbl,cfl */ + I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | + BDW_DISABLE_HDC_INVALIDATION); /* WaDisableSamplerPowerBypassForSOPingPong:skl,bxt,kbl,cfl */ if (IS_SKYLAKE(dev_priv) || -- cgit v1.2.3 From 61894b02716f122dd7662d5d89f5b2245ca551e2 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 29 Jun 2017 13:59:25 +0100 Subject: dma-buf/sw-sync: Fix the is-signaled test to handle u32 wraparound Use the canonical __dma_fence_is_later() to compare the fence seqno against the timeline seqno to check if the fence is signaled. Signed-off-by: Chris Wilson Cc: Sumit Semwal Cc: Sean Paul Cc: Gustavo Padovan Reviewed-by: Sean Paul Signed-off-by: Gustavo Padovan Link: http://patchwork.freedesktop.org/patch/msgid/20170629125930.821-2-chris@chris-wilson.co.uk --- drivers/dma-buf/sw_sync.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c index 69c5ff36e2f9..4d5d8c5e2534 100644 --- a/drivers/dma-buf/sw_sync.c +++ b/drivers/dma-buf/sw_sync.c @@ -219,7 +219,7 @@ static bool timeline_fence_signaled(struct dma_fence *fence) { struct sync_timeline *parent = dma_fence_parent(fence); - return (fence->seqno > parent->value) ? false : true; + return !__dma_fence_is_later(fence->seqno, parent->value); } static bool timeline_fence_enable_signaling(struct dma_fence *fence) -- cgit v1.2.3 From 8f66d3aa1735bc95ae58d846a157357e8d41abb8 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 29 Jun 2017 13:59:26 +0100 Subject: dma-buf/sw-sync: Prevent user overflow on timeline advance The timeline is u32, which limits any single advance to INT_MAX so that we can detect all fences that need signaling. Signed-off-by: Chris Wilson Cc: Sumit Semwal Cc: Sean Paul Cc: Gustavo Padovan Reviewed-by: Sean Paul Signed-off-by: Gustavo Padovan Link: http://patchwork.freedesktop.org/patch/msgid/20170629125930.821-3-chris@chris-wilson.co.uk --- drivers/dma-buf/sw_sync.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c index 4d5d8c5e2534..0e676d08aa70 100644 --- a/drivers/dma-buf/sw_sync.c +++ b/drivers/dma-buf/sw_sync.c @@ -345,6 +345,11 @@ static long sw_sync_ioctl_inc(struct sync_timeline *obj, unsigned long arg) if (copy_from_user(&value, (void __user *)arg, sizeof(value))) return -EFAULT; + while (value > INT_MAX) { + sync_timeline_signal(obj, INT_MAX); + value -= INT_MAX; + } + sync_timeline_signal(obj, value); return 0; -- cgit v1.2.3 From a6aa8fca4d792c72947e341d7842d2f700534335 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 29 Jun 2017 13:59:27 +0100 Subject: dma-buf/sw-sync: Reduce irqsave/irqrestore from known context If we know the context under which we are called, then we can use the simpler form of spin_lock_irq (saving the save/restore). Signed-off-by: Chris Wilson Cc: Sumit Semwal Cc: Sean Paul Cc: Gustavo Padovan Reviewed-by: Sean Paul Signed-off-by: Gustavo Padovan Link: http://patchwork.freedesktop.org/patch/msgid/20170629125930.821-4-chris@chris-wilson.co.uk --- drivers/dma-buf/sw_sync.c | 15 +++++++++------ drivers/dma-buf/sync_debug.c | 14 ++++++-------- 2 files changed, 15 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c index 0e676d08aa70..fc733621987d 100644 --- a/drivers/dma-buf/sw_sync.c +++ b/drivers/dma-buf/sw_sync.c @@ -135,12 +135,11 @@ static void sync_timeline_put(struct sync_timeline *obj) */ static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc) { - unsigned long flags; struct sync_pt *pt, *next; trace_sync_timeline(obj); - spin_lock_irqsave(&obj->child_list_lock, flags); + spin_lock_irq(&obj->child_list_lock); obj->value += inc; @@ -150,7 +149,7 @@ static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc) list_del_init(&pt->active_list); } - spin_unlock_irqrestore(&obj->child_list_lock, flags); + spin_unlock_irq(&obj->child_list_lock); } /** @@ -167,7 +166,6 @@ static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc) static struct sync_pt *sync_pt_create(struct sync_timeline *obj, int size, unsigned int value) { - unsigned long flags; struct sync_pt *pt; if (size < sizeof(*pt)) @@ -177,13 +175,16 @@ static struct sync_pt *sync_pt_create(struct sync_timeline *obj, int size, if (!pt) return NULL; - spin_lock_irqsave(&obj->child_list_lock, flags); + spin_lock_irq(&obj->child_list_lock); + sync_timeline_get(obj); dma_fence_init(&pt->base, &timeline_fence_ops, &obj->child_list_lock, obj->context, value); list_add_tail(&pt->child_list, &obj->child_list_head); INIT_LIST_HEAD(&pt->active_list); - spin_unlock_irqrestore(&obj->child_list_lock, flags); + + spin_unlock_irq(&obj->child_list_lock); + return pt; } @@ -206,9 +207,11 @@ static void timeline_fence_release(struct dma_fence *fence) unsigned long flags; spin_lock_irqsave(fence->lock, flags); + list_del(&pt->child_list); if (!list_empty(&pt->active_list)) list_del(&pt->active_list); + spin_unlock_irqrestore(fence->lock, flags); sync_timeline_put(parent); diff --git a/drivers/dma-buf/sync_debug.c b/drivers/dma-buf/sync_debug.c index 82a6e7f6d37f..0e91632248ba 100644 --- a/drivers/dma-buf/sync_debug.c +++ b/drivers/dma-buf/sync_debug.c @@ -116,17 +116,16 @@ static void sync_print_fence(struct seq_file *s, static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj) { struct list_head *pos; - unsigned long flags; seq_printf(s, "%s: %d\n", obj->name, obj->value); - spin_lock_irqsave(&obj->child_list_lock, flags); + spin_lock_irq(&obj->child_list_lock); list_for_each(pos, &obj->child_list_head) { struct sync_pt *pt = container_of(pos, struct sync_pt, child_list); sync_print_fence(s, &pt->base, false); } - spin_unlock_irqrestore(&obj->child_list_lock, flags); + spin_unlock_irq(&obj->child_list_lock); } static void sync_print_sync_file(struct seq_file *s, @@ -151,12 +150,11 @@ static void sync_print_sync_file(struct seq_file *s, static int sync_debugfs_show(struct seq_file *s, void *unused) { - unsigned long flags; struct list_head *pos; seq_puts(s, "objs:\n--------------\n"); - spin_lock_irqsave(&sync_timeline_list_lock, flags); + spin_lock_irq(&sync_timeline_list_lock); list_for_each(pos, &sync_timeline_list_head) { struct sync_timeline *obj = container_of(pos, struct sync_timeline, @@ -165,11 +163,11 @@ static int sync_debugfs_show(struct seq_file *s, void *unused) sync_print_obj(s, obj); seq_putc(s, '\n'); } - spin_unlock_irqrestore(&sync_timeline_list_lock, flags); + spin_unlock_irq(&sync_timeline_list_lock); seq_puts(s, "fences:\n--------------\n"); - spin_lock_irqsave(&sync_file_list_lock, flags); + spin_lock_irq(&sync_file_list_lock); list_for_each(pos, &sync_file_list_head) { struct sync_file *sync_file = container_of(pos, struct sync_file, sync_file_list); @@ -177,7 +175,7 @@ static int sync_debugfs_show(struct seq_file *s, void *unused) sync_print_sync_file(s, sync_file); seq_putc(s, '\n'); } - spin_unlock_irqrestore(&sync_file_list_lock, flags); + spin_unlock_irq(&sync_file_list_lock); return 0; } -- cgit v1.2.3 From 3b52ce44e720c240afc4c4b03140d7b7811b23bd Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 29 Jun 2017 13:59:28 +0100 Subject: dma-buf/sw-sync: sync_pt is private and of fixed size Since sync_pt is only allocated from a single location and is no longer the base class for fences (that is struct dma_fence) it no longer needs a generic unsized allocator. Signed-off-by: Chris Wilson Cc: Sumit Semwal Cc: Sean Paul Cc: Gustavo Padovan Reviewed-by: Sean Paul Signed-off-by: Gustavo Padovan Link: http://patchwork.freedesktop.org/patch/msgid/20170629125930.821-5-chris@chris-wilson.co.uk --- drivers/dma-buf/sw_sync.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c index fc733621987d..6effa1ce010e 100644 --- a/drivers/dma-buf/sw_sync.c +++ b/drivers/dma-buf/sw_sync.c @@ -155,7 +155,6 @@ static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc) /** * sync_pt_create() - creates a sync pt * @parent: fence's parent sync_timeline - * @size: size to allocate for this pt * @inc: value of the fence * * Creates a new sync_pt as a child of @parent. @size bytes will be @@ -163,15 +162,12 @@ static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc) * the generic sync_timeline struct. Returns the sync_pt object or * NULL in case of error. */ -static struct sync_pt *sync_pt_create(struct sync_timeline *obj, int size, - unsigned int value) +static struct sync_pt *sync_pt_create(struct sync_timeline *obj, + unsigned int value) { struct sync_pt *pt; - if (size < sizeof(*pt)) - return NULL; - - pt = kzalloc(size, GFP_KERNEL); + pt = kzalloc(sizeof(*pt), GFP_KERNEL); if (!pt) return NULL; @@ -312,7 +308,7 @@ static long sw_sync_ioctl_create_fence(struct sync_timeline *obj, goto err; } - pt = sync_pt_create(obj, sizeof(*pt), data.value); + pt = sync_pt_create(obj, data.value); if (!pt) { err = -ENOMEM; goto err; -- cgit v1.2.3 From d3862e44daa7a0c94d2f6193502a8c49379acfce Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 29 Jun 2017 22:05:32 +0100 Subject: dma-buf/sw-sync: Fix locking around sync_timeline lists The sync_pt were not adding themselves atomically to the timeline lists, corruption imminent. Only a single list is required to track the unsignaled sync_pt, so reduce it and rename the lock more appropriately along with using idiomatic names to distinguish a list from links along it. v2: Prevent spinlock recursion on free during create (next patch) and fixup crossref in kerneldoc Signed-off-by: Chris Wilson Cc: Sumit Semwal Cc: Sean Paul Cc: Gustavo Padovan Reviewed-by: Sean Paul Signed-off-by: Gustavo Padovan Link: http://patchwork.freedesktop.org/patch/msgid/20170629210532.5617-1-chris@chris-wilson.co.uk --- drivers/dma-buf/sw_sync.c | 48 ++++++++++++++++++-------------------------- drivers/dma-buf/sync_debug.c | 9 ++++----- drivers/dma-buf/sync_debug.h | 21 ++++++++----------- 3 files changed, 31 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c index 6effa1ce010e..f20d18c421a3 100644 --- a/drivers/dma-buf/sw_sync.c +++ b/drivers/dma-buf/sw_sync.c @@ -96,9 +96,8 @@ static struct sync_timeline *sync_timeline_create(const char *name) obj->context = dma_fence_context_alloc(1); strlcpy(obj->name, name, sizeof(obj->name)); - INIT_LIST_HEAD(&obj->child_list_head); - INIT_LIST_HEAD(&obj->active_list_head); - spin_lock_init(&obj->child_list_lock); + INIT_LIST_HEAD(&obj->pt_list); + spin_lock_init(&obj->lock); sync_timeline_debug_add(obj); @@ -139,17 +138,15 @@ static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc) trace_sync_timeline(obj); - spin_lock_irq(&obj->child_list_lock); + spin_lock_irq(&obj->lock); obj->value += inc; - list_for_each_entry_safe(pt, next, &obj->active_list_head, - active_list) { + list_for_each_entry_safe(pt, next, &obj->pt_list, link) if (dma_fence_is_signaled_locked(&pt->base)) - list_del_init(&pt->active_list); - } + list_del_init(&pt->link); - spin_unlock_irq(&obj->child_list_lock); + spin_unlock_irq(&obj->lock); } /** @@ -171,15 +168,15 @@ static struct sync_pt *sync_pt_create(struct sync_timeline *obj, if (!pt) return NULL; - spin_lock_irq(&obj->child_list_lock); - sync_timeline_get(obj); - dma_fence_init(&pt->base, &timeline_fence_ops, &obj->child_list_lock, + dma_fence_init(&pt->base, &timeline_fence_ops, &obj->lock, obj->context, value); - list_add_tail(&pt->child_list, &obj->child_list_head); - INIT_LIST_HEAD(&pt->active_list); + INIT_LIST_HEAD(&pt->link); - spin_unlock_irq(&obj->child_list_lock); + spin_lock_irq(&obj->lock); + if (!dma_fence_is_signaled_locked(&pt->base)) + list_add_tail(&pt->link, &obj->pt_list); + spin_unlock_irq(&obj->lock); return pt; } @@ -200,15 +197,15 @@ static void timeline_fence_release(struct dma_fence *fence) { struct sync_pt *pt = dma_fence_to_sync_pt(fence); struct sync_timeline *parent = dma_fence_parent(fence); - unsigned long flags; - spin_lock_irqsave(fence->lock, flags); + if (!list_empty(&pt->link)) { + unsigned long flags; - list_del(&pt->child_list); - if (!list_empty(&pt->active_list)) - list_del(&pt->active_list); - - spin_unlock_irqrestore(fence->lock, flags); + spin_lock_irqsave(fence->lock, flags); + if (!list_empty(&pt->link)) + list_del(&pt->link); + spin_unlock_irqrestore(fence->lock, flags); + } sync_timeline_put(parent); dma_fence_free(fence); @@ -223,13 +220,6 @@ static bool timeline_fence_signaled(struct dma_fence *fence) static bool timeline_fence_enable_signaling(struct dma_fence *fence) { - struct sync_pt *pt = dma_fence_to_sync_pt(fence); - struct sync_timeline *parent = dma_fence_parent(fence); - - if (timeline_fence_signaled(fence)) - return false; - - list_add_tail(&pt->active_list, &parent->active_list_head); return true; } diff --git a/drivers/dma-buf/sync_debug.c b/drivers/dma-buf/sync_debug.c index 0e91632248ba..2264a075f6a9 100644 --- a/drivers/dma-buf/sync_debug.c +++ b/drivers/dma-buf/sync_debug.c @@ -119,13 +119,12 @@ static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj) seq_printf(s, "%s: %d\n", obj->name, obj->value); - spin_lock_irq(&obj->child_list_lock); - list_for_each(pos, &obj->child_list_head) { - struct sync_pt *pt = - container_of(pos, struct sync_pt, child_list); + spin_lock_irq(&obj->lock); + list_for_each(pos, &obj->pt_list) { + struct sync_pt *pt = container_of(pos, struct sync_pt, link); sync_print_fence(s, &pt->base, false); } - spin_unlock_irq(&obj->child_list_lock); + spin_unlock_irq(&obj->lock); } static void sync_print_sync_file(struct seq_file *s, diff --git a/drivers/dma-buf/sync_debug.h b/drivers/dma-buf/sync_debug.h index 26fe8b9907b3..6a2a8e69a7d0 100644 --- a/drivers/dma-buf/sync_debug.h +++ b/drivers/dma-buf/sync_debug.h @@ -24,42 +24,37 @@ * struct sync_timeline - sync object * @kref: reference count on fence. * @name: name of the sync_timeline. Useful for debugging - * @child_list_head: list of children sync_pts for this sync_timeline - * @child_list_lock: lock protecting @child_list_head and fence.status - * @active_list_head: list of active (unsignaled/errored) sync_pts + * @lock: lock protecting @pt_list and @value + * @pt_list: list of active (unsignaled/errored) sync_pts * @sync_timeline_list: membership in global sync_timeline_list */ struct sync_timeline { struct kref kref; char name[32]; - /* protected by child_list_lock */ + /* protected by lock */ u64 context; int value; - struct list_head child_list_head; - spinlock_t child_list_lock; - - struct list_head active_list_head; + struct list_head pt_list; + spinlock_t lock; struct list_head sync_timeline_list; }; static inline struct sync_timeline *dma_fence_parent(struct dma_fence *fence) { - return container_of(fence->lock, struct sync_timeline, child_list_lock); + return container_of(fence->lock, struct sync_timeline, lock); } /** * struct sync_pt - sync_pt object * @base: base fence object - * @child_list: sync timeline child's list - * @active_list: sync timeline active child's list + * @link: link on the sync timeline's list */ struct sync_pt { struct dma_fence base; - struct list_head child_list; - struct list_head active_list; + struct list_head link; }; #ifdef CONFIG_SW_SYNC -- cgit v1.2.3 From f1e8c67123cf171e2b0357e885e426328b241d7d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 29 Jun 2017 22:12:53 +0100 Subject: dma-buf/sw-sync: Use an rbtree to sort fences in the timeline Reduce the list iteration when incrementing the timeline by storing the fences in increasing order. v2: Prevent spinlock recursion on free during create v3: Fixup rebase conflict inside comments that escaped the compiler. Signed-off-by: Chris Wilson Cc: Sumit Semwal Cc: Sean Paul Cc: Gustavo Padovan Reviewed-by: Sean Paul Signed-off-by: Gustavo Padovan Link: http://patchwork.freedesktop.org/patch/msgid/20170629211253.22766-1-chris@chris-wilson.co.uk --- drivers/dma-buf/sw_sync.c | 49 ++++++++++++++++++++++++++++++++++++++------ drivers/dma-buf/sync_debug.h | 5 +++++ 2 files changed, 48 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c index f20d18c421a3..af1bc84802e5 100644 --- a/drivers/dma-buf/sw_sync.c +++ b/drivers/dma-buf/sw_sync.c @@ -96,6 +96,7 @@ static struct sync_timeline *sync_timeline_create(const char *name) obj->context = dma_fence_context_alloc(1); strlcpy(obj->name, name, sizeof(obj->name)); + obj->pt_tree = RB_ROOT; INIT_LIST_HEAD(&obj->pt_list); spin_lock_init(&obj->lock); @@ -142,9 +143,13 @@ static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc) obj->value += inc; - list_for_each_entry_safe(pt, next, &obj->pt_list, link) - if (dma_fence_is_signaled_locked(&pt->base)) - list_del_init(&pt->link); + list_for_each_entry_safe(pt, next, &obj->pt_list, link) { + if (!dma_fence_is_signaled_locked(&pt->base)) + break; + + list_del_init(&pt->link); + rb_erase(&pt->node, &obj->pt_tree); + } spin_unlock_irq(&obj->lock); } @@ -174,8 +179,38 @@ static struct sync_pt *sync_pt_create(struct sync_timeline *obj, INIT_LIST_HEAD(&pt->link); spin_lock_irq(&obj->lock); - if (!dma_fence_is_signaled_locked(&pt->base)) - list_add_tail(&pt->link, &obj->pt_list); + if (!dma_fence_is_signaled_locked(&pt->base)) { + struct rb_node **p = &obj->pt_tree.rb_node; + struct rb_node *parent = NULL; + + while (*p) { + struct sync_pt *other; + int cmp; + + parent = *p; + other = rb_entry(parent, typeof(*pt), node); + cmp = value - other->base.seqno; + if (cmp > 0) { + p = &parent->rb_right; + } else if (cmp < 0) { + p = &parent->rb_left; + } else { + if (dma_fence_get_rcu(&other->base)) { + dma_fence_put(&pt->base); + pt = other; + goto unlock; + } + p = &parent->rb_left; + } + } + rb_link_node(&pt->node, parent, p); + rb_insert_color(&pt->node, &obj->pt_tree); + + parent = rb_next(&pt->node); + list_add_tail(&pt->link, + parent ? &rb_entry(parent, typeof(*pt), node)->link : &obj->pt_list); + } +unlock: spin_unlock_irq(&obj->lock); return pt; @@ -202,8 +237,10 @@ static void timeline_fence_release(struct dma_fence *fence) unsigned long flags; spin_lock_irqsave(fence->lock, flags); - if (!list_empty(&pt->link)) + if (!list_empty(&pt->link)) { list_del(&pt->link); + rb_erase(&pt->node, &parent->pt_tree); + } spin_unlock_irqrestore(fence->lock, flags); } diff --git a/drivers/dma-buf/sync_debug.h b/drivers/dma-buf/sync_debug.h index 6a2a8e69a7d0..d615a89f774c 100644 --- a/drivers/dma-buf/sync_debug.h +++ b/drivers/dma-buf/sync_debug.h @@ -14,6 +14,7 @@ #define _LINUX_SYNC_H #include +#include #include #include @@ -25,6 +26,7 @@ * @kref: reference count on fence. * @name: name of the sync_timeline. Useful for debugging * @lock: lock protecting @pt_list and @value + * @pt_tree: rbtree of active (unsignaled/errored) sync_pts * @pt_list: list of active (unsignaled/errored) sync_pts * @sync_timeline_list: membership in global sync_timeline_list */ @@ -36,6 +38,7 @@ struct sync_timeline { u64 context; int value; + struct rb_root pt_tree; struct list_head pt_list; spinlock_t lock; @@ -51,10 +54,12 @@ static inline struct sync_timeline *dma_fence_parent(struct dma_fence *fence) * struct sync_pt - sync_pt object * @base: base fence object * @link: link on the sync timeline's list + * @node: node in the sync timeline's tree */ struct sync_pt { struct dma_fence base; struct list_head link; + struct rb_node node; }; #ifdef CONFIG_SW_SYNC -- cgit v1.2.3 From 0b20a0f8c3cb6f74fe326101b62eeb5e2c56a53c Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 30 Jun 2017 12:36:44 +0300 Subject: drm: Add old state pointer to CRTC .enable() helper function The old state is useful for drivers that need to perform operations at enable time that depend on the transition between the old and new states. While at it, rename the operation to .atomic_enable() to be consistent with .atomic_disable(), as the .enable() operation is used by atomic helpers only. Signed-off-by: Laurent Pinchart Acked-by: Maxime Ripard # for sun4i Acked-by: Philipp Zabel # for imx-drm and mediatek Acked-by: Alexey Brodkin # for arcpgu Acked-by: Boris Brezillon # for atmel-hlcdc Acked-by: Liviu Dudau # for hdlcd and mali-dp Acked-by: Stefan Agner # for fsl-dcu Tested-by: Philippe Cornu # for stm Acked-by: Philippe Cornu # for stm Acked-by: Vincent Abriou # for sti Reviewed-by: Thomas Hellstrom # for vmwgfx Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170630093646.7928-2-laurent.pinchart+renesas@ideasonboard.com --- drivers/gpu/drm/arc/arcpgu_crtc.c | 5 ++- drivers/gpu/drm/arm/hdlcd_crtc.c | 5 ++- drivers/gpu/drm/arm/malidp_crtc.c | 5 ++- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 5 ++- drivers/gpu/drm/drm_atomic_helper.c | 7 ++-- drivers/gpu/drm/drm_simple_kms_helper.c | 5 ++- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 5 ++- drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c | 5 ++- drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c | 5 ++- drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c | 5 ++- drivers/gpu/drm/imx/ipuv3-crtc.c | 5 ++- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 5 ++- drivers/gpu/drm/meson/meson_crtc.c | 5 ++- drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | 5 ++- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 5 ++- drivers/gpu/drm/omapdrm/omap_crtc.c | 5 ++- drivers/gpu/drm/qxl/qxl_display.c | 5 ++- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 5 ++- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 5 ++- drivers/gpu/drm/sti/sti_crtc.c | 5 ++- drivers/gpu/drm/stm/ltdc.c | 5 ++- drivers/gpu/drm/sun4i/sun4i_crtc.c | 5 ++- drivers/gpu/drm/tegra/dc.c | 5 ++- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 8 +++- drivers/gpu/drm/vc4/vc4_crtc.c | 5 ++- drivers/gpu/drm/virtio/virtgpu_display.c | 5 ++- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 7 ++-- drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 7 ++-- drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 5 ++- drivers/gpu/drm/zte/zx_vou.c | 5 ++- include/drm/drm_modeset_helper_vtables.h | 56 ++++++++++++++----------- 31 files changed, 128 insertions(+), 87 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c index 1f306781c9d5..c9bc6a90ac83 100644 --- a/drivers/gpu/drm/arc/arcpgu_crtc.c +++ b/drivers/gpu/drm/arc/arcpgu_crtc.c @@ -119,7 +119,8 @@ static void arc_pgu_crtc_mode_set_nofb(struct drm_crtc *crtc) clk_set_rate(arcpgu->clk, m->crtc_clock * 1000); } -static void arc_pgu_crtc_enable(struct drm_crtc *crtc) +static void arc_pgu_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc); @@ -161,9 +162,9 @@ static const struct drm_crtc_helper_funcs arc_pgu_crtc_helper_funcs = { .mode_set = drm_helper_crtc_mode_set, .mode_set_base = drm_helper_crtc_mode_set_base, .mode_set_nofb = arc_pgu_crtc_mode_set_nofb, - .enable = arc_pgu_crtc_enable, .disable = arc_pgu_crtc_disable, .atomic_begin = arc_pgu_crtc_atomic_begin, + .atomic_enable = arc_pgu_crtc_atomic_enable, }; static void arc_pgu_plane_atomic_update(struct drm_plane *plane, diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c index d67b6f15e8b8..2b7f4f05d91f 100644 --- a/drivers/gpu/drm/arm/hdlcd_crtc.c +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c @@ -165,7 +165,8 @@ static void hdlcd_crtc_mode_set_nofb(struct drm_crtc *crtc) clk_set_rate(hdlcd->clk, m->crtc_clock * 1000); } -static void hdlcd_crtc_enable(struct drm_crtc *crtc) +static void hdlcd_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc); @@ -218,10 +219,10 @@ static void hdlcd_crtc_atomic_begin(struct drm_crtc *crtc, } static const struct drm_crtc_helper_funcs hdlcd_crtc_helper_funcs = { - .enable = hdlcd_crtc_enable, .disable = hdlcd_crtc_disable, .atomic_check = hdlcd_crtc_atomic_check, .atomic_begin = hdlcd_crtc_atomic_begin, + .atomic_enable = hdlcd_crtc_atomic_enable, }; static int hdlcd_plane_atomic_check(struct drm_plane *plane, diff --git a/drivers/gpu/drm/arm/malidp_crtc.c b/drivers/gpu/drm/arm/malidp_crtc.c index 4bb38a21efec..8e5b1c0181ab 100644 --- a/drivers/gpu/drm/arm/malidp_crtc.c +++ b/drivers/gpu/drm/arm/malidp_crtc.c @@ -46,7 +46,8 @@ static enum drm_mode_status malidp_crtc_mode_valid(struct drm_crtc *crtc, return MODE_OK; } -static void malidp_crtc_enable(struct drm_crtc *crtc) +static void malidp_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct malidp_drm *malidp = crtc_to_malidp_device(crtc); struct malidp_hw_device *hwdev = malidp->dev; @@ -408,9 +409,9 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc, static const struct drm_crtc_helper_funcs malidp_crtc_helper_funcs = { .mode_valid = malidp_crtc_mode_valid, - .enable = malidp_crtc_enable, .disable = malidp_crtc_disable, .atomic_check = malidp_crtc_atomic_check, + .atomic_enable = malidp_crtc_atomic_enable, }; static struct drm_crtc_state *malidp_crtc_duplicate_state(struct drm_crtc *crtc) diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c index f6b8c5908a20..e54e503180f4 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c @@ -183,7 +183,8 @@ static void atmel_hlcdc_crtc_disable(struct drm_crtc *c) pm_runtime_put_sync(dev->dev); } -static void atmel_hlcdc_crtc_enable(struct drm_crtc *c) +static void atmel_hlcdc_crtc_atomic_enable(struct drm_crtc *c, + struct drm_crtc_state *old_state) { struct drm_device *dev = c->dev; struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); @@ -320,10 +321,10 @@ static const struct drm_crtc_helper_funcs lcdc_crtc_helper_funcs = { .mode_set_nofb = atmel_hlcdc_crtc_mode_set_nofb, .mode_set_base = drm_helper_crtc_mode_set_base, .disable = atmel_hlcdc_crtc_disable, - .enable = atmel_hlcdc_crtc_enable, .atomic_check = atmel_hlcdc_crtc_atomic_check, .atomic_begin = atmel_hlcdc_crtc_atomic_begin, .atomic_flush = atmel_hlcdc_crtc_atomic_flush, + .atomic_enable = atmel_hlcdc_crtc_atomic_enable, }; static void atmel_hlcdc_crtc_destroy(struct drm_crtc *c) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 2f269e4267da..23e4661a62fe 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1069,12 +1069,13 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev, struct drm_atomic_state *old_state) { struct drm_crtc *crtc; + struct drm_crtc_state *old_crtc_state; struct drm_crtc_state *new_crtc_state; struct drm_connector *connector; struct drm_connector_state *new_conn_state; int i; - for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) { + for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) { const struct drm_crtc_helper_funcs *funcs; /* Need to filter out CRTCs where only planes change. */ @@ -1090,8 +1091,8 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev, DRM_DEBUG_ATOMIC("enabling [CRTC:%d:%s]\n", crtc->base.id, crtc->name); - if (funcs->enable) - funcs->enable(crtc); + if (funcs->atomic_enable) + funcs->atomic_enable(crtc, old_crtc_state); else funcs->commit(crtc); } diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c index e084f9f8ca66..58c27ab1756f 100644 --- a/drivers/gpu/drm/drm_simple_kms_helper.c +++ b/drivers/gpu/drm/drm_simple_kms_helper.c @@ -40,7 +40,8 @@ static int drm_simple_kms_crtc_check(struct drm_crtc *crtc, return drm_atomic_add_affected_planes(state->state, crtc); } -static void drm_simple_kms_crtc_enable(struct drm_crtc *crtc) +static void drm_simple_kms_crtc_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct drm_simple_display_pipe *pipe; @@ -64,8 +65,8 @@ static void drm_simple_kms_crtc_disable(struct drm_crtc *crtc) static const struct drm_crtc_helper_funcs drm_simple_kms_crtc_helper_funcs = { .atomic_check = drm_simple_kms_crtc_check, + .atomic_enable = drm_simple_kms_crtc_enable, .disable = drm_simple_kms_crtc_disable, - .enable = drm_simple_kms_crtc_enable, }; static const struct drm_crtc_funcs drm_simple_kms_crtc_funcs = { diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index d72777f6411a..b7e2fadb6442 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -21,7 +21,8 @@ #include "exynos_drm_drv.h" #include "exynos_drm_plane.h" -static void exynos_drm_crtc_enable(struct drm_crtc *crtc) +static void exynos_drm_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); @@ -82,11 +83,11 @@ static void exynos_crtc_atomic_flush(struct drm_crtc *crtc, } static const struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = { - .enable = exynos_drm_crtc_enable, .disable = exynos_drm_crtc_disable, .atomic_check = exynos_crtc_atomic_check, .atomic_begin = exynos_crtc_atomic_begin, .atomic_flush = exynos_crtc_atomic_flush, + .atomic_enable = exynos_drm_crtc_atomic_enable, }; void exynos_crtc_handle_event(struct exynos_drm_crtc *exynos_crtc) diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c index cc4e944a1d3c..0e3752437e44 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c @@ -63,7 +63,8 @@ static void fsl_dcu_drm_crtc_atomic_disable(struct drm_crtc *crtc, clk_disable_unprepare(fsl_dev->pix_clk); } -static void fsl_dcu_drm_crtc_enable(struct drm_crtc *crtc) +static void fsl_dcu_drm_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct drm_device *dev = crtc->dev; struct fsl_dcu_drm_device *fsl_dev = dev->dev_private; @@ -133,7 +134,7 @@ static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc) static const struct drm_crtc_helper_funcs fsl_dcu_drm_crtc_helper_funcs = { .atomic_disable = fsl_dcu_drm_crtc_atomic_disable, .atomic_flush = fsl_dcu_drm_crtc_atomic_flush, - .enable = fsl_dcu_drm_crtc_enable, + .atomic_enable = fsl_dcu_drm_crtc_atomic_enable, .mode_set_nofb = fsl_dcu_drm_crtc_mode_set_nofb, }; diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c index 59542bddc980..49ef47c0c81a 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c @@ -192,7 +192,8 @@ static struct drm_plane *hibmc_plane_init(struct hibmc_drm_private *priv) return plane; } -static void hibmc_crtc_enable(struct drm_crtc *crtc) +static void hibmc_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { unsigned int reg; struct hibmc_drm_private *priv = crtc->dev->dev_private; @@ -453,11 +454,11 @@ static const struct drm_crtc_funcs hibmc_crtc_funcs = { }; static const struct drm_crtc_helper_funcs hibmc_crtc_helper_funcs = { - .enable = hibmc_crtc_enable, .disable = hibmc_crtc_disable, .mode_set_nofb = hibmc_crtc_mode_set_nofb, .atomic_begin = hibmc_crtc_atomic_begin, .atomic_flush = hibmc_crtc_atomic_flush, + .atomic_enable = hibmc_crtc_atomic_enable, }; int hibmc_de_init(struct hibmc_drm_private *priv) diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c index c96c228a9898..8e00818b24fc 100644 --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c @@ -467,7 +467,8 @@ static void ade_dump_regs(void __iomem *base) static void ade_dump_regs(void __iomem *base) { } #endif -static void ade_crtc_enable(struct drm_crtc *crtc) +static void ade_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct ade_crtc *acrtc = to_ade_crtc(crtc); struct ade_hw_ctx *ctx = acrtc->ctx; @@ -553,11 +554,11 @@ static void ade_crtc_atomic_flush(struct drm_crtc *crtc, } static const struct drm_crtc_helper_funcs ade_crtc_helper_funcs = { - .enable = ade_crtc_enable, .disable = ade_crtc_disable, .mode_set_nofb = ade_crtc_mode_set_nofb, .atomic_begin = ade_crtc_atomic_begin, .atomic_flush = ade_crtc_atomic_flush, + .atomic_enable = ade_crtc_atomic_enable, }; static const struct drm_crtc_funcs ade_crtc_funcs = { diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c index 5456c15d962c..53e0b24beda6 100644 --- a/drivers/gpu/drm/imx/ipuv3-crtc.c +++ b/drivers/gpu/drm/imx/ipuv3-crtc.c @@ -50,7 +50,8 @@ static inline struct ipu_crtc *to_ipu_crtc(struct drm_crtc *crtc) return container_of(crtc, struct ipu_crtc, base); } -static void ipu_crtc_enable(struct drm_crtc *crtc) +static void ipu_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent); @@ -293,7 +294,7 @@ static const struct drm_crtc_helper_funcs ipu_helper_funcs = { .atomic_check = ipu_crtc_atomic_check, .atomic_begin = ipu_crtc_atomic_begin, .atomic_disable = ipu_crtc_atomic_disable, - .enable = ipu_crtc_enable, + .atomic_enable = ipu_crtc_atomic_enable, }; static void ipu_put_resources(struct ipu_crtc *ipu_crtc) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index 6582e1f56d37..5971b0827d1b 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -366,7 +366,8 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc) } } -static void mtk_drm_crtc_enable(struct drm_crtc *crtc) +static void mtk_drm_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); struct mtk_ddp_comp *ovl = mtk_crtc->ddp_comp[0]; @@ -487,10 +488,10 @@ static const struct drm_crtc_funcs mtk_crtc_funcs = { static const struct drm_crtc_helper_funcs mtk_crtc_helper_funcs = { .mode_fixup = mtk_drm_crtc_mode_fixup, .mode_set_nofb = mtk_drm_crtc_mode_set_nofb, - .enable = mtk_drm_crtc_enable, .disable = mtk_drm_crtc_disable, .atomic_begin = mtk_drm_crtc_atomic_begin, .atomic_flush = mtk_drm_crtc_atomic_flush, + .atomic_enable = mtk_drm_crtc_atomic_enable, }; static int mtk_drm_crtc_init(struct drm_device *drm, diff --git a/drivers/gpu/drm/meson/meson_crtc.c b/drivers/gpu/drm/meson/meson_crtc.c index c986eb03b9d9..6f148307b0e0 100644 --- a/drivers/gpu/drm/meson/meson_crtc.c +++ b/drivers/gpu/drm/meson/meson_crtc.c @@ -79,7 +79,8 @@ static const struct drm_crtc_funcs meson_crtc_funcs = { }; -static void meson_crtc_enable(struct drm_crtc *crtc) +static void meson_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct meson_crtc *meson_crtc = to_meson_crtc(crtc); struct drm_crtc_state *crtc_state = crtc->state; @@ -149,10 +150,10 @@ static void meson_crtc_atomic_flush(struct drm_crtc *crtc, } static const struct drm_crtc_helper_funcs meson_crtc_helper_funcs = { - .enable = meson_crtc_enable, .disable = meson_crtc_disable, .atomic_begin = meson_crtc_atomic_begin, .atomic_flush = meson_crtc_atomic_flush, + .atomic_enable = meson_crtc_atomic_enable, }; void meson_crtc_irq(struct meson_drm *priv) diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c index 615e1def64d9..9c20133f3f8d 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c @@ -295,7 +295,8 @@ static void mdp4_crtc_disable(struct drm_crtc *crtc) mdp4_crtc->enabled = false; } -static void mdp4_crtc_enable(struct drm_crtc *crtc) +static void mdp4_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); struct mdp4_kms *mdp4_kms = get_kms(crtc); @@ -493,10 +494,10 @@ static const struct drm_crtc_funcs mdp4_crtc_funcs = { static const struct drm_crtc_helper_funcs mdp4_crtc_helper_funcs = { .mode_set_nofb = mdp4_crtc_mode_set_nofb, .disable = mdp4_crtc_disable, - .enable = mdp4_crtc_enable, .atomic_check = mdp4_crtc_atomic_check, .atomic_begin = mdp4_crtc_atomic_begin, .atomic_flush = mdp4_crtc_atomic_flush, + .atomic_enable = mdp4_crtc_atomic_enable, }; static void mdp4_crtc_vblank_irq(struct mdp_irq *irq, uint32_t irqstatus) diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c index cb5415d6c04b..d39d9d24d169 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c @@ -429,7 +429,8 @@ static void mdp5_crtc_disable(struct drm_crtc *crtc) mdp5_crtc->enabled = false; } -static void mdp5_crtc_enable(struct drm_crtc *crtc) +static void mdp5_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state); @@ -940,10 +941,10 @@ static const struct drm_crtc_funcs mdp5_crtc_no_lm_cursor_funcs = { static const struct drm_crtc_helper_funcs mdp5_crtc_helper_funcs = { .mode_set_nofb = mdp5_crtc_mode_set_nofb, .disable = mdp5_crtc_disable, - .enable = mdp5_crtc_enable, .atomic_check = mdp5_crtc_atomic_check, .atomic_begin = mdp5_crtc_atomic_begin, .atomic_flush = mdp5_crtc_atomic_flush, + .atomic_enable = mdp5_crtc_atomic_enable, }; static void mdp5_crtc_vblank_irq(struct mdp_irq *irq, uint32_t irqstatus) diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index dd0ef40ca469..7a1b7a9cc270 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -356,7 +356,8 @@ static void omap_crtc_arm_event(struct drm_crtc *crtc) } } -static void omap_crtc_enable(struct drm_crtc *crtc) +static void omap_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct omap_crtc *omap_crtc = to_omap_crtc(crtc); int ret; @@ -568,10 +569,10 @@ static const struct drm_crtc_funcs omap_crtc_funcs = { static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = { .mode_set_nofb = omap_crtc_mode_set_nofb, .disable = omap_crtc_disable, - .enable = omap_crtc_enable, .atomic_check = omap_crtc_atomic_check, .atomic_begin = omap_crtc_atomic_begin, .atomic_flush = omap_crtc_atomic_flush, + .atomic_enable = omap_crtc_atomic_enable, }; /* ----------------------------------------------------------------------------- diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 7ede5f131a5c..ea95e7e7cc7f 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -447,7 +447,8 @@ static void qxl_mode_set_nofb(struct drm_crtc *crtc) } -static void qxl_crtc_enable(struct drm_crtc *crtc) +static void qxl_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { DRM_DEBUG("\n"); } @@ -466,8 +467,8 @@ static const struct drm_crtc_helper_funcs qxl_crtc_helper_funcs = { .disable = qxl_crtc_disable, .mode_fixup = qxl_crtc_mode_fixup, .mode_set_nofb = qxl_mode_set_nofb, - .enable = qxl_crtc_enable, .atomic_flush = qxl_crtc_atomic_flush, + .atomic_enable = qxl_crtc_atomic_enable, }; static int qxl_primary_atomic_check(struct drm_plane *plane, diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 345eff72f581..6aa3fa8d06f9 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -552,7 +552,8 @@ void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc) * CRTC Functions */ -static void rcar_du_crtc_enable(struct drm_crtc *crtc) +static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); @@ -610,9 +611,9 @@ static void rcar_du_crtc_atomic_flush(struct drm_crtc *crtc, static const struct drm_crtc_helper_funcs crtc_helper_funcs = { .disable = rcar_du_crtc_disable, - .enable = rcar_du_crtc_enable, .atomic_begin = rcar_du_crtc_atomic_begin, .atomic_flush = rcar_du_crtc_atomic_flush, + .atomic_enable = rcar_du_crtc_atomic_enable, }; static int rcar_du_crtc_enable_vblank(struct drm_crtc *crtc) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 5d450332c2fd..bb59f7410634 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -871,7 +871,8 @@ static bool vop_crtc_mode_fixup(struct drm_crtc *crtc, return true; } -static void vop_crtc_enable(struct drm_crtc *crtc) +static void vop_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct vop *vop = to_vop(crtc); const struct vop_data *vop_data = vop->data; @@ -1079,11 +1080,11 @@ static void vop_crtc_atomic_begin(struct drm_crtc *crtc, } static const struct drm_crtc_helper_funcs vop_crtc_helper_funcs = { - .enable = vop_crtc_enable, .disable = vop_crtc_disable, .mode_fixup = vop_crtc_mode_fixup, .atomic_flush = vop_crtc_atomic_flush, .atomic_begin = vop_crtc_atomic_begin, + .atomic_enable = vop_crtc_atomic_enable, }; static void vop_crtc_destroy(struct drm_crtc *crtc) diff --git a/drivers/gpu/drm/sti/sti_crtc.c b/drivers/gpu/drm/sti/sti_crtc.c index d45a4335df5d..bb864345fedf 100644 --- a/drivers/gpu/drm/sti/sti_crtc.c +++ b/drivers/gpu/drm/sti/sti_crtc.c @@ -20,7 +20,8 @@ #include "sti_vid.h" #include "sti_vtg.h" -static void sti_crtc_enable(struct drm_crtc *crtc) +static void sti_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct sti_mixer *mixer = to_sti_mixer(crtc); @@ -222,10 +223,10 @@ static void sti_crtc_atomic_flush(struct drm_crtc *crtc, } static const struct drm_crtc_helper_funcs sti_crtc_helper_funcs = { - .enable = sti_crtc_enable, .disable = sti_crtc_disabling, .mode_set_nofb = sti_crtc_mode_set_nofb, .atomic_flush = sti_crtc_atomic_flush, + .atomic_enable = sti_crtc_atomic_enable, }; static void sti_crtc_destroy(struct drm_crtc *crtc) diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c index 1b9483d4f2a4..337fce004d08 100644 --- a/drivers/gpu/drm/stm/ltdc.c +++ b/drivers/gpu/drm/stm/ltdc.c @@ -386,7 +386,8 @@ static void ltdc_crtc_load_lut(struct drm_crtc *crtc) ldev->clut[i]); } -static void ltdc_crtc_enable(struct drm_crtc *crtc) +static void ltdc_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct ltdc_device *ldev = crtc_to_ltdc(crtc); @@ -524,10 +525,10 @@ static void ltdc_crtc_atomic_flush(struct drm_crtc *crtc, static struct drm_crtc_helper_funcs ltdc_crtc_helper_funcs = { .load_lut = ltdc_crtc_load_lut, - .enable = ltdc_crtc_enable, .disable = ltdc_crtc_disable, .mode_set_nofb = ltdc_crtc_mode_set_nofb, .atomic_flush = ltdc_crtc_atomic_flush, + .atomic_enable = ltdc_crtc_atomic_enable, }; int ltdc_crtc_enable_vblank(struct drm_device *ddev, unsigned int pipe) diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c index f8c70439d1e2..509e4d8014f3 100644 --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c @@ -86,7 +86,8 @@ static void sun4i_crtc_disable(struct drm_crtc *crtc) } } -static void sun4i_crtc_enable(struct drm_crtc *crtc) +static void sun4i_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc); @@ -98,8 +99,8 @@ static void sun4i_crtc_enable(struct drm_crtc *crtc) static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = { .atomic_begin = sun4i_crtc_atomic_begin, .atomic_flush = sun4i_crtc_atomic_flush, + .atomic_enable = sun4i_crtc_atomic_enable, .disable = sun4i_crtc_disable, - .enable = sun4i_crtc_enable, }; static int sun4i_crtc_enable_vblank(struct drm_crtc *crtc) diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index c875f11786b9..2e0d167cb657 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -1243,7 +1243,8 @@ static void tegra_crtc_disable(struct drm_crtc *crtc) pm_runtime_put_sync(dc->dev); } -static void tegra_crtc_enable(struct drm_crtc *crtc) +static void tegra_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct drm_display_mode *mode = &crtc->state->adjusted_mode; struct tegra_dc_state *state = to_dc_state(crtc->state); @@ -1352,10 +1353,10 @@ static void tegra_crtc_atomic_flush(struct drm_crtc *crtc, static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = { .disable = tegra_crtc_disable, - .enable = tegra_crtc_enable, .atomic_check = tegra_crtc_atomic_check, .atomic_begin = tegra_crtc_atomic_begin, .atomic_flush = tegra_crtc_atomic_flush, + .atomic_enable = tegra_crtc_atomic_enable, }; static irqreturn_t tegra_dc_irq(int irq, void *data) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index d524ed0d5146..6c5892763d27 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -504,6 +504,12 @@ static void tilcdc_crtc_enable(struct drm_crtc *crtc) mutex_unlock(&tilcdc_crtc->enable_lock); } +static void tilcdc_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) +{ + tilcdc_crtc_enable(crtc); +} + static void tilcdc_crtc_off(struct drm_crtc *crtc, bool shutdown) { struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); @@ -729,9 +735,9 @@ static const struct drm_crtc_funcs tilcdc_crtc_funcs = { static const struct drm_crtc_helper_funcs tilcdc_crtc_helper_funcs = { .mode_fixup = tilcdc_crtc_mode_fixup, - .enable = tilcdc_crtc_enable, .disable = tilcdc_crtc_disable, .atomic_check = tilcdc_crtc_atomic_check, + .atomic_enable = tilcdc_crtc_atomic_enable, }; int tilcdc_crtc_max_width(struct drm_crtc *crtc) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index f20c01759c0d..4c03a565b276 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -533,7 +533,8 @@ static void vc4_crtc_disable(struct drm_crtc *crtc) } } -static void vc4_crtc_enable(struct drm_crtc *crtc) +static void vc4_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct drm_device *dev = crtc->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); @@ -870,10 +871,10 @@ static const struct drm_crtc_funcs vc4_crtc_funcs = { static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = { .mode_set_nofb = vc4_crtc_mode_set_nofb, .disable = vc4_crtc_disable, - .enable = vc4_crtc_enable, .mode_valid = vc4_crtc_mode_valid, .atomic_check = vc4_crtc_atomic_check, .atomic_flush = vc4_crtc_atomic_flush, + .atomic_enable = vc4_crtc_atomic_enable, }; static const struct vc4_crtc_data pv0_data = { diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index d51bd4521f17..03a3c12ed100 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c @@ -113,7 +113,8 @@ static void virtio_gpu_crtc_mode_set_nofb(struct drm_crtc *crtc) crtc->mode.vdisplay, 0, 0); } -static void virtio_gpu_crtc_enable(struct drm_crtc *crtc) +static void virtio_gpu_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { } @@ -145,11 +146,11 @@ static void virtio_gpu_crtc_atomic_flush(struct drm_crtc *crtc, } static const struct drm_crtc_helper_funcs virtio_gpu_crtc_helper_funcs = { - .enable = virtio_gpu_crtc_enable, .disable = virtio_gpu_crtc_disable, .mode_set_nofb = virtio_gpu_crtc_mode_set_nofb, .atomic_check = virtio_gpu_crtc_atomic_check, .atomic_flush = virtio_gpu_crtc_atomic_flush, + .atomic_enable = virtio_gpu_crtc_atomic_enable, }; static void virtio_gpu_enc_mode_set(struct drm_encoder *encoder, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index f8acd3a15523..832b83c582c2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -203,7 +203,7 @@ static void vmw_ldu_crtc_mode_set_nofb(struct drm_crtc *crtc) } /** - * vmw_ldu_crtc_helper_enable - Noop + * vmw_ldu_crtc_atomic_enable - Noop * * @crtc: CRTC associated with the new screen * @@ -212,7 +212,8 @@ static void vmw_ldu_crtc_mode_set_nofb(struct drm_crtc *crtc) * but since for LDU the display plane is closely tied to the * CRTC, it makes more sense to do those at plane update time. */ -static void vmw_ldu_crtc_helper_enable(struct drm_crtc *crtc) +static void vmw_ldu_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { } @@ -376,12 +377,12 @@ drm_plane_helper_funcs vmw_ldu_primary_plane_helper_funcs = { }; static const struct drm_crtc_helper_funcs vmw_ldu_crtc_helper_funcs = { - .enable = vmw_ldu_crtc_helper_enable, .disable = vmw_ldu_crtc_helper_disable, .mode_set_nofb = vmw_ldu_crtc_mode_set_nofb, .atomic_check = vmw_du_crtc_atomic_check, .atomic_begin = vmw_du_crtc_atomic_begin, .atomic_flush = vmw_du_crtc_atomic_flush, + .atomic_enable = vmw_ldu_crtc_atomic_enable, }; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index 1cb826c503bf..8ba3bad06909 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c @@ -270,13 +270,14 @@ static void vmw_sou_crtc_helper_prepare(struct drm_crtc *crtc) } /** - * vmw_sou_crtc_helper_enable - Noop + * vmw_sou_crtc_atomic_enable - Noop * * @crtc: CRTC associated with the new screen * * This is called after a mode set has been completed. */ -static void vmw_sou_crtc_helper_enable(struct drm_crtc *crtc) +static void vmw_sou_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { } @@ -573,12 +574,12 @@ drm_plane_helper_funcs vmw_sou_primary_plane_helper_funcs = { static const struct drm_crtc_helper_funcs vmw_sou_crtc_helper_funcs = { .prepare = vmw_sou_crtc_helper_prepare, - .enable = vmw_sou_crtc_helper_enable, .disable = vmw_sou_crtc_helper_disable, .mode_set_nofb = vmw_sou_crtc_mode_set_nofb, .atomic_check = vmw_du_crtc_atomic_check, .atomic_begin = vmw_du_crtc_atomic_begin, .atomic_flush = vmw_du_crtc_atomic_flush, + .atomic_enable = vmw_sou_crtc_atomic_enable, }; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c index 4eb93b47d6db..f2b39d9c51cc 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c @@ -412,7 +412,8 @@ static void vmw_stdu_crtc_helper_prepare(struct drm_crtc *crtc) } -static void vmw_stdu_crtc_helper_enable(struct drm_crtc *crtc) +static void vmw_stdu_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct vmw_private *dev_priv; struct vmw_screen_target_display_unit *stdu; @@ -1415,12 +1416,12 @@ drm_plane_helper_funcs vmw_stdu_primary_plane_helper_funcs = { static const struct drm_crtc_helper_funcs vmw_stdu_crtc_helper_funcs = { .prepare = vmw_stdu_crtc_helper_prepare, - .enable = vmw_stdu_crtc_helper_enable, .disable = vmw_stdu_crtc_helper_disable, .mode_set_nofb = vmw_stdu_crtc_mode_set_nofb, .atomic_check = vmw_du_crtc_atomic_check, .atomic_begin = vmw_du_crtc_atomic_begin, .atomic_flush = vmw_du_crtc_atomic_flush, + .atomic_enable = vmw_stdu_crtc_atomic_enable, }; diff --git a/drivers/gpu/drm/zte/zx_vou.c b/drivers/gpu/drm/zte/zx_vou.c index 5fbd10b60ee5..ccb4b0bdb8c6 100644 --- a/drivers/gpu/drm/zte/zx_vou.c +++ b/drivers/gpu/drm/zte/zx_vou.c @@ -350,7 +350,8 @@ static inline void vou_chn_set_update(struct zx_crtc *zcrtc) zx_writel(zcrtc->chnreg + CHN_UPDATE, 1); } -static void zx_crtc_enable(struct drm_crtc *crtc) +static void zx_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct drm_display_mode *mode = &crtc->state->adjusted_mode; bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE; @@ -490,9 +491,9 @@ static void zx_crtc_atomic_flush(struct drm_crtc *crtc, } static const struct drm_crtc_helper_funcs zx_crtc_helper_funcs = { - .enable = zx_crtc_enable, .disable = zx_crtc_disable, .atomic_flush = zx_crtc_atomic_flush, + .atomic_enable = zx_crtc_atomic_enable, }; static int zx_vou_enable_vblank(struct drm_crtc *crtc) diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h index 474a1029ec79..c85124f687ba 100644 --- a/include/drm/drm_modeset_helper_vtables.h +++ b/include/drm/drm_modeset_helper_vtables.h @@ -71,7 +71,7 @@ struct drm_crtc_helper_funcs { * This callback is used by the legacy CRTC helpers. Atomic helpers * also support using this hook for enabling and disabling a CRTC to * facilitate transitions to atomic, but it is deprecated. Instead - * @enable and @disable should be used. + * @atomic_enable and @atomic_disable should be used. */ void (*dpms)(struct drm_crtc *crtc, int mode); @@ -85,8 +85,8 @@ struct drm_crtc_helper_funcs { * * This callback is used by the legacy CRTC helpers. Atomic helpers * also support using this hook for disabling a CRTC to facilitate - * transitions to atomic, but it is deprecated. Instead @disable should - * be used. + * transitions to atomic, but it is deprecated. Instead @atomic_disable + * should be used. */ void (*prepare)(struct drm_crtc *crtc); @@ -100,8 +100,8 @@ struct drm_crtc_helper_funcs { * * This callback is used by the legacy CRTC helpers. Atomic helpers * also support using this hook for enabling a CRTC to facilitate - * transitions to atomic, but it is deprecated. Instead @enable should - * be used. + * transitions to atomic, but it is deprecated. Instead @atomic_enable + * should be used. */ void (*commit)(struct drm_crtc *crtc); @@ -222,7 +222,7 @@ struct drm_crtc_helper_funcs { * pipeline is suspended using either DPMS or the new "ACTIVE" property. * Which means register values set in this callback might get reset when * the CRTC is suspended, but not restored. Such drivers should instead - * move all their CRTC setup into the @enable callback. + * move all their CRTC setup into the @atomic_enable callback. * * This callback is optional. */ @@ -297,7 +297,7 @@ struct drm_crtc_helper_funcs { * Atomic drivers don't need to implement it if there's no need to * disable anything at the CRTC level. To ensure that runtime PM * handling (using either DPMS or the new "ACTIVE" property) works - * @disable must be the inverse of @enable for atomic drivers. + * @disable must be the inverse of @atomic_enable for atomic drivers. * Atomic drivers should consider to use @atomic_disable instead of * this one. * @@ -315,24 +315,6 @@ struct drm_crtc_helper_funcs { */ void (*disable)(struct drm_crtc *crtc); - /** - * @enable: - * - * This callback should be used to enable the CRTC. With the atomic - * drivers it is called before all encoders connected to this CRTC are - * enabled through the encoder's own &drm_encoder_helper_funcs.enable - * hook. If that sequence is too simple drivers can just add their own - * hooks and call it from this CRTC callback here by looping over all - * encoders connected to it using for_each_encoder_on_crtc(). - * - * This hook is used only by atomic helpers, for symmetry with @disable. - * Atomic drivers don't need to implement it if there's no need to - * enable anything at the CRTC level. To ensure that runtime PM handling - * (using either DPMS or the new "ACTIVE" property) works - * @enable must be the inverse of @disable for atomic drivers. - */ - void (*enable)(struct drm_crtc *crtc); - /** * @atomic_check: * @@ -432,6 +414,30 @@ struct drm_crtc_helper_funcs { void (*atomic_flush)(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state); + /** + * @atomic_enable: + * + * This callback should be used to enable the CRTC. With the atomic + * drivers it is called before all encoders connected to this CRTC are + * enabled through the encoder's own &drm_encoder_helper_funcs.enable + * hook. If that sequence is too simple drivers can just add their own + * hooks and call it from this CRTC callback here by looping over all + * encoders connected to it using for_each_encoder_on_crtc(). + * + * This hook is used only by atomic helpers, for symmetry with + * @atomic_disable. Atomic drivers don't need to implement it if there's + * no need to enable anything at the CRTC level. To ensure that runtime + * PM handling (using either DPMS or the new "ACTIVE" property) works + * @atomic_enable must be the inverse of @atomic_disable for atomic + * drivers. + * + * Drivers can use the @old_crtc_state input parameter if the operations + * needed to enable the CRTC don't depend solely on the new state but + * also on the transition between the old state and the new state. + */ + void (*atomic_enable)(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state); + /** * @atomic_disable: * -- cgit v1.2.3 From 64581714b58bc3e16ede8dc37a025c3aa0e0eef1 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 30 Jun 2017 12:36:45 +0300 Subject: drm: Convert atomic drivers from CRTC .disable() to .atomic_disable() The CRTC .disable() helper operation is deprecated for atomic drivers, the new .atomic_disable() helper operation being preferred. Convert all atomic drivers to .atomic_disable() to avoid cargo-cult use of .disable() in new drivers. Signed-off-by: Laurent Pinchart Acked-by: Maxime Ripard # for sun4i Acked-by: Philipp Zabel # for mediatek Acked-by: Alexey Brodkin # for arcpgu Acked-by: Boris Brezillon # for atmel-hlcdc Tested-by: Philippe Cornu # for stm Acked-by: Philippe Cornu # for stm Acked-by: Vincent Abriou # for sti Reviewed-by: Thomas Hellstrom # for vmwgfx Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170630093646.7928-3-laurent.pinchart+renesas@ideasonboard.com --- drivers/gpu/drm/arc/arcpgu_crtc.c | 5 +++-- drivers/gpu/drm/arm/hdlcd_crtc.c | 5 +++-- drivers/gpu/drm/arm/malidp_crtc.c | 5 +++-- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 5 +++-- drivers/gpu/drm/drm_simple_kms_helper.c | 5 +++-- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 5 +++-- drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c | 5 +++-- drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c | 5 +++-- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 5 +++-- drivers/gpu/drm/meson/meson_crtc.c | 5 +++-- drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | 5 +++-- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 5 +++-- drivers/gpu/drm/omapdrm/omap_crtc.c | 5 +++-- drivers/gpu/drm/qxl/qxl_display.c | 5 +++-- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 5 +++-- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 5 +++-- drivers/gpu/drm/sti/sti_crtc.c | 5 +++-- drivers/gpu/drm/stm/ltdc.c | 5 +++-- drivers/gpu/drm/sun4i/sun4i_crtc.c | 5 +++-- drivers/gpu/drm/tegra/dc.c | 5 +++-- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 8 +++++++- drivers/gpu/drm/vc4/vc4_crtc.c | 5 +++-- drivers/gpu/drm/virtio/virtgpu_display.c | 5 +++-- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 7 ++++--- drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 7 ++++--- drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 5 +++-- drivers/gpu/drm/zte/zx_vou.c | 5 +++-- 27 files changed, 87 insertions(+), 55 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c index c9bc6a90ac83..1859dd3ad622 100644 --- a/drivers/gpu/drm/arc/arcpgu_crtc.c +++ b/drivers/gpu/drm/arc/arcpgu_crtc.c @@ -130,7 +130,8 @@ static void arc_pgu_crtc_atomic_enable(struct drm_crtc *crtc, ARCPGU_CTRL_ENABLE_MASK); } -static void arc_pgu_crtc_disable(struct drm_crtc *crtc) +static void arc_pgu_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc); @@ -162,9 +163,9 @@ static const struct drm_crtc_helper_funcs arc_pgu_crtc_helper_funcs = { .mode_set = drm_helper_crtc_mode_set, .mode_set_base = drm_helper_crtc_mode_set_base, .mode_set_nofb = arc_pgu_crtc_mode_set_nofb, - .disable = arc_pgu_crtc_disable, .atomic_begin = arc_pgu_crtc_atomic_begin, .atomic_enable = arc_pgu_crtc_atomic_enable, + .atomic_disable = arc_pgu_crtc_atomic_disable, }; static void arc_pgu_plane_atomic_update(struct drm_plane *plane, diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c index 2b7f4f05d91f..16e1e20cf04c 100644 --- a/drivers/gpu/drm/arm/hdlcd_crtc.c +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c @@ -176,7 +176,8 @@ static void hdlcd_crtc_atomic_enable(struct drm_crtc *crtc, drm_crtc_vblank_on(crtc); } -static void hdlcd_crtc_disable(struct drm_crtc *crtc) +static void hdlcd_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc); @@ -219,10 +220,10 @@ static void hdlcd_crtc_atomic_begin(struct drm_crtc *crtc, } static const struct drm_crtc_helper_funcs hdlcd_crtc_helper_funcs = { - .disable = hdlcd_crtc_disable, .atomic_check = hdlcd_crtc_atomic_check, .atomic_begin = hdlcd_crtc_atomic_begin, .atomic_enable = hdlcd_crtc_atomic_enable, + .atomic_disable = hdlcd_crtc_atomic_disable, }; static int hdlcd_plane_atomic_check(struct drm_plane *plane, diff --git a/drivers/gpu/drm/arm/malidp_crtc.c b/drivers/gpu/drm/arm/malidp_crtc.c index 8e5b1c0181ab..3615d18a7ddf 100644 --- a/drivers/gpu/drm/arm/malidp_crtc.c +++ b/drivers/gpu/drm/arm/malidp_crtc.c @@ -70,7 +70,8 @@ static void malidp_crtc_atomic_enable(struct drm_crtc *crtc, drm_crtc_vblank_on(crtc); } -static void malidp_crtc_disable(struct drm_crtc *crtc) +static void malidp_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct malidp_drm *malidp = crtc_to_malidp_device(crtc); struct malidp_hw_device *hwdev = malidp->dev; @@ -409,9 +410,9 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc, static const struct drm_crtc_helper_funcs malidp_crtc_helper_funcs = { .mode_valid = malidp_crtc_mode_valid, - .disable = malidp_crtc_disable, .atomic_check = malidp_crtc_atomic_check, .atomic_enable = malidp_crtc_atomic_enable, + .atomic_disable = malidp_crtc_atomic_disable, }; static struct drm_crtc_state *malidp_crtc_duplicate_state(struct drm_crtc *crtc) diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c index e54e503180f4..441769c5bcd4 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c @@ -149,7 +149,8 @@ atmel_hlcdc_crtc_mode_valid(struct drm_crtc *c, return atmel_hlcdc_dc_mode_valid(crtc->dc, mode); } -static void atmel_hlcdc_crtc_disable(struct drm_crtc *c) +static void atmel_hlcdc_crtc_atomic_disable(struct drm_crtc *c, + struct drm_crtc_state *old_state) { struct drm_device *dev = c->dev; struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); @@ -320,11 +321,11 @@ static const struct drm_crtc_helper_funcs lcdc_crtc_helper_funcs = { .mode_set = drm_helper_crtc_mode_set, .mode_set_nofb = atmel_hlcdc_crtc_mode_set_nofb, .mode_set_base = drm_helper_crtc_mode_set_base, - .disable = atmel_hlcdc_crtc_disable, .atomic_check = atmel_hlcdc_crtc_atomic_check, .atomic_begin = atmel_hlcdc_crtc_atomic_begin, .atomic_flush = atmel_hlcdc_crtc_atomic_flush, .atomic_enable = atmel_hlcdc_crtc_atomic_enable, + .atomic_disable = atmel_hlcdc_crtc_atomic_disable, }; static void atmel_hlcdc_crtc_destroy(struct drm_crtc *c) diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c index 58c27ab1756f..98250854af75 100644 --- a/drivers/gpu/drm/drm_simple_kms_helper.c +++ b/drivers/gpu/drm/drm_simple_kms_helper.c @@ -52,7 +52,8 @@ static void drm_simple_kms_crtc_enable(struct drm_crtc *crtc, pipe->funcs->enable(pipe, crtc->state); } -static void drm_simple_kms_crtc_disable(struct drm_crtc *crtc) +static void drm_simple_kms_crtc_disable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct drm_simple_display_pipe *pipe; @@ -66,7 +67,7 @@ static void drm_simple_kms_crtc_disable(struct drm_crtc *crtc) static const struct drm_crtc_helper_funcs drm_simple_kms_crtc_helper_funcs = { .atomic_check = drm_simple_kms_crtc_check, .atomic_enable = drm_simple_kms_crtc_enable, - .disable = drm_simple_kms_crtc_disable, + .atomic_disable = drm_simple_kms_crtc_disable, }; static const struct drm_crtc_funcs drm_simple_kms_crtc_funcs = { diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index b7e2fadb6442..c37078fbe0ea 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -32,7 +32,8 @@ static void exynos_drm_crtc_atomic_enable(struct drm_crtc *crtc, drm_crtc_vblank_on(crtc); } -static void exynos_drm_crtc_disable(struct drm_crtc *crtc) +static void exynos_drm_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); @@ -83,11 +84,11 @@ static void exynos_crtc_atomic_flush(struct drm_crtc *crtc, } static const struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = { - .disable = exynos_drm_crtc_disable, .atomic_check = exynos_crtc_atomic_check, .atomic_begin = exynos_crtc_atomic_begin, .atomic_flush = exynos_crtc_atomic_flush, .atomic_enable = exynos_drm_crtc_atomic_enable, + .atomic_disable = exynos_drm_crtc_atomic_disable, }; void exynos_crtc_handle_event(struct exynos_drm_crtc *exynos_crtc) diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c index 49ef47c0c81a..54a4542a40f1 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c @@ -210,7 +210,8 @@ static void hibmc_crtc_atomic_enable(struct drm_crtc *crtc, drm_crtc_vblank_on(crtc); } -static void hibmc_crtc_disable(struct drm_crtc *crtc) +static void hibmc_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { unsigned int reg; struct hibmc_drm_private *priv = crtc->dev->dev_private; @@ -454,11 +455,11 @@ static const struct drm_crtc_funcs hibmc_crtc_funcs = { }; static const struct drm_crtc_helper_funcs hibmc_crtc_helper_funcs = { - .disable = hibmc_crtc_disable, .mode_set_nofb = hibmc_crtc_mode_set_nofb, .atomic_begin = hibmc_crtc_atomic_begin, .atomic_flush = hibmc_crtc_atomic_flush, .atomic_enable = hibmc_crtc_atomic_enable, + .atomic_disable = hibmc_crtc_atomic_disable, }; int hibmc_de_init(struct hibmc_drm_private *priv) diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c index 8e00818b24fc..7e3abbf4ef73 100644 --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c @@ -490,7 +490,8 @@ static void ade_crtc_atomic_enable(struct drm_crtc *crtc, acrtc->enable = true; } -static void ade_crtc_disable(struct drm_crtc *crtc) +static void ade_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct ade_crtc *acrtc = to_ade_crtc(crtc); struct ade_hw_ctx *ctx = acrtc->ctx; @@ -554,11 +555,11 @@ static void ade_crtc_atomic_flush(struct drm_crtc *crtc, } static const struct drm_crtc_helper_funcs ade_crtc_helper_funcs = { - .disable = ade_crtc_disable, .mode_set_nofb = ade_crtc_mode_set_nofb, .atomic_begin = ade_crtc_atomic_begin, .atomic_flush = ade_crtc_atomic_flush, .atomic_enable = ade_crtc_atomic_enable, + .atomic_disable = ade_crtc_atomic_disable, }; static const struct drm_crtc_funcs ade_crtc_funcs = { diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index 5971b0827d1b..fc65c57dda8c 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -391,7 +391,8 @@ static void mtk_drm_crtc_atomic_enable(struct drm_crtc *crtc, mtk_crtc->enabled = true; } -static void mtk_drm_crtc_disable(struct drm_crtc *crtc) +static void mtk_drm_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); struct mtk_ddp_comp *ovl = mtk_crtc->ddp_comp[0]; @@ -488,10 +489,10 @@ static const struct drm_crtc_funcs mtk_crtc_funcs = { static const struct drm_crtc_helper_funcs mtk_crtc_helper_funcs = { .mode_fixup = mtk_drm_crtc_mode_fixup, .mode_set_nofb = mtk_drm_crtc_mode_set_nofb, - .disable = mtk_drm_crtc_disable, .atomic_begin = mtk_drm_crtc_atomic_begin, .atomic_flush = mtk_drm_crtc_atomic_flush, .atomic_enable = mtk_drm_crtc_atomic_enable, + .atomic_disable = mtk_drm_crtc_atomic_disable, }; static int mtk_drm_crtc_init(struct drm_device *drm, diff --git a/drivers/gpu/drm/meson/meson_crtc.c b/drivers/gpu/drm/meson/meson_crtc.c index 6f148307b0e0..5155f0179b61 100644 --- a/drivers/gpu/drm/meson/meson_crtc.c +++ b/drivers/gpu/drm/meson/meson_crtc.c @@ -103,7 +103,8 @@ static void meson_crtc_atomic_enable(struct drm_crtc *crtc, priv->viu.osd1_enabled = true; } -static void meson_crtc_disable(struct drm_crtc *crtc) +static void meson_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct meson_crtc *meson_crtc = to_meson_crtc(crtc); struct meson_drm *priv = meson_crtc->priv; @@ -150,10 +151,10 @@ static void meson_crtc_atomic_flush(struct drm_crtc *crtc, } static const struct drm_crtc_helper_funcs meson_crtc_helper_funcs = { - .disable = meson_crtc_disable, .atomic_begin = meson_crtc_atomic_begin, .atomic_flush = meson_crtc_atomic_flush, .atomic_enable = meson_crtc_atomic_enable, + .atomic_disable = meson_crtc_atomic_disable, }; void meson_crtc_irq(struct meson_drm *priv) diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c index 9c20133f3f8d..3c7a9d343e05 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c @@ -279,7 +279,8 @@ static void mdp4_crtc_mode_set_nofb(struct drm_crtc *crtc) } } -static void mdp4_crtc_disable(struct drm_crtc *crtc) +static void mdp4_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); struct mdp4_kms *mdp4_kms = get_kms(crtc); @@ -493,11 +494,11 @@ static const struct drm_crtc_funcs mdp4_crtc_funcs = { static const struct drm_crtc_helper_funcs mdp4_crtc_helper_funcs = { .mode_set_nofb = mdp4_crtc_mode_set_nofb, - .disable = mdp4_crtc_disable, .atomic_check = mdp4_crtc_atomic_check, .atomic_begin = mdp4_crtc_atomic_begin, .atomic_flush = mdp4_crtc_atomic_flush, .atomic_enable = mdp4_crtc_atomic_enable, + .atomic_disable = mdp4_crtc_atomic_disable, }; static void mdp4_crtc_vblank_irq(struct mdp_irq *irq, uint32_t irqstatus) diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c index d39d9d24d169..4322a502555a 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c @@ -409,7 +409,8 @@ static void mdp5_crtc_mode_set_nofb(struct drm_crtc *crtc) spin_unlock_irqrestore(&mdp5_crtc->lm_lock, flags); } -static void mdp5_crtc_disable(struct drm_crtc *crtc) +static void mdp5_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state); @@ -940,11 +941,11 @@ static const struct drm_crtc_funcs mdp5_crtc_no_lm_cursor_funcs = { static const struct drm_crtc_helper_funcs mdp5_crtc_helper_funcs = { .mode_set_nofb = mdp5_crtc_mode_set_nofb, - .disable = mdp5_crtc_disable, .atomic_check = mdp5_crtc_atomic_check, .atomic_begin = mdp5_crtc_atomic_begin, .atomic_flush = mdp5_crtc_atomic_flush, .atomic_enable = mdp5_crtc_atomic_enable, + .atomic_disable = mdp5_crtc_atomic_disable, }; static void mdp5_crtc_vblank_irq(struct mdp_irq *irq, uint32_t irqstatus) diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 7a1b7a9cc270..14e8a7738b06 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -373,7 +373,8 @@ static void omap_crtc_atomic_enable(struct drm_crtc *crtc, spin_unlock_irq(&crtc->dev->event_lock); } -static void omap_crtc_disable(struct drm_crtc *crtc) +static void omap_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct omap_crtc *omap_crtc = to_omap_crtc(crtc); @@ -568,11 +569,11 @@ static const struct drm_crtc_funcs omap_crtc_funcs = { static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = { .mode_set_nofb = omap_crtc_mode_set_nofb, - .disable = omap_crtc_disable, .atomic_check = omap_crtc_atomic_check, .atomic_begin = omap_crtc_atomic_begin, .atomic_flush = omap_crtc_atomic_flush, .atomic_enable = omap_crtc_atomic_enable, + .atomic_disable = omap_crtc_atomic_disable, }; /* ----------------------------------------------------------------------------- diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index ea95e7e7cc7f..5eeae89c138d 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -453,7 +453,8 @@ static void qxl_crtc_atomic_enable(struct drm_crtc *crtc, DRM_DEBUG("\n"); } -static void qxl_crtc_disable(struct drm_crtc *crtc) +static void qxl_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct qxl_crtc *qcrtc = to_qxl_crtc(crtc); struct qxl_device *qdev = crtc->dev->dev_private; @@ -464,11 +465,11 @@ static void qxl_crtc_disable(struct drm_crtc *crtc) } static const struct drm_crtc_helper_funcs qxl_crtc_helper_funcs = { - .disable = qxl_crtc_disable, .mode_fixup = qxl_crtc_mode_fixup, .mode_set_nofb = qxl_mode_set_nofb, .atomic_flush = qxl_crtc_atomic_flush, .atomic_enable = qxl_crtc_atomic_enable, + .atomic_disable = qxl_crtc_atomic_disable, }; static int qxl_primary_atomic_check(struct drm_plane *plane, diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 6aa3fa8d06f9..f131fc68cc46 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -561,7 +561,8 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc, rcar_du_crtc_start(rcrtc); } -static void rcar_du_crtc_disable(struct drm_crtc *crtc) +static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); @@ -610,10 +611,10 @@ static void rcar_du_crtc_atomic_flush(struct drm_crtc *crtc, } static const struct drm_crtc_helper_funcs crtc_helper_funcs = { - .disable = rcar_du_crtc_disable, .atomic_begin = rcar_du_crtc_atomic_begin, .atomic_flush = rcar_du_crtc_atomic_flush, .atomic_enable = rcar_du_crtc_atomic_enable, + .atomic_disable = rcar_du_crtc_atomic_disable, }; static int rcar_du_crtc_enable_vblank(struct drm_crtc *crtc) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index bb59f7410634..ee876a9631f0 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -563,7 +563,8 @@ err_put_pm_runtime: return ret; } -static void vop_crtc_disable(struct drm_crtc *crtc) +static void vop_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct vop *vop = to_vop(crtc); int i; @@ -1080,11 +1081,11 @@ static void vop_crtc_atomic_begin(struct drm_crtc *crtc, } static const struct drm_crtc_helper_funcs vop_crtc_helper_funcs = { - .disable = vop_crtc_disable, .mode_fixup = vop_crtc_mode_fixup, .atomic_flush = vop_crtc_atomic_flush, .atomic_begin = vop_crtc_atomic_begin, .atomic_enable = vop_crtc_atomic_enable, + .atomic_disable = vop_crtc_atomic_disable, }; static void vop_crtc_destroy(struct drm_crtc *crtc) diff --git a/drivers/gpu/drm/sti/sti_crtc.c b/drivers/gpu/drm/sti/sti_crtc.c index bb864345fedf..e8a4d48e985a 100644 --- a/drivers/gpu/drm/sti/sti_crtc.c +++ b/drivers/gpu/drm/sti/sti_crtc.c @@ -32,7 +32,8 @@ static void sti_crtc_atomic_enable(struct drm_crtc *crtc, drm_crtc_vblank_on(crtc); } -static void sti_crtc_disabling(struct drm_crtc *crtc) +static void sti_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct sti_mixer *mixer = to_sti_mixer(crtc); @@ -223,10 +224,10 @@ static void sti_crtc_atomic_flush(struct drm_crtc *crtc, } static const struct drm_crtc_helper_funcs sti_crtc_helper_funcs = { - .disable = sti_crtc_disabling, .mode_set_nofb = sti_crtc_mode_set_nofb, .atomic_flush = sti_crtc_atomic_flush, .atomic_enable = sti_crtc_atomic_enable, + .atomic_disable = sti_crtc_atomic_disable, }; static void sti_crtc_destroy(struct drm_crtc *crtc) diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c index 337fce004d08..533176015cbb 100644 --- a/drivers/gpu/drm/stm/ltdc.c +++ b/drivers/gpu/drm/stm/ltdc.c @@ -408,7 +408,8 @@ static void ltdc_crtc_atomic_enable(struct drm_crtc *crtc, drm_crtc_vblank_on(crtc); } -static void ltdc_crtc_disable(struct drm_crtc *crtc) +static void ltdc_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct ltdc_device *ldev = crtc_to_ltdc(crtc); @@ -525,10 +526,10 @@ static void ltdc_crtc_atomic_flush(struct drm_crtc *crtc, static struct drm_crtc_helper_funcs ltdc_crtc_helper_funcs = { .load_lut = ltdc_crtc_load_lut, - .disable = ltdc_crtc_disable, .mode_set_nofb = ltdc_crtc_mode_set_nofb, .atomic_flush = ltdc_crtc_atomic_flush, .atomic_enable = ltdc_crtc_atomic_enable, + .atomic_disable = ltdc_crtc_atomic_disable, }; int ltdc_crtc_enable_vblank(struct drm_device *ddev, unsigned int pipe) diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c index 509e4d8014f3..d097c6f93ad0 100644 --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c @@ -69,7 +69,8 @@ static void sun4i_crtc_atomic_flush(struct drm_crtc *crtc, } } -static void sun4i_crtc_disable(struct drm_crtc *crtc) +static void sun4i_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc); @@ -100,7 +101,7 @@ static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = { .atomic_begin = sun4i_crtc_atomic_begin, .atomic_flush = sun4i_crtc_atomic_flush, .atomic_enable = sun4i_crtc_atomic_enable, - .disable = sun4i_crtc_disable, + .atomic_disable = sun4i_crtc_atomic_disable, }; static int sun4i_crtc_enable_vblank(struct drm_crtc *crtc) diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 2e0d167cb657..0cb9b90e2e68 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -1199,7 +1199,8 @@ static int tegra_dc_wait_idle(struct tegra_dc *dc, unsigned long timeout) return -ETIMEDOUT; } -static void tegra_crtc_disable(struct drm_crtc *crtc) +static void tegra_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct tegra_dc *dc = to_tegra_dc(crtc); u32 value; @@ -1352,11 +1353,11 @@ static void tegra_crtc_atomic_flush(struct drm_crtc *crtc, } static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = { - .disable = tegra_crtc_disable, .atomic_check = tegra_crtc_atomic_check, .atomic_begin = tegra_crtc_atomic_begin, .atomic_flush = tegra_crtc_atomic_flush, .atomic_enable = tegra_crtc_atomic_enable, + .atomic_disable = tegra_crtc_atomic_disable, }; static irqreturn_t tegra_dc_irq(int irq, void *data) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 6c5892763d27..a43e720ab4e8 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -568,6 +568,12 @@ static void tilcdc_crtc_disable(struct drm_crtc *crtc) tilcdc_crtc_off(crtc, false); } +static void tilcdc_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) +{ + tilcdc_crtc_disable(crtc); +} + void tilcdc_crtc_shutdown(struct drm_crtc *crtc) { tilcdc_crtc_off(crtc, true); @@ -735,9 +741,9 @@ static const struct drm_crtc_funcs tilcdc_crtc_funcs = { static const struct drm_crtc_helper_funcs tilcdc_crtc_helper_funcs = { .mode_fixup = tilcdc_crtc_mode_fixup, - .disable = tilcdc_crtc_disable, .atomic_check = tilcdc_crtc_atomic_check, .atomic_enable = tilcdc_crtc_atomic_enable, + .atomic_disable = tilcdc_crtc_atomic_disable, }; int tilcdc_crtc_max_width(struct drm_crtc *crtc) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 4c03a565b276..9e0c1500375c 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -479,7 +479,8 @@ static void require_hvs_enabled(struct drm_device *dev) SCALER_DISPCTRL_ENABLE); } -static void vc4_crtc_disable(struct drm_crtc *crtc) +static void vc4_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct drm_device *dev = crtc->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); @@ -870,11 +871,11 @@ static const struct drm_crtc_funcs vc4_crtc_funcs = { static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = { .mode_set_nofb = vc4_crtc_mode_set_nofb, - .disable = vc4_crtc_disable, .mode_valid = vc4_crtc_mode_valid, .atomic_check = vc4_crtc_atomic_check, .atomic_flush = vc4_crtc_atomic_flush, .atomic_enable = vc4_crtc_atomic_enable, + .atomic_disable = vc4_crtc_atomic_disable, }; static const struct vc4_crtc_data pv0_data = { diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index 03a3c12ed100..ffd22e5ab43a 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c @@ -118,7 +118,8 @@ static void virtio_gpu_crtc_atomic_enable(struct drm_crtc *crtc, { } -static void virtio_gpu_crtc_disable(struct drm_crtc *crtc) +static void virtio_gpu_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct drm_device *dev = crtc->dev; struct virtio_gpu_device *vgdev = dev->dev_private; @@ -146,11 +147,11 @@ static void virtio_gpu_crtc_atomic_flush(struct drm_crtc *crtc, } static const struct drm_crtc_helper_funcs virtio_gpu_crtc_helper_funcs = { - .disable = virtio_gpu_crtc_disable, .mode_set_nofb = virtio_gpu_crtc_mode_set_nofb, .atomic_check = virtio_gpu_crtc_atomic_check, .atomic_flush = virtio_gpu_crtc_atomic_flush, .atomic_enable = virtio_gpu_crtc_atomic_enable, + .atomic_disable = virtio_gpu_crtc_atomic_disable, }; static void virtio_gpu_enc_mode_set(struct drm_encoder *encoder, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 832b83c582c2..6391069498d6 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -218,11 +218,12 @@ static void vmw_ldu_crtc_atomic_enable(struct drm_crtc *crtc, } /** - * vmw_ldu_crtc_helper_disable - Turns off CRTC + * vmw_ldu_crtc_atomic_disable - Turns off CRTC * * @crtc: CRTC to be turned off */ -static void vmw_ldu_crtc_helper_disable(struct drm_crtc *crtc) +static void vmw_ldu_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { } @@ -377,12 +378,12 @@ drm_plane_helper_funcs vmw_ldu_primary_plane_helper_funcs = { }; static const struct drm_crtc_helper_funcs vmw_ldu_crtc_helper_funcs = { - .disable = vmw_ldu_crtc_helper_disable, .mode_set_nofb = vmw_ldu_crtc_mode_set_nofb, .atomic_check = vmw_du_crtc_atomic_check, .atomic_begin = vmw_du_crtc_atomic_begin, .atomic_flush = vmw_du_crtc_atomic_flush, .atomic_enable = vmw_ldu_crtc_atomic_enable, + .atomic_disable = vmw_ldu_crtc_atomic_disable, }; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index 8ba3bad06909..854403509216 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c @@ -282,11 +282,12 @@ static void vmw_sou_crtc_atomic_enable(struct drm_crtc *crtc, } /** - * vmw_sou_crtc_helper_disable - Turns off CRTC + * vmw_sou_crtc_atomic_disable - Turns off CRTC * * @crtc: CRTC to be turned off */ -static void vmw_sou_crtc_helper_disable(struct drm_crtc *crtc) +static void vmw_sou_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct vmw_private *dev_priv; struct vmw_screen_object_unit *sou; @@ -574,12 +575,12 @@ drm_plane_helper_funcs vmw_sou_primary_plane_helper_funcs = { static const struct drm_crtc_helper_funcs vmw_sou_crtc_helper_funcs = { .prepare = vmw_sou_crtc_helper_prepare, - .disable = vmw_sou_crtc_helper_disable, .mode_set_nofb = vmw_sou_crtc_mode_set_nofb, .atomic_check = vmw_du_crtc_atomic_check, .atomic_begin = vmw_du_crtc_atomic_begin, .atomic_flush = vmw_du_crtc_atomic_flush, .atomic_enable = vmw_sou_crtc_atomic_enable, + .atomic_disable = vmw_sou_crtc_atomic_disable, }; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c index f2b39d9c51cc..ed9404a7f457 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c @@ -433,7 +433,8 @@ static void vmw_stdu_crtc_atomic_enable(struct drm_crtc *crtc, vmw_kms_del_active(dev_priv, &stdu->base); } -static void vmw_stdu_crtc_helper_disable(struct drm_crtc *crtc) +static void vmw_stdu_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct vmw_private *dev_priv; struct vmw_screen_target_display_unit *stdu; @@ -1416,12 +1417,12 @@ drm_plane_helper_funcs vmw_stdu_primary_plane_helper_funcs = { static const struct drm_crtc_helper_funcs vmw_stdu_crtc_helper_funcs = { .prepare = vmw_stdu_crtc_helper_prepare, - .disable = vmw_stdu_crtc_helper_disable, .mode_set_nofb = vmw_stdu_crtc_mode_set_nofb, .atomic_check = vmw_du_crtc_atomic_check, .atomic_begin = vmw_du_crtc_atomic_begin, .atomic_flush = vmw_du_crtc_atomic_flush, .atomic_enable = vmw_stdu_crtc_atomic_enable, + .atomic_disable = vmw_stdu_crtc_atomic_disable, }; diff --git a/drivers/gpu/drm/zte/zx_vou.c b/drivers/gpu/drm/zte/zx_vou.c index ccb4b0bdb8c6..7491813131f3 100644 --- a/drivers/gpu/drm/zte/zx_vou.c +++ b/drivers/gpu/drm/zte/zx_vou.c @@ -455,7 +455,8 @@ static void zx_crtc_atomic_enable(struct drm_crtc *crtc, DRM_DEV_ERROR(vou->dev, "failed to enable pixclk: %d\n", ret); } -static void zx_crtc_disable(struct drm_crtc *crtc) +static void zx_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct zx_crtc *zcrtc = to_zx_crtc(crtc); const struct zx_crtc_bits *bits = zcrtc->bits; @@ -491,9 +492,9 @@ static void zx_crtc_atomic_flush(struct drm_crtc *crtc, } static const struct drm_crtc_helper_funcs zx_crtc_helper_funcs = { - .disable = zx_crtc_disable, .atomic_flush = zx_crtc_atomic_flush, .atomic_enable = zx_crtc_atomic_enable, + .atomic_disable = zx_crtc_atomic_disable, }; static int zx_vou_enable_vblank(struct drm_crtc *crtc) -- cgit v1.2.3 From d48cb5f541c953ae2a33657f582d93c4151f27d9 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 30 Jun 2017 09:39:21 +0200 Subject: drm/atomic: Drop helper include from drm_atomic.c Core code should never have to look at helper stuff, to make sure that all helper code is 100% optional and can be overriden. Cc: Gustavo Padovan Reviewed-by: Gustavo Padovan Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170630073921.2345-1-daniel.vetter@ffwll.ch --- drivers/gpu/drm/drm_atomic.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 095e87278a88..09ca662fcd35 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include -- cgit v1.2.3 From fcace3b9b727e25ffa3f7ad2c96e76b8584a9f3e Mon Sep 17 00:00:00 2001 From: "Navare, Manasi D" Date: Thu, 29 Jun 2017 18:14:01 -0700 Subject: drm/i915/cnl: Fix the CURSOR_COEFF_MASK used in DDI Vswing Programming The Cursor Coeff is lower 6 bits in the PORT_TX_DW4 register and hence the CURSOR_COEFF_MASK should be (0x3F << 0) Fixes: 04416108ccea ("drm/i915/cnl: Add registers related to voltage swing sequences.") Signed-off-by: Manasi Navare Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi Link: http://patchwork.freedesktop.org/patch/msgid/1498785241-21138-1-git-send-email-manasi.d.navare@intel.com --- drivers/gpu/drm/i915/i915_reg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index c8647cfa81ba..64cc674b652a 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1802,7 +1802,7 @@ enum skl_disp_power_wells { #define POST_CURSOR_2(x) ((x) << 6) #define POST_CURSOR_2_MASK (0x3F << 6) #define CURSOR_COEFF(x) ((x) << 0) -#define CURSOR_COEFF_MASK (0x3F << 6) +#define CURSOR_COEFF_MASK (0x3F << 0) #define _CNL_PORT_TX_DW5_GRP_AE 0x162354 #define _CNL_PORT_TX_DW5_GRP_B 0x1623D4 -- cgit v1.2.3 From 1911f48de0d90b30a424906b7343b20dac90e3d9 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 19 Jun 2017 08:22:25 +0200 Subject: iio: accel: bmc150: Add support for BOSC0200 ACPI device id Add support for the BOSC0200 ACPI device id used on some x86 tablets. note driver_data is not set to a specific model, driver_data is not used anyways (instead detection is done on the chip_id reg) and the 2 tablets with a BOSC0200 ACPI device id I've have 2 different chips, one has a BMA250E, the other a BMA222E. Signed-off-by: Hans de Goede Signed-off-by: Jonathan Cameron --- drivers/iio/accel/bmc150-accel-i2c.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/iio/accel/bmc150-accel-i2c.c b/drivers/iio/accel/bmc150-accel-i2c.c index 8ca8041267ef..f85014fbaa12 100644 --- a/drivers/iio/accel/bmc150-accel-i2c.c +++ b/drivers/iio/accel/bmc150-accel-i2c.c @@ -64,6 +64,7 @@ static const struct acpi_device_id bmc150_accel_acpi_match[] = { {"BMA250E", bma250e}, {"BMA222E", bma222e}, {"BMA0280", bma280}, + {"BOSC0200"}, { }, }; MODULE_DEVICE_TABLE(acpi, bmc150_accel_acpi_match); -- cgit v1.2.3 From 45a4e4220bf4927e321e18750e47c576bf62b000 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 19 Jun 2017 22:04:30 +0200 Subject: iio: gyro: st_gyro: fix L3GD20H support Add proper support for L3GD20H gyroscope sensor. In particular: - use L3GD20H as device name instead of L3GD20 - fix available full scales - fix available sample frequencies Note that the original patch listed first below introduced broken support for this part. The second patch drops the support as it didn't work. This new patch brings in working support. Fixes: 9444a300c2be (IIO: Add support for L3GD20H gyroscope) Fixes: a0657716416f ("iio:gyro: bug on L3GD20H gyroscope support") Signed-off-by: Lorenzo Bianconi Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/st_gyro.h | 1 + drivers/iio/gyro/st_gyro_core.c | 13 +++++++------ drivers/iio/gyro/st_gyro_i2c.c | 5 +++++ drivers/iio/gyro/st_gyro_spi.c | 1 + 4 files changed, 14 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/gyro/st_gyro.h b/drivers/iio/gyro/st_gyro.h index a5c5c4e29add..48923ae6ac3b 100644 --- a/drivers/iio/gyro/st_gyro.h +++ b/drivers/iio/gyro/st_gyro.h @@ -19,6 +19,7 @@ #define LSM330DL_GYRO_DEV_NAME "lsm330dl_gyro" #define LSM330DLC_GYRO_DEV_NAME "lsm330dlc_gyro" #define L3GD20_GYRO_DEV_NAME "l3gd20" +#define L3GD20H_GYRO_DEV_NAME "l3gd20h" #define L3G4IS_GYRO_DEV_NAME "l3g4is_ui" #define LSM330_GYRO_DEV_NAME "lsm330_gyro" #define LSM9DS0_GYRO_DEV_NAME "lsm9ds0_gyro" diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c index 2a42b3d583e8..e366422e8512 100644 --- a/drivers/iio/gyro/st_gyro_core.c +++ b/drivers/iio/gyro/st_gyro_core.c @@ -35,6 +35,7 @@ #define ST_GYRO_DEFAULT_OUT_Z_L_ADDR 0x2c /* FULLSCALE */ +#define ST_GYRO_FS_AVL_245DPS 245 #define ST_GYRO_FS_AVL_250DPS 250 #define ST_GYRO_FS_AVL_500DPS 500 #define ST_GYRO_FS_AVL_2000DPS 2000 @@ -196,17 +197,17 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { .wai = 0xd7, .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, .sensors_supported = { - [0] = L3GD20_GYRO_DEV_NAME, + [0] = L3GD20H_GYRO_DEV_NAME, }, .ch = (struct iio_chan_spec *)st_gyro_16bit_channels, .odr = { .addr = 0x20, .mask = 0xc0, .odr_avl = { - { .hz = 95, .value = 0x00, }, - { .hz = 190, .value = 0x01, }, - { .hz = 380, .value = 0x02, }, - { .hz = 760, .value = 0x03, }, + { .hz = 100, .value = 0x00, }, + { .hz = 200, .value = 0x01, }, + { .hz = 400, .value = 0x02, }, + { .hz = 800, .value = 0x03, }, }, }, .pw = { @@ -224,7 +225,7 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { .mask = 0x30, .fs_avl = { [0] = { - .num = ST_GYRO_FS_AVL_250DPS, + .num = ST_GYRO_FS_AVL_245DPS, .value = 0x00, .gain = IIO_DEGREE_TO_RAD(8750), }, diff --git a/drivers/iio/gyro/st_gyro_i2c.c b/drivers/iio/gyro/st_gyro_i2c.c index 40056b821036..3f628746cb93 100644 --- a/drivers/iio/gyro/st_gyro_i2c.c +++ b/drivers/iio/gyro/st_gyro_i2c.c @@ -40,6 +40,10 @@ static const struct of_device_id st_gyro_of_match[] = { .compatible = "st,l3gd20-gyro", .data = L3GD20_GYRO_DEV_NAME, }, + { + .compatible = "st,l3gd20h-gyro", + .data = L3GD20H_GYRO_DEV_NAME, + }, { .compatible = "st,l3g4is-gyro", .data = L3G4IS_GYRO_DEV_NAME, @@ -95,6 +99,7 @@ static const struct i2c_device_id st_gyro_id_table[] = { { LSM330DL_GYRO_DEV_NAME }, { LSM330DLC_GYRO_DEV_NAME }, { L3GD20_GYRO_DEV_NAME }, + { L3GD20H_GYRO_DEV_NAME }, { L3G4IS_GYRO_DEV_NAME }, { LSM330_GYRO_DEV_NAME }, { LSM9DS0_GYRO_DEV_NAME }, diff --git a/drivers/iio/gyro/st_gyro_spi.c b/drivers/iio/gyro/st_gyro_spi.c index fbf2faed501c..fa14d8f2170d 100644 --- a/drivers/iio/gyro/st_gyro_spi.c +++ b/drivers/iio/gyro/st_gyro_spi.c @@ -52,6 +52,7 @@ static const struct spi_device_id st_gyro_id_table[] = { { LSM330DL_GYRO_DEV_NAME }, { LSM330DLC_GYRO_DEV_NAME }, { L3GD20_GYRO_DEV_NAME }, + { L3GD20H_GYRO_DEV_NAME }, { L3G4IS_GYRO_DEV_NAME }, { LSM330_GYRO_DEV_NAME }, { LSM9DS0_GYRO_DEV_NAME }, -- cgit v1.2.3 From 8f4c9575a8e29f6ee0a45a1288eb4af9f215279d Mon Sep 17 00:00:00 2001 From: Michael Stecklein Date: Mon, 19 Jun 2017 11:01:05 -0500 Subject: iio: humidity: hdc100x: document compatible HDC10xx devices Include datasheet links, add i2c_device_id entries, and update kconfig help for compatible HDC10xx devices: HDC1000, HDC1008, HDC1010, HDC1050, and HDC1080. Signed-off-by: Michael Stecklein Signed-off-by: Jonathan Cameron --- drivers/iio/humidity/Kconfig | 3 ++- drivers/iio/humidity/hdc100x.c | 11 +++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/humidity/Kconfig b/drivers/iio/humidity/Kconfig index 14b9ce453d9d..2c0fc9a400b8 100644 --- a/drivers/iio/humidity/Kconfig +++ b/drivers/iio/humidity/Kconfig @@ -31,7 +31,8 @@ config HDC100X select IIO_TRIGGERED_BUFFER help Say yes here to build support for the Texas Instruments - HDC1000 and HDC1008 relative humidity and temperature sensors. + HDC1000, HDC1008, HDC1010, HDC1050, and HDC1080 relative + humidity and temperature sensors. To compile this driver as a module, choose M here: the module will be called hdc100x. diff --git a/drivers/iio/humidity/hdc100x.c b/drivers/iio/humidity/hdc100x.c index aa17115f54c9..6778bc73d5c4 100644 --- a/drivers/iio/humidity/hdc100x.c +++ b/drivers/iio/humidity/hdc100x.c @@ -13,6 +13,12 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * + * Datasheets: + * http://www.ti.com/product/HDC1000/datasheet + * http://www.ti.com/product/HDC1008/datasheet + * http://www.ti.com/product/HDC1010/datasheet + * http://www.ti.com/product/HDC1050/datasheet + * http://www.ti.com/product/HDC1080/datasheet */ #include @@ -414,6 +420,11 @@ static int hdc100x_remove(struct i2c_client *client) static const struct i2c_device_id hdc100x_id[] = { { "hdc100x", 0 }, + { "hdc1000", 0 }, + { "hdc1008", 0 }, + { "hdc1010", 0 }, + { "hdc1050", 0 }, + { "hdc1080", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, hdc100x_id); -- cgit v1.2.3 From a2d80de873de0a01c14aae4d85c5558be23c42d1 Mon Sep 17 00:00:00 2001 From: Michael Stecklein Date: Mon, 19 Jun 2017 11:01:06 -0500 Subject: iio: humidity: hdc100x: add match table and device id's Add of_match_table and point it to a list of compatible device tree device id's. Signed-off-by: Michael Stecklein Signed-off-by: Jonathan Cameron --- drivers/iio/humidity/hdc100x.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/iio/humidity/hdc100x.c b/drivers/iio/humidity/hdc100x.c index 6778bc73d5c4..7851bd90ef64 100644 --- a/drivers/iio/humidity/hdc100x.c +++ b/drivers/iio/humidity/hdc100x.c @@ -429,9 +429,20 @@ static const struct i2c_device_id hdc100x_id[] = { }; MODULE_DEVICE_TABLE(i2c, hdc100x_id); +static const struct of_device_id hdc100x_dt_ids[] = { + { .compatible = "ti,hdc1000" }, + { .compatible = "ti,hdc1008" }, + { .compatible = "ti,hdc1010" }, + { .compatible = "ti,hdc1050" }, + { .compatible = "ti,hdc1080" }, + { } +}; +MODULE_DEVICE_TABLE(of, hdc100x_dt_ids); + static struct i2c_driver hdc100x_driver = { .driver = { .name = "hdc100x", + .of_match_table = of_match_ptr(hdc100x_dt_ids), }, .probe = hdc100x_probe, .remove = hdc100x_remove, -- cgit v1.2.3 From edd80a5f511c5c9f01042a12588be5e5af4efab7 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sat, 17 Jun 2017 18:00:16 -0300 Subject: iio: adc: Kconfig: Append vendor name for IMX7D_ADC To keep IMX7D_ADC text consistent with other iio/adc entries, add the vendor name to the driver menu text. Signed-off-by: Fabio Estevam Signed-off-by: Jonathan Cameron --- drivers/iio/adc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 614fa41559b1..b56c4a1989a7 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -322,7 +322,7 @@ config INA2XX_ADC This driver is mutually exclusive with the HWMON version. config IMX7D_ADC - tristate "IMX7D ADC driver" + tristate "Freescale IMX7D ADC driver" depends on ARCH_MXC || COMPILE_TEST depends on HAS_IOMEM help -- cgit v1.2.3 From 5e1a1da0f8c9142902a97fe48b008860f5c7a305 Mon Sep 17 00:00:00 2001 From: Eugen Hristev Date: Thu, 15 Jun 2017 16:24:57 +0300 Subject: iio: adc: at91-sama5d2_adc: add hw trigger and buffer support Added support for the external hardware trigger on pin ADTRG, integrated the three possible edges into the driver and created buffer management for data retrieval Signed-off-by: Eugen Hristev Acked-by: Ludovic Desroches Signed-off-by: Jonathan Cameron --- drivers/iio/adc/at91-sama5d2_adc.c | 237 ++++++++++++++++++++++++++++++++++++- 1 file changed, 232 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c index e10dca3ed74b..1773a5dc06b2 100644 --- a/drivers/iio/adc/at91-sama5d2_adc.c +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -25,6 +25,10 @@ #include #include #include +#include +#include +#include +#include #include /* Control Register */ @@ -132,6 +136,17 @@ #define AT91_SAMA5D2_PRESSR 0xbc /* Trigger Register */ #define AT91_SAMA5D2_TRGR 0xc0 +/* Mask for TRGMOD field of TRGR register */ +#define AT91_SAMA5D2_TRGR_TRGMOD_MASK GENMASK(2, 0) +/* No trigger, only software trigger can start conversions */ +#define AT91_SAMA5D2_TRGR_TRGMOD_NO_TRIGGER 0 +/* Trigger Mode external trigger rising edge */ +#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_RISE 1 +/* Trigger Mode external trigger falling edge */ +#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_FALL 2 +/* Trigger Mode external trigger any edge */ +#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_ANY 3 + /* Correction Select Register */ #define AT91_SAMA5D2_COSR 0xd0 /* Correction Value Register */ @@ -145,14 +160,29 @@ /* Version Register */ #define AT91_SAMA5D2_VERSION 0xfc +#define AT91_SAMA5D2_HW_TRIG_CNT 3 +#define AT91_SAMA5D2_SINGLE_CHAN_CNT 12 +#define AT91_SAMA5D2_DIFF_CHAN_CNT 6 + +/* + * Maximum number of bytes to hold conversion from all channels + * plus the timestamp + */ +#define AT91_BUFFER_MAX_BYTES ((AT91_SAMA5D2_SINGLE_CHAN_CNT + \ + AT91_SAMA5D2_DIFF_CHAN_CNT) * 2 + 8) + +#define AT91_BUFFER_MAX_HWORDS (AT91_BUFFER_MAX_BYTES / 2) + #define AT91_SAMA5D2_CHAN_SINGLE(num, addr) \ { \ .type = IIO_VOLTAGE, \ .channel = num, \ .address = addr, \ + .scan_index = num, \ .scan_type = { \ .sign = 'u', \ .realbits = 12, \ + .storagebits = 16, \ }, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ @@ -168,9 +198,11 @@ .channel = num, \ .channel2 = num2, \ .address = addr, \ + .scan_index = num + AT91_SAMA5D2_SINGLE_CHAN_CNT, \ .scan_type = { \ .sign = 's', \ .realbits = 12, \ + .storagebits = 16, \ }, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ @@ -188,6 +220,12 @@ struct at91_adc_soc_info { unsigned max_sample_rate; }; +struct at91_adc_trigger { + char *name; + unsigned int trgmod_value; + unsigned int edge_type; +}; + struct at91_adc_state { void __iomem *base; int irq; @@ -195,11 +233,14 @@ struct at91_adc_state { struct regulator *reg; struct regulator *vref; int vref_uv; + struct iio_trigger *trig; + const struct at91_adc_trigger *selected_trig; const struct iio_chan_spec *chan; bool conversion_done; u32 conversion_value; struct at91_adc_soc_info soc_info; wait_queue_head_t wq_data_available; + u16 buffer[AT91_BUFFER_MAX_HWORDS]; /* * lock to prevent concurrent 'single conversion' requests through * sysfs. @@ -207,6 +248,24 @@ struct at91_adc_state { struct mutex lock; }; +static const struct at91_adc_trigger at91_adc_trigger_list[] = { + { + .name = "external_rising", + .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_RISE, + .edge_type = IRQ_TYPE_EDGE_RISING, + }, + { + .name = "external_falling", + .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_FALL, + .edge_type = IRQ_TYPE_EDGE_FALLING, + }, + { + .name = "external_any", + .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_ANY, + .edge_type = IRQ_TYPE_EDGE_BOTH, + }, +}; + static const struct iio_chan_spec at91_adc_channels[] = { AT91_SAMA5D2_CHAN_SINGLE(0, 0x50), AT91_SAMA5D2_CHAN_SINGLE(1, 0x54), @@ -226,8 +285,128 @@ static const struct iio_chan_spec at91_adc_channels[] = { AT91_SAMA5D2_CHAN_DIFF(6, 7, 0x68), AT91_SAMA5D2_CHAN_DIFF(8, 9, 0x70), AT91_SAMA5D2_CHAN_DIFF(10, 11, 0x78), + IIO_CHAN_SOFT_TIMESTAMP(AT91_SAMA5D2_SINGLE_CHAN_CNT + + AT91_SAMA5D2_DIFF_CHAN_CNT + 1), +}; + +static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state) +{ + struct iio_dev *indio = iio_trigger_get_drvdata(trig); + struct at91_adc_state *st = iio_priv(indio); + u32 status = at91_adc_readl(st, AT91_SAMA5D2_TRGR); + u8 bit; + + /* clear TRGMOD */ + status &= ~AT91_SAMA5D2_TRGR_TRGMOD_MASK; + + if (state) + status |= st->selected_trig->trgmod_value; + + /* set/unset hw trigger */ + at91_adc_writel(st, AT91_SAMA5D2_TRGR, status); + + for_each_set_bit(bit, indio->active_scan_mask, indio->num_channels) { + struct iio_chan_spec const *chan = indio->channels + bit; + + if (state) { + at91_adc_writel(st, AT91_SAMA5D2_CHER, + BIT(chan->channel)); + at91_adc_writel(st, AT91_SAMA5D2_IER, + BIT(chan->channel)); + } else { + at91_adc_writel(st, AT91_SAMA5D2_IDR, + BIT(chan->channel)); + at91_adc_writel(st, AT91_SAMA5D2_CHDR, + BIT(chan->channel)); + } + } + + return 0; +} + +static int at91_adc_reenable_trigger(struct iio_trigger *trig) +{ + struct iio_dev *indio = iio_trigger_get_drvdata(trig); + struct at91_adc_state *st = iio_priv(indio); + + enable_irq(st->irq); + + /* Needed to ACK the DRDY interruption */ + at91_adc_readl(st, AT91_SAMA5D2_LCDR); + return 0; +} + +static const struct iio_trigger_ops at91_adc_trigger_ops = { + .owner = THIS_MODULE, + .set_trigger_state = &at91_adc_configure_trigger, + .try_reenable = &at91_adc_reenable_trigger, }; +static struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *indio, + char *trigger_name) +{ + struct iio_trigger *trig; + int ret; + + trig = devm_iio_trigger_alloc(&indio->dev, "%s-dev%d-%s", indio->name, + indio->id, trigger_name); + if (!trig) + return NULL; + + trig->dev.parent = indio->dev.parent; + iio_trigger_set_drvdata(trig, indio); + trig->ops = &at91_adc_trigger_ops; + + ret = devm_iio_trigger_register(&indio->dev, trig); + if (ret) + return ERR_PTR(ret); + + return trig; +} + +static int at91_adc_trigger_init(struct iio_dev *indio) +{ + struct at91_adc_state *st = iio_priv(indio); + + st->trig = at91_adc_allocate_trigger(indio, st->selected_trig->name); + if (IS_ERR(st->trig)) { + dev_err(&indio->dev, + "could not allocate trigger\n"); + return PTR_ERR(st->trig); + } + + return 0; +} + +static irqreturn_t at91_adc_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio = pf->indio_dev; + struct at91_adc_state *st = iio_priv(indio); + int i = 0; + u8 bit; + + for_each_set_bit(bit, indio->active_scan_mask, indio->num_channels) { + struct iio_chan_spec const *chan = indio->channels + bit; + + st->buffer[i] = at91_adc_readl(st, chan->address); + i++; + } + + iio_push_to_buffers_with_timestamp(indio, st->buffer, pf->timestamp); + + iio_trigger_notify_done(indio->trig); + + return IRQ_HANDLED; +} + +static int at91_adc_buffer_init(struct iio_dev *indio) +{ + return devm_iio_triggered_buffer_setup(&indio->dev, indio, + &iio_pollfunc_store_time, + &at91_adc_trigger_handler, NULL); +} + static unsigned at91_adc_startup_time(unsigned startup_time_min, unsigned adc_clk_khz) { @@ -293,14 +472,18 @@ static irqreturn_t at91_adc_interrupt(int irq, void *private) u32 status = at91_adc_readl(st, AT91_SAMA5D2_ISR); u32 imr = at91_adc_readl(st, AT91_SAMA5D2_IMR); - if (status & imr) { + if (!(status & imr)) + return IRQ_NONE; + + if (iio_buffer_enabled(indio)) { + disable_irq_nosync(irq); + iio_trigger_poll(indio->trig); + } else { st->conversion_value = at91_adc_readl(st, st->chan->address); st->conversion_done = true; wake_up_interruptible(&st->wq_data_available); - return IRQ_HANDLED; } - - return IRQ_NONE; + return IRQ_HANDLED; } static int at91_adc_read_raw(struct iio_dev *indio_dev, @@ -313,6 +496,11 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: + /* we cannot use software trigger if hw trigger enabled */ + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + mutex_lock(&st->lock); st->chan = chan; @@ -344,6 +532,8 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev, at91_adc_writel(st, AT91_SAMA5D2_CHDR, BIT(chan->channel)); mutex_unlock(&st->lock); + + iio_device_release_direct_mode(indio_dev); return ret; case IIO_CHAN_INFO_SCALE: @@ -391,7 +581,8 @@ static int at91_adc_probe(struct platform_device *pdev) struct iio_dev *indio_dev; struct at91_adc_state *st; struct resource *res; - int ret; + int ret, i; + u32 edge_type; indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st)); if (!indio_dev) @@ -432,6 +623,27 @@ static int at91_adc_probe(struct platform_device *pdev) return ret; } + ret = of_property_read_u32(pdev->dev.of_node, + "atmel,trigger-edge-type", &edge_type); + if (ret) { + dev_err(&pdev->dev, + "invalid or missing value for atmel,trigger-edge-type\n"); + return ret; + } + + st->selected_trig = NULL; + + for (i = 0; i < AT91_SAMA5D2_HW_TRIG_CNT; i++) + if (at91_adc_trigger_list[i].edge_type == edge_type) { + st->selected_trig = &at91_adc_trigger_list[i]; + break; + } + + if (!st->selected_trig) { + dev_err(&pdev->dev, "invalid external trigger edge value\n"); + return -EINVAL; + } + init_waitqueue_head(&st->wq_data_available); mutex_init(&st->lock); @@ -499,10 +711,25 @@ static int at91_adc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, indio_dev); + ret = at91_adc_buffer_init(indio_dev); + if (ret < 0) { + dev_err(&pdev->dev, "couldn't initialize the buffer.\n"); + goto per_clk_disable_unprepare; + } + + ret = at91_adc_trigger_init(indio_dev); + if (ret < 0) { + dev_err(&pdev->dev, "couldn't setup the triggers.\n"); + goto per_clk_disable_unprepare; + } + ret = iio_device_register(indio_dev); if (ret < 0) goto per_clk_disable_unprepare; + dev_info(&pdev->dev, "setting up trigger as %s\n", + st->selected_trig->name); + dev_info(&pdev->dev, "version: %x\n", readl_relaxed(st->base + AT91_SAMA5D2_VERSION)); -- cgit v1.2.3 From 55eaac2b9980a8a24f0f7ad6dde8a48e1795fbd9 Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Tue, 13 Jun 2017 21:22:22 +0530 Subject: iio: temperature: tsys01: Add OF match table Add of_match_table for Measurement Specialties TSYS01 temperature sensor Signed-off-by: Manivannan Sadhasivam Signed-off-by: Jonathan Cameron --- drivers/iio/temperature/tsys01.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/iio/temperature/tsys01.c b/drivers/iio/temperature/tsys01.c index 3e60c6189d98..d8aa211d76e4 100644 --- a/drivers/iio/temperature/tsys01.c +++ b/drivers/iio/temperature/tsys01.c @@ -214,11 +214,18 @@ static const struct i2c_device_id tsys01_id[] = { }; MODULE_DEVICE_TABLE(i2c, tsys01_id); +static const struct of_device_id tsys01_of_match[] = { + { .compatible = "meas,tsys01", }, + { }, +}; +MODULE_DEVICE_TABLE(of, tsys01_of_match); + static struct i2c_driver tsys01_driver = { .probe = tsys01_i2c_probe, .id_table = tsys01_id, .driver = { .name = "tsys01", + .of_match_table = of_match_ptr(tsys01_of_match), }, }; -- cgit v1.2.3 From e5c2ce6bacfa98fdfc6fe984833656fabaeecd2b Mon Sep 17 00:00:00 2001 From: Stefan Brüns Date: Wed, 24 May 2017 02:09:07 +0200 Subject: iio: adc: Fix polling of INA219 conversion ready flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While the INA226 has a conversion ready flag (CVRF) in the R/W Mask/Enable register with read-to-clear semantics, the corresponding bit of the INA219 (CNVR) is part of the bus voltage register. The flag is cleared by reading the power register. Signed-off-by: Stefan Brüns Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ina2xx-adc.c | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c index 232c0b80d658..68884d26b50c 100644 --- a/drivers/iio/adc/ina2xx-adc.c +++ b/drivers/iio/adc/ina2xx-adc.c @@ -44,6 +44,7 @@ #define INA226_MASK_ENABLE 0x06 #define INA226_CVRF BIT(3) +#define INA219_CNVR BIT(1) #define INA2XX_MAX_REGISTERS 8 @@ -592,6 +593,7 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev) int bit, ret, i = 0; s64 time_a, time_b; unsigned int alert; + int cnvr_need_clear = 0; time_a = iio_get_time_ns(indio_dev); @@ -603,22 +605,30 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev) * we check the ConVersionReadyFlag. * On hardware that supports using the ALERT pin to toggle a * GPIO a triggered buffer could be used instead. - * For now, we pay for that extra read of the ALERT register + * For now, we do an extra read of the MASK_ENABLE register (INA226) + * resp. the BUS_VOLTAGE register (INA219). */ if (!chip->allow_async_readout) do { - ret = regmap_read(chip->regmap, INA226_MASK_ENABLE, - &alert); + if (chip->config->chip_id == ina226) { + ret = regmap_read(chip->regmap, + INA226_MASK_ENABLE, &alert); + alert &= INA226_CVRF; + } else { + ret = regmap_read(chip->regmap, + INA2XX_BUS_VOLTAGE, &alert); + alert &= INA219_CNVR; + cnvr_need_clear = alert; + } + if (ret < 0) return ret; - alert &= INA226_CVRF; } while (!alert); /* - * Single register reads: bulk_read will not work with ina226 - * as there is no auto-increment of the address register for - * data length longer than 16bits. + * Single register reads: bulk_read will not work with ina226/219 + * as there is no auto-increment of the register pointer. */ for_each_set_bit(bit, indio_dev->active_scan_mask, indio_dev->masklength) { @@ -630,6 +640,18 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev) return ret; data[i++] = val; + + if (INA2XX_SHUNT_VOLTAGE + bit == INA2XX_POWER) + cnvr_need_clear = 0; + } + + /* Dummy read on INA219 power register to clear CNVR flag */ + if (cnvr_need_clear && chip->config->chip_id == ina219) { + unsigned int val; + + ret = regmap_read(chip->regmap, INA2XX_POWER, &val); + if (ret < 0) + return ret; } time_b = iio_get_time_ns(indio_dev); -- cgit v1.2.3 From 53d7d8139f652f87e1d9aa877007e757d08fc59e Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Tue, 13 Jun 2017 00:05:08 +0900 Subject: iio: light: tcs3472: fix ATIME register write The integration time is controlled by the ATIME register only. However, this register is written by i2c_smbus_write_word_data() in write_raw(). We actually don't need to write a subsequent register. So just use i2c_smbus_write_byte_data() instead. Cc: Peter Meerwald Cc: Jonathan Cameron Signed-off-by: Akinobu Mita Acked-by: Peter Meerwald-Stadler Signed-off-by: Jonathan Cameron --- drivers/iio/light/tcs3472.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/light/tcs3472.c b/drivers/iio/light/tcs3472.c index 3aa71e34ae28..a9e153b3e1f9 100644 --- a/drivers/iio/light/tcs3472.c +++ b/drivers/iio/light/tcs3472.c @@ -169,7 +169,7 @@ static int tcs3472_write_raw(struct iio_dev *indio_dev, for (i = 0; i < 256; i++) { if (val2 == (256 - i) * 2400) { data->atime = i; - return i2c_smbus_write_word_data( + return i2c_smbus_write_byte_data( data->client, TCS3472_ATIME, data->atime); } -- cgit v1.2.3 From 13718564167da80b6169809185b4c5a32497d0c1 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 20 Jun 2017 19:42:45 +0200 Subject: iio: magnetometer: st_magn_core: enable multiread by default for LIS3MDL Enable multiread by default for LIS3MDL since using I2C interface the subaddr Msb is used to automatically increase the slave address during multiple data read/write. In the same way, using SPI interface, bit 1 in register address is used to enable auto-increment of the slave address in multiple read/write. Fixes: 872e79add756 (iio:magn: Add STMicroelectronics magn driver) Signed-off-by: Lorenzo Bianconi Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/st_magn_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c index 8e1b0861fbe4..3573636bad8e 100644 --- a/drivers/iio/magnetometer/st_magn_core.c +++ b/drivers/iio/magnetometer/st_magn_core.c @@ -315,7 +315,7 @@ static const struct st_sensor_settings st_magn_sensors_settings[] = { }, }, }, - .multi_read_bit = false, + .multi_read_bit = true, .bootime = 2, }, { -- cgit v1.2.3 From 250bbbdbed93ca27c9f4d445c960a87d9f7e2044 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 20 Jun 2017 21:52:08 +0200 Subject: iio: common: st_sensors: move st_sensors_of_i2c_probe() in common code Move st_sensors_of_i2c_probe() in st_sensors_core and rename it in st_sensors_of_name_probe(). That change is necessary to add device-tree support in spi code otherwise the rest of the autodetection will fail since spi->modalias (and indio_dev->name) will be set using compatible string value that differs from standard sensor name Signed-off-by: Lorenzo Bianconi Signed-off-by: Jonathan Cameron --- drivers/iio/accel/st_accel_i2c.c | 3 ++- drivers/iio/common/st_sensors/st_sensors_core.c | 31 +++++++++++++++++++++++++ drivers/iio/common/st_sensors/st_sensors_i2c.c | 29 ----------------------- drivers/iio/gyro/st_gyro_i2c.c | 3 ++- drivers/iio/magnetometer/st_magn_i2c.c | 3 ++- drivers/iio/pressure/st_pressure_i2c.c | 3 ++- include/linux/iio/common/st_sensors.h | 12 ++++++++++ include/linux/iio/common/st_sensors_i2c.h | 10 -------- 8 files changed, 51 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c index 543f0ad7fd7e..ac67826135be 100644 --- a/drivers/iio/accel/st_accel_i2c.c +++ b/drivers/iio/accel/st_accel_i2c.c @@ -144,7 +144,8 @@ static int st_accel_i2c_probe(struct i2c_client *client, adata = iio_priv(indio_dev); if (client->dev.of_node) { - st_sensors_of_i2c_probe(client, st_accel_of_match); + st_sensors_of_name_probe(&client->dev, st_accel_of_match, + client->name, sizeof(client->name)); } else if (ACPI_HANDLE(&client->dev)) { ret = st_sensors_match_acpi_device(&client->dev); if ((ret < 0) || (ret >= ST_ACCEL_MAX)) diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c index 79c8c7cd70d5..274868100fd0 100644 --- a/drivers/iio/common/st_sensors/st_sensors_core.c +++ b/drivers/iio/common/st_sensors/st_sensors_core.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -345,6 +346,36 @@ static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev, return pdata; } + +/** + * st_sensors_of_name_probe() - device tree probe for ST sensor name + * @dev: driver model representation of the device. + * @match: the OF match table for the device, containing compatible strings + * but also a .data field with the corresponding internal kernel name + * used by this sensor. + * @name: device name buffer reference. + * @len: device name buffer length. + * + * In effect this function matches a compatible string to an internal kernel + * name for a certain sensor device, so that the rest of the autodetection can + * rely on that name from this point on. I2C/SPI devices will be renamed + * to match the internal kernel convention. + */ +void st_sensors_of_name_probe(struct device *dev, + const struct of_device_id *match, + char *name, int len) +{ + const struct of_device_id *of_id; + + of_id = of_match_device(match, dev); + if (!of_id || !of_id->data) + return; + + /* The name from the OF match takes precedence if present */ + strncpy(name, of_id->data, len); + name[len - 1] = '\0'; +} +EXPORT_SYMBOL(st_sensors_of_name_probe); #else static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev, struct st_sensors_platform_data *defdata) diff --git a/drivers/iio/common/st_sensors/st_sensors_i2c.c b/drivers/iio/common/st_sensors/st_sensors_i2c.c index c83df4dbfcd7..b81e48e9f27e 100644 --- a/drivers/iio/common/st_sensors/st_sensors_i2c.c +++ b/drivers/iio/common/st_sensors/st_sensors_i2c.c @@ -79,35 +79,6 @@ void st_sensors_i2c_configure(struct iio_dev *indio_dev, } EXPORT_SYMBOL(st_sensors_i2c_configure); -#ifdef CONFIG_OF -/** - * st_sensors_of_i2c_probe() - device tree probe for ST I2C sensors - * @client: the I2C client device for the sensor - * @match: the OF match table for the device, containing compatible strings - * but also a .data field with the corresponding internal kernel name - * used by this sensor. - * - * In effect this function matches a compatible string to an internal kernel - * name for a certain sensor device, so that the rest of the autodetection can - * rely on that name from this point on. I2C client devices will be renamed - * to match the internal kernel convention. - */ -void st_sensors_of_i2c_probe(struct i2c_client *client, - const struct of_device_id *match) -{ - const struct of_device_id *of_id; - - of_id = of_match_device(match, &client->dev); - if (!of_id) - return; - - /* The name from the OF match takes precedence if present */ - strncpy(client->name, of_id->data, sizeof(client->name)); - client->name[sizeof(client->name) - 1] = '\0'; -} -EXPORT_SYMBOL(st_sensors_of_i2c_probe); -#endif - #ifdef CONFIG_ACPI int st_sensors_match_acpi_device(struct device *dev) { diff --git a/drivers/iio/gyro/st_gyro_i2c.c b/drivers/iio/gyro/st_gyro_i2c.c index 3f628746cb93..b405b82b9177 100644 --- a/drivers/iio/gyro/st_gyro_i2c.c +++ b/drivers/iio/gyro/st_gyro_i2c.c @@ -75,7 +75,8 @@ static int st_gyro_i2c_probe(struct i2c_client *client, return -ENOMEM; gdata = iio_priv(indio_dev); - st_sensors_of_i2c_probe(client, st_gyro_of_match); + st_sensors_of_name_probe(&client->dev, st_gyro_of_match, + client->name, sizeof(client->name)); st_sensors_i2c_configure(indio_dev, client, gdata); diff --git a/drivers/iio/magnetometer/st_magn_i2c.c b/drivers/iio/magnetometer/st_magn_i2c.c index 8aa37af306ed..6a6c8121ac2c 100644 --- a/drivers/iio/magnetometer/st_magn_i2c.c +++ b/drivers/iio/magnetometer/st_magn_i2c.c @@ -59,7 +59,8 @@ static int st_magn_i2c_probe(struct i2c_client *client, return -ENOMEM; mdata = iio_priv(indio_dev); - st_sensors_of_i2c_probe(client, st_magn_of_match); + st_sensors_of_name_probe(&client->dev, st_magn_of_match, + client->name, sizeof(client->name)); st_sensors_i2c_configure(indio_dev, client, mdata); diff --git a/drivers/iio/pressure/st_pressure_i2c.c b/drivers/iio/pressure/st_pressure_i2c.c index 17417a4d5a5f..7f15e927fa2b 100644 --- a/drivers/iio/pressure/st_pressure_i2c.c +++ b/drivers/iio/pressure/st_pressure_i2c.c @@ -77,7 +77,8 @@ static int st_press_i2c_probe(struct i2c_client *client, press_data = iio_priv(indio_dev); if (client->dev.of_node) { - st_sensors_of_i2c_probe(client, st_press_of_match); + st_sensors_of_name_probe(&client->dev, st_press_of_match, + client->name, sizeof(client->name)); } else if (ACPI_HANDLE(&client->dev)) { ret = st_sensors_match_acpi_device(&client->dev); if ((ret < 0) || (ret >= ST_PRESS_MAX)) diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h index 497f2b3a5a62..1f8211b6438b 100644 --- a/include/linux/iio/common/st_sensors.h +++ b/include/linux/iio/common/st_sensors.h @@ -325,4 +325,16 @@ ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev, ssize_t st_sensors_sysfs_scale_avail(struct device *dev, struct device_attribute *attr, char *buf); +#ifdef CONFIG_OF +void st_sensors_of_name_probe(struct device *dev, + const struct of_device_id *match, + char *name, int len); +#else +static inline void st_sensors_of_name_probe(struct device *dev, + const struct of_device_id *match, + char *name, int len) +{ +} +#endif + #endif /* ST_SENSORS_H */ diff --git a/include/linux/iio/common/st_sensors_i2c.h b/include/linux/iio/common/st_sensors_i2c.h index 254de3c7dde8..0a2c25e06d1f 100644 --- a/include/linux/iio/common/st_sensors_i2c.h +++ b/include/linux/iio/common/st_sensors_i2c.h @@ -18,16 +18,6 @@ void st_sensors_i2c_configure(struct iio_dev *indio_dev, struct i2c_client *client, struct st_sensor_data *sdata); -#ifdef CONFIG_OF -void st_sensors_of_i2c_probe(struct i2c_client *client, - const struct of_device_id *match); -#else -static inline void st_sensors_of_i2c_probe(struct i2c_client *client, - const struct of_device_id *match) -{ -} -#endif - #ifdef CONFIG_ACPI int st_sensors_match_acpi_device(struct device *dev); #else -- cgit v1.2.3 From c24f83bad9a4f1c8ea2f39771f6b2e3b2afd35ed Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 20 Jun 2017 21:52:09 +0200 Subject: iio: accel: st_accel_spi: rename of_device_id table in st_accel_of_match In order to add proper device tree support give a more general name to of_device_id table Signed-off-by: Lorenzo Bianconi Signed-off-by: Jonathan Cameron --- drivers/iio/accel/st_accel_spi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/accel/st_accel_spi.c b/drivers/iio/accel/st_accel_spi.c index 1a867f5563a4..d13742edee0e 100644 --- a/drivers/iio/accel/st_accel_spi.c +++ b/drivers/iio/accel/st_accel_spi.c @@ -62,17 +62,17 @@ static const struct spi_device_id st_accel_id_table[] = { MODULE_DEVICE_TABLE(spi, st_accel_id_table); #ifdef CONFIG_OF -static const struct of_device_id lis302dl_spi_dt_ids[] = { +static const struct of_device_id st_accel_of_match[] = { { .compatible = "st,lis302dl-spi" }, {} }; -MODULE_DEVICE_TABLE(of, lis302dl_spi_dt_ids); +MODULE_DEVICE_TABLE(of, st_accel_of_match); #endif static struct spi_driver st_accel_driver = { .driver = { .name = "st-accel-spi", - .of_match_table = of_match_ptr(lis302dl_spi_dt_ids), + .of_match_table = of_match_ptr(st_accel_of_match), }, .probe = st_accel_spi_probe, .remove = st_accel_spi_remove, -- cgit v1.2.3 From 500a2eefd6b16ba141a8fb777ea6962d2eb65e3b Mon Sep 17 00:00:00 2001 From: Eugen Hristev Date: Fri, 23 Jun 2017 15:54:57 +0300 Subject: iio: adc: at91-sama5d2_adc: add support for suspend/resume functionality Added support for suspend/resume functionality for the ADC IP in sama5d2 SoC. In order to enter Suspend to ram mode (backup + self refresh mode for memory), in which the ADC IP is no longer powered, we need to reset the pins to default state, for the scenario when they are also used for I2C bus to communicate with the PMIC. On resume, we need to reconfigure the ADC IP registers and reconfigure the trigger registers in the case when the suspend procedure is done while sysfs has the buffer and trigger enabled. In the case the suspend happens exactly during a software triggered conversion, the request will time out, because we reset and power down the ADC. Signed-off-by: Eugen Hristev Signed-off-by: Jonathan Cameron --- drivers/iio/adc/at91-sama5d2_adc.c | 90 +++++++++++++++++++++++++++++++++----- 1 file changed, 80 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c index 1773a5dc06b2..57e1eb23c45d 100644 --- a/drivers/iio/adc/at91-sama5d2_adc.c +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -29,6 +29,7 @@ #include #include #include +#include #include /* Control Register */ @@ -576,6 +577,20 @@ static const struct iio_info at91_adc_info = { .driver_module = THIS_MODULE, }; +static void at91_adc_hw_init(struct at91_adc_state *st) +{ + at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_SWRST); + at91_adc_writel(st, AT91_SAMA5D2_IDR, 0xffffffff); + /* + * Transfer field must be set to 2 according to the datasheet and + * allows different analog settings for each channel. + */ + at91_adc_writel(st, AT91_SAMA5D2_MR, + AT91_SAMA5D2_MR_TRANSFER(2) | AT91_SAMA5D2_MR_ANACH); + + at91_adc_setup_samp_freq(st, st->soc_info.min_sample_rate); +} + static int at91_adc_probe(struct platform_device *pdev) { struct iio_dev *indio_dev; @@ -694,16 +709,7 @@ static int at91_adc_probe(struct platform_device *pdev) goto vref_disable; } - at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_SWRST); - at91_adc_writel(st, AT91_SAMA5D2_IDR, 0xffffffff); - /* - * Transfer field must be set to 2 according to the datasheet and - * allows different analog settings for each channel. - */ - at91_adc_writel(st, AT91_SAMA5D2_MR, - AT91_SAMA5D2_MR_TRANSFER(2) | AT91_SAMA5D2_MR_ANACH); - - at91_adc_setup_samp_freq(st, st->soc_info.min_sample_rate); + at91_adc_hw_init(st); ret = clk_prepare_enable(st->per_clk); if (ret) @@ -759,6 +765,69 @@ static int at91_adc_remove(struct platform_device *pdev) return 0; } +static __maybe_unused int at91_adc_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = + platform_get_drvdata(to_platform_device(dev)); + struct at91_adc_state *st = iio_priv(indio_dev); + + /* + * Do a sofware reset of the ADC before we go to suspend. + * this will ensure that all pins are free from being muxed by the ADC + * and can be used by for other devices. + * Otherwise, ADC will hog them and we can't go to suspend mode. + */ + at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_SWRST); + + clk_disable_unprepare(st->per_clk); + regulator_disable(st->vref); + regulator_disable(st->reg); + + return pinctrl_pm_select_sleep_state(dev); +} + +static __maybe_unused int at91_adc_resume(struct device *dev) +{ + struct iio_dev *indio_dev = + platform_get_drvdata(to_platform_device(dev)); + struct at91_adc_state *st = iio_priv(indio_dev); + int ret; + + ret = pinctrl_pm_select_default_state(dev); + if (ret) + goto resume_failed; + + ret = regulator_enable(st->reg); + if (ret) + goto resume_failed; + + ret = regulator_enable(st->vref); + if (ret) + goto reg_disable_resume; + + ret = clk_prepare_enable(st->per_clk); + if (ret) + goto vref_disable_resume; + + at91_adc_hw_init(st); + + /* reconfiguring trigger hardware state */ + if (iio_buffer_enabled(indio_dev)) + at91_adc_configure_trigger(st->trig, true); + + return 0; + +vref_disable_resume: + regulator_disable(st->vref); +reg_disable_resume: + regulator_disable(st->reg); +resume_failed: + dev_err(&indio_dev->dev, "failed to resume\n"); + return ret; +} + +static SIMPLE_DEV_PM_OPS(at91_adc_pm_ops, at91_adc_suspend, at91_adc_resume); + static const struct of_device_id at91_adc_dt_match[] = { { .compatible = "atmel,sama5d2-adc", @@ -774,6 +843,7 @@ static struct platform_driver at91_adc_driver = { .driver = { .name = "at91-sama5d2_adc", .of_match_table = at91_adc_dt_match, + .pm = &at91_adc_pm_ops, }, }; module_platform_driver(at91_adc_driver) -- cgit v1.2.3 From c43aaa2772732a24a642afc26c030a2bee35aa0c Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Tue, 13 Jun 2017 22:50:05 +0530 Subject: iio: humidity: htu21: Add OF match table Add of_match_table for Measurement-Specialties htu21 temperature & humidity sensor and humidity part of MS8607 sensor Signed-off-by: Manivannan Sadhasivam Signed-off-by: Jonathan Cameron --- drivers/iio/humidity/htu21.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/iio/humidity/htu21.c b/drivers/iio/humidity/htu21.c index 0fbbd8c40894..2c4b9be85a05 100644 --- a/drivers/iio/humidity/htu21.c +++ b/drivers/iio/humidity/htu21.c @@ -238,11 +238,19 @@ static const struct i2c_device_id htu21_id[] = { }; MODULE_DEVICE_TABLE(i2c, htu21_id); +static const struct of_device_id htu21_of_match[] = { + { .compatible = "meas,htu21", }, + { .compatible = "meas,ms8607-humidity", }, + { }, +}; +MODULE_DEVICE_TABLE(of, htu21_of_match); + static struct i2c_driver htu21_driver = { .probe = htu21_probe, .id_table = htu21_id, .driver = { .name = "htu21", + .of_match_table = of_match_ptr(htu21_of_match), }, }; -- cgit v1.2.3 From 1813c71317df7a4b2578346967a3b3f6e6ab6c0e Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Tue, 13 Jun 2017 22:51:13 +0530 Subject: iio: pressure: ms5637: Add OF match table Add of_match_table for Measurement-Specialties MS5637, MS5805, MS5837 and MS8607 pressure & temperature sensor Signed-off-by: Manivannan Sadhasivam Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/ms5637.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/pressure/ms5637.c b/drivers/iio/pressure/ms5637.c index 953ffbc0ef96..c413f8a84a63 100644 --- a/drivers/iio/pressure/ms5637.c +++ b/drivers/iio/pressure/ms5637.c @@ -181,11 +181,21 @@ static const struct i2c_device_id ms5637_id[] = { }; MODULE_DEVICE_TABLE(i2c, ms5637_id); +static const struct of_device_id ms5637_of_match[] = { + { .compatible = "meas,ms5637", }, + { .compatible = "meas,ms5805", }, + { .compatible = "meas,ms5837", }, + { .compatible = "meas,ms8607-temppressure", }, + { }, +}; +MODULE_DEVICE_TABLE(of, ms5637_of_match); + static struct i2c_driver ms5637_driver = { .probe = ms5637_probe, .id_table = ms5637_id, .driver = { - .name = "ms5637" + .name = "ms5637", + .of_match_table = of_match_ptr(ms5637_of_match), }, }; -- cgit v1.2.3 From ff5fff4af47970cdeb92cb8194c8933db4ae248b Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 21 Jun 2017 21:21:28 +0200 Subject: iio: imu: st_lsm6dsx: support open drain mode Add open drain support in order to share requested IRQ line between st_lsm6dsx device and other peripherals Signed-off-by: Lorenzo Bianconi Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers') diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c index 2a72acc6e049..e2737dc71b67 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c @@ -31,6 +31,8 @@ #include #include +#include + #include "st_lsm6dsx.h" #define ST_LSM6DSX_REG_FIFO_THL_ADDR 0x06 @@ -39,6 +41,8 @@ #define ST_LSM6DSX_REG_FIFO_DEC_GXL_ADDR 0x08 #define ST_LSM6DSX_REG_HLACTIVE_ADDR 0x12 #define ST_LSM6DSX_REG_HLACTIVE_MASK BIT(5) +#define ST_LSM6DSX_REG_PP_OD_ADDR 0x12 +#define ST_LSM6DSX_REG_PP_OD_MASK BIT(4) #define ST_LSM6DSX_REG_FIFO_MODE_ADDR 0x0a #define ST_LSM6DSX_FIFO_MODE_MASK GENMASK(2, 0) #define ST_LSM6DSX_FIFO_ODR_MASK GENMASK(6, 3) @@ -417,6 +421,8 @@ static const struct iio_buffer_setup_ops st_lsm6dsx_buffer_ops = { int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw) { + struct device_node *np = hw->dev->of_node; + struct st_sensors_platform_data *pdata; struct iio_buffer *buffer; unsigned long irq_type; bool irq_active_low; @@ -444,6 +450,17 @@ int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw) if (err < 0) return err; + pdata = (struct st_sensors_platform_data *)hw->dev->platform_data; + if ((np && of_property_read_bool(np, "drive-open-drain")) || + (pdata && pdata->open_drain)) { + err = st_lsm6dsx_write_with_mask(hw, ST_LSM6DSX_REG_PP_OD_ADDR, + ST_LSM6DSX_REG_PP_OD_MASK, 1); + if (err < 0) + return err; + + irq_type |= IRQF_SHARED; + } + err = devm_request_threaded_irq(hw->dev, hw->irq, st_lsm6dsx_handler_irq, st_lsm6dsx_handler_thread, -- cgit v1.2.3 From 5236bbc6cd688c0065bf0fba59097b010dc22040 Mon Sep 17 00:00:00 2001 From: Zhiyong Tao Date: Mon, 26 Jun 2017 14:11:41 +0800 Subject: iio: adc: mt7622: add support for suspend/resume. This patch supports auxadc suspend/resume flow. Disable auxadc clk and power in suspend function. Enable axuadc clk and power in resume function. Signed-off-by: Zhiyong Tao Signed-off-by: Jonathan Cameron --- drivers/iio/adc/mt6577_auxadc.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'drivers') diff --git a/drivers/iio/adc/mt6577_auxadc.c b/drivers/iio/adc/mt6577_auxadc.c index 2d104c828041..914314a4436b 100644 --- a/drivers/iio/adc/mt6577_auxadc.c +++ b/drivers/iio/adc/mt6577_auxadc.c @@ -184,6 +184,37 @@ static const struct iio_info mt6577_auxadc_info = { .read_raw = &mt6577_auxadc_read_raw, }; +static int __maybe_unused mt6577_auxadc_resume(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct mt6577_auxadc_device *adc_dev = iio_priv(indio_dev); + int ret; + + ret = clk_prepare_enable(adc_dev->adc_clk); + if (ret) { + pr_err("failed to enable auxadc clock\n"); + return ret; + } + + mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC, + MT6577_AUXADC_PDN_EN, 0); + mdelay(MT6577_AUXADC_POWER_READY_MS); + + return 0; +} + +static int __maybe_unused mt6577_auxadc_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct mt6577_auxadc_device *adc_dev = iio_priv(indio_dev); + + mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC, + 0, MT6577_AUXADC_PDN_EN); + clk_disable_unprepare(adc_dev->adc_clk); + + return 0; +} + static int mt6577_auxadc_probe(struct platform_device *pdev) { struct mt6577_auxadc_device *adc_dev; @@ -269,6 +300,10 @@ static int mt6577_auxadc_remove(struct platform_device *pdev) return 0; } +static SIMPLE_DEV_PM_OPS(mt6577_auxadc_pm_ops, + mt6577_auxadc_suspend, + mt6577_auxadc_resume); + static const struct of_device_id mt6577_auxadc_of_match[] = { { .compatible = "mediatek,mt2701-auxadc", }, { .compatible = "mediatek,mt8173-auxadc", }, @@ -280,6 +315,7 @@ static struct platform_driver mt6577_auxadc_driver = { .driver = { .name = "mt6577-auxadc", .of_match_table = mt6577_auxadc_of_match, + .pm = &mt6577_auxadc_pm_ops, }, .probe = mt6577_auxadc_probe, .remove = mt6577_auxadc_remove, -- cgit v1.2.3 From 65746eb742f344f8d90a87910003c2e402a33c6f Mon Sep 17 00:00:00 2001 From: Zhiyong Tao Date: Mon, 26 Jun 2017 14:11:42 +0800 Subject: iio: adc: mt7622: Add compatible node for mt7622. This commit adds mt7622 compatible node. Signed-off-by: Zhiyong Tao Signed-off-by: Jonathan Cameron --- drivers/iio/adc/mt6577_auxadc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/iio/adc/mt6577_auxadc.c b/drivers/iio/adc/mt6577_auxadc.c index 914314a4436b..414cf44bf19d 100644 --- a/drivers/iio/adc/mt6577_auxadc.c +++ b/drivers/iio/adc/mt6577_auxadc.c @@ -306,6 +306,7 @@ static SIMPLE_DEV_PM_OPS(mt6577_auxadc_pm_ops, static const struct of_device_id mt6577_auxadc_of_match[] = { { .compatible = "mediatek,mt2701-auxadc", }, + { .compatible = "mediatek,mt7622-auxadc", }, { .compatible = "mediatek,mt8173-auxadc", }, { } }; -- cgit v1.2.3 From ea5c6e262c8557731d76b2346ebfa6b25e2fa302 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Tue, 27 Jun 2017 00:44:54 +0900 Subject: iio: light: tcs3472: add link to datasheet Add a link to the TCS3472 datasheet in the AMS's website. Cc: Peter Meerwald Cc: Jonathan Cameron Signed-off-by: Akinobu Mita Signed-off-by: Jonathan Cameron --- drivers/iio/light/tcs3472.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/iio/light/tcs3472.c b/drivers/iio/light/tcs3472.c index a9e153b3e1f9..09e6ca5e332e 100644 --- a/drivers/iio/light/tcs3472.c +++ b/drivers/iio/light/tcs3472.c @@ -11,6 +11,8 @@ * 7-bit I2C slave address 0x39 (TCS34721, TCS34723) or 0x29 (TCS34725, * TCS34727) * + * Datasheet: http://ams.com/eng/content/download/319364/1117183/file/TCS3472_Datasheet_EN_v2.pdf + * * TODO: interrupt support, thresholds, wait time */ -- cgit v1.2.3 From b64a097af4c86102866eb20ecc55058ca76fc2e8 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 29 Jun 2017 13:57:04 +0200 Subject: iio: gyro: mpu3050: Allow open drain with anything Open drain should work fine with rising or high level IRQs, this code was due to some misunderstanding on my part. Reported-by: Lorenzo Bianconi Signed-off-by: Linus Walleij Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/mpu3050-core.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/gyro/mpu3050-core.c b/drivers/iio/gyro/mpu3050-core.c index 2be2a5d287e6..e0d241a9aa30 100644 --- a/drivers/iio/gyro/mpu3050-core.c +++ b/drivers/iio/gyro/mpu3050-core.c @@ -1063,11 +1063,6 @@ static int mpu3050_trigger_probe(struct iio_dev *indio_dev, int irq) case IRQF_TRIGGER_RISING: dev_info(&indio_dev->dev, "pulse interrupts on the rising edge\n"); - if (mpu3050->irq_opendrain) { - dev_info(&indio_dev->dev, - "rising edge incompatible with open drain\n"); - mpu3050->irq_opendrain = false; - } break; case IRQF_TRIGGER_FALLING: mpu3050->irq_actl = true; @@ -1078,11 +1073,6 @@ static int mpu3050_trigger_probe(struct iio_dev *indio_dev, int irq) mpu3050->irq_latch = true; dev_info(&indio_dev->dev, "interrupts active high level\n"); - if (mpu3050->irq_opendrain) { - dev_info(&indio_dev->dev, - "active high incompatible with open drain\n"); - mpu3050->irq_opendrain = false; - } /* * With level IRQs, we mask the IRQ until it is processed, * but with edge IRQs (pulses) we can queue several interrupts -- cgit v1.2.3 From e3169994f6563f7e80a357ea68d5e9b040cb126c Mon Sep 17 00:00:00 2001 From: Angelo Compagnucci Date: Wed, 28 Jun 2017 23:53:09 +0200 Subject: iio: adc: mcp3422: Changing initial channel Initial channel should be the first available channel on all configurations, so changing to channel 0 available on all supported chips. Signed-off-by: Angelo Compagnucci Reported-by: Maarten Brock Signed-off-by: Jonathan Cameron --- drivers/iio/adc/mcp3422.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/adc/mcp3422.c b/drivers/iio/adc/mcp3422.c index 254135e07792..6737df8d9bdd 100644 --- a/drivers/iio/adc/mcp3422.c +++ b/drivers/iio/adc/mcp3422.c @@ -379,7 +379,7 @@ static int mcp3422_probe(struct i2c_client *client, /* meaningful default configuration */ config = (MCP3422_CONT_SAMPLING - | MCP3422_CHANNEL_VALUE(1) + | MCP3422_CHANNEL_VALUE(0) | MCP3422_PGA_VALUE(MCP3422_PGA_1) | MCP3422_SAMPLE_RATE_VALUE(MCP3422_SRATE_240)); mcp3422_update_config(adc, config); -- cgit v1.2.3 From 6be72b9067d443a44065541853edfb92ffca0401 Mon Sep 17 00:00:00 2001 From: Angelo Compagnucci Date: Wed, 28 Jun 2017 23:53:10 +0200 Subject: iio: adc: mcp3422: Checking for error on probe Some part of the configuration are not touched after the probe and if something goes wrong on writing the initial one, the chip will misbehave. Adding an error checking ensures that the inital configuration will be written correctly. Moreover ensures that a sensible configuration will be saved in driver data and used subsequently as intended. Signed-off-by: Angelo Compagnucci Reported-by: Maarten Brock Signed-off-by: Jonathan Cameron --- drivers/iio/adc/mcp3422.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/adc/mcp3422.c b/drivers/iio/adc/mcp3422.c index 6737df8d9bdd..63de705086ed 100644 --- a/drivers/iio/adc/mcp3422.c +++ b/drivers/iio/adc/mcp3422.c @@ -382,7 +382,9 @@ static int mcp3422_probe(struct i2c_client *client, | MCP3422_CHANNEL_VALUE(0) | MCP3422_PGA_VALUE(MCP3422_PGA_1) | MCP3422_SAMPLE_RATE_VALUE(MCP3422_SRATE_240)); - mcp3422_update_config(adc, config); + err = mcp3422_update_config(adc, config); + if (err < 0) + return err; err = devm_iio_device_register(&client->dev, indio_dev); if (err < 0) -- cgit v1.2.3 From 004123f3dfb8bef1458508c1b1f18e56cc1cd336 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 28 Jun 2017 14:06:50 +0100 Subject: iio: adc: stm32: make array stm32h7_adc_ckmodes_spec static The array stm32h7_adc_ckmodes_spec does not need to be in global scope, so make it static. Cleans up sparse warning: "symbol 'stm32h7_adc_ckmodes_spec' was not declared. Should it be static?" Signed-off-by: Colin Ian King Acked-by: Fabrice Gasnier Signed-off-by: Jonathan Cameron --- drivers/iio/adc/stm32-adc-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c index e09233b03c05..9d083c2338f9 100644 --- a/drivers/iio/adc/stm32-adc-core.c +++ b/drivers/iio/adc/stm32-adc-core.c @@ -172,7 +172,7 @@ struct stm32h7_adc_ck_spec { int div; }; -const struct stm32h7_adc_ck_spec stm32h7_adc_ckmodes_spec[] = { +static const struct stm32h7_adc_ck_spec stm32h7_adc_ckmodes_spec[] = { /* 00: CK_ADC[1..3]: Asynchronous clock modes */ { 0, 0, 1 }, { 0, 1, 2 }, -- cgit v1.2.3 From b995a732daabbcac2b8fdbba638c6e91ba95209a Mon Sep 17 00:00:00 2001 From: Gaurav Gupta Date: Tue, 27 Jun 2017 11:59:56 -0700 Subject: iio:adc:ltc2497: Add support for board file based iio consumer mapping. Add missing hooks in the LTC2497 IIO driver to allow hwmon mapping. Signed-off-by: Gaurav Gupta Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ltc2497.c | 54 ++++++++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/adc/ltc2497.c b/drivers/iio/adc/ltc2497.c index 2691b10023f5..5bf8011dcde9 100644 --- a/drivers/iio/adc/ltc2497.c +++ b/drivers/iio/adc/ltc2497.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -127,13 +128,14 @@ static int ltc2497_read_raw(struct iio_dev *indio_dev, } } -#define LTC2497_CHAN(_chan, _addr) { \ +#define LTC2497_CHAN(_chan, _addr, _ds_name) { \ .type = IIO_VOLTAGE, \ .indexed = 1, \ .channel = (_chan), \ .address = (_addr | (_chan / 2) | ((_chan & 1) ? LTC2497_SIGN : 0)), \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .datasheet_name = (_ds_name), \ } #define LTC2497_CHAN_DIFF(_chan, _addr) { \ @@ -148,22 +150,22 @@ static int ltc2497_read_raw(struct iio_dev *indio_dev, } static const struct iio_chan_spec ltc2497_channel[] = { - LTC2497_CHAN(0, LTC2497_SGL), - LTC2497_CHAN(1, LTC2497_SGL), - LTC2497_CHAN(2, LTC2497_SGL), - LTC2497_CHAN(3, LTC2497_SGL), - LTC2497_CHAN(4, LTC2497_SGL), - LTC2497_CHAN(5, LTC2497_SGL), - LTC2497_CHAN(6, LTC2497_SGL), - LTC2497_CHAN(7, LTC2497_SGL), - LTC2497_CHAN(8, LTC2497_SGL), - LTC2497_CHAN(9, LTC2497_SGL), - LTC2497_CHAN(10, LTC2497_SGL), - LTC2497_CHAN(11, LTC2497_SGL), - LTC2497_CHAN(12, LTC2497_SGL), - LTC2497_CHAN(13, LTC2497_SGL), - LTC2497_CHAN(14, LTC2497_SGL), - LTC2497_CHAN(15, LTC2497_SGL), + LTC2497_CHAN(0, LTC2497_SGL, "CH0"), + LTC2497_CHAN(1, LTC2497_SGL, "CH1"), + LTC2497_CHAN(2, LTC2497_SGL, "CH2"), + LTC2497_CHAN(3, LTC2497_SGL, "CH3"), + LTC2497_CHAN(4, LTC2497_SGL, "CH4"), + LTC2497_CHAN(5, LTC2497_SGL, "CH5"), + LTC2497_CHAN(6, LTC2497_SGL, "CH6"), + LTC2497_CHAN(7, LTC2497_SGL, "CH7"), + LTC2497_CHAN(8, LTC2497_SGL, "CH8"), + LTC2497_CHAN(9, LTC2497_SGL, "CH9"), + LTC2497_CHAN(10, LTC2497_SGL, "CH10"), + LTC2497_CHAN(11, LTC2497_SGL, "CH11"), + LTC2497_CHAN(12, LTC2497_SGL, "CH12"), + LTC2497_CHAN(13, LTC2497_SGL, "CH13"), + LTC2497_CHAN(14, LTC2497_SGL, "CH14"), + LTC2497_CHAN(15, LTC2497_SGL, "CH15"), LTC2497_CHAN_DIFF(0, LTC2497_DIFF), LTC2497_CHAN_DIFF(1, LTC2497_DIFF), LTC2497_CHAN_DIFF(2, LTC2497_DIFF), @@ -192,6 +194,7 @@ static int ltc2497_probe(struct i2c_client *client, { struct iio_dev *indio_dev; struct ltc2497_st *st; + struct iio_map *plat_data; int ret; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C | @@ -221,19 +224,31 @@ static int ltc2497_probe(struct i2c_client *client, if (ret < 0) return ret; + if (client->dev.platform_data) { + plat_data = ((struct iio_map *)client->dev.platform_data); + ret = iio_map_array_register(indio_dev, plat_data); + if (ret) { + dev_err(&indio_dev->dev, "iio map err: %d\n", ret); + goto err_regulator_disable; + } + } + ret = i2c_smbus_write_byte(st->client, LTC2497_CONFIG_DEFAULT); if (ret < 0) - goto err_regulator_disable; + goto err_array_unregister; st->addr_prev = LTC2497_CONFIG_DEFAULT; st->time_prev = ktime_get(); ret = iio_device_register(indio_dev); if (ret < 0) - goto err_regulator_disable; + goto err_array_unregister; return 0; +err_array_unregister: + iio_map_array_unregister(indio_dev); + err_regulator_disable: regulator_disable(st->ref); @@ -245,6 +260,7 @@ static int ltc2497_remove(struct i2c_client *client) struct iio_dev *indio_dev = i2c_get_clientdata(client); struct ltc2497_st *st = iio_priv(indio_dev); + iio_map_array_unregister(indio_dev); iio_device_unregister(indio_dev); regulator_disable(st->ref); -- cgit v1.2.3 From 893bd0ebfa285bc869ae43484567758fce2f3204 Mon Sep 17 00:00:00 2001 From: Reno Farnesi Date: Mon, 26 Jun 2017 21:45:22 -0400 Subject: iio: sca3000: Remove trailing whitespace Removes trailing whitespace to fix checkpatch errors Signed-off-by: Reno Farnesi Signed-off-by: Jonathan Cameron --- drivers/iio/accel/sca3000.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/accel/sca3000.c b/drivers/iio/accel/sca3000.c index cb1d83fa19a0..39ab210c44f6 100644 --- a/drivers/iio/accel/sca3000.c +++ b/drivers/iio/accel/sca3000.c @@ -36,7 +36,7 @@ #define SCA3000_LOCKED BIT(5) #define SCA3000_EEPROM_CS_ERROR BIT(1) #define SCA3000_SPI_FRAME_ERROR BIT(0) - + /* All reads done using register decrement so no need to directly access LSBs */ #define SCA3000_REG_X_MSB_ADDR 0x05 #define SCA3000_REG_Y_MSB_ADDR 0x07 @@ -74,7 +74,7 @@ #define SCA3000_REG_INT_STATUS_ADDR 0x16 #define SCA3000_REG_INT_STATUS_THREE_QUARTERS BIT(7) #define SCA3000_REG_INT_STATUS_HALF BIT(6) - + #define SCA3000_INT_STATUS_FREE_FALL BIT(3) #define SCA3000_INT_STATUS_Y_TRIGGER BIT(2) #define SCA3000_INT_STATUS_X_TRIGGER BIT(1) @@ -124,7 +124,7 @@ #define SCA3000_REG_INT_MASK_ADDR 0x21 #define SCA3000_REG_INT_MASK_PROT_MASK 0x1C - + #define SCA3000_REG_INT_MASK_RING_THREE_QUARTER BIT(7) #define SCA3000_REG_INT_MASK_RING_HALF BIT(6) -- cgit v1.2.3 From 2aac3388f1682d6208f6759c338a7efa37b0deca Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Mon, 26 Jun 2017 17:25:33 -0700 Subject: iio: magnetometer: Only declare ACPI table when ACPI is enable Don't inflate the kernel size with data that isn't used. The conditional declaration also fixes the following warning when building with clang: drivers/iio/magnetometer/ak8975.c:704:36: error: variable 'ak_acpi_match' is not needed and will not be emitted [-Werror,-Wunneeded-internal-declaration] Signed-off-by: Matthias Kaehlcke Acked-by: Linus Walleij Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/ak8975.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index 825369fb1c57..4ff883942f7b 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -784,6 +784,7 @@ static const struct iio_info ak8975_info = { .driver_module = THIS_MODULE, }; +#ifdef CONFIG_ACPI static const struct acpi_device_id ak_acpi_match[] = { {"AK8975", AK8975}, {"AK8963", AK8963}, @@ -793,6 +794,7 @@ static const struct acpi_device_id ak_acpi_match[] = { { }, }; MODULE_DEVICE_TABLE(acpi, ak_acpi_match); +#endif static const char *ak8975_match_acpi_device(struct device *dev, enum asahi_compass_chipset *chipset) -- cgit v1.2.3 From ff73e8611e95ebcb9e88b533d9a666bc13c82a88 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 27 Jun 2017 00:53:43 +0200 Subject: iio: accel: st_accel_spi: add OF capability to st_accel_spi Add device tree support for LIS3DH, LSM330D, LSM330DL, LSM330DLC, LIS331DLH, LSM330, LSM303AGR, LIS2DH12, LIS3L02DQ, LNG2DM accel sensors. Fix LIS302DL support defining of_device_id data field in st_accel_of_match table Fixes: 762227721fe6 (iio: accel: st_accel: handle deprecated bindings) Signed-off-by: Lorenzo Bianconi Reviewed-by: Linus Walleij Signed-off-by: Jonathan Cameron --- drivers/iio/accel/st_accel_spi.c | 69 +++++++++++++++++++++++++++++++++++----- 1 file changed, 61 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/accel/st_accel_spi.c b/drivers/iio/accel/st_accel_spi.c index d13742edee0e..6b2eafa45cbb 100644 --- a/drivers/iio/accel/st_accel_spi.c +++ b/drivers/iio/accel/st_accel_spi.c @@ -18,6 +18,65 @@ #include #include "st_accel.h" +#ifdef CONFIG_OF +/* + * For new single-chip sensors use as compatible string. + * For old single-chip devices keep -accel to maintain + * compatibility + */ +static const struct of_device_id st_accel_of_match[] = { + { + /* An older compatible */ + .compatible = "st,lis302dl-spi", + .data = LIS3LV02DL_ACCEL_DEV_NAME, + }, + { + .compatible = "st,lis3dh-accel", + .data = LIS3DH_ACCEL_DEV_NAME, + }, + { + .compatible = "st,lsm330d-accel", + .data = LSM330D_ACCEL_DEV_NAME, + }, + { + .compatible = "st,lsm330dl-accel", + .data = LSM330DL_ACCEL_DEV_NAME, + }, + { + .compatible = "st,lsm330dlc-accel", + .data = LSM330DLC_ACCEL_DEV_NAME, + }, + { + .compatible = "st,lis331dlh-accel", + .data = LIS331DLH_ACCEL_DEV_NAME, + }, + { + .compatible = "st,lsm330-accel", + .data = LSM330_ACCEL_DEV_NAME, + }, + { + .compatible = "st,lsm303agr-accel", + .data = LSM303AGR_ACCEL_DEV_NAME, + }, + { + .compatible = "st,lis2dh12-accel", + .data = LIS2DH12_ACCEL_DEV_NAME, + }, + { + .compatible = "st,lis3l02dq", + .data = LIS3L02DQ_ACCEL_DEV_NAME, + }, + { + .compatible = "st,lng2dm-accel", + .data = LNG2DM_ACCEL_DEV_NAME, + }, + {} +}; +MODULE_DEVICE_TABLE(of, st_accel_of_match); +#else +#define st_accel_of_match NULL +#endif + static int st_accel_spi_probe(struct spi_device *spi) { struct iio_dev *indio_dev; @@ -30,6 +89,8 @@ static int st_accel_spi_probe(struct spi_device *spi) adata = iio_priv(indio_dev); + st_sensors_of_name_probe(&spi->dev, st_accel_of_match, + spi->modalias, sizeof(spi->modalias)); st_sensors_spi_configure(indio_dev, spi, adata); err = st_accel_common_probe(indio_dev); @@ -61,14 +122,6 @@ static const struct spi_device_id st_accel_id_table[] = { }; MODULE_DEVICE_TABLE(spi, st_accel_id_table); -#ifdef CONFIG_OF -static const struct of_device_id st_accel_of_match[] = { - { .compatible = "st,lis302dl-spi" }, - {} -}; -MODULE_DEVICE_TABLE(of, st_accel_of_match); -#endif - static struct spi_driver st_accel_driver = { .driver = { .name = "st-accel-spi", -- cgit v1.2.3 From 65a687a22dbcb97d4747fd4c8edc55d73b5a3907 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 27 Jun 2017 00:53:44 +0200 Subject: iio: magnetometer: st_magn_spi: add OF capability to st_magn_spi Add device tree support for LIS3MDL and LSM303AGR magnetometer sensors Signed-off-by: Lorenzo Bianconi Reviewed-by: Linus Walleij Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/st_magn_spi.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'drivers') diff --git a/drivers/iio/magnetometer/st_magn_spi.c b/drivers/iio/magnetometer/st_magn_spi.c index f3cb4dc05391..1ea64dd318aa 100644 --- a/drivers/iio/magnetometer/st_magn_spi.c +++ b/drivers/iio/magnetometer/st_magn_spi.c @@ -18,6 +18,28 @@ #include #include "st_magn.h" +#ifdef CONFIG_OF +/* + * For new single-chip sensors use as compatible string. + * For old single-chip devices keep -magn to maintain + * compatibility + */ +static const struct of_device_id st_magn_of_match[] = { + { + .compatible = "st,lis3mdl-magn", + .data = LIS3MDL_MAGN_DEV_NAME, + }, + { + .compatible = "st,lsm303agr-magn", + .data = LSM303AGR_MAGN_DEV_NAME, + }, + {} +}; +MODULE_DEVICE_TABLE(of, st_magn_of_match); +#else +#define st_magn_of_match NULL +#endif + static int st_magn_spi_probe(struct spi_device *spi) { struct iio_dev *indio_dev; @@ -30,6 +52,8 @@ static int st_magn_spi_probe(struct spi_device *spi) mdata = iio_priv(indio_dev); + st_sensors_of_name_probe(&spi->dev, st_magn_of_match, + spi->modalias, sizeof(spi->modalias)); st_sensors_spi_configure(indio_dev, spi, mdata); err = st_magn_common_probe(indio_dev); @@ -57,6 +81,7 @@ MODULE_DEVICE_TABLE(spi, st_magn_id_table); static struct spi_driver st_magn_driver = { .driver = { .name = "st-magn-spi", + .of_match_table = of_match_ptr(st_magn_of_match), }, .probe = st_magn_spi_probe, .remove = st_magn_spi_remove, -- cgit v1.2.3 From 794694ce233fa595e5125cd52475e76397d395e3 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 27 Jun 2017 00:53:45 +0200 Subject: iio: gyro: st_gyro_spi: add OF capability to st_gyro_spi Add device tree support for L3G4200D, LSM330D, LSM330DL, LSM330DLC, L3GD20, L3GD20H, L3G4IS, LSM330, LSM9DS0 gyroscope sensors Signed-off-by: Lorenzo Bianconi Reviewed-by: Linus Walleij Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/st_gyro_spi.c | 53 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) (limited to 'drivers') diff --git a/drivers/iio/gyro/st_gyro_spi.c b/drivers/iio/gyro/st_gyro_spi.c index fa14d8f2170d..0b52ed577dc2 100644 --- a/drivers/iio/gyro/st_gyro_spi.c +++ b/drivers/iio/gyro/st_gyro_spi.c @@ -18,6 +18,56 @@ #include #include "st_gyro.h" +#ifdef CONFIG_OF +/* + * For new single-chip sensors use as compatible string. + * For old single-chip devices keep -gyro to maintain + * compatibility + */ +static const struct of_device_id st_gyro_of_match[] = { + { + .compatible = "st,l3g4200d-gyro", + .data = L3G4200D_GYRO_DEV_NAME, + }, + { + .compatible = "st,lsm330d-gyro", + .data = LSM330D_GYRO_DEV_NAME, + }, + { + .compatible = "st,lsm330dl-gyro", + .data = LSM330DL_GYRO_DEV_NAME, + }, + { + .compatible = "st,lsm330dlc-gyro", + .data = LSM330DLC_GYRO_DEV_NAME, + }, + { + .compatible = "st,l3gd20-gyro", + .data = L3GD20_GYRO_DEV_NAME, + }, + { + .compatible = "st,l3gd20h-gyro", + .data = L3GD20H_GYRO_DEV_NAME, + }, + { + .compatible = "st,l3g4is-gyro", + .data = L3G4IS_GYRO_DEV_NAME, + }, + { + .compatible = "st,lsm330-gyro", + .data = LSM330_GYRO_DEV_NAME, + }, + { + .compatible = "st,lsm9ds0-gyro", + .data = LSM9DS0_GYRO_DEV_NAME, + }, + {}, +}; +MODULE_DEVICE_TABLE(of, st_gyro_of_match); +#else +#define st_gyro_of_match NULL +#endif + static int st_gyro_spi_probe(struct spi_device *spi) { struct iio_dev *indio_dev; @@ -30,6 +80,8 @@ static int st_gyro_spi_probe(struct spi_device *spi) gdata = iio_priv(indio_dev); + st_sensors_of_name_probe(&spi->dev, st_gyro_of_match, + spi->modalias, sizeof(spi->modalias)); st_sensors_spi_configure(indio_dev, spi, gdata); err = st_gyro_common_probe(indio_dev); @@ -63,6 +115,7 @@ MODULE_DEVICE_TABLE(spi, st_gyro_id_table); static struct spi_driver st_gyro_driver = { .driver = { .name = "st-gyro-spi", + .of_match_table = of_match_ptr(st_gyro_of_match), }, .probe = st_gyro_spi_probe, .remove = st_gyro_spi_remove, -- cgit v1.2.3 From 2ff59bf39bbdc3b187050f8bf3a486b4ac416e86 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 27 Jun 2017 00:53:46 +0200 Subject: iio: pressure: st_pressure_spi: add OF capability to st_pressure_spi Add device tree support for LPS22HB, LPS25H, LPS331AP, LPS001WP pressure sensors Signed-off-by: Lorenzo Bianconi Reviewed-by: Linus Walleij Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/st_pressure_spi.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'drivers') diff --git a/drivers/iio/pressure/st_pressure_spi.c b/drivers/iio/pressure/st_pressure_spi.c index 550508025af1..f5ebd36bb4bf 100644 --- a/drivers/iio/pressure/st_pressure_spi.c +++ b/drivers/iio/pressure/st_pressure_spi.c @@ -18,6 +18,36 @@ #include #include "st_pressure.h" +#ifdef CONFIG_OF +/* + * For new single-chip sensors use as compatible string. + * For old single-chip devices keep -press to maintain + * compatibility + */ +static const struct of_device_id st_press_of_match[] = { + { + .compatible = "st,lps001wp-press", + .data = LPS001WP_PRESS_DEV_NAME, + }, + { + .compatible = "st,lps25h-press", + .data = LPS25H_PRESS_DEV_NAME, + }, + { + .compatible = "st,lps331ap-press", + .data = LPS331AP_PRESS_DEV_NAME, + }, + { + .compatible = "st,lps22hb-press", + .data = LPS22HB_PRESS_DEV_NAME, + }, + {}, +}; +MODULE_DEVICE_TABLE(of, st_press_of_match); +#else +#define st_press_of_match NULL +#endif + static int st_press_spi_probe(struct spi_device *spi) { struct iio_dev *indio_dev; @@ -30,6 +60,8 @@ static int st_press_spi_probe(struct spi_device *spi) press_data = iio_priv(indio_dev); + st_sensors_of_name_probe(&spi->dev, st_press_of_match, + spi->modalias, sizeof(spi->modalias)); st_sensors_spi_configure(indio_dev, spi, press_data); err = st_press_common_probe(indio_dev); @@ -58,6 +90,7 @@ MODULE_DEVICE_TABLE(spi, st_press_id_table); static struct spi_driver st_press_driver = { .driver = { .name = "st-press-spi", + .of_match_table = of_match_ptr(st_press_of_match), }, .probe = st_press_spi_probe, .remove = st_press_spi_remove, -- cgit v1.2.3 From aab498ba12172e81b2deffda9400ebcf41e3462f Mon Sep 17 00:00:00 2001 From: Reno Farnesi Date: Sat, 1 Jul 2017 17:54:08 -0400 Subject: iio: adis16400: Change unsigned to unsigned int This patch fixes the following checkpatch warnings: Prefer 'unsigned int' to bare use of 'unsigned Signed-off-by: Reno Farnesi Signed-off-by: Jonathan Cameron --- drivers/iio/imu/adis16400_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/imu/adis16400_core.c b/drivers/iio/imu/adis16400_core.c index fb7c0dbed51c..9b697d35dbef 100644 --- a/drivers/iio/imu/adis16400_core.c +++ b/drivers/iio/imu/adis16400_core.c @@ -217,7 +217,7 @@ static int adis16400_set_freq(struct adis16400_state *st, unsigned int freq) return adis_write_reg_8(&st->adis, ADIS16400_SMPL_PRD, val); } -static const unsigned adis16400_3db_divisors[] = { +static const unsigned int adis16400_3db_divisors[] = { [0] = 2, /* Special case */ [1] = 6, [2] = 12, @@ -890,7 +890,7 @@ static const struct adis_data adis16400_data = { static void adis16400_setup_chan_mask(struct adis16400_state *st) { const struct adis16400_chip_info *chip_info = st->variant; - unsigned i; + unsigned int i; for (i = 0; i < chip_info->num_channels; i++) { const struct iio_chan_spec *ch = &chip_info->channels[i]; -- cgit v1.2.3 From 2c4b851933a6aae3e3a034f23fbcb3ec345d7e51 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 3 Jul 2017 08:40:41 +0200 Subject: drm/i915: Update DRIVER_DATE to 20170703 Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ddb5ee8e0535..29d162b24d8d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -80,8 +80,8 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20170619" -#define DRIVER_TIMESTAMP 1497857498 +#define DRIVER_DATE "20170703" +#define DRIVER_TIMESTAMP 1499064041 /* Use I915_STATE_WARN(x) and I915_STATE_WARN_ON() (rather than WARN() and * WARN_ON()) for hw state sanity checks to check for unexpected conditions -- cgit v1.2.3 From fef9df8b594531a4257b6a3bf7e190570c17be29 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Fri, 30 Jun 2017 15:03:17 -0300 Subject: drm/atomic: initial support for asynchronous plane update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In some cases, like cursor updates, it is interesting to update the plane in an asynchronous fashion to avoid big delays. The current queued update could be still waiting for a fence to signal and thus block any subsequent update until its scan out. In cases like this if we update the cursor synchronously through the atomic API it will cause significant delays that would even be noticed by the final user. This patch creates a fast path to jump ahead the current queued state and do single planes updates without going through all atomic steps in drm_atomic_helper_commit(). We take this path for legacy cursor updates. For now only single plane updates are supported, but we plan to support multiple planes updates and async PageFlips through this interface as well in the near future. v6: - move check code to drm_atomic_helper.c (Daniel Vetter) v5: - improve comments (Eric Anholt) v4: - fix state->crtc NULL check (Archit Taneja) v3: - fix iteration on the wrong crtc state - put back code to forbid updates if there is a queued update for the same plane (Ville Syrjälä) - move size checks back to drivers (Ville Syrjälä) - move ASYNC_UPDATE flag addition to its own patch (Ville Syrjälä) v2: - allow updates even if there is a queued update for the same plane. - fixes on the documentation (Emil Velikov) - unconditionally call ->atomic_async_update (Emil Velikov) - check for ->atomic_async_update earlier (Daniel Vetter) - make ->atomic_async_check() the last step (Daniel Vetter) - add ASYNC_UPDATE flag (Eric Anholt) - update state in core after ->atomic_async_update (Eric Anholt) - update docs (Eric Anholt) Cc: Daniel Vetter Cc: Rob Clark Cc: Eric Anholt Signed-off-by: Gustavo Padovan Reviewed-by: Archit Taneja (v5) Acked-by: Eric Anholt (v5) Reviewed-by: Daniel Vetter Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170630180322.29007-2-gustavo@padovan.org --- drivers/gpu/drm/drm_atomic_helper.c | 122 +++++++++++++++++++++++++++++++ include/drm/drm_atomic.h | 2 + include/drm/drm_atomic_helper.h | 4 + include/drm/drm_modeset_helper_vtables.h | 50 +++++++++++++ 4 files changed, 178 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 23e4661a62fe..4f6e52961951 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -795,6 +795,9 @@ int drm_atomic_helper_check(struct drm_device *dev, if (ret) return ret; + if (state->legacy_cursor_update) + state->async_update = !drm_atomic_helper_async_check(dev, state); + return ret; } EXPORT_SYMBOL(drm_atomic_helper_check); @@ -1352,6 +1355,114 @@ static void commit_work(struct work_struct *work) commit_tail(state); } +/** + * drm_atomic_helper_async_check - check if state can be commited asynchronously + * @dev: DRM device + * @state: the driver state object + * + * This helper will check if it is possible to commit the state asynchronously. + * Async commits are not supposed to swap the states like normal sync commits + * but just do in-place changes on the current state. + * + * It will return 0 if the commit can happen in an asynchronous fashion or error + * if not. Note that error just mean it can't be commited asynchronously, if it + * fails the commit should be treated like a normal synchronous commit. + */ +int drm_atomic_helper_async_check(struct drm_device *dev, + struct drm_atomic_state *state) +{ + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; + struct drm_crtc_commit *commit; + struct drm_plane *__plane, *plane = NULL; + struct drm_plane_state *__plane_state, *plane_state = NULL; + const struct drm_plane_helper_funcs *funcs; + int i, j, n_planes = 0; + + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { + if (drm_atomic_crtc_needs_modeset(crtc_state)) + return -EINVAL; + } + + for_each_new_plane_in_state(state, __plane, __plane_state, i) { + n_planes++; + plane = __plane; + plane_state = __plane_state; + } + + /* FIXME: we support only single plane updates for now */ + if (!plane || n_planes != 1) + return -EINVAL; + + if (!plane_state->crtc) + return -EINVAL; + + funcs = plane->helper_private; + if (!funcs->atomic_async_update) + return -EINVAL; + + if (plane_state->fence) + return -EINVAL; + + /* + * Don't do an async update if there is an outstanding commit modifying + * the plane. This prevents our async update's changes from getting + * overridden by a previous synchronous update's state. + */ + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { + if (plane->crtc != crtc) + continue; + + spin_lock(&crtc->commit_lock); + commit = list_first_entry_or_null(&crtc->commit_list, + struct drm_crtc_commit, + commit_entry); + if (!commit) { + spin_unlock(&crtc->commit_lock); + continue; + } + spin_unlock(&crtc->commit_lock); + + if (!crtc->state->state) + continue; + + for_each_plane_in_state(crtc->state->state, __plane, + __plane_state, j) { + if (__plane == plane) + return -EINVAL; + } + } + + return funcs->atomic_async_check(plane, plane_state); +} +EXPORT_SYMBOL(drm_atomic_helper_async_check); + +/** + * drm_atomic_helper_async_commit - commit state asynchronously + * @dev: DRM device + * @state: the driver state object + * + * This function commits a state asynchronously, i.e., not vblank + * synchronized. It should be used on a state only when + * drm_atomic_async_check() succeeds. Async commits are not supposed to swap + * the states like normal sync commits, but just do in-place changes on the + * current state. + */ +void drm_atomic_helper_async_commit(struct drm_device *dev, + struct drm_atomic_state *state) +{ + struct drm_plane *plane; + struct drm_plane_state *plane_state; + const struct drm_plane_helper_funcs *funcs; + int i; + + for_each_new_plane_in_state(state, plane, plane_state, i) { + funcs = plane->helper_private; + funcs->atomic_async_update(plane, plane_state); + } +} +EXPORT_SYMBOL(drm_atomic_helper_async_commit); + /** * drm_atomic_helper_commit - commit validated state object * @dev: DRM device @@ -1376,6 +1487,17 @@ int drm_atomic_helper_commit(struct drm_device *dev, { int ret; + if (state->async_update) { + ret = drm_atomic_helper_prepare_planes(dev, state); + if (ret) + return ret; + + drm_atomic_helper_async_commit(dev, state); + drm_atomic_helper_cleanup_planes(dev, state); + + return 0; + } + ret = drm_atomic_helper_setup_commit(state, nonblock); if (ret) return ret; diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 0196f264a418..dcc8e0cdb7ff 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -207,6 +207,7 @@ struct __drm_private_objs_state { * @dev: parent DRM device * @allow_modeset: allow full modeset * @legacy_cursor_update: hint to enforce legacy cursor IOCTL semantics + * @async_update: hint for asynchronous plane update * @planes: pointer to array of structures with per-plane data * @crtcs: pointer to array of CRTC pointers * @num_connector: size of the @connectors and @connector_states arrays @@ -221,6 +222,7 @@ struct drm_atomic_state { struct drm_device *dev; bool allow_modeset : 1; bool legacy_cursor_update : 1; + bool async_update : 1; struct __drm_planes_state *planes; struct __drm_crtcs_state *crtcs; int num_connector; diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index 3bfeb2b2f746..dd196cc0afd7 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -44,6 +44,10 @@ void drm_atomic_helper_commit_tail(struct drm_atomic_state *state); int drm_atomic_helper_commit(struct drm_device *dev, struct drm_atomic_state *state, bool nonblock); +int drm_atomic_helper_async_check(struct drm_device *dev, + struct drm_atomic_state *state); +void drm_atomic_helper_async_commit(struct drm_device *dev, + struct drm_atomic_state *state); int drm_atomic_helper_wait_for_fences(struct drm_device *dev, struct drm_atomic_state *state, diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h index c85124f687ba..06569845708c 100644 --- a/include/drm/drm_modeset_helper_vtables.h +++ b/include/drm/drm_modeset_helper_vtables.h @@ -1135,6 +1135,56 @@ struct drm_plane_helper_funcs { */ void (*atomic_disable)(struct drm_plane *plane, struct drm_plane_state *old_state); + + /** + * @atomic_async_check: + * + * Drivers should set this function pointer to check if the plane state + * can be updated in a async fashion. Here async means "not vblank + * synchronized". + * + * This hook is called by drm_atomic_async_check() to establish if a + * given update can be committed asynchronously, that is, if it can + * jump ahead of the state currently queued for update. + * + * RETURNS: + * + * Return 0 on success and any error returned indicates that the update + * can not be applied in asynchronous manner. + */ + int (*atomic_async_check)(struct drm_plane *plane, + struct drm_plane_state *state); + + /** + * @atomic_async_update: + * + * Drivers should set this function pointer to perform asynchronous + * updates of planes, that is, jump ahead of the currently queued + * state and update the plane. Here async means "not vblank + * synchronized". + * + * This hook is called by drm_atomic_helper_async_commit(). + * + * An async update will happen on legacy cursor updates. An async + * update won't happen if there is an outstanding commit modifying + * the same plane. + * + * Note that unlike &drm_plane_helper_funcs.atomic_update this hook + * takes the new &drm_plane_state as parameter. When doing async_update + * drivers shouldn't replace the &drm_plane_state but update the + * current one with the new plane configurations in the new + * plane_state. + * + * FIXME: + * - It only works for single plane updates + * - Async Pageflips are not supported yet + * - Some hw might still scan out the old buffer until the next + * vblank, however we let go of the fb references as soon as + * we run this hook. For now drivers must implement their own workers + * for deferring if needed, until a common solution is created. + */ + void (*atomic_async_update)(struct drm_plane *plane, + struct drm_plane_state *new_state); }; /** -- cgit v1.2.3 From aaaf2f12999a416514368e32853fb13f745e27fc Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Sat, 1 Jul 2017 15:30:15 +0530 Subject: drm: armada: constify drm_prop_enum_list structures. drm_prop_enum_lists are not supposed to change at runtime. All functions working with drm_prop_enum_list provided by work with const drm_prop_enum_list. So mark the non-const structs as const. File size before: text data bss dec hex filename 9629 744 0 10373 2885 drivers/gpu/drm/armada/armada_crtc.o File size After adding 'const': text data bss dec hex filename 9757 616 0 10373 2885 drivers/gpu/drm/armada/armada_crtc.o Signed-off-by: Arvind Yadav Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/d2344c4dc40238cfe48fa6d917767df0f053150a.1498902844.git.arvind.yadav.cs@gmail.com --- drivers/gpu/drm/armada/armada_crtc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 94b76bdd7553..b57fb80acec1 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -1150,13 +1150,13 @@ int armada_drm_plane_init(struct armada_plane *plane) return 0; } -static struct drm_prop_enum_list armada_drm_csc_yuv_enum_list[] = { +static const struct drm_prop_enum_list armada_drm_csc_yuv_enum_list[] = { { CSC_AUTO, "Auto" }, { CSC_YUV_CCIR601, "CCIR601" }, { CSC_YUV_CCIR709, "CCIR709" }, }; -static struct drm_prop_enum_list armada_drm_csc_rgb_enum_list[] = { +static const struct drm_prop_enum_list armada_drm_csc_rgb_enum_list[] = { { CSC_AUTO, "Auto" }, { CSC_RGB_COMPUTER, "Computer system" }, { CSC_RGB_STUDIO, "Studio" }, -- cgit v1.2.3 From 8a63ca58f879f7ac40fac5af0bc1b37393ad18ea Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Sat, 1 Jul 2017 16:24:42 +0530 Subject: drm: armada: Constify drm_prop_enum_list structures. drm_prop_enum_lists are not supposed to change at runtime. All functions working with drm_prop_enum_list provided by work with const drm_prop_enum_list. So mark the non-const structs as const. File size before: text data bss dec hex filename 3594 176 0 3770 eba drivers/gpu/drm/armada/armada_overlay.o File size After adding 'const': text data bss dec hex filename 3722 48 0 3770 eba drivers/gpu/drm/armada/armada_overlay.o Signed-off-by: Arvind Yadav Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/dbeb176765bda8eaa9efdaa2dcd14c7bbae39cfa.1498905467.git.arvind.yadav.cs@gmail.com --- drivers/gpu/drm/armada/armada_overlay.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index e9a29df4b443..677b44f3534b 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c @@ -388,7 +388,7 @@ static const uint32_t armada_ovl_formats[] = { DRM_FORMAT_BGR565, }; -static struct drm_prop_enum_list armada_drm_colorkey_enum_list[] = { +static const struct drm_prop_enum_list armada_drm_colorkey_enum_list[] = { { CKMODE_DISABLE, "disabled" }, { CKMODE_Y, "Y component" }, { CKMODE_U, "U component" }, -- cgit v1.2.3 From 7b4e1eaa9d9eb3662876833bafcbe059eb6ac186 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Sat, 1 Jul 2017 18:06:46 +0530 Subject: drm/udl: dma-buf: Constify dma_buf_ops structures. dma_buf_ops are not supposed to change at runtime. All functions working with dma_buf_ops provided by work with const dma_buf_ops. So mark the non-const structs as const. File size before: text data bss dec hex filename 2002 112 0 2114 842 drivers/gpu/drm/udl/udl_dmabuf.o File size After adding 'const': text data bss dec hex filename 2114 0 0 2114 842 drivers/gpu/drm/udl/udl_dmabuf.o Signed-off-by: Arvind Yadav Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/cb4dfac90e85e2270779331f8cb10b635042bad7.1498912415.git.arvind.yadav.cs@gmail.com --- drivers/gpu/drm/udl/udl_dmabuf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/udl/udl_dmabuf.c b/drivers/gpu/drm/udl/udl_dmabuf.c index 2e031a894813..2867ed155ff6 100644 --- a/drivers/gpu/drm/udl/udl_dmabuf.c +++ b/drivers/gpu/drm/udl/udl_dmabuf.c @@ -186,7 +186,7 @@ static int udl_dmabuf_mmap(struct dma_buf *dma_buf, return -EINVAL; } -static struct dma_buf_ops udl_dmabuf_ops = { +static const struct dma_buf_ops udl_dmabuf_ops = { .attach = udl_attach_dma_buf, .detach = udl_detach_dma_buf, .map_dma_buf = udl_map_dma_buf, -- cgit v1.2.3 From 05ccf211efbb6c8b5da2b5fda4f9399a7bc0db2e Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Sun, 2 Jul 2017 13:11:02 +0530 Subject: drm: ttm: virtio-gpu: dma-buf: Constify ttm_place structures. ttm_place are not supposed to change at runtime. All functions working with ttm_place provided by work with const ttm_place. So mark the non-const structs as const. File size before: text data bss dec hex filename 2315 184 0 2499 9c3 drivers/gpu/drm/virtio/virtgpu_ttm.o File size After adding 'const': text data bss dec hex filename 2347 152 0 2499 9c3 drivers/gpu/drm/virtio/virtgpu_ttm.o Signed-off-by: Arvind Yadav Link: http://patchwork.freedesktop.org/patch/msgid/25a189402a516a0142d9a4412da0a597c660a96a.1498981093.git.arvind.yadav.cs@gmail.com Signed-off-by: Gerd Hoffmann --- drivers/gpu/drm/virtio/virtgpu_ttm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/virtio/virtgpu_ttm.c b/drivers/gpu/drm/virtio/virtgpu_ttm.c index c1f2af4ca4ca..e695d74eaa9f 100644 --- a/drivers/gpu/drm/virtio/virtgpu_ttm.c +++ b/drivers/gpu/drm/virtio/virtgpu_ttm.c @@ -234,7 +234,7 @@ static int virtio_gpu_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, static void virtio_gpu_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *placement) { - static struct ttm_place placements = { + static const struct ttm_place placements = { .fpfn = 0, .lpfn = 0, .flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM, -- cgit v1.2.3 From 9e2033a6bb13346620dbeb659b284a2bef8eb4d6 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Sun, 2 Jul 2017 23:03:35 +0530 Subject: drm: qxl: constify ttm_place structures. ttm_place are not supposed to change at runtime. All functions working with ttm_place provided by work with const ttm_place. So mark the non-const structs as const. File size before: text data bss dec hex filename 3485 184 264 3933 f5d drivers/gpu/drm/qxl/qxl_ttm.o File size After adding 'const': text data bss dec hex filename 3501 152 264 3917 f4d drivers/gpu/drm/qxl/qxl_ttm.o Signed-off-by: Arvind Yadav Link: http://patchwork.freedesktop.org/patch/msgid/a4f21d3bd2497129f084b8055ecf27f0d3ff1bba.1499013516.git.arvind.yadav.cs@gmail.com Signed-off-by: Gerd Hoffmann --- drivers/gpu/drm/qxl/qxl_ttm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index 87fc1dbd0a2f..7ecf8a4b9fe6 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -187,7 +187,7 @@ static void qxl_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *placement) { struct qxl_bo *qbo; - static struct ttm_place placements = { + static const struct ttm_place placements = { .fpfn = 0, .lpfn = 0, .flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM -- cgit v1.2.3 From 931e8c661a2d85e6bdfe145cfc52dffaf4a60516 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Sun, 2 Jul 2017 22:52:43 +0100 Subject: drm/bochs: switch fb_ops over to use drm_fb_helper_cfb helpers The current drm_fb_helper_sys helpers referenced in fb_ops assume that the video memory is in system RAM. This is not the case for sparc which uses direct physical memory accesses for IO memory and causes the bochs_drm module to panic immediately upon startup as it tries to initialise the framebuffer. Switching fb_ops over to use the drm_fb_helper_cfb helpers ensures that the correct accesses are used on sparc, fixing the panic and allowing the bochs_drm module to function under qemu-system-sparc64. Signed-off-by: Mark Cave-Ayland Link: http://patchwork.freedesktop.org/patch/msgid/1499032363-8290-1-git-send-email-mark.cave-ayland@ilande.co.uk Signed-off-by: Gerd Hoffmann --- drivers/gpu/drm/bochs/bochs_fbdev.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/bochs/bochs_fbdev.c b/drivers/gpu/drm/bochs/bochs_fbdev.c index c38deffa14de..49d5a2b7d630 100644 --- a/drivers/gpu/drm/bochs/bochs_fbdev.c +++ b/drivers/gpu/drm/bochs/bochs_fbdev.c @@ -23,9 +23,9 @@ static int bochsfb_mmap(struct fb_info *info, static struct fb_ops bochsfb_ops = { .owner = THIS_MODULE, DRM_FB_HELPER_DEFAULT_OPS, - .fb_fillrect = drm_fb_helper_sys_fillrect, - .fb_copyarea = drm_fb_helper_sys_copyarea, - .fb_imageblit = drm_fb_helper_sys_imageblit, + .fb_fillrect = drm_fb_helper_cfb_fillrect, + .fb_copyarea = drm_fb_helper_cfb_copyarea, + .fb_imageblit = drm_fb_helper_cfb_imageblit, .fb_mmap = bochsfb_mmap, }; -- cgit v1.2.3 From 6cbf04001ec0eede72a43f297c93586971445128 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Tue, 6 Jun 2017 09:17:06 +0200 Subject: drm/etnaviv: don't trigger OOM killer when page allocation fails GPU buffers can be quite large, so userspace is expected to deal with allocation failure. Don't trigger the OOM killer when page allocation for the GEM objects fails, as this opens an easy possiblity for unprivileged applications to DOS the system,a s the shmem pages are not fully accounted to the allocating process. Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_gem.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c index 9a3bea738330..b7541a455451 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c @@ -662,7 +662,8 @@ static struct drm_gem_object *__etnaviv_gem_new(struct drm_device *dev, * going to pin these pages. */ mapping = obj->filp->f_mapping; - mapping_set_gfp_mask(mapping, GFP_HIGHUSER); + mapping_set_gfp_mask(mapping, GFP_HIGHUSER | + __GFP_NORETRY | __GFP_NOWARN); } if (ret) -- cgit v1.2.3 From f91ac470a8b1b358e9c2c7dc17da2642d125c3ac Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Tue, 6 Jun 2017 09:17:07 +0200 Subject: drm/etnaviv: reduce allocation failure message severity The GPU userspace is expected to deal with failure to allocate memory for the GPU buffers, there is no need to spam the log on failure. Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c index b7541a455451..a4f392c38b38 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c @@ -68,7 +68,7 @@ static int etnaviv_gem_shmem_get_pages(struct etnaviv_gem_object *etnaviv_obj) struct page **p = drm_gem_get_pages(&etnaviv_obj->base); if (IS_ERR(p)) { - dev_err(dev->dev, "could not get pages: %ld\n", PTR_ERR(p)); + dev_dbg(dev->dev, "could not get pages: %ld\n", PTR_ERR(p)); return PTR_ERR(p); } -- cgit v1.2.3 From 8cc47b3ea0822175deb8bf436e4c59a7f128ac30 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Tue, 6 Jun 2017 09:17:08 +0200 Subject: drm/etnaviv: populate GEM objects on cpu_prep CPU prep is the point where we can reasonably return an error to userspace when something goes wrong while populating the object. If we leave the object unpopulated at this point, the allocation will happen in the fault handler when userspace accesses the object through the mmap space, where we don't have any other option than to OOM the system. Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_gem.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c index a4f392c38b38..408c0fc476dd 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c @@ -413,6 +413,16 @@ int etnaviv_gem_cpu_prep(struct drm_gem_object *obj, u32 op, bool write = !!(op & ETNA_PREP_WRITE); int ret; + if (!etnaviv_obj->sgt) { + void *ret; + + mutex_lock(&etnaviv_obj->lock); + ret = etnaviv_gem_get_pages(etnaviv_obj); + mutex_unlock(&etnaviv_obj->lock); + if (IS_ERR(ret)) + return PTR_ERR(ret); + } + if (op & ETNA_PREP_NOSYNC) { if (!reservation_object_test_signaled_rcu(etnaviv_obj->resv, write)) @@ -427,16 +437,6 @@ int etnaviv_gem_cpu_prep(struct drm_gem_object *obj, u32 op, } if (etnaviv_obj->flags & ETNA_BO_CACHED) { - if (!etnaviv_obj->sgt) { - void *ret; - - mutex_lock(&etnaviv_obj->lock); - ret = etnaviv_gem_get_pages(etnaviv_obj); - mutex_unlock(&etnaviv_obj->lock); - if (IS_ERR(ret)) - return PTR_ERR(ret); - } - dma_sync_sg_for_cpu(dev->dev, etnaviv_obj->sgt->sgl, etnaviv_obj->sgt->nents, etnaviv_op_to_dma_dir(op)); -- cgit v1.2.3 From 987f8c444aa2c33d98e7030d0c5f0a5325cc84ea Mon Sep 17 00:00:00 2001 From: "sagar.a.kamble@intel.com" Date: Tue, 27 Jun 2017 23:09:41 +0530 Subject: drm/i915: Hold RPM wakelock while initializing OA buffer OA buffer initialization involves access to HW registers to set the OA base, head and tail. Ensure device is awake while setting these. With this, all oa.ops are covered under RPM and forcewake wakelock. Cc: Lionel Landwerlin Signed-off-by: Sagar Arun Kamble Reviewed-by: Lionel Landwerlin Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1498585181-23048-1-git-send-email-sagar.a.kamble@intel.com Fixes: d79651522e89c ("drm/i915: Enable i915 perf stream for Haswell OA unit") Cc: # v4.11+ --- drivers/gpu/drm/i915/i915_perf.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index afd8260cd096..d9f77a4d85db 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -2067,10 +2067,6 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream, return ret; } - ret = alloc_oa_buffer(dev_priv); - if (ret) - goto err_oa_buf_alloc; - /* PRM - observability performance counters: * * OACONTROL, performance counter enable, note: @@ -2086,6 +2082,10 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream, intel_runtime_pm_get(dev_priv); intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); + ret = alloc_oa_buffer(dev_priv); + if (ret) + goto err_oa_buf_alloc; + ret = dev_priv->perf.oa.ops.enable_metric_set(dev_priv); if (ret) goto err_enable; @@ -2097,11 +2097,11 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream, return 0; err_enable: - intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); - intel_runtime_pm_put(dev_priv); free_oa_buffer(dev_priv); err_oa_buf_alloc: + intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); + intel_runtime_pm_put(dev_priv); if (stream->ctx) oa_put_render_ctx_id(stream); -- cgit v1.2.3 From a874b6a3fb22c8c30f36b1f6ba5430a4c2278a6a Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Mon, 26 Jun 2017 10:18:35 +0200 Subject: drm/i915: Prevent kernel panic when reading/writing compliance debugfs files, v2. When reading all debugfs files on a system with DP-MST the kernel panics on a null pointer dereference because intel_dp is null for a DP-MST connector. Detect this case and skip those connectors. Also fix the write for the DP compliance file in the same way. Changes since v1: - Fix i915_displayport_test_active_write too. (DK) Signed-off-by: Maarten Lankhorst Cc: Dhinakaran Pandiyan Cc: Manasi Navare Reviewed-by: Dhinakaran Pandiyan Link: http://patchwork.freedesktop.org/patch/msgid/20170626081835.24251-1-maarten.lankhorst@linux.intel.com --- drivers/gpu/drm/i915/i915_debugfs.c | 44 +++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 580bd4f4a49e..643f56b8b87c 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -3778,13 +3778,18 @@ static ssize_t i915_displayport_test_active_write(struct file *file, drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) { + struct intel_encoder *encoder; + if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) continue; - if (connector->status == connector_status_connected && - connector->encoder != NULL) { - intel_dp = enc_to_intel_dp(connector->encoder); + encoder = to_intel_encoder(connector->encoder); + if (encoder && encoder->type == INTEL_OUTPUT_DP_MST) + continue; + + if (encoder && connector->status == connector_status_connected) { + intel_dp = enc_to_intel_dp(&encoder->base); status = kstrtoint(input_buffer, 10, &val); if (status < 0) break; @@ -3816,13 +3821,18 @@ static int i915_displayport_test_active_show(struct seq_file *m, void *data) drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) { + struct intel_encoder *encoder; + if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) continue; - if (connector->status == connector_status_connected && - connector->encoder != NULL) { - intel_dp = enc_to_intel_dp(connector->encoder); + encoder = to_intel_encoder(connector->encoder); + if (encoder && encoder->type == INTEL_OUTPUT_DP_MST) + continue; + + if (encoder && connector->status == connector_status_connected) { + intel_dp = enc_to_intel_dp(&encoder->base); if (intel_dp->compliance.test_active) seq_puts(m, "1"); else @@ -3862,13 +3872,18 @@ static int i915_displayport_test_data_show(struct seq_file *m, void *data) drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) { + struct intel_encoder *encoder; + if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) continue; - if (connector->status == connector_status_connected && - connector->encoder != NULL) { - intel_dp = enc_to_intel_dp(connector->encoder); + encoder = to_intel_encoder(connector->encoder); + if (encoder && encoder->type == INTEL_OUTPUT_DP_MST) + continue; + + if (encoder && connector->status == connector_status_connected) { + intel_dp = enc_to_intel_dp(&encoder->base); if (intel_dp->compliance.test_type == DP_TEST_LINK_EDID_READ) seq_printf(m, "%lx", @@ -3915,13 +3930,18 @@ static int i915_displayport_test_type_show(struct seq_file *m, void *data) drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) { + struct intel_encoder *encoder; + if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) continue; - if (connector->status == connector_status_connected && - connector->encoder != NULL) { - intel_dp = enc_to_intel_dp(connector->encoder); + encoder = to_intel_encoder(connector->encoder); + if (encoder && encoder->type == INTEL_OUTPUT_DP_MST) + continue; + + if (encoder && connector->status == connector_status_connected) { + intel_dp = enc_to_intel_dp(&encoder->base); seq_printf(m, "%02lx", intel_dp->compliance.test_type); } else seq_puts(m, "0"); -- cgit v1.2.3 From 7114d2e22fadd9060fd8c38b1dbc3ceeac7c536b Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Mon, 3 Jul 2017 13:51:06 +0200 Subject: drm/fb-helper: Remove drm_mode_config_fb. Remove drm_mode_config_fb, I don't see the point of it. To make it clear that it's ok to use plane->fb directly, move up drm_drv_uses_atomic_modeset so the code is skipped for atomic drivers that require plane_state->fb. Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/20170703115106.18783-1-maarten.lankhorst@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/drm_fb_helper.c | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 574af01d3ce9..84e47e512fe9 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -298,20 +298,6 @@ int drm_fb_helper_debug_enter(struct fb_info *info) } EXPORT_SYMBOL(drm_fb_helper_debug_enter); -/* Find the real fb for a given fb helper CRTC */ -static struct drm_framebuffer *drm_mode_config_fb(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct drm_crtc *c; - - drm_for_each_crtc(c, dev) { - if (crtc->base.id == c->base.id) - return c->primary->fb; - } - - return NULL; -} - /** * drm_fb_helper_debug_leave - implementation for &fb_ops.fb_debug_leave * @info: fbdev registered by the helper @@ -328,8 +314,11 @@ int drm_fb_helper_debug_leave(struct fb_info *info) struct drm_mode_set *mode_set = &helper->crtc_info[i].mode_set; crtc = mode_set->crtc; + if (drm_drv_uses_atomic_modeset(crtc->dev)) + continue; + funcs = crtc->helper_private; - fb = drm_mode_config_fb(crtc); + fb = crtc->primary->fb; if (!crtc->enabled) continue; @@ -342,9 +331,6 @@ int drm_fb_helper_debug_leave(struct fb_info *info) if (funcs->mode_set_base_atomic == NULL) continue; - if (drm_drv_uses_atomic_modeset(crtc->dev)) - continue; - drm_fb_helper_restore_lut_atomic(mode_set->crtc); funcs->mode_set_base_atomic(mode_set->crtc, fb, crtc->x, crtc->y, LEAVE_ATOMIC_MODE_SET); -- cgit v1.2.3 From 469bcef53c546bb792aa66303933272991b7831d Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Tue, 4 Jul 2017 11:10:39 +0200 Subject: irqchip/atmel-aic: Fix unbalanced of_node_put() in aic_common_irq_fixup() aic_common_irq_fixup() is calling twice of_node_put() on the same node thus leading to an unbalanced refcount on the root node. Signed-off-by: Boris Brezillon Reported-by: Alexandre Belloni Fixes: b2f579b58e93 ("irqchip: atmel-aic: Add irq fixup infrastructure") Cc: Signed-off-by: Marc Zyngier --- drivers/irqchip/irq-atmel-aic-common.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/irqchip/irq-atmel-aic-common.c b/drivers/irqchip/irq-atmel-aic-common.c index 28b26c80f4cf..7c5a43488d27 100644 --- a/drivers/irqchip/irq-atmel-aic-common.c +++ b/drivers/irqchip/irq-atmel-aic-common.c @@ -196,7 +196,6 @@ static void __init aic_common_irq_fixup(const struct of_device_id *matches) return; match = of_match_node(matches, root); - of_node_put(root); if (match) { void (*fixup)(struct device_node *) = match->data; -- cgit v1.2.3 From 277867ade8262583f4280cadbe90e0031a3706a7 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Tue, 4 Jul 2017 11:10:40 +0200 Subject: irqchip/atmel-aic: Fix unbalanced refcount in aic_common_rtc_irq_fixup() of_find_compatible_node() is calling of_node_put() on its first argument thus leading to an unbalanced of_node_get/put() issue if the node has not been retained before that. Instead of passing the root node, pass NULL, which does exactly the same: iterate over all DT nodes, starting from the root node. Signed-off-by: Boris Brezillon Reported-by: Alexandre Belloni Fixes: 3d61467f9bab ("irqchip: atmel-aic: Implement RTC irq fixup") Cc: Signed-off-by: Marc Zyngier --- drivers/irqchip/irq-atmel-aic-common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/irqchip/irq-atmel-aic-common.c b/drivers/irqchip/irq-atmel-aic-common.c index 7c5a43488d27..056507099725 100644 --- a/drivers/irqchip/irq-atmel-aic-common.c +++ b/drivers/irqchip/irq-atmel-aic-common.c @@ -142,9 +142,9 @@ void __init aic_common_rtc_irq_fixup(struct device_node *root) struct device_node *np; void __iomem *regs; - np = of_find_compatible_node(root, NULL, "atmel,at91rm9200-rtc"); + np = of_find_compatible_node(NULL, NULL, "atmel,at91rm9200-rtc"); if (!np) - np = of_find_compatible_node(root, NULL, + np = of_find_compatible_node(NULL, NULL, "atmel,at91sam9x5-rtc"); if (!np) -- cgit v1.2.3 From 0a46230bf03549435156b36dee9e7489b8270be7 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Tue, 4 Jul 2017 11:10:41 +0200 Subject: irqchip/atmel-aic: Remove root argument from ->fixup() prototype We are no longer using the root argument passed to the ->fixup() hooks. Remove it. Signed-off-by: Boris Brezillon Signed-off-by: Marc Zyngier --- drivers/irqchip/irq-atmel-aic-common.c | 8 ++++---- drivers/irqchip/irq-atmel-aic-common.h | 4 ++-- drivers/irqchip/irq-atmel-aic.c | 14 +++++++------- drivers/irqchip/irq-atmel-aic5.c | 4 ++-- 4 files changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/irqchip/irq-atmel-aic-common.c b/drivers/irqchip/irq-atmel-aic-common.c index 056507099725..072bd227b6c6 100644 --- a/drivers/irqchip/irq-atmel-aic-common.c +++ b/drivers/irqchip/irq-atmel-aic-common.c @@ -137,7 +137,7 @@ static void __init aic_common_ext_irq_of_init(struct irq_domain *domain) #define AT91_RTC_IMR 0x28 #define AT91_RTC_IRQ_MASK 0x1f -void __init aic_common_rtc_irq_fixup(struct device_node *root) +void __init aic_common_rtc_irq_fixup(void) { struct device_node *np; void __iomem *regs; @@ -165,7 +165,7 @@ void __init aic_common_rtc_irq_fixup(struct device_node *root) #define AT91_RTT_ALMIEN (1 << 16) /* Alarm Interrupt Enable */ #define AT91_RTT_RTTINCIEN (1 << 17) /* Real Time Timer Increment Interrupt Enable */ -void __init aic_common_rtt_irq_fixup(struct device_node *root) +void __init aic_common_rtt_irq_fixup(void) { struct device_node *np; void __iomem *regs; @@ -198,8 +198,8 @@ static void __init aic_common_irq_fixup(const struct of_device_id *matches) match = of_match_node(matches, root); if (match) { - void (*fixup)(struct device_node *) = match->data; - fixup(root); + void (*fixup)(void) = match->data; + fixup(); } of_node_put(root); diff --git a/drivers/irqchip/irq-atmel-aic-common.h b/drivers/irqchip/irq-atmel-aic-common.h index af60376d50de..242e62c1851e 100644 --- a/drivers/irqchip/irq-atmel-aic-common.h +++ b/drivers/irqchip/irq-atmel-aic-common.h @@ -33,8 +33,8 @@ struct irq_domain *__init aic_common_of_init(struct device_node *node, const char *name, int nirqs, const struct of_device_id *matches); -void __init aic_common_rtc_irq_fixup(struct device_node *root); +void __init aic_common_rtc_irq_fixup(void); -void __init aic_common_rtt_irq_fixup(struct device_node *root); +void __init aic_common_rtt_irq_fixup(void); #endif /* __IRQ_ATMEL_AIC_COMMON_H */ diff --git a/drivers/irqchip/irq-atmel-aic.c b/drivers/irqchip/irq-atmel-aic.c index 37f952dd9fc9..bb1ad451392f 100644 --- a/drivers/irqchip/irq-atmel-aic.c +++ b/drivers/irqchip/irq-atmel-aic.c @@ -209,20 +209,20 @@ static const struct irq_domain_ops aic_irq_ops = { .xlate = aic_irq_domain_xlate, }; -static void __init at91rm9200_aic_irq_fixup(struct device_node *root) +static void __init at91rm9200_aic_irq_fixup(void) { - aic_common_rtc_irq_fixup(root); + aic_common_rtc_irq_fixup(); } -static void __init at91sam9260_aic_irq_fixup(struct device_node *root) +static void __init at91sam9260_aic_irq_fixup(void) { - aic_common_rtt_irq_fixup(root); + aic_common_rtt_irq_fixup(); } -static void __init at91sam9g45_aic_irq_fixup(struct device_node *root) +static void __init at91sam9g45_aic_irq_fixup(void) { - aic_common_rtc_irq_fixup(root); - aic_common_rtt_irq_fixup(root); + aic_common_rtc_irq_fixup(); + aic_common_rtt_irq_fixup(); } static const struct of_device_id aic_irq_fixups[] __initconst = { diff --git a/drivers/irqchip/irq-atmel-aic5.c b/drivers/irqchip/irq-atmel-aic5.c index c04ee9a23d09..6acad2ea0fb3 100644 --- a/drivers/irqchip/irq-atmel-aic5.c +++ b/drivers/irqchip/irq-atmel-aic5.c @@ -305,9 +305,9 @@ static const struct irq_domain_ops aic5_irq_ops = { .xlate = aic5_irq_domain_xlate, }; -static void __init sama5d3_aic_irq_fixup(struct device_node *root) +static void __init sama5d3_aic_irq_fixup(void) { - aic_common_rtc_irq_fixup(root); + aic_common_rtc_irq_fixup(); } static const struct of_device_id aic5_irq_fixups[] __initconst = { -- cgit v1.2.3 From 456c59c31c5126fe31c64956c43670060ea9debd Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Tue, 4 Jul 2017 10:56:34 +0100 Subject: irqchip/gic-v2: Report failures in gic_irq_domain_alloc If the GIC cannot map an IRQ via irq_domain_ops->alloc(), it doesn't return an error code. This can cause a problem with drivers, where it thinks it has successfully got an IRQ for the device, but requesting the same ends up failure with -ENOSYS (as the IRQ's chip is not set). Fixes: commit 9a1091ef0017c ("irqchip: gic: Support hierarchy irq domain.") Cc: Yingjoe Chen Cc: Marc Zyngier Signed-off-by: Suzuki K Poulose Signed-off-by: Marc Zyngier --- drivers/irqchip/irq-gic.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 1b1df4f770bd..940c16278758 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -1027,8 +1027,11 @@ static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, if (ret) return ret; - for (i = 0; i < nr_irqs; i++) - gic_irq_domain_map(domain, virq + i, hwirq + i); + for (i = 0; i < nr_irqs; i++) { + ret = gic_irq_domain_map(domain, virq + i, hwirq + i); + if (ret) + return ret; + } return 0; } -- cgit v1.2.3 From 63c16c6eacb69d0cbdaee5dea0dd56d238375fe6 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Tue, 4 Jul 2017 10:56:33 +0100 Subject: irqchip/gic-v3: Report failures in gic_irq_domain_alloc If the GIC cannot map an IRQ via irq_domain_ops->alloc(), it doesn't return an error code. This can cause a problem with drivers, where it thinks it has successfully got an IRQ for the device, but requesting the same ends up failure with -ENOSYS (as the IRQ's chip is not set). Fixes: commit 443acc4f37f6 ("irqchip: GICv3: Convert to domain hierarchy") Cc: Marc Zyngier Signed-off-by: Suzuki K Poulose Signed-off-by: Marc Zyngier --- drivers/irqchip/irq-gic-v3.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index dbffb7ab6203..47630e9998b3 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -831,8 +831,11 @@ static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, if (ret) return ret; - for (i = 0; i < nr_irqs; i++) - gic_irq_domain_map(domain, virq + i, hwirq + i); + for (i = 0; i < nr_irqs; i++) { + ret = gic_irq_domain_map(domain, virq + i, hwirq + i); + if (ret) + return ret; + } return 0; } -- cgit v1.2.3 From 65a30f8b300107266f316d550f060ccc186201a3 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Tue, 4 Jul 2017 10:56:35 +0100 Subject: irqchip/gic-v3: Honor forced affinity setting Honor the 'force' flag for set_affinity, by selecting a CPU from the given mask (which may not be reported "online" by the cpu_online_mask). Some drivers, like ARM PMU, rely on it. Cc: Marc Zyngier Reported-by: Mark Rutland Signed-off-by: Suzuki K Poulose Signed-off-by: Marc Zyngier --- drivers/irqchip/irq-gic-v3.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 47630e9998b3..5ba64a7584a3 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -640,11 +640,16 @@ static void gic_smp_init(void) static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, bool force) { - unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask); + unsigned int cpu; void __iomem *reg; int enabled; u64 val; + if (force) + cpu = cpumask_first(mask_val); + else + cpu = cpumask_any_and(mask_val, cpu_online_mask); + if (cpu >= nr_cpu_ids) return -EINVAL; -- cgit v1.2.3 From fad2083483bb7f743486199f90dc042939323453 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 1 Jul 2017 00:05:17 +0100 Subject: drm/i915: Fix use-after-free of context during free_contexts When iterating the list of contexts to free, we need to use a safe iterator as we are freeing the link as we go. Pass an extra thick brown paper bag. Fixes: 5f09a9c8ab6b ("drm/i915: Allow contexts to be unreferenced locklessly") Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Cc: Tvrtko Ursulin Cc: Matthew Auld Link: http://patchwork.freedesktop.org/patch/msgid/20170630230517.1938-1-chris@chris-wilson.co.uk Reviewed-by: Matthew Auld --- drivers/gpu/drm/i915/i915_gem_context.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 71d2ea7dab64..2eb5d8203999 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -193,11 +193,11 @@ static void i915_gem_context_free(struct i915_gem_context *ctx) static void contexts_free(struct drm_i915_private *i915) { struct llist_node *freed = llist_del_all(&i915->contexts.free_list); - struct i915_gem_context *ctx; + struct i915_gem_context *ctx, *cn; lockdep_assert_held(&i915->drm.struct_mutex); - llist_for_each_entry(ctx, freed, free_link) + llist_for_each_entry_safe(ctx, cn, freed, free_link) i915_gem_context_free(ctx); } -- cgit v1.2.3 From 15727ed0d944ce1dec8b9e1082dd3df29a0fdf44 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 22 Jun 2017 17:02:11 +0100 Subject: drm/i915/fbdev: Check for existence of ifbdev->vma before operations Commit fabef825626d ("drm/i915: Drop struct_mutex around frontbuffer flushes") adds a dependency to ifbdev->vma when flushing the framebufer, but the checks are only against the existence of the ifbdev->fb and not against ifbdev->vma. This leaves a window of opportunity where we may try to operate on the fbdev prior to it being probed (thanks to asynchronous booting). Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=101534 Fixes: fabef825626d ("drm/i915: Drop struct_mutex around frontbuffer flushes") Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Cc: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170622160211.783-1-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin Cc: stable@vger.kernel.org --- drivers/gpu/drm/i915/intel_fbdev.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index 03347c6ae599..0c4cde6b2e6f 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -535,13 +535,14 @@ static void intel_fbdev_destroy(struct intel_fbdev *ifbdev) drm_fb_helper_fini(&ifbdev->helper); - if (ifbdev->fb) { + if (ifbdev->vma) { mutex_lock(&ifbdev->helper.dev->struct_mutex); intel_unpin_fb_vma(ifbdev->vma); mutex_unlock(&ifbdev->helper.dev->struct_mutex); + } + if (ifbdev->fb) drm_framebuffer_remove(&ifbdev->fb->base); - } kfree(ifbdev); } @@ -765,7 +766,7 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous struct intel_fbdev *ifbdev = dev_priv->fbdev; struct fb_info *info; - if (!ifbdev || !ifbdev->fb) + if (!ifbdev || !ifbdev->vma) return; info = ifbdev->helper.fbdev; @@ -812,7 +813,7 @@ void intel_fbdev_output_poll_changed(struct drm_device *dev) { struct intel_fbdev *ifbdev = to_i915(dev)->fbdev; - if (ifbdev && ifbdev->fb) + if (ifbdev && ifbdev->vma) drm_fb_helper_hotplug_event(&ifbdev->helper); } @@ -824,7 +825,7 @@ void intel_fbdev_restore_mode(struct drm_device *dev) return; intel_fbdev_sync(ifbdev); - if (!ifbdev->fb) + if (!ifbdev->vma) return; if (drm_fb_helper_restore_fbdev_mode_unlocked(&ifbdev->helper) == 0) -- cgit v1.2.3 From 11f489d3c62b1e55efbc5f1ab058d85851a96d0e Mon Sep 17 00:00:00 2001 From: Mahesh Kumar Date: Fri, 30 Jun 2017 17:40:59 +0530 Subject: drm/i915/skl+: Check for supported plane configuration in Interlace mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In Gen9 platform Interlaced fetch mode doesn't support following plane configuration: - Y/Yf tiling - 90/270 rotation - YUV420 hybrid planar source pixel formats. This patch adds check to fail the flip if any of the above configuration is requested. Changes since V1: - handle checks in intel_plane_atomic_check_with_state (ville) - takeout plane scaler checks combile with pipe scaler in next patch Changes since V2: - No need to check for NV12 as it need scaling, so it will be rejected by scaling check (ville) Signed-off-by: Mahesh Kumar Link: http://patchwork.freedesktop.org/patch/msgid/20170630121100.20159-2-mahesh1.kumar@intel.com Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=90238 Reviewed-by: Ville Syrjälä Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_atomic_plane.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c index 4325cb0a04f5..ee76fab7bb6f 100644 --- a/drivers/gpu/drm/i915/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c @@ -114,6 +114,8 @@ int intel_plane_atomic_check_with_state(struct intel_crtc_state *crtc_state, struct drm_i915_private *dev_priv = to_i915(plane->dev); struct drm_plane_state *state = &intel_state->base; struct intel_plane *intel_plane = to_intel_plane(plane); + const struct drm_display_mode *adjusted_mode = + &crtc_state->base.adjusted_mode; int ret; /* @@ -173,6 +175,19 @@ int intel_plane_atomic_check_with_state(struct intel_crtc_state *crtc_state, if (ret) return ret; + /* + * Y-tiling is not supported in IF-ID Interlace mode in + * GEN9 and above. + */ + if (state->fb && INTEL_GEN(dev_priv) >= 9 && crtc_state->base.enable && + adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { + if (state->fb->modifier == I915_FORMAT_MOD_Y_TILED || + state->fb->modifier == I915_FORMAT_MOD_Yf_TILED) { + DRM_DEBUG_KMS("Y/Yf tiling not supported in IF-ID mode\n"); + return -EINVAL; + } + } + /* FIXME pre-g4x don't work like this */ if (intel_state->base.visible) crtc_state->active_planes |= BIT(intel_plane->id); -- cgit v1.2.3 From 7f58cbb187aff05e179c2d7bef9d4605fb3ced72 Mon Sep 17 00:00:00 2001 From: Mahesh Kumar Date: Fri, 30 Jun 2017 17:41:00 +0530 Subject: drm/i915/skl+: Scaling not supported in IF-ID Interlace mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GEN9+ Interlace fetch mode doesn't support pipe/plane scaling, This patch adds check to fail the flip if pipe/plane scaling is requested in Interlace fetch mode. Changes since V1: - move check to skl_update_scaler (ville) - mode to adjusted_mode (ville) - combine pipe/plane scaling check Changes since V2: - Indentation fix - Added TODO to handle/reject NV12 with interlace mode Signed-off-by: Mahesh Kumar Link: http://patchwork.freedesktop.org/patch/msgid/20170630121100.20159-3-mahesh1.kumar@intel.com Reviewed-by: Ville Syrjälä Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_display.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 4836e537c7f8..9b6689ef5e30 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4612,6 +4612,9 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, &crtc_state->scaler_state; struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc); + struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); + const struct drm_display_mode *adjusted_mode = + &crtc_state->base.adjusted_mode; int need_scaling; /* @@ -4621,6 +4624,18 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, */ need_scaling = src_w != dst_w || src_h != dst_h; + /* + * Scaling/fitting not supported in IF-ID mode in GEN9+ + * TODO: Interlace fetch mode doesn't support YUV420 planar formats. + * Once NV12 is enabled, handle it here while allocating scaler + * for NV12. + */ + if (INTEL_GEN(dev_priv) >= 9 && crtc_state->base.enable && + need_scaling && adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { + DRM_DEBUG_KMS("Pipe/Plane scaling not supported with IF-ID mode\n"); + return -EINVAL; + } + /* * if plane is being disabled or scaler is no more required or force detach * - free scaler binded to this plane/crtc -- cgit v1.2.3 From c99a259b4b5192ba30d37fe25f09632d4c52f5d7 Mon Sep 17 00:00:00 2001 From: Manasi Navare Date: Fri, 30 Jun 2017 09:33:48 -0700 Subject: drm/i915/edp: Add a T12 panel delay quirk to fix DP AUX CH timeouts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes the DP AUX CH timeouts observed during CI IGT tests thus fixing the CI failures. This is done by adding a quirk for a particular PCI device that requires the panel power cycle delay (T12) to be set to 800ms which is 300msecs more than the minimum value specified in the eDP spec. So a quirk is implemented for that specific PCI device. v4: * Add Bugzilla links for FDO bugs in the commit message (Ville, Jani) v3: * Change some comments, specify the delay as 800 * 10 (Ville) v2: * Change the function and variable names to from PPS_T12_ to _T12 since it is a T12 delay (Clint) Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=101144 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=101154 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=101167 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=101515 Cc: Ville Syrjala Cc: Clinton Taylor Signed-off-by: Manasi Navare Reviewed-by: Clinton Taylor Link: http://patchwork.freedesktop.org/patch/msgid/1498840428-23176-1-git-send-email-manasi.d.navare@intel.com Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_display.c | 14 ++++++++++++++ drivers/gpu/drm/i915/intel_dp.c | 10 ++++++++++ 3 files changed, 25 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 29d162b24d8d..a7db1ab60884 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1166,6 +1166,7 @@ enum intel_sbi_destination { #define QUIRK_INVERT_BRIGHTNESS (1<<2) #define QUIRK_BACKLIGHT_PRESENT (1<<3) #define QUIRK_PIN_SWIZZLED_PAGES (1<<5) +#define QUIRK_INCREASE_T12_DELAY (1<<6) struct intel_fbdev; struct intel_fbc_work; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 9b6689ef5e30..ede3c6c02ec5 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14771,6 +14771,17 @@ static void quirk_backlight_present(struct drm_device *dev) DRM_INFO("applying backlight present quirk\n"); } +/* Toshiba Satellite P50-C-18C requires T12 delay to be min 800ms + * which is 300 ms greater than eDP spec T12 min. + */ +static void quirk_increase_t12_delay(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = to_i915(dev); + + dev_priv->quirks |= QUIRK_INCREASE_T12_DELAY; + DRM_INFO("Applying T12 delay quirk\n"); +} + struct intel_quirk { int device; int subsystem_vendor; @@ -14854,6 +14865,9 @@ static struct intel_quirk intel_quirks[] = { /* Dell Chromebook 11 (2015 version) */ { 0x0a16, 0x1028, 0x0a35, quirk_backlight_present }, + + /* Toshiba Satellite P50-C-18C */ + { 0x191B, 0x1179, 0xF840, quirk_increase_t12_delay }, }; static void intel_init_quirks(struct drm_device *dev) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 0445d11224d4..a9022d13e959 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -5255,6 +5255,16 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev, intel_pps_dump_state("cur", &cur); vbt = dev_priv->vbt.edp.pps; + /* On Toshiba Satellite P50-C-18C system the VBT T12 delay + * of 500ms appears to be too short. Ocassionally the panel + * just fails to power back on. Increasing the delay to 800ms + * seems sufficient to avoid this problem. + */ + if (dev_priv->quirks & QUIRK_INCREASE_T12_DELAY) { + vbt.t11_t12 = max_t(u16, vbt.t11_t12, 800 * 10); + DRM_DEBUG_KMS("Increasing T12 panel delay as per the quirk to %d\n", + vbt.t11_t12); + } /* T11_T12 delay is special and actually in units of 100ms, but zero * based in the hw (so we need to add 100 ms). But the sw vbt * table multiplies it with 1000 to make it in units of 100usec, -- cgit v1.2.3 From 8c3a8181a46b55ec0ab9dee3c178ba2b2b6ed77b Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 27 Jun 2017 16:59:36 +0200 Subject: drm/atomic-helper: Realign function parameters Too jarring. Fixes: f869a6ecf254 ("drm/atomic: Add target_vblank support in atomic helpers (v2)") Cc: Andrey Grodzovsky Cc: Alex Deucher Reviewed-by: Alex Deucher Reviewed-by: Harry Wentland Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170627145936.18983-14-daniel.vetter@ffwll.ch --- drivers/gpu/drm/drm_atomic_helper.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 4f6e52961951..667ec97d4efb 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -3087,12 +3087,11 @@ backoff: } EXPORT_SYMBOL(drm_atomic_helper_connector_set_property); -static int page_flip_common( - struct drm_atomic_state *state, - struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct drm_pending_vblank_event *event, - uint32_t flags) +static int page_flip_common(struct drm_atomic_state *state, + struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event, + uint32_t flags) { struct drm_plane *plane = crtc->primary; struct drm_plane_state *plane_state; @@ -3186,13 +3185,12 @@ EXPORT_SYMBOL(drm_atomic_helper_page_flip); * Returns: * Returns 0 on success, negative errno numbers on failure. */ -int drm_atomic_helper_page_flip_target( - struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct drm_pending_vblank_event *event, - uint32_t flags, - uint32_t target, - struct drm_modeset_acquire_ctx *ctx) +int drm_atomic_helper_page_flip_target(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event, + uint32_t flags, + uint32_t target, + struct drm_modeset_acquire_ctx *ctx) { struct drm_plane *plane = crtc->primary; struct drm_atomic_state *state; -- cgit v1.2.3 From be2ea53330f1865ac5b00377f2074f8e255bf74c Mon Sep 17 00:00:00 2001 From: Quentin Schulz Date: Mon, 3 Jul 2017 15:09:26 +0200 Subject: iio: adc: sun4i-gpadc-iio: fix unbalanced irq enable/disable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When initializing interrupts, the devm_request_any_context_irq will enable them right away. An atomic flag was set in sun4i_irq_init and read in the interrupt handler to make sure no unwanted interrupts were handled. If an unwanted interrupt occurred, the handler would disable the irq and return IRQ_HANDLED. However, at the end of sun4i_irq_init, the irq would be disabled as well, resulting in an unbalanced enable (since there are more disables than enables, the code enabling the interrupt would never be called). When reading the ADC or the temperature, the respective irq would be enabled in the read function and disabled in the irq handler. In the read function, we would wait for a completion (with a timeout) that will be set in the irq handler. However, if the completion is never set or if the wait for completion times out, the irq would not be disabled in the read function resulting in an unbalanced enable once the read function is called again (since there are 2+ enables for no disable). Moving disable_irq from the irq handler to the read function get rid of these two cases of unbalanced enable. Fixes: d1caa9905538 ("iio: adc: add support for Allwinner SoCs ADC") Reported-by: Andreas Färber Signed-off-by: Quentin Schulz Acked-by: Maxime Ripard Signed-off-by: Jonathan Cameron --- drivers/iio/adc/sun4i-gpadc-iio.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c index 81d4c39e414a..137f577d9432 100644 --- a/drivers/iio/adc/sun4i-gpadc-iio.c +++ b/drivers/iio/adc/sun4i-gpadc-iio.c @@ -256,6 +256,7 @@ static int sun4i_gpadc_read(struct iio_dev *indio_dev, int channel, int *val, err: pm_runtime_put_autosuspend(indio_dev->dev.parent); + disable_irq(irq); mutex_unlock(&info->mutex); return ret; @@ -365,7 +366,6 @@ static irqreturn_t sun4i_gpadc_temp_data_irq_handler(int irq, void *dev_id) complete(&info->completion); out: - disable_irq_nosync(info->temp_data_irq); return IRQ_HANDLED; } @@ -380,7 +380,6 @@ static irqreturn_t sun4i_gpadc_fifo_data_irq_handler(int irq, void *dev_id) complete(&info->completion); out: - disable_irq_nosync(info->fifo_data_irq); return IRQ_HANDLED; } -- cgit v1.2.3 From 631b010abc5b57009c6a8328f51492665f6ef310 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 30 Jun 2017 19:42:54 +0200 Subject: iio: adc: Revert "axp288: Drop bogus AXP288_ADC_TS_PIN_CTRL register modifications" Inheriting the ADC BIAS current settings from the BIOS instead of hardcoding then causes the AXP288 to disable charging (I think it mis-detects an overheated battery) on at least one model tablet. So lets go back to hard coding the values, this reverts commit fa2849e9649b ("iio: adc: axp288: Drop bogus AXP288_ADC_TS_PIN_CTRL register modifications"), fixing charging not working on the model tablet in question. The exact cause is not fully understood, hence the revert to a known working state. Cc: stable@vger.kernel.org Reported-by: Umberto Ixxo Signed-off-by: Hans de Goede Signed-off-by: Jonathan Cameron --- drivers/iio/adc/axp288_adc.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/adc/axp288_adc.c b/drivers/iio/adc/axp288_adc.c index 64799ad7ebad..7fd24949c0c1 100644 --- a/drivers/iio/adc/axp288_adc.c +++ b/drivers/iio/adc/axp288_adc.c @@ -28,6 +28,8 @@ #include #define AXP288_ADC_EN_MASK 0xF1 +#define AXP288_ADC_TS_PIN_GPADC 0xF2 +#define AXP288_ADC_TS_PIN_ON 0xF3 enum axp288_adc_id { AXP288_ADC_TS, @@ -121,6 +123,16 @@ static int axp288_adc_read_channel(int *val, unsigned long address, return IIO_VAL_INT; } +static int axp288_adc_set_ts(struct regmap *regmap, unsigned int mode, + unsigned long address) +{ + /* channels other than GPADC do not need to switch TS pin */ + if (address != AXP288_GP_ADC_H) + return 0; + + return regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, mode); +} + static int axp288_adc_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -131,7 +143,16 @@ static int axp288_adc_read_raw(struct iio_dev *indio_dev, mutex_lock(&indio_dev->mlock); switch (mask) { case IIO_CHAN_INFO_RAW: + if (axp288_adc_set_ts(info->regmap, AXP288_ADC_TS_PIN_GPADC, + chan->address)) { + dev_err(&indio_dev->dev, "GPADC mode\n"); + ret = -EINVAL; + break; + } ret = axp288_adc_read_channel(val, chan->address, info->regmap); + if (axp288_adc_set_ts(info->regmap, AXP288_ADC_TS_PIN_ON, + chan->address)) + dev_err(&indio_dev->dev, "TS pin restore\n"); break; default: ret = -EINVAL; @@ -141,6 +162,15 @@ static int axp288_adc_read_raw(struct iio_dev *indio_dev, return ret; } +static int axp288_adc_set_state(struct regmap *regmap) +{ + /* ADC should be always enabled for internal FG to function */ + if (regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, AXP288_ADC_TS_PIN_ON)) + return -EIO; + + return regmap_write(regmap, AXP20X_ADC_EN1, AXP288_ADC_EN_MASK); +} + static const struct iio_info axp288_adc_iio_info = { .read_raw = &axp288_adc_read_raw, .driver_module = THIS_MODULE, @@ -169,7 +199,7 @@ static int axp288_adc_probe(struct platform_device *pdev) * Set ADC to enabled state at all time, including system suspend. * otherwise internal fuel gauge functionality may be affected. */ - ret = regmap_write(info->regmap, AXP20X_ADC_EN1, AXP288_ADC_EN_MASK); + ret = axp288_adc_set_state(axp20x->regmap); if (ret) { dev_err(&pdev->dev, "unable to enable ADC device\n"); return ret; -- cgit v1.2.3 From e12ffd241c00146665cc2355263888c0f9e2b7fd Mon Sep 17 00:00:00 2001 From: Mikko Koivunen Date: Mon, 3 Jul 2017 15:50:13 +0300 Subject: iio: light: rpr0521 triggered buffer Set up and use triggered buffer if there is irq defined for device in device tree. Trigger producer triggers from rpr0521 drdy interrupt line. Trigger consumer reads rpr0521 data to scan buffer. Depends on previous commits of _scale and _offset. Signed-off-by: Mikko Koivunen Signed-off-by: Jonathan Cameron --- drivers/iio/light/rpr0521.c | 336 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 329 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/light/rpr0521.c b/drivers/iio/light/rpr0521.c index 9d0c2e859bb2..a6efa12613a2 100644 --- a/drivers/iio/light/rpr0521.c +++ b/drivers/iio/light/rpr0521.c @@ -9,7 +9,7 @@ * * IIO driver for RPR-0521RS (7-bit I2C slave address 0x38). * - * TODO: illuminance channel, buffer + * TODO: illuminance channel */ #include @@ -20,6 +20,10 @@ #include #include +#include +#include +#include +#include #include #include @@ -30,6 +34,7 @@ #define RPR0521_REG_PXS_DATA 0x44 /* 16-bit, little endian */ #define RPR0521_REG_ALS_DATA0 0x46 /* 16-bit, little endian */ #define RPR0521_REG_ALS_DATA1 0x48 /* 16-bit, little endian */ +#define RPR0521_REG_INTERRUPT 0x4A #define RPR0521_REG_PS_OFFSET_LSB 0x53 #define RPR0521_REG_ID 0x92 @@ -42,16 +47,31 @@ #define RPR0521_ALS_DATA1_GAIN_SHIFT 2 #define RPR0521_PXS_GAIN_MASK GENMASK(5, 4) #define RPR0521_PXS_GAIN_SHIFT 4 +#define RPR0521_PXS_PERSISTENCE_MASK GENMASK(3, 0) +#define RPR0521_INTERRUPT_INT_TRIG_PS_MASK BIT(0) +#define RPR0521_INTERRUPT_INT_TRIG_ALS_MASK BIT(1) +#define RPR0521_INTERRUPT_INT_REASSERT_MASK BIT(3) +#define RPR0521_INTERRUPT_ALS_INT_STATUS_MASK BIT(6) +#define RPR0521_INTERRUPT_PS_INT_STATUS_MASK BIT(7) #define RPR0521_MODE_ALS_ENABLE BIT(7) #define RPR0521_MODE_ALS_DISABLE 0x00 #define RPR0521_MODE_PXS_ENABLE BIT(6) #define RPR0521_MODE_PXS_DISABLE 0x00 +#define RPR0521_PXS_PERSISTENCE_DRDY 0x00 + +#define RPR0521_INTERRUPT_INT_TRIG_PS_ENABLE BIT(0) +#define RPR0521_INTERRUPT_INT_TRIG_PS_DISABLE 0x00 +#define RPR0521_INTERRUPT_INT_TRIG_ALS_ENABLE BIT(1) +#define RPR0521_INTERRUPT_INT_TRIG_ALS_DISABLE 0x00 +#define RPR0521_INTERRUPT_INT_REASSERT_ENABLE BIT(3) +#define RPR0521_INTERRUPT_INT_REASSERT_DISABLE 0x00 #define RPR0521_MANUFACT_ID 0xE0 #define RPR0521_DEFAULT_MEAS_TIME 0x06 /* ALS - 100ms, PXS - 100ms */ #define RPR0521_DRV_NAME "RPR0521" +#define RPR0521_IRQ_NAME "rpr0521_event" #define RPR0521_REGMAP_NAME "rpr0521_regmap" #define RPR0521_SLEEP_DELAY_MS 2000 @@ -167,6 +187,9 @@ struct rpr0521_data { bool als_dev_en; bool pxs_dev_en; + struct iio_trigger *drdy_trigger0; + s64 irq_timestamp; + /* optimize runtime pm ops - enable/disable device only if needed */ bool als_ps_need_en; bool pxs_ps_need_en; @@ -196,6 +219,19 @@ static const struct attribute_group rpr0521_attribute_group = { .attrs = rpr0521_attributes, }; +/* Order of the channel data in buffer */ +enum rpr0521_scan_index_order { + RPR0521_CHAN_INDEX_PXS, + RPR0521_CHAN_INDEX_BOTH, + RPR0521_CHAN_INDEX_IR, +}; + +static const unsigned long rpr0521_available_scan_masks[] = { + BIT(RPR0521_CHAN_INDEX_PXS) | BIT(RPR0521_CHAN_INDEX_BOTH) | + BIT(RPR0521_CHAN_INDEX_IR), + 0 +}; + static const struct iio_chan_spec rpr0521_channels[] = { { .type = IIO_PROXIMITY, @@ -204,6 +240,13 @@ static const struct iio_chan_spec rpr0521_channels[] = { BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE), .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), + .scan_index = RPR0521_CHAN_INDEX_PXS, + .scan_type = { + .sign = 'u', + .realbits = 16, + .storagebits = 16, + .endianness = IIO_LE, + }, }, { .type = IIO_INTENSITY, @@ -213,6 +256,13 @@ static const struct iio_chan_spec rpr0521_channels[] = { .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), + .scan_index = RPR0521_CHAN_INDEX_BOTH, + .scan_type = { + .sign = 'u', + .realbits = 16, + .storagebits = 16, + .endianness = IIO_LE, + }, }, { .type = IIO_INTENSITY, @@ -222,6 +272,13 @@ static const struct iio_chan_spec rpr0521_channels[] = { .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), + .scan_index = RPR0521_CHAN_INDEX_IR, + .scan_type = { + .sign = 'u', + .realbits = 16, + .storagebits = 16, + .endianness = IIO_LE, + }, }, }; @@ -330,6 +387,198 @@ static int rpr0521_set_power_state(struct rpr0521_data *data, bool on, return 0; } +/* Interrupt register tells if this sensor caused the interrupt or not. */ +static inline bool rpr0521_is_triggered(struct rpr0521_data *data) +{ + int ret; + int reg; + + ret = regmap_read(data->regmap, RPR0521_REG_INTERRUPT, ®); + if (ret < 0) + return false; /* Reg read failed. */ + if (reg & + (RPR0521_INTERRUPT_ALS_INT_STATUS_MASK | + RPR0521_INTERRUPT_PS_INT_STATUS_MASK)) + return true; + else + return false; /* Int not from this sensor. */ +} + +/* IRQ to trigger handler */ +static irqreturn_t rpr0521_drdy_irq_handler(int irq, void *private) +{ + struct iio_dev *indio_dev = private; + struct rpr0521_data *data = iio_priv(indio_dev); + + data->irq_timestamp = iio_get_time_ns(indio_dev); + /* + * We need to wake the thread to read the interrupt reg. It + * is not possible to do that here because regmap_read takes a + * mutex. + */ + + return IRQ_WAKE_THREAD; +} + +static irqreturn_t rpr0521_drdy_irq_thread(int irq, void *private) +{ + struct iio_dev *indio_dev = private; + struct rpr0521_data *data = iio_priv(indio_dev); + + if (rpr0521_is_triggered(data)) { + iio_trigger_poll_chained(data->drdy_trigger0); + return IRQ_HANDLED; + } + + return IRQ_NONE; +} + +static irqreturn_t rpr0521_trigger_consumer_store_time(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + + /* Other trigger polls store time here. */ + if (!iio_trigger_using_own(indio_dev)) + pf->timestamp = iio_get_time_ns(indio_dev); + + return IRQ_WAKE_THREAD; +} + +static irqreturn_t rpr0521_trigger_consumer_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct rpr0521_data *data = iio_priv(indio_dev); + int err; + + u8 buffer[16]; /* 3 16-bit channels + padding + ts */ + + /* Use irq timestamp when reasonable. */ + if (iio_trigger_using_own(indio_dev) && data->irq_timestamp) { + pf->timestamp = data->irq_timestamp; + data->irq_timestamp = 0; + } + /* Other chained trigger polls get timestamp only here. */ + if (!pf->timestamp) + pf->timestamp = iio_get_time_ns(indio_dev); + + err = regmap_bulk_read(data->regmap, RPR0521_REG_PXS_DATA, + &buffer, + (3 * 2) + 1); /* 3 * 16-bit + (discarded) int clear reg. */ + if (!err) + iio_push_to_buffers_with_timestamp(indio_dev, + buffer, pf->timestamp); + else + dev_err(&data->client->dev, + "Trigger consumer can't read from sensor.\n"); + pf->timestamp = 0; + + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static int rpr0521_write_int_enable(struct rpr0521_data *data) +{ + int err; + + /* Interrupt after each measurement */ + err = regmap_update_bits(data->regmap, RPR0521_REG_PXS_CTRL, + RPR0521_PXS_PERSISTENCE_MASK, + RPR0521_PXS_PERSISTENCE_DRDY); + if (err) { + dev_err(&data->client->dev, "PS control reg write fail.\n"); + return -EBUSY; + } + + /* Ignore latch and mode because of drdy */ + err = regmap_write(data->regmap, RPR0521_REG_INTERRUPT, + RPR0521_INTERRUPT_INT_REASSERT_DISABLE | + RPR0521_INTERRUPT_INT_TRIG_ALS_DISABLE | + RPR0521_INTERRUPT_INT_TRIG_PS_ENABLE + ); + if (err) { + dev_err(&data->client->dev, "Interrupt setup write fail.\n"); + return -EBUSY; + } + + return 0; +} + +static int rpr0521_write_int_disable(struct rpr0521_data *data) +{ + /* Don't care of clearing mode, assert and latch. */ + return regmap_write(data->regmap, RPR0521_REG_INTERRUPT, + RPR0521_INTERRUPT_INT_TRIG_ALS_DISABLE | + RPR0521_INTERRUPT_INT_TRIG_PS_DISABLE + ); +} + +/* + * Trigger producer enable / disable. Note that there will be trigs only when + * measurement data is ready to be read. + */ +static int rpr0521_pxs_drdy_set_state(struct iio_trigger *trigger, + bool enable_drdy) +{ + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trigger); + struct rpr0521_data *data = iio_priv(indio_dev); + int err; + + if (enable_drdy) + err = rpr0521_write_int_enable(data); + else + err = rpr0521_write_int_disable(data); + if (err) + dev_err(&data->client->dev, "rpr0521_pxs_drdy_set_state failed\n"); + + return err; +} + +static const struct iio_trigger_ops rpr0521_trigger_ops = { + .set_trigger_state = rpr0521_pxs_drdy_set_state, + .owner = THIS_MODULE, + }; + + +static int rpr0521_buffer_preenable(struct iio_dev *indio_dev) +{ + int err; + struct rpr0521_data *data = iio_priv(indio_dev); + + mutex_lock(&data->lock); + err = rpr0521_set_power_state(data, true, + (RPR0521_MODE_PXS_MASK | RPR0521_MODE_ALS_MASK)); + mutex_unlock(&data->lock); + if (err) + dev_err(&data->client->dev, "_buffer_preenable fail\n"); + + return err; +} + +static int rpr0521_buffer_postdisable(struct iio_dev *indio_dev) +{ + int err; + struct rpr0521_data *data = iio_priv(indio_dev); + + mutex_lock(&data->lock); + err = rpr0521_set_power_state(data, false, + (RPR0521_MODE_PXS_MASK | RPR0521_MODE_ALS_MASK)); + mutex_unlock(&data->lock); + if (err) + dev_err(&data->client->dev, "_buffer_postdisable fail\n"); + + return err; +} + +static const struct iio_buffer_setup_ops rpr0521_buffer_setup_ops = { + .preenable = rpr0521_buffer_preenable, + .postenable = iio_triggered_buffer_postenable, + .predisable = iio_triggered_buffer_predisable, + .postdisable = rpr0521_buffer_postdisable, +}; + static int rpr0521_get_gain(struct rpr0521_data *data, int chan, int *val, int *val2) { @@ -473,6 +722,7 @@ static int rpr0521_read_raw(struct iio_dev *indio_dev, { struct rpr0521_data *data = iio_priv(indio_dev); int ret; + int busy; u8 device_mask; __le16 raw_data; @@ -481,26 +731,30 @@ static int rpr0521_read_raw(struct iio_dev *indio_dev, if (chan->type != IIO_INTENSITY && chan->type != IIO_PROXIMITY) return -EINVAL; + busy = iio_device_claim_direct_mode(indio_dev); + if (busy) + return -EBUSY; + device_mask = rpr0521_data_reg[chan->address].device_mask; mutex_lock(&data->lock); ret = rpr0521_set_power_state(data, true, device_mask); - if (ret < 0) { - mutex_unlock(&data->lock); - return ret; - } + if (ret < 0) + goto rpr0521_read_raw_out; ret = regmap_bulk_read(data->regmap, rpr0521_data_reg[chan->address].address, &raw_data, sizeof(raw_data)); if (ret < 0) { rpr0521_set_power_state(data, false, device_mask); - mutex_unlock(&data->lock); - return ret; + goto rpr0521_read_raw_out; } ret = rpr0521_set_power_state(data, false, device_mask); + +rpr0521_read_raw_out: mutex_unlock(&data->lock); + iio_device_release_direct_mode(indio_dev); if (ret < 0) return ret; @@ -617,12 +871,15 @@ static int rpr0521_init(struct rpr0521_data *data) return ret; #endif + data->irq_timestamp = 0; + return 0; } static int rpr0521_poweroff(struct rpr0521_data *data) { int ret; + int tmp; ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL, RPR0521_MODE_ALS_MASK | @@ -635,6 +892,16 @@ static int rpr0521_poweroff(struct rpr0521_data *data) data->als_dev_en = false; data->pxs_dev_en = false; + /* + * Int pin keeps state after power off. Set pin to high impedance + * mode to prevent power drain. + */ + ret = regmap_read(data->regmap, RPR0521_REG_INTERRUPT, &tmp); + if (ret) { + dev_err(&data->client->dev, "Failed to reset int pin.\n"); + return ret; + } + return 0; } @@ -707,6 +974,61 @@ static int rpr0521_probe(struct i2c_client *client, pm_runtime_set_autosuspend_delay(&client->dev, RPR0521_SLEEP_DELAY_MS); pm_runtime_use_autosuspend(&client->dev); + /* + * If sensor write/read is needed in _probe after _use_autosuspend, + * sensor needs to be _resumed first using rpr0521_set_power_state(). + */ + + /* IRQ to trigger setup */ + if (client->irq) { + /* Trigger0 producer setup */ + data->drdy_trigger0 = devm_iio_trigger_alloc( + indio_dev->dev.parent, + "%s-dev%d", indio_dev->name, indio_dev->id); + if (!data->drdy_trigger0) { + ret = -ENOMEM; + goto err_pm_disable; + } + data->drdy_trigger0->dev.parent = indio_dev->dev.parent; + data->drdy_trigger0->ops = &rpr0521_trigger_ops; + indio_dev->available_scan_masks = rpr0521_available_scan_masks; + iio_trigger_set_drvdata(data->drdy_trigger0, indio_dev); + + /* Ties irq to trigger producer handler. */ + ret = devm_request_threaded_irq(&client->dev, client->irq, + rpr0521_drdy_irq_handler, rpr0521_drdy_irq_thread, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + RPR0521_IRQ_NAME, indio_dev); + if (ret < 0) { + dev_err(&client->dev, "request irq %d for trigger0 failed\n", + client->irq); + goto err_pm_disable; + } + + ret = devm_iio_trigger_register(indio_dev->dev.parent, + data->drdy_trigger0); + if (ret) { + dev_err(&client->dev, "iio trigger register failed\n"); + goto err_pm_disable; + } + + /* + * Now whole pipe from physical interrupt (irq defined by + * devicetree to device) to trigger0 output is set up. + */ + + /* Trigger consumer setup */ + ret = devm_iio_triggered_buffer_setup(indio_dev->dev.parent, + indio_dev, + rpr0521_trigger_consumer_store_time, + rpr0521_trigger_consumer_handler, + &rpr0521_buffer_setup_ops); + if (ret < 0) { + dev_err(&client->dev, "iio triggered buffer setup failed\n"); + goto err_pm_disable; + } + } + ret = iio_device_register(indio_dev); if (ret) goto err_pm_disable; -- cgit v1.2.3 From 1d3eacbfa64411465c568d58583be3b9fa26857b Mon Sep 17 00:00:00 2001 From: Mike Looijmans Date: Mon, 3 Jul 2017 08:25:57 +0200 Subject: iio: Add LTC2471/LTC2473 driver The LTC2741 and LTC2473 are single voltage ADC chips. The LTC2473 is similar to the LTC2471 but outputs a signed differential value. Datasheet: http://cds.linear.com/docs/en/datasheet/24713fb.pdf Signed-off-by: Mike Looijmans Reviewed-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/adc/Kconfig | 10 +++ drivers/iio/adc/Makefile | 1 + drivers/iio/adc/ltc2471.c | 160 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 171 insertions(+) create mode 100644 drivers/iio/adc/ltc2471.c (limited to 'drivers') diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index b56c4a1989a7..8a6edf5bb1e5 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -362,6 +362,16 @@ config LPC32XX_ADC activate only one via device tree selection. Provides direct access via sysfs. +config LTC2471 + tristate "Linear Technology LTC2471 and LTC2473 ADC driver" + depends on I2C + help + Say yes here to build support for Linear Technology LTC2471 and + LTC2473 16-bit I2C ADC. + + This driver can also be built as a module. If so, the module will + be called ltc2471. + config LTC2485 tristate "Linear Technology LTC2485 ADC driver" depends on I2C diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index b546736a5541..73c206209f1f 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o +obj-$(CONFIG_LTC2471) += ltc2471.o obj-$(CONFIG_LTC2485) += ltc2485.o obj-$(CONFIG_LTC2497) += ltc2497.o obj-$(CONFIG_MAX1027) += max1027.o diff --git a/drivers/iio/adc/ltc2471.c b/drivers/iio/adc/ltc2471.c new file mode 100644 index 000000000000..29b7ed60cdb0 --- /dev/null +++ b/drivers/iio/adc/ltc2471.c @@ -0,0 +1,160 @@ +/* + * Driver for Linear Technology LTC2471 and LTC2473 voltage monitors + * The LTC2473 is identical to the 2471, but reports a differential signal. + * + * Copyright (C) 2017 Topic Embedded Products + * Author: Mike Looijmans + * + * License: GPLv2 + */ + +#include +#include +#include +#include +#include +#include + +enum ltc2471_chips { + ltc2471, + ltc2473, +}; + +struct ltc2471_data { + struct i2c_client *client; +}; + +/* Reference voltage is 1.25V */ +#define LTC2471_VREF 1250 + +/* Read two bytes from the I2C bus to obtain the ADC result */ +static int ltc2471_get_value(struct i2c_client *client) +{ + int ret; + __be16 buf; + + ret = i2c_master_recv(client, (char *)&buf, sizeof(buf)); + if (ret < 0) + return ret; + if (ret != sizeof(buf)) + return -EIO; + + /* MSB first */ + return be16_to_cpu(buf); +} + +static int ltc2471_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long info) +{ + struct ltc2471_data *data = iio_priv(indio_dev); + int ret; + + switch (info) { + case IIO_CHAN_INFO_RAW: + ret = ltc2471_get_value(data->client); + if (ret < 0) + return ret; + *val = ret; + return IIO_VAL_INT; + + case IIO_CHAN_INFO_SCALE: + if (chan->differential) + /* Output ranges from -VREF to +VREF */ + *val = 2 * LTC2471_VREF; + else + /* Output ranges from 0 to VREF */ + *val = LTC2471_VREF; + *val2 = 16; /* 16 data bits */ + return IIO_VAL_FRACTIONAL_LOG2; + + case IIO_CHAN_INFO_OFFSET: + /* Only differential chip has this property */ + *val = -LTC2471_VREF; + return IIO_VAL_INT; + + default: + return -EINVAL; + } +} + +static const struct iio_chan_spec ltc2471_channel[] = { + { + .type = IIO_VOLTAGE, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + }, +}; + +static const struct iio_chan_spec ltc2473_channel[] = { + { + .type = IIO_VOLTAGE, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_OFFSET), + .differential = 1, + }, +}; + +static const struct iio_info ltc2471_info = { + .read_raw = ltc2471_read_raw, + .driver_module = THIS_MODULE, +}; + +static int ltc2471_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct iio_dev *indio_dev; + struct ltc2471_data *data; + int ret; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return -EOPNOTSUPP; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + data->client = client; + + indio_dev->dev.parent = &client->dev; + indio_dev->name = id->name; + indio_dev->info = <c2471_info; + indio_dev->modes = INDIO_DIRECT_MODE; + if (id->driver_data == ltc2473) + indio_dev->channels = ltc2473_channel; + else + indio_dev->channels = ltc2471_channel; + indio_dev->num_channels = 1; + + /* Trigger once to start conversion and check if chip is there */ + ret = ltc2471_get_value(client); + if (ret < 0) { + dev_err(&client->dev, "Cannot read from device.\n"); + return ret; + } + + return devm_iio_device_register(&client->dev, indio_dev); +} + +static const struct i2c_device_id ltc2471_i2c_id[] = { + { "ltc2471", ltc2471 }, + { "ltc2473", ltc2473 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, ltc2471_i2c_id); + +static struct i2c_driver ltc2471_i2c_driver = { + .driver = { + .name = "ltc2471", + }, + .probe = ltc2471_i2c_probe, + .id_table = ltc2471_i2c_id, +}; + +module_i2c_driver(ltc2471_i2c_driver); + +MODULE_DESCRIPTION("LTC2471/LTC2473 ADC driver"); +MODULE_AUTHOR("Topic Embedded Products"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 43858b4f25cf0adc5c2ca9cf5ce5fdf2532941e5 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Thu, 29 Jun 2017 08:53:18 -0700 Subject: x86/mm: Stop calling leave_mm() in idle code Now that lazy TLB suppresses all flush IPIs (as opposed to all but the first), there's no need to leave_mm() when going idle. This means we can get rid of the rcuidle hack in switch_mm_irqs_off() and we can unexport leave_mm(). This also removes acpi_unlazy_tlb() from the x86 and ia64 headers, since it has no callers any more. Signed-off-by: Andy Lutomirski Reviewed-by: Nadav Amit Reviewed-by: Borislav Petkov Reviewed-by: Thomas Gleixner Cc: Andrew Morton Cc: Arjan van de Ven Cc: Borislav Petkov Cc: Dave Hansen Cc: Linus Torvalds Cc: Mel Gorman Cc: Peter Zijlstra Cc: Rik van Riel Cc: linux-mm@kvack.org Link: http://lkml.kernel.org/r/03c699cfd6021e467be650d6b73deaccfe4b4bd7.1498751203.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/ia64/include/asm/acpi.h | 2 -- arch/x86/include/asm/acpi.h | 2 -- arch/x86/mm/tlb.c | 20 +++----------------- drivers/acpi/processor_idle.c | 2 -- drivers/idle/intel_idle.c | 9 ++++----- 5 files changed, 7 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/arch/ia64/include/asm/acpi.h b/arch/ia64/include/asm/acpi.h index a3d0211970e9..c86a947f5368 100644 --- a/arch/ia64/include/asm/acpi.h +++ b/arch/ia64/include/asm/acpi.h @@ -112,8 +112,6 @@ static inline void arch_acpi_set_pdc_bits(u32 *buf) buf[2] |= ACPI_PDC_EST_CAPABILITY_SMP; } -#define acpi_unlazy_tlb(x) - #ifdef CONFIG_ACPI_NUMA extern cpumask_t early_cpu_possible_map; #define for_each_possible_early_cpu(cpu) \ diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h index 2efc768e4362..562286fa151f 100644 --- a/arch/x86/include/asm/acpi.h +++ b/arch/x86/include/asm/acpi.h @@ -150,8 +150,6 @@ static inline void disable_acpi(void) { } extern int x86_acpi_numa_init(void); #endif /* CONFIG_ACPI_NUMA */ -#define acpi_unlazy_tlb(x) leave_mm(x) - #ifdef CONFIG_ACPI_APEI static inline pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr) { diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index 0982c997d36f..2c1b8881e9d3 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c @@ -50,7 +50,6 @@ void leave_mm(int cpu) switch_mm(NULL, &init_mm, NULL); } -EXPORT_SYMBOL_GPL(leave_mm); void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk) @@ -117,15 +116,8 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next, this_cpu_write(cpu_tlbstate.ctxs[0].tlb_gen, next_tlb_gen); write_cr3(__pa(next->pgd)); - - /* - * This gets called via leave_mm() in the idle path - * where RCU functions differently. Tracing normally - * uses RCU, so we have to call the tracepoint - * specially here. - */ - trace_tlb_flush_rcuidle(TLB_FLUSH_ON_TASK_SWITCH, - TLB_FLUSH_ALL); + trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, + TLB_FLUSH_ALL); } /* @@ -167,13 +159,7 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next, this_cpu_write(cpu_tlbstate.loaded_mm, next); write_cr3(__pa(next->pgd)); - /* - * This gets called via leave_mm() in the idle path where RCU - * functions differently. Tracing normally uses RCU, so we - * have to call the tracepoint specially here. - */ - trace_tlb_flush_rcuidle(TLB_FLUSH_ON_TASK_SWITCH, - TLB_FLUSH_ALL); + trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, TLB_FLUSH_ALL); } load_mm_cr4(next); diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 5c8aa9cf62d7..fe3d2a40f311 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -708,8 +708,6 @@ static DEFINE_RAW_SPINLOCK(c3_lock); static void acpi_idle_enter_bm(struct acpi_processor *pr, struct acpi_processor_cx *cx, bool timer_bc) { - acpi_unlazy_tlb(smp_processor_id()); - /* * Must be done before busmaster disable as we might need to * access HPET ! diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 216d7ec88c0c..2ae43f59091d 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -912,16 +912,15 @@ static __cpuidle int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state = &drv->states[index]; unsigned long eax = flg2MWAIT(state->flags); unsigned int cstate; - int cpu = smp_processor_id(); cstate = (((eax) >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK) + 1; /* - * leave_mm() to avoid costly and often unnecessary wakeups - * for flushing the user TLB's associated with the active mm. + * NB: if CPUIDLE_FLAG_TLB_FLUSHED is set, this idle transition + * will probably flush the TLB. It's not guaranteed to flush + * the TLB, though, so it's not clear that we can do anything + * useful with this knowledge. */ - if (state->flags & CPUIDLE_FLAG_TLB_FLUSHED) - leave_mm(cpu); if (!(lapic_timer_reliable_states & (1 << (cstate)))) tick_broadcast_enter(); -- cgit v1.2.3 From af2405af07d168e2905f2ac9494d3a804a549f0f Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 4 Jul 2017 17:18:21 +0200 Subject: drm/fb-helper: Push down modeset lock into FB helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the modeset locking from drivers into FB helpers. v2: Also handle intel_connector_add_to_fbdev. v3: Prevent race in intel_dp_mst with ->detect (Maarten) Cc: Maarten Lankhorst Cc: Alex Deucher Cc: Christian König Tested-by: John Stultz Signed-off-by: Thierry Reding (v1) Reviewed-by: Maarten Lankhorst Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170704151833.17304-2-daniel.vetter@ffwll.ch --- drivers/gpu/drm/drm_fb_helper.c | 40 +++++++++++++++++++++++++++++----- drivers/gpu/drm/i915/intel_dp_mst.c | 9 +++----- drivers/gpu/drm/radeon/radeon_dp_mst.c | 7 ------ 3 files changed, 37 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 84e47e512fe9..7d0d50e404ee 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -109,8 +109,8 @@ static DEFINE_MUTEX(kernel_fb_helper_lock); for (({ lockdep_assert_held(&(fbh)->dev->mode_config.mutex); }), \ i__ = 0; i__ < (fbh)->connector_count; i__++) -int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, - struct drm_connector *connector) +static int __drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, + struct drm_connector *connector) { struct drm_fb_helper_connector *fb_conn; struct drm_fb_helper_connector **temp; @@ -141,8 +141,23 @@ int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, drm_connector_get(connector); fb_conn->connector = connector; fb_helper->connector_info[fb_helper->connector_count++] = fb_conn; + return 0; } + +int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, + struct drm_connector *connector) +{ + int err; + + mutex_lock(&fb_helper->dev->mode_config.mutex); + + err = __drm_fb_helper_add_one_connector(fb_helper, connector); + + mutex_unlock(&fb_helper->dev->mode_config.mutex); + + return err; +} EXPORT_SYMBOL(drm_fb_helper_add_one_connector); /** @@ -172,8 +187,7 @@ int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper) mutex_lock(&dev->mode_config.mutex); drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) { - ret = drm_fb_helper_add_one_connector(fb_helper, connector); - + ret = __drm_fb_helper_add_one_connector(fb_helper, connector); if (ret) goto fail; } @@ -198,8 +212,8 @@ out: } EXPORT_SYMBOL(drm_fb_helper_single_add_all_connectors); -int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, - struct drm_connector *connector) +static int __drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, + struct drm_connector *connector) { struct drm_fb_helper_connector *fb_helper_connector; int i, j; @@ -227,6 +241,20 @@ int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, return 0; } + +int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, + struct drm_connector *connector) +{ + int err; + + mutex_lock(&fb_helper->dev->mode_config.mutex); + + err = __drm_fb_helper_remove_one_connector(fb_helper, connector); + + mutex_unlock(&fb_helper->dev->mode_config.mutex); + + return err; +} EXPORT_SYMBOL(drm_fb_helper_remove_one_connector); static void drm_fb_helper_save_lut_atomic(struct drm_crtc *crtc, struct drm_fb_helper *helper) diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 2cf046beae0f..9aa959284497 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -501,11 +501,8 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo static void intel_dp_register_mst_connector(struct drm_connector *connector) { struct intel_connector *intel_connector = to_intel_connector(connector); - struct drm_device *dev = connector->dev; - drm_modeset_lock_all(dev); intel_connector_add_to_fbdev(intel_connector); - drm_modeset_unlock_all(dev); drm_connector_register(&intel_connector->base); } @@ -514,15 +511,15 @@ static void intel_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr, struct drm_connector *connector) { struct intel_connector *intel_connector = to_intel_connector(connector); - struct drm_device *dev = connector->dev; drm_connector_unregister(connector); /* need to nuke the connector */ - drm_modeset_lock_all(dev); intel_connector_remove_from_fbdev(intel_connector); + /* prevent race with the check in ->detect */ + drm_modeset_lock(&connector->dev->mode_config.connection_mutex, NULL); intel_connector->mst_port = NULL; - drm_modeset_unlock_all(dev); + drm_modeset_unlock(&connector->dev->mode_config.connection_mutex); drm_connector_unreference(&intel_connector->base); DRM_DEBUG_KMS("\n"); diff --git a/drivers/gpu/drm/radeon/radeon_dp_mst.c b/drivers/gpu/drm/radeon/radeon_dp_mst.c index 6598306dca9b..ebdf1b859cb6 100644 --- a/drivers/gpu/drm/radeon/radeon_dp_mst.c +++ b/drivers/gpu/drm/radeon/radeon_dp_mst.c @@ -300,9 +300,7 @@ static void radeon_dp_register_mst_connector(struct drm_connector *connector) struct drm_device *dev = connector->dev; struct radeon_device *rdev = dev->dev_private; - drm_modeset_lock_all(dev); radeon_fb_add_connector(rdev, connector); - drm_modeset_unlock_all(dev); drm_connector_register(connector); } @@ -315,13 +313,8 @@ static void radeon_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr, struct radeon_device *rdev = dev->dev_private; drm_connector_unregister(connector); - /* need to nuke the connector */ - drm_modeset_lock_all(dev); - /* dpms off */ radeon_fb_remove_connector(rdev, connector); - drm_connector_cleanup(connector); - drm_modeset_unlock_all(dev); kfree(connector); DRM_DEBUG_KMS("\n"); -- cgit v1.2.3 From 666b7cdc69b03cb55266a14aa5874af0d27bfb0f Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 4 Jul 2017 17:18:22 +0200 Subject: drm/i915: Drop FBDEV #ifdev in mst code Since commit a03fdcb1863297481a4b817c2a759cafcbdfa0ae Author: Archit Taneja Date: Wed Aug 5 12:28:57 2015 +0530 drm: Add top level Kconfig option for DRM fbdev emulation this is properly handled using dummy functions. This essentially undoes commit 7296c849bf2eca2bd7d34a4686a53e3089150ac1 Author: Chris Wilson Date: Tue Jul 22 20:10:28 2014 +1000 drm/i915: fix build without fbde v2: We also need to drop the #ifdef from headers. Seems like a small price to pay for slightly cleaner code. Cc: Chris Wilson Reviewed-by: Maarten Lankhorst Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170704151833.17304-3-daniel.vetter@ffwll.ch --- drivers/gpu/drm/i915/i915_drv.h | 2 -- drivers/gpu/drm/i915/intel_dp_mst.c | 38 ++++++++++--------------------------- 2 files changed, 10 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e1f7c97a338a..2981014fcfe2 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2303,11 +2303,9 @@ struct drm_i915_private { struct drm_i915_gem_object *vlv_pctx; -#ifdef CONFIG_DRM_FBDEV_EMULATION /* list of fbdev register on this device */ struct intel_fbdev *fbdev; struct work_struct fbdev_suspend_work; -#endif struct drm_property *broadcast_rgb_property; struct drm_property *force_audio_property; diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 9aa959284497..e4ea968b1d6b 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -443,28 +443,6 @@ static bool intel_dp_mst_get_hw_state(struct intel_connector *connector) return false; } -static void intel_connector_add_to_fbdev(struct intel_connector *connector) -{ -#ifdef CONFIG_DRM_FBDEV_EMULATION - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); - - if (dev_priv->fbdev) - drm_fb_helper_add_one_connector(&dev_priv->fbdev->helper, - &connector->base); -#endif -} - -static void intel_connector_remove_from_fbdev(struct intel_connector *connector) -{ -#ifdef CONFIG_DRM_FBDEV_EMULATION - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); - - if (dev_priv->fbdev) - drm_fb_helper_remove_one_connector(&dev_priv->fbdev->helper, - &connector->base); -#endif -} - static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, const char *pathprop) { struct intel_dp *intel_dp = container_of(mgr, struct intel_dp, mst_mgr); @@ -500,28 +478,32 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo static void intel_dp_register_mst_connector(struct drm_connector *connector) { - struct intel_connector *intel_connector = to_intel_connector(connector); + struct drm_i915_private *dev_priv = to_i915(connector->dev); - intel_connector_add_to_fbdev(intel_connector); + if (dev_priv->fbdev) + drm_fb_helper_add_one_connector(&dev_priv->fbdev->helper, + connector); - drm_connector_register(&intel_connector->base); + drm_connector_register(connector); } static void intel_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr, struct drm_connector *connector) { struct intel_connector *intel_connector = to_intel_connector(connector); + struct drm_i915_private *dev_priv = to_i915(connector->dev); drm_connector_unregister(connector); - /* need to nuke the connector */ - intel_connector_remove_from_fbdev(intel_connector); + if (dev_priv->fbdev) + drm_fb_helper_remove_one_connector(&dev_priv->fbdev->helper, + connector); /* prevent race with the check in ->detect */ drm_modeset_lock(&connector->dev->mode_config.connection_mutex, NULL); intel_connector->mst_port = NULL; drm_modeset_unlock(&connector->dev->mode_config.connection_mutex); - drm_connector_unreference(&intel_connector->base); + drm_connector_unreference(connector); DRM_DEBUG_KMS("\n"); } -- cgit v1.2.3 From e9827d8ea2142d49a6622c72a3371a1d1e929c1d Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 4 Jul 2017 17:18:23 +0200 Subject: drm/fb-helper: Add top-level lock Introduce a new top-level lock for the FB helper code. This will allow better locking granularity and avoid the need to abuse modeset locking for this purpose instead. This patch just adds the new lock everywhere we currently grab mode_config->mutex (explicitly, or through drm_modeset_lock_all). Follow-up patches will push the kms locking down into only the places that need it. v2: - use lockdep_assert_held - use drm_fb_helper_for_each_connector where possible - use the new top-level lock consistently, i.e. in all the places we're currently acquiring mode_config.mutex. - small polish to the kerneldoc Tested-by: John Stultz Signed-off-by: Thierry Reding (v1) Reviewed-by: Maarten Lankhorst Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170704151833.17304-4-daniel.vetter@ffwll.ch --- drivers/gpu/drm/drm_fb_helper.c | 47 +++++++++++++++++++++++++++++++++++++---- include/drm/drm_fb_helper.h | 19 ++++++++++++++++- 2 files changed, 61 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 7d0d50e404ee..30188ec809b5 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -119,7 +119,8 @@ static int __drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, if (!drm_fbdev_emulation) return 0; - WARN_ON(!mutex_is_locked(&fb_helper->dev->mode_config.mutex)); + lockdep_assert_held(&fb_helper->lock); + lockdep_assert_held(&fb_helper->dev->mode_config.mutex); count = fb_helper->connector_count + 1; @@ -150,11 +151,13 @@ int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, { int err; + mutex_lock(&fb_helper->lock); mutex_lock(&fb_helper->dev->mode_config.mutex); err = __drm_fb_helper_add_one_connector(fb_helper, connector); mutex_unlock(&fb_helper->dev->mode_config.mutex); + mutex_unlock(&fb_helper->lock); return err; } @@ -184,6 +187,7 @@ int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper) if (!drm_fbdev_emulation) return 0; + mutex_lock(&fb_helper->lock); mutex_lock(&dev->mode_config.mutex); drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) { @@ -207,6 +211,7 @@ fail: out: drm_connector_list_iter_end(&conn_iter); mutex_unlock(&dev->mode_config.mutex); + mutex_unlock(&fb_helper->lock); return ret; } @@ -221,9 +226,9 @@ static int __drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, if (!drm_fbdev_emulation) return 0; - WARN_ON(!mutex_is_locked(&fb_helper->dev->mode_config.mutex)); + lockdep_assert_held(&fb_helper->lock); - for (i = 0; i < fb_helper->connector_count; i++) { + drm_fb_helper_for_each_connector(fb_helper, i) { if (fb_helper->connector_info[i]->connector == connector) break; } @@ -247,11 +252,13 @@ int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, { int err; + mutex_lock(&fb_helper->lock); mutex_lock(&fb_helper->dev->mode_config.mutex); err = __drm_fb_helper_remove_one_connector(fb_helper, connector); mutex_unlock(&fb_helper->dev->mode_config.mutex); + mutex_unlock(&fb_helper->lock); return err; } @@ -503,16 +510,21 @@ int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper) if (!drm_fbdev_emulation) return -ENODEV; + mutex_lock(&fb_helper->lock); drm_modeset_lock_all(dev); + ret = restore_fbdev_mode(fb_helper); do_delayed = fb_helper->delayed_hotplug; if (do_delayed) fb_helper->delayed_hotplug = false; + drm_modeset_unlock_all(dev); + mutex_unlock(&fb_helper->lock); if (do_delayed) drm_fb_helper_hotplug_event(fb_helper); + return ret; } EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode_unlocked); @@ -562,11 +574,13 @@ static bool drm_fb_helper_force_kernel_mode(void) if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) continue; + mutex_lock(&helper->lock); drm_modeset_lock_all(dev); ret = restore_fbdev_mode(helper); if (ret) error = true; drm_modeset_unlock_all(dev); + mutex_unlock(&helper->lock); } return error; } @@ -606,9 +620,11 @@ static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode) /* * For each CRTC in this fb, turn the connectors on/off. */ + mutex_lock(&fb_helper->lock); drm_modeset_lock_all(dev); if (!drm_fb_helper_is_bound(fb_helper)) { drm_modeset_unlock_all(dev); + mutex_unlock(&fb_helper->lock); return; } @@ -627,6 +643,7 @@ static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode) } } drm_modeset_unlock_all(dev); + mutex_unlock(&fb_helper->lock); } /** @@ -748,6 +765,7 @@ void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper, INIT_WORK(&helper->resume_work, drm_fb_helper_resume_worker); INIT_WORK(&helper->dirty_work, drm_fb_helper_dirty_work); helper->dirty_clip.x1 = helper->dirty_clip.y1 = ~0; + mutex_init(&helper->lock); helper->funcs = funcs; helper->dev = dev; } @@ -913,6 +931,7 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper) } mutex_unlock(&kernel_fb_helper_lock); + mutex_destroy(&fb_helper->lock); drm_fb_helper_crtc_free(fb_helper); } @@ -1243,9 +1262,11 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) if (oops_in_progress) return -EBUSY; + mutex_lock(&fb_helper->lock); drm_modeset_lock_all(dev); if (!drm_fb_helper_is_bound(fb_helper)) { drm_modeset_unlock_all(dev); + mutex_unlock(&fb_helper->lock); return -EBUSY; } @@ -1278,6 +1299,7 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) } out: drm_modeset_unlock_all(dev); + mutex_unlock(&fb_helper->lock); return rc; } EXPORT_SYMBOL(drm_fb_helper_setcmap); @@ -1300,6 +1322,7 @@ int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd, struct drm_crtc *crtc; int ret = 0; + mutex_lock(&fb_helper->lock); mutex_lock(&dev->mode_config.mutex); if (!drm_fb_helper_is_bound(fb_helper)) { ret = -EBUSY; @@ -1346,6 +1369,7 @@ int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd, unlock: mutex_unlock(&dev->mode_config.mutex); + mutex_unlock(&fb_helper->lock); return ret; } EXPORT_SYMBOL(drm_fb_helper_ioctl); @@ -1575,9 +1599,11 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo *var, if (oops_in_progress) return -EBUSY; + mutex_lock(&fb_helper->lock); drm_modeset_lock_all(dev); if (!drm_fb_helper_is_bound(fb_helper)) { drm_modeset_unlock_all(dev); + mutex_unlock(&fb_helper->lock); return -EBUSY; } @@ -1586,6 +1612,7 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo *var, else ret = pan_display_legacy(var, info); drm_modeset_unlock_all(dev); + mutex_unlock(&fb_helper->lock); return ret; } @@ -2252,6 +2279,7 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, DRM_DEBUG_KMS("No connectors reported connected with modes\n"); /* prevent concurrent modification of connector_count by hotplug */ + lockdep_assert_held(&fb_helper->lock); lockdep_assert_held(&fb_helper->dev->mode_config.mutex); crtcs = kcalloc(fb_helper->connector_count, @@ -2378,12 +2406,14 @@ int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel) if (!drm_fbdev_emulation) return 0; + mutex_lock(&fb_helper->lock); mutex_lock(&dev->mode_config.mutex); drm_setup_crtcs(fb_helper, dev->mode_config.max_width, dev->mode_config.max_height); ret = drm_fb_helper_single_fb_probe(fb_helper, bpp_sel); mutex_unlock(&dev->mode_config.mutex); + mutex_unlock(&fb_helper->lock); if (ret) return ret; @@ -2431,25 +2461,34 @@ EXPORT_SYMBOL(drm_fb_helper_initial_config); int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) { struct drm_device *dev = fb_helper->dev; + int err = 0; if (!drm_fbdev_emulation) return 0; + mutex_lock(&fb_helper->lock); mutex_lock(&dev->mode_config.mutex); + if (!fb_helper->fb || !drm_fb_helper_is_bound(fb_helper)) { fb_helper->delayed_hotplug = true; mutex_unlock(&dev->mode_config.mutex); - return 0; + goto unlock; } + DRM_DEBUG_KMS("\n"); drm_setup_crtcs(fb_helper, fb_helper->fb->width, fb_helper->fb->height); mutex_unlock(&dev->mode_config.mutex); + mutex_unlock(&fb_helper->lock); drm_fb_helper_set_par(fb_helper->fbdev); return 0; + +unlock: + mutex_unlock(&fb_helper->lock); + return err; } EXPORT_SYMBOL(drm_fb_helper_hotplug_event); diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 119e5e4609c7..ea170b96e88d 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -169,7 +169,6 @@ struct drm_fb_helper_connector { * @crtc_info: per-CRTC helper state (mode, x/y offset, etc) * @connector_count: number of connected connectors * @connector_info_alloc_count: size of connector_info - * @connector_info: array of per-connector information * @funcs: driver callbacks for fb helper * @fbdev: emulated fbdev device info struct * @pseudo_palette: fake palette of 16 colors @@ -191,6 +190,12 @@ struct drm_fb_helper { struct drm_fb_helper_crtc *crtc_info; int connector_count; int connector_info_alloc_count; + /** + * @connector_info: + * + * Array of per-connector information. Do not iterate directly, but use + * drm_fb_helper_for_each_connector. + */ struct drm_fb_helper_connector **connector_info; const struct drm_fb_helper_funcs *funcs; struct fb_info *fbdev; @@ -200,6 +205,18 @@ struct drm_fb_helper { struct work_struct dirty_work; struct work_struct resume_work; + /** + * @lock: + * + * Top-level FBDEV helper lock. This protects all internal data + * structures and lists, such as @connector_info and @crtc_info. + * + * FIXME: fbdev emulation locking is a mess and long term we want to + * protect all helper internal state with this lock as well as reduce + * core KMS locking as much as possible. + */ + struct mutex lock; + /** * @kernel_fb_list: * -- cgit v1.2.3 From bdac4a052a47920eeae22441ab608612dc0ef4e5 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 4 Jul 2017 17:18:24 +0200 Subject: drm/fb-helper: Push locking in fb_is_bound That function only needs to take the individual crtc locks, not all the kms locks. Push down the locking and then minimize it. Cc: John Stultz Cc: Thierry Reding Reviewed-by: Maarten Lankhorst Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170704151833.17304-5-daniel.vetter@ffwll.ch --- drivers/gpu/drm/drm_fb_helper.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 30188ec809b5..08a5e0d23a42 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -543,10 +543,12 @@ static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper) return false; drm_for_each_crtc(crtc, dev) { + drm_modeset_lock(&crtc->mutex, NULL); if (crtc->primary->fb) crtcs_bound++; if (crtc->primary->fb == fb_helper->fb) bound++; + drm_modeset_unlock(&crtc->mutex); } if (bound < crtcs_bound) @@ -621,13 +623,12 @@ static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode) * For each CRTC in this fb, turn the connectors on/off. */ mutex_lock(&fb_helper->lock); - drm_modeset_lock_all(dev); if (!drm_fb_helper_is_bound(fb_helper)) { - drm_modeset_unlock_all(dev); mutex_unlock(&fb_helper->lock); return; } + drm_modeset_lock_all(dev); for (i = 0; i < fb_helper->crtc_count; i++) { crtc = fb_helper->crtc_info[i].mode_set.crtc; @@ -1263,13 +1264,12 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) return -EBUSY; mutex_lock(&fb_helper->lock); - drm_modeset_lock_all(dev); if (!drm_fb_helper_is_bound(fb_helper)) { - drm_modeset_unlock_all(dev); mutex_unlock(&fb_helper->lock); return -EBUSY; } + drm_modeset_lock_all(dev); for (i = 0; i < fb_helper->crtc_count; i++) { crtc = fb_helper->crtc_info[i].mode_set.crtc; crtc_funcs = crtc->helper_private; @@ -1323,12 +1323,12 @@ int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd, int ret = 0; mutex_lock(&fb_helper->lock); - mutex_lock(&dev->mode_config.mutex); if (!drm_fb_helper_is_bound(fb_helper)) { ret = -EBUSY; goto unlock; } + mutex_lock(&dev->mode_config.mutex); switch (cmd) { case FBIO_WAITFORVSYNC: /* @@ -1600,13 +1600,12 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo *var, return -EBUSY; mutex_lock(&fb_helper->lock); - drm_modeset_lock_all(dev); if (!drm_fb_helper_is_bound(fb_helper)) { - drm_modeset_unlock_all(dev); mutex_unlock(&fb_helper->lock); return -EBUSY; } + drm_modeset_lock_all(dev); if (drm_drv_uses_atomic_modeset(dev)) ret = pan_display_atomic(var, info); else @@ -2467,16 +2466,15 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) return 0; mutex_lock(&fb_helper->lock); - mutex_lock(&dev->mode_config.mutex); - if (!fb_helper->fb || !drm_fb_helper_is_bound(fb_helper)) { fb_helper->delayed_hotplug = true; - mutex_unlock(&dev->mode_config.mutex); - goto unlock; + mutex_unlock(&fb_helper->lock); + return err; } DRM_DEBUG_KMS("\n"); + mutex_lock(&dev->mode_config.mutex); drm_setup_crtcs(fb_helper, fb_helper->fb->width, fb_helper->fb->height); mutex_unlock(&dev->mode_config.mutex); @@ -2485,10 +2483,6 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) drm_fb_helper_set_par(fb_helper->fbdev); return 0; - -unlock: - mutex_unlock(&fb_helper->lock); - return err; } EXPORT_SYMBOL(drm_fb_helper_hotplug_event); -- cgit v1.2.3 From 235d3e4fa115b39a72112f29ec5c84b847111edd Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 4 Jul 2017 17:18:25 +0200 Subject: drm/fb-helper: Drop locking from the vsync wait ioctl code Like with the drm-native vblank wait ioctl we can entirely rely on the spinlocks in drm_vblank.c, no need at all to take expensive mutexes. The only reason we had to take mode_config.mutex was to protect the fbdev helper's data-structures, but that's now done by fb_helper->lock. Cc: John Stultz Cc: Thierry Reding Reviewed-by: Maarten Lankhorst Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170704151833.17304-6-daniel.vetter@ffwll.ch --- drivers/gpu/drm/drm_fb_helper.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 08a5e0d23a42..9efb17c3cbe8 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1328,7 +1328,6 @@ int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd, goto unlock; } - mutex_lock(&dev->mode_config.mutex); switch (cmd) { case FBIO_WAITFORVSYNC: /* @@ -1368,7 +1367,6 @@ int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd, } unlock: - mutex_unlock(&dev->mode_config.mutex); mutex_unlock(&fb_helper->lock); return ret; } -- cgit v1.2.3 From 5c2e3448d104dc85250467af9ecc1e4779c56090 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 4 Jul 2017 17:18:26 +0200 Subject: drm/fb-helper: Push locking into pan_display_atomic|legacy For the legacy path we'll keep drm_modeset_lock_all, for the atomic one we drop the use of the magic implicit context and wire it up properly. Cc: John Stultz Cc: Thierry Reding Reviewed-by: Maarten Lankhorst Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170704151833.17304-7-daniel.vetter@ffwll.ch --- drivers/gpu/drm/drm_fb_helper.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 9efb17c3cbe8..7c24c8cd2e23 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1317,7 +1317,6 @@ int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { struct drm_fb_helper *fb_helper = info->par; - struct drm_device *dev = fb_helper->dev; struct drm_mode_set *mode_set; struct drm_crtc *crtc; int ret = 0; @@ -1508,12 +1507,17 @@ static int pan_display_atomic(struct fb_var_screeninfo *var, struct drm_plane *plane; int i, ret; unsigned int plane_mask; + struct drm_modeset_acquire_ctx ctx; + + drm_modeset_acquire_init(&ctx, 0); state = drm_atomic_state_alloc(dev); - if (!state) - return -ENOMEM; + if (!state) { + ret = -ENOMEM; + goto out_ctx; + } - state->acquire_ctx = dev->mode_config.acquire_ctx; + state->acquire_ctx = &ctx; retry: plane_mask = 0; for (i = 0; i < fb_helper->crtc_count; i++) { @@ -1526,7 +1530,7 @@ retry: ret = __drm_atomic_helper_set_config(mode_set, state); if (ret != 0) - goto fail; + goto out_state; plane = mode_set->crtc->primary; plane_mask |= (1 << drm_plane_index(plane)); @@ -1535,23 +1539,27 @@ retry: ret = drm_atomic_commit(state); if (ret != 0) - goto fail; + goto out_state; info->var.xoffset = var->xoffset; info->var.yoffset = var->yoffset; -fail: +out_state: drm_atomic_clean_old_fb(dev, plane_mask, ret); if (ret == -EDEADLK) goto backoff; drm_atomic_state_put(state); +out_ctx: + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); + return ret; backoff: drm_atomic_state_clear(state); - drm_atomic_legacy_backoff(state); + drm_modeset_backoff(&ctx); goto retry; } @@ -1564,6 +1572,7 @@ static int pan_display_legacy(struct fb_var_screeninfo *var, int ret = 0; int i; + drm_modeset_lock_all(fb_helper->dev); for (i = 0; i < fb_helper->crtc_count; i++) { modeset = &fb_helper->crtc_info[i].mode_set; @@ -1578,6 +1587,7 @@ static int pan_display_legacy(struct fb_var_screeninfo *var, } } } + drm_modeset_unlock_all(fb_helper->dev); return ret; } @@ -1603,12 +1613,10 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo *var, return -EBUSY; } - drm_modeset_lock_all(dev); if (drm_drv_uses_atomic_modeset(dev)) ret = pan_display_atomic(var, info); else ret = pan_display_legacy(var, info); - drm_modeset_unlock_all(dev); mutex_unlock(&fb_helper->lock); return ret; -- cgit v1.2.3 From 1d0c641091805b9ca382ac44d022a4963e47f33e Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 4 Jul 2017 17:18:27 +0200 Subject: drm/fb-helper: Push locking into restore_fbdev_mode_atomic|legacy Same game as with the panning function, use drm_modeset_lock_all for legacy paths, and a proper acquire ctx w/w mutex dance for atomic. Cc: John Stultz Cc: Thierry Reding Reviewed-by: Maarten Lankhorst Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170704151833.17304-8-daniel.vetter@ffwll.ch --- drivers/gpu/drm/drm_fb_helper.c | 48 +++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 7c24c8cd2e23..c5bf37f3bcdd 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -382,12 +382,17 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper) struct drm_atomic_state *state; int i, ret; unsigned int plane_mask; + struct drm_modeset_acquire_ctx ctx; + + drm_modeset_acquire_init(&ctx, 0); state = drm_atomic_state_alloc(dev); - if (!state) - return -ENOMEM; + if (!state) { + ret = -ENOMEM; + goto out_ctx; + } - state->acquire_ctx = dev->mode_config.acquire_ctx; + state->acquire_ctx = &ctx; retry: plane_mask = 0; drm_for_each_plane(plane, dev) { @@ -396,7 +401,7 @@ retry: plane_state = drm_atomic_get_plane_state(state, plane); if (IS_ERR(plane_state)) { ret = PTR_ERR(plane_state); - goto fail; + goto out_state; } plane_state->rotation = DRM_MODE_ROTATE_0; @@ -410,7 +415,7 @@ retry: ret = __drm_atomic_helper_disable_plane(plane, plane_state); if (ret != 0) - goto fail; + goto out_state; } for (i = 0; i < fb_helper->crtc_count; i++) { @@ -418,23 +423,27 @@ retry: ret = __drm_atomic_helper_set_config(mode_set, state); if (ret != 0) - goto fail; + goto out_state; } ret = drm_atomic_commit(state); -fail: +out_state: drm_atomic_clean_old_fb(dev, plane_mask, ret); if (ret == -EDEADLK) goto backoff; drm_atomic_state_put(state); +out_ctx: + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); + return ret; backoff: drm_atomic_state_clear(state); - drm_atomic_legacy_backoff(state); + drm_modeset_backoff(&ctx); goto retry; } @@ -443,8 +452,9 @@ static int restore_fbdev_mode_legacy(struct drm_fb_helper *fb_helper) { struct drm_device *dev = fb_helper->dev; struct drm_plane *plane; - int i; + int i, ret = 0; + drm_modeset_lock_all(fb_helper->dev); drm_for_each_plane(plane, dev) { if (plane->type != DRM_PLANE_TYPE_PRIMARY) drm_plane_force_disable(plane); @@ -458,32 +468,31 @@ static int restore_fbdev_mode_legacy(struct drm_fb_helper *fb_helper) for (i = 0; i < fb_helper->crtc_count; i++) { struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set; struct drm_crtc *crtc = mode_set->crtc; - int ret; if (crtc->funcs->cursor_set2) { ret = crtc->funcs->cursor_set2(crtc, NULL, 0, 0, 0, 0, 0); if (ret) - return ret; + goto out; } else if (crtc->funcs->cursor_set) { ret = crtc->funcs->cursor_set(crtc, NULL, 0, 0, 0); if (ret) - return ret; + goto out; } ret = drm_mode_set_config_internal(mode_set); if (ret) - return ret; + goto out; } +out: + drm_modeset_unlock_all(fb_helper->dev); - return 0; + return ret; } static int restore_fbdev_mode(struct drm_fb_helper *fb_helper) { struct drm_device *dev = fb_helper->dev; - drm_warn_on_modeset_not_all_locked(dev); - if (drm_drv_uses_atomic_modeset(dev)) return restore_fbdev_mode_atomic(fb_helper); else @@ -503,7 +512,6 @@ static int restore_fbdev_mode(struct drm_fb_helper *fb_helper) */ int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper) { - struct drm_device *dev = fb_helper->dev; bool do_delayed; int ret; @@ -511,15 +519,11 @@ int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper) return -ENODEV; mutex_lock(&fb_helper->lock); - drm_modeset_lock_all(dev); - ret = restore_fbdev_mode(fb_helper); do_delayed = fb_helper->delayed_hotplug; if (do_delayed) fb_helper->delayed_hotplug = false; - - drm_modeset_unlock_all(dev); mutex_unlock(&fb_helper->lock); if (do_delayed) @@ -577,11 +581,9 @@ static bool drm_fb_helper_force_kernel_mode(void) continue; mutex_lock(&helper->lock); - drm_modeset_lock_all(dev); ret = restore_fbdev_mode(helper); if (ret) error = true; - drm_modeset_unlock_all(dev); mutex_unlock(&helper->lock); } return error; -- cgit v1.2.3 From e13a058310509b22b2b45cbdd82d8797e173c3db Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 5 Jul 2017 06:56:29 +0200 Subject: drm/fb-helper: Stop using mode_config.mutex for internals MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Those are now all protected using fb_helper->lock. v2: We still need to hold mode_config.mutex right around calling connector->fill_modes. v3: I forgot to hold mode_config.mutex while looking at connector->status and the mode list. Also, we need to patch up the i915 ->initial_config callback to grab the locks it needs to inspect the modeset state recovered from the fw. v4: Don't reorder the probe too much (Ville). Cc: Ville Syrjälä Cc: John Stultz Cc: Thierry Reding Reviewed-by: Maarten Lankhorst Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170705045629.31265-1-daniel.vetter@ffwll.ch --- drivers/gpu/drm/drm_fb_helper.c | 33 ++++++++------------------------- drivers/gpu/drm/drm_vblank.c | 2 +- drivers/gpu/drm/i915/intel_fbdev.c | 16 ++++++++++++---- 3 files changed, 21 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index c5bf37f3bcdd..5d3d776508b3 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -106,7 +106,7 @@ static DEFINE_MUTEX(kernel_fb_helper_lock); */ #define drm_fb_helper_for_each_connector(fbh, i__) \ - for (({ lockdep_assert_held(&(fbh)->dev->mode_config.mutex); }), \ + for (({ lockdep_assert_held(&(fbh)->lock); }), \ i__ = 0; i__ < (fbh)->connector_count; i__++) static int __drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, @@ -120,7 +120,6 @@ static int __drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, return 0; lockdep_assert_held(&fb_helper->lock); - lockdep_assert_held(&fb_helper->dev->mode_config.mutex); count = fb_helper->connector_count + 1; @@ -152,11 +151,7 @@ int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, int err; mutex_lock(&fb_helper->lock); - mutex_lock(&fb_helper->dev->mode_config.mutex); - err = __drm_fb_helper_add_one_connector(fb_helper, connector); - - mutex_unlock(&fb_helper->dev->mode_config.mutex); mutex_unlock(&fb_helper->lock); return err; @@ -188,7 +183,6 @@ int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper) return 0; mutex_lock(&fb_helper->lock); - mutex_lock(&dev->mode_config.mutex); drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) { ret = __drm_fb_helper_add_one_connector(fb_helper, connector); @@ -210,7 +204,6 @@ fail: fb_helper->connector_count = 0; out: drm_connector_list_iter_end(&conn_iter); - mutex_unlock(&dev->mode_config.mutex); mutex_unlock(&fb_helper->lock); return ret; @@ -253,11 +246,7 @@ int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, int err; mutex_lock(&fb_helper->lock); - mutex_lock(&fb_helper->dev->mode_config.mutex); - err = __drm_fb_helper_remove_one_connector(fb_helper, connector); - - mutex_unlock(&fb_helper->dev->mode_config.mutex); mutex_unlock(&fb_helper->lock); return err; @@ -1879,12 +1868,11 @@ void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helpe EXPORT_SYMBOL(drm_fb_helper_fill_var); static int drm_fb_helper_probe_connector_modes(struct drm_fb_helper *fb_helper, - uint32_t maxX, - uint32_t maxY) + uint32_t maxX, + uint32_t maxY) { struct drm_connector *connector; - int count = 0; - int i; + int i, count = 0; drm_fb_helper_for_each_connector(fb_helper, i) { connector = fb_helper->connector_info[i]->connector; @@ -2282,12 +2270,8 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, int i; DRM_DEBUG_KMS("\n"); - if (drm_fb_helper_probe_connector_modes(fb_helper, width, height) == 0) - DRM_DEBUG_KMS("No connectors reported connected with modes\n"); - /* prevent concurrent modification of connector_count by hotplug */ lockdep_assert_held(&fb_helper->lock); - lockdep_assert_held(&fb_helper->dev->mode_config.mutex); crtcs = kcalloc(fb_helper->connector_count, sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL); @@ -2302,6 +2286,9 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, goto out; } + mutex_lock(&fb_helper->dev->mode_config.mutex); + if (drm_fb_helper_probe_connector_modes(fb_helper, width, height) == 0) + DRM_DEBUG_KMS("No connectors reported connected with modes\n"); drm_enable_connectors(fb_helper, enabled); if (!(fb_helper->funcs->initial_config && @@ -2323,6 +2310,7 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, drm_pick_crtcs(fb_helper, crtcs, modes, 0, width, height); } + mutex_unlock(&fb_helper->dev->mode_config.mutex); /* need to set the modesets up here for use later */ /* fill out the connector<->crtc mappings into the modesets */ @@ -2414,12 +2402,10 @@ int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel) return 0; mutex_lock(&fb_helper->lock); - mutex_lock(&dev->mode_config.mutex); drm_setup_crtcs(fb_helper, dev->mode_config.max_width, dev->mode_config.max_height); ret = drm_fb_helper_single_fb_probe(fb_helper, bpp_sel); - mutex_unlock(&dev->mode_config.mutex); mutex_unlock(&fb_helper->lock); if (ret) return ret; @@ -2482,10 +2468,7 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) DRM_DEBUG_KMS("\n"); - mutex_lock(&dev->mode_config.mutex); drm_setup_crtcs(fb_helper, fb_helper->fb->width, fb_helper->fb->height); - - mutex_unlock(&dev->mode_config.mutex); mutex_unlock(&fb_helper->lock); drm_fb_helper_set_par(fb_helper->fbdev); diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index 05d043e9219f..8099574c8a11 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -836,7 +836,7 @@ static void send_vblank_event(struct drm_device *dev, * NOTE: Drivers using this to send out the &drm_crtc_state.event as part of an * atomic commit must ensure that the next vblank happens at exactly the same * time as the atomic commit is committed to the hardware. This function itself - * does **not** protect again the next vblank interrupt racing with either this + * does **not** protect against the next vblank interrupt racing with either this * function call or the atomic commit operation. A possible sequence could be: * * 1. Driver commits new hardware state into vblank-synchronized registers. diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index 03347c6ae599..460ca0b3fb88 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -352,14 +352,20 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper, unsigned int count = min(fb_helper->connector_count, BITS_PER_LONG); int i, j; bool *save_enabled; - bool fallback = true; + bool fallback = true, ret = true; int num_connectors_enabled = 0; int num_connectors_detected = 0; + struct drm_modeset_acquire_ctx ctx; save_enabled = kcalloc(count, sizeof(bool), GFP_KERNEL); if (!save_enabled) return false; + drm_modeset_acquire_init(&ctx, 0); + + while (drm_modeset_lock_all_ctx(fb_helper->dev, &ctx) != 0) + drm_modeset_backoff(&ctx); + memcpy(save_enabled, enabled, count); mask = GENMASK(count - 1, 0); conn_configured = 0; @@ -509,12 +515,14 @@ retry: bail: DRM_DEBUG_KMS("Not using firmware configuration\n"); memcpy(enabled, save_enabled, count); - kfree(save_enabled); - return false; + ret = false; } + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); + kfree(save_enabled); - return true; + return ret; } static const struct drm_fb_helper_funcs intel_fb_helper_funcs = { -- cgit v1.2.3 From 6b7dc6e9f82615836b389cb5f806914048b132cd Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 4 Jul 2017 17:18:29 +0200 Subject: drm/fb-helper: Split dpms handling into legacy and atomic paths Like with panning and modesetting, and like with those, stick with simple drm_modeset_locking_all for the legacy path, and the full atomic dance for atomic drivers. This means a bit more boilerplate since setting up the atomic state machinery is rather verbose, but then this is shared code for 30+ drivers or so, so meh. After this patch there's only the LUT/cmap path which is still using drm_modeset_lock_all for an atomic driver. But Peter is already locking into reworking that, so I'll leave that code as-is for now. v2: Squash in patches from Maarten to unify all the various atomic paths into just one atomic update function for fbdev overall. On top do one s/restore_fbdev_mode/restore_fbdev_mode_atomic/ so that we have all-atomic callchains after the first check. Cc: Peter Rosin Cc: John Stultz Cc: Thierry Reding Cc: Maarten Lankhorst Reviewed-by: Maarten Lankhorst Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170704151833.17304-10-daniel.vetter@ffwll.ch --- drivers/gpu/drm/drm_fb_helper.c | 115 +++++++++++++++++----------------------- 1 file changed, 50 insertions(+), 65 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 5d3d776508b3..1915e64c6e69 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -364,7 +364,7 @@ int drm_fb_helper_debug_leave(struct fb_info *info) } EXPORT_SYMBOL(drm_fb_helper_debug_leave); -static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper) +static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool active) { struct drm_device *dev = fb_helper->dev; struct drm_plane *plane; @@ -413,6 +413,17 @@ retry: ret = __drm_atomic_helper_set_config(mode_set, state); if (ret != 0) goto out_state; + + /* + * __drm_atomic_helper_set_config() sets active when a + * mode is set, unconditionally clear it if we force DPMS off + */ + if (!active) { + struct drm_crtc *crtc = mode_set->crtc; + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + + crtc_state->active = false; + } } ret = drm_atomic_commit(state); @@ -483,7 +494,7 @@ static int restore_fbdev_mode(struct drm_fb_helper *fb_helper) struct drm_device *dev = fb_helper->dev; if (drm_drv_uses_atomic_modeset(dev)) - return restore_fbdev_mode_atomic(fb_helper); + return restore_fbdev_mode_atomic(fb_helper, true); else return restore_fbdev_mode_legacy(fb_helper); } @@ -602,23 +613,13 @@ static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { }; #endif -static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode) +static void dpms_legacy(struct drm_fb_helper *fb_helper, int dpms_mode) { - struct drm_fb_helper *fb_helper = info->par; struct drm_device *dev = fb_helper->dev; struct drm_crtc *crtc; struct drm_connector *connector; int i, j; - /* - * For each CRTC in this fb, turn the connectors on/off. - */ - mutex_lock(&fb_helper->lock); - if (!drm_fb_helper_is_bound(fb_helper)) { - mutex_unlock(&fb_helper->lock); - return; - } - drm_modeset_lock_all(dev); for (i = 0; i < fb_helper->crtc_count; i++) { crtc = fb_helper->crtc_info[i].mode_set.crtc; @@ -635,6 +636,25 @@ static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode) } } drm_modeset_unlock_all(dev); +} + +static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode) +{ + struct drm_fb_helper *fb_helper = info->par; + + /* + * For each CRTC in this fb, turn the connectors on/off. + */ + mutex_lock(&fb_helper->lock); + if (!drm_fb_helper_is_bound(fb_helper)) { + mutex_unlock(&fb_helper->lock); + return; + } + + if (drm_drv_uses_atomic_modeset(fb_helper->dev)) + restore_fbdev_mode_atomic(fb_helper, dpms_mode == DRM_MODE_DPMS_ON); + else + dpms_legacy(fb_helper, dpms_mode); mutex_unlock(&fb_helper->lock); } @@ -1489,70 +1509,36 @@ int drm_fb_helper_set_par(struct fb_info *info) } EXPORT_SYMBOL(drm_fb_helper_set_par); -static int pan_display_atomic(struct fb_var_screeninfo *var, - struct fb_info *info) +static void pan_set(struct drm_fb_helper *fb_helper, int x, int y) { - struct drm_fb_helper *fb_helper = info->par; - struct drm_device *dev = fb_helper->dev; - struct drm_atomic_state *state; - struct drm_plane *plane; - int i, ret; - unsigned int plane_mask; - struct drm_modeset_acquire_ctx ctx; - - drm_modeset_acquire_init(&ctx, 0); - - state = drm_atomic_state_alloc(dev); - if (!state) { - ret = -ENOMEM; - goto out_ctx; - } + int i; - state->acquire_ctx = &ctx; -retry: - plane_mask = 0; for (i = 0; i < fb_helper->crtc_count; i++) { struct drm_mode_set *mode_set; mode_set = &fb_helper->crtc_info[i].mode_set; - mode_set->x = var->xoffset; - mode_set->y = var->yoffset; - - ret = __drm_atomic_helper_set_config(mode_set, state); - if (ret != 0) - goto out_state; - - plane = mode_set->crtc->primary; - plane_mask |= (1 << drm_plane_index(plane)); - plane->old_fb = plane->fb; + mode_set->x = x; + mode_set->y = y; } +} - ret = drm_atomic_commit(state); - if (ret != 0) - goto out_state; - - info->var.xoffset = var->xoffset; - info->var.yoffset = var->yoffset; - -out_state: - drm_atomic_clean_old_fb(dev, plane_mask, ret); +static int pan_display_atomic(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + struct drm_fb_helper *fb_helper = info->par; + int ret; - if (ret == -EDEADLK) - goto backoff; + pan_set(fb_helper, var->xoffset, var->yoffset); - drm_atomic_state_put(state); -out_ctx: - drm_modeset_drop_locks(&ctx); - drm_modeset_acquire_fini(&ctx); + ret = restore_fbdev_mode_atomic(fb_helper, true); + if (!ret) { + info->var.xoffset = var->xoffset; + info->var.yoffset = var->yoffset; + } else + pan_set(fb_helper, info->var.xoffset, info->var.yoffset); return ret; - -backoff: - drm_atomic_state_clear(state); - drm_modeset_backoff(&ctx); - - goto retry; } static int pan_display_legacy(struct fb_var_screeninfo *var, @@ -2453,7 +2439,6 @@ EXPORT_SYMBOL(drm_fb_helper_initial_config); */ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) { - struct drm_device *dev = fb_helper->dev; int err = 0; if (!drm_fbdev_emulation) -- cgit v1.2.3 From b8e2b0199cc377617dc238f5106352c06dcd3fa2 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Tue, 4 Jul 2017 12:36:57 +0200 Subject: drm/fb-helper: factor out pseudo-palette The pseudo-palette has nothing to do with the crtc, so move it out of the crtc loop and update the palette once, then break out early. Signed-off-by: Peter Rosin Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1499164632-5582-2-git-send-email-peda@axentia.se --- drivers/gpu/drm/drm_fb_helper.c | 60 +++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 1915e64c6e69..02a0fb880241 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1218,29 +1218,6 @@ static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green, struct drm_fb_helper *fb_helper = info->par; struct drm_framebuffer *fb = fb_helper->fb; - if (info->fix.visual == FB_VISUAL_TRUECOLOR) { - u32 *palette; - u32 value; - /* place color in psuedopalette */ - if (regno > 16) - return -EINVAL; - palette = (u32 *)info->pseudo_palette; - red >>= (16 - info->var.red.length); - green >>= (16 - info->var.green.length); - blue >>= (16 - info->var.blue.length); - value = (red << info->var.red.offset) | - (green << info->var.green.offset) | - (blue << info->var.blue.offset); - if (info->var.transp.length > 0) { - u32 mask = (1 << info->var.transp.length) - 1; - - mask <<= info->var.transp.offset; - value |= mask; - } - palette[regno] = value; - return 0; - } - /* * The driver really shouldn't advertise pseudo/directcolor * visuals if it can't deal with the palette. @@ -1256,6 +1233,38 @@ static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green, return 0; } +static int setcmap_pseudo_palette(struct fb_cmap *cmap, struct fb_info *info) +{ + u32 *palette = (u32 *)info->pseudo_palette; + int i; + + if (cmap->start + cmap->len > 16) + return -EINVAL; + + for (i = 0; i < cmap->len; ++i) { + u16 red = cmap->red[i]; + u16 green = cmap->green[i]; + u16 blue = cmap->blue[i]; + u32 value; + + red >>= 16 - info->var.red.length; + green >>= 16 - info->var.green.length; + blue >>= 16 - info->var.blue.length; + value = (red << info->var.red.offset) | + (green << info->var.green.offset) | + (blue << info->var.blue.offset); + if (info->var.transp.length > 0) { + u32 mask = (1 << info->var.transp.length) - 1; + + mask <<= info->var.transp.offset; + value |= mask; + } + palette[cmap->start + i] = value; + } + + return 0; +} + /** * drm_fb_helper_setcmap - implementation for &fb_ops.fb_setcmap * @cmap: cmap to set @@ -1281,6 +1290,11 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) } drm_modeset_lock_all(dev); + if (info->fix.visual == FB_VISUAL_TRUECOLOR) { + rc = setcmap_pseudo_palette(cmap, info); + goto out; + } + for (i = 0; i < fb_helper->crtc_count; i++) { crtc = fb_helper->crtc_info[i].mode_set.crtc; crtc_funcs = crtc->helper_private; -- cgit v1.2.3 From a3562a0e471df02234f74ab4e0625042f44a76e9 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Tue, 4 Jul 2017 12:36:58 +0200 Subject: drm/fb-helper: keep the .gamma_store updated in drm_fb_helper_setcmap I think the gamma_store can end up invalid on error. But the way I read it, that can happen in drm_mode_gamma_set_ioctl as well, so why should this pesky legacy fbdev stuff be any better? Signed-off-by: Peter Rosin Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1499164632-5582-3-git-send-email-peda@axentia.se --- drivers/gpu/drm/drm_fb_helper.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 02a0fb880241..bcf227fa3e28 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1277,6 +1277,7 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) const struct drm_crtc_helper_funcs *crtc_funcs; u16 *red, *green, *blue, *transp; struct drm_crtc *crtc; + u16 *r, *g, *b; int i, j, rc = 0; int start; @@ -1305,6 +1306,24 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) transp = cmap->transp; start = cmap->start; + if (!crtc->gamma_size) { + rc = -EINVAL; + goto out; + } + + if (cmap->start + cmap->len > crtc->gamma_size) { + rc = -EINVAL; + goto out; + } + + r = crtc->gamma_store; + g = r + crtc->gamma_size; + b = g + crtc->gamma_size; + + memcpy(r + cmap->start, cmap->red, cmap->len * sizeof(*r)); + memcpy(g + cmap->start, cmap->green, cmap->len * sizeof(*g)); + memcpy(b + cmap->start, cmap->blue, cmap->len * sizeof(*b)); + for (j = 0; j < cmap->len; j++) { u16 hred, hgreen, hblue, htransp = 0xffff; -- cgit v1.2.3 From 08c992c55dffdffcaeb25ebaaf28c7cfc0c21ac1 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Tue, 4 Jul 2017 12:36:59 +0200 Subject: drm/fb-helper: remove drm_fb_helper_save_lut_atomic drm_fb_helper_save_lut_atomic is redundant since the .gamma_store is now always kept up to date by drm_fb_helper_setcmap. Signed-off-by: Peter Rosin Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1499164632-5582-4-git-send-email-peda@axentia.se --- drivers/gpu/drm/drm_fb_helper.c | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index bcf227fa3e28..721511da4de6 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -253,22 +253,6 @@ int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, } EXPORT_SYMBOL(drm_fb_helper_remove_one_connector); -static void drm_fb_helper_save_lut_atomic(struct drm_crtc *crtc, struct drm_fb_helper *helper) -{ - uint16_t *r_base, *g_base, *b_base; - int i; - - if (helper->funcs->gamma_get == NULL) - return; - - r_base = crtc->gamma_store; - g_base = r_base + crtc->gamma_size; - b_base = g_base + crtc->gamma_size; - - for (i = 0; i < crtc->gamma_size; i++) - helper->funcs->gamma_get(crtc, &r_base[i], &g_base[i], &b_base[i], i); -} - static void drm_fb_helper_restore_lut_atomic(struct drm_crtc *crtc) { uint16_t *r_base, *g_base, *b_base; @@ -309,7 +293,6 @@ int drm_fb_helper_debug_enter(struct fb_info *info) if (drm_drv_uses_atomic_modeset(mode_set->crtc->dev)) continue; - drm_fb_helper_save_lut_atomic(mode_set->crtc, helper); funcs->mode_set_base_atomic(mode_set->crtc, mode_set->fb, mode_set->x, -- cgit v1.2.3 From 9a120848d53b2abd6a91d1140081e883c748735a Mon Sep 17 00:00:00 2001 From: Inki Dae Date: Mon, 3 Jul 2017 17:42:18 +0900 Subject: drm/bridge: adv7511: clean up drm_bridge_add call This patch removes unnecessary checking of return value. Signed-off-by: Inki Dae Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/1499071350-25168-3-git-send-email-inki.dae@samsung.com --- drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c index f75ab6278113..ff9792d350c8 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c @@ -1126,11 +1126,7 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id) adv7511->bridge.funcs = &adv7511_bridge_funcs; adv7511->bridge.of_node = dev->of_node; - ret = drm_bridge_add(&adv7511->bridge); - if (ret) { - dev_err(dev, "failed to add adv7511 bridge\n"); - goto err_unregister_cec; - } + drm_bridge_add(&adv7511->bridge); adv7511_audio_init(dev, adv7511); -- cgit v1.2.3 From dd2adf743bc47ac14999bb375fed390af6524f29 Mon Sep 17 00:00:00 2001 From: Inki Dae Date: Mon, 3 Jul 2017 17:42:19 +0900 Subject: drm/bridge: analogix-anx78xx: clean up drm_bridge_add call This patch removes unnecessary checking of return value. Signed-off-by: Inki Dae Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/1499071350-25168-4-git-send-email-inki.dae@samsung.com --- drivers/gpu/drm/bridge/analogix-anx78xx.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/bridge/analogix-anx78xx.c b/drivers/gpu/drm/bridge/analogix-anx78xx.c index 9006578b9789..c2fac3947006 100644 --- a/drivers/gpu/drm/bridge/analogix-anx78xx.c +++ b/drivers/gpu/drm/bridge/analogix-anx78xx.c @@ -1438,11 +1438,7 @@ static int anx78xx_i2c_probe(struct i2c_client *client, anx78xx->bridge.funcs = &anx78xx_bridge_funcs; - err = drm_bridge_add(&anx78xx->bridge); - if (err < 0) { - DRM_ERROR("Failed to add drm bridge: %d\n", err); - goto err_poweroff; - } + drm_bridge_add(&anx78xx->bridge); /* If cable is pulled out, just poweroff and wait for HPD event */ if (!gpiod_get_value(anx78xx->pdata.gpiod_hpd)) -- cgit v1.2.3 From 47e34278549ca44f093bfcc427f4713a17b1a8c8 Mon Sep 17 00:00:00 2001 From: Inki Dae Date: Mon, 3 Jul 2017 17:42:20 +0900 Subject: drm/bridge: vga-dac: clean up drm_bridge_add call This patch removes unnecessary checking of return value. Signed-off-by: Inki Dae Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/1499071350-25168-5-git-send-email-inki.dae@samsung.com --- drivers/gpu/drm/bridge/dumb-vga-dac.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c b/drivers/gpu/drm/bridge/dumb-vga-dac.c index 831a606c4706..8a52539e618e 100644 --- a/drivers/gpu/drm/bridge/dumb-vga-dac.c +++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c @@ -177,7 +177,6 @@ static struct i2c_adapter *dumb_vga_retrieve_ddc(struct device *dev) static int dumb_vga_probe(struct platform_device *pdev) { struct dumb_vga *vga; - int ret; vga = devm_kzalloc(&pdev->dev, sizeof(*vga), GFP_KERNEL); if (!vga) @@ -186,7 +185,7 @@ static int dumb_vga_probe(struct platform_device *pdev) vga->vdd = devm_regulator_get_optional(&pdev->dev, "vdd"); if (IS_ERR(vga->vdd)) { - ret = PTR_ERR(vga->vdd); + int ret = PTR_ERR(vga->vdd); if (ret == -EPROBE_DEFER) return -EPROBE_DEFER; vga->vdd = NULL; @@ -207,11 +206,9 @@ static int dumb_vga_probe(struct platform_device *pdev) vga->bridge.funcs = &dumb_vga_bridge_funcs; vga->bridge.of_node = pdev->dev.of_node; - ret = drm_bridge_add(&vga->bridge); - if (ret && !IS_ERR(vga->ddc)) - i2c_put_adapter(vga->ddc); + drm_bridge_add(&vga->bridge); - return ret; + return 0; } static int dumb_vga_remove(struct platform_device *pdev) -- cgit v1.2.3 From 830dcb44511170ec9ffc91855464156ce13d63ab Mon Sep 17 00:00:00 2001 From: Inki Dae Date: Mon, 3 Jul 2017 17:42:21 +0900 Subject: drm/bridge: nxp-ptn3460: clean up drm_bridge_add call This patch removes unnecessary checking of return value. Signed-off-by: Inki Dae Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/1499071350-25168-6-git-send-email-inki.dae@samsung.com --- drivers/gpu/drm/bridge/nxp-ptn3460.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/bridge/nxp-ptn3460.c b/drivers/gpu/drm/bridge/nxp-ptn3460.c index 4f64e717e01b..f0b5d0fc8594 100644 --- a/drivers/gpu/drm/bridge/nxp-ptn3460.c +++ b/drivers/gpu/drm/bridge/nxp-ptn3460.c @@ -332,11 +332,7 @@ static int ptn3460_probe(struct i2c_client *client, ptn_bridge->bridge.funcs = &ptn3460_bridge_funcs; ptn_bridge->bridge.of_node = dev->of_node; - ret = drm_bridge_add(&ptn_bridge->bridge); - if (ret) { - DRM_ERROR("Failed to add bridge\n"); - return ret; - } + drm_bridge_add(&ptn_bridge->bridge); i2c_set_clientdata(client, ptn_bridge); -- cgit v1.2.3 From 3a45d25dcfc7cfd699707fc1a4f719a8d4f93442 Mon Sep 17 00:00:00 2001 From: Inki Dae Date: Mon, 3 Jul 2017 17:42:22 +0900 Subject: drm/bridge: panel: clean up drm_bridge_add call This patch removes unnecessary checking of return value. Signed-off-by: Inki Dae Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/1499071350-25168-7-git-send-email-inki.dae@samsung.com --- drivers/gpu/drm/bridge/panel.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c index 99f9a4beb859..65ab28cc2946 100644 --- a/drivers/gpu/drm/bridge/panel.c +++ b/drivers/gpu/drm/bridge/panel.c @@ -158,7 +158,6 @@ struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel, u32 connector_type) { struct panel_bridge *panel_bridge; - int ret; if (!panel) return ERR_PTR(EINVAL); @@ -176,9 +175,7 @@ struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel, panel_bridge->bridge.of_node = panel->dev->of_node; #endif - ret = drm_bridge_add(&panel_bridge->bridge); - if (ret) - return ERR_PTR(ret); + drm_bridge_add(&panel_bridge->bridge); return &panel_bridge->bridge; } -- cgit v1.2.3 From d0ceb3ec4a014a5465aae4952e9c18d7722dc50f Mon Sep 17 00:00:00 2001 From: Inki Dae Date: Mon, 3 Jul 2017 17:42:23 +0900 Subject: drm/bridge: ps8622: clean up drm_bridge_add call This patch removes unnecessary checking of return value. Signed-off-by: Inki Dae Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/1499071350-25168-8-git-send-email-inki.dae@samsung.com --- drivers/gpu/drm/bridge/parade-ps8622.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/bridge/parade-ps8622.c b/drivers/gpu/drm/bridge/parade-ps8622.c index 6f22f9fec9bf..4f7725d4a309 100644 --- a/drivers/gpu/drm/bridge/parade-ps8622.c +++ b/drivers/gpu/drm/bridge/parade-ps8622.c @@ -598,11 +598,7 @@ static int ps8622_probe(struct i2c_client *client, ps8622->bridge.funcs = &ps8622_bridge_funcs; ps8622->bridge.of_node = dev->of_node; - ret = drm_bridge_add(&ps8622->bridge); - if (ret) { - DRM_ERROR("Failed to add bridge\n"); - return ret; - } + drm_bridge_add(&ps8622->bridge); i2c_set_clientdata(client, ps8622); -- cgit v1.2.3 From d341a640db81cfe7a4a4e93a9fc79c66dd781834 Mon Sep 17 00:00:00 2001 From: Inki Dae Date: Mon, 3 Jul 2017 17:42:24 +0900 Subject: drm/bridge: sii902x: clean up drm_bridge_add call This patch removes unnecessary checking of return value. Signed-off-by: Inki Dae Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/1499071350-25168-9-git-send-email-inki.dae@samsung.com --- drivers/gpu/drm/bridge/sii902x.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c index 9b87067c022c..b8d10e599df0 100644 --- a/drivers/gpu/drm/bridge/sii902x.c +++ b/drivers/gpu/drm/bridge/sii902x.c @@ -418,11 +418,7 @@ static int sii902x_probe(struct i2c_client *client, sii902x->bridge.funcs = &sii902x_bridge_funcs; sii902x->bridge.of_node = dev->of_node; - ret = drm_bridge_add(&sii902x->bridge); - if (ret) { - dev_err(dev, "Failed to add drm_bridge\n"); - return ret; - } + drm_bridge_add(&sii902x->bridge); i2c_set_clientdata(client, sii902x); -- cgit v1.2.3 From b678682e846d91a105d2ca8a9bf3831ebd7c9d9b Mon Sep 17 00:00:00 2001 From: Inki Dae Date: Mon, 3 Jul 2017 17:42:25 +0900 Subject: drm/bridge: synopsys: dw-hdmi: clean up drm_bridge_add call This patch removes unnecessary checking of return value. Signed-off-by: Inki Dae Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/1499071350-25168-10-git-send-email-inki.dae@samsung.com --- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index ead11242c4b9..de1308b61390 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -2485,17 +2485,12 @@ int dw_hdmi_probe(struct platform_device *pdev, const struct dw_hdmi_plat_data *plat_data) { struct dw_hdmi *hdmi; - int ret; hdmi = __dw_hdmi_probe(pdev, plat_data); if (IS_ERR(hdmi)) return PTR_ERR(hdmi); - ret = drm_bridge_add(&hdmi->bridge); - if (ret < 0) { - __dw_hdmi_remove(hdmi); - return ret; - } + drm_bridge_add(&hdmi->bridge); return 0; } -- cgit v1.2.3 From dc01732eee8c029bf148be2e9476b9526727b56f Mon Sep 17 00:00:00 2001 From: Inki Dae Date: Mon, 3 Jul 2017 17:42:26 +0900 Subject: drm/bridge: tc358767: clean up drm_bridge_add call This patch removes unnecessary checking of return value. Signed-off-by: Inki Dae Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/1499071350-25168-11-git-send-email-inki.dae@samsung.com --- drivers/gpu/drm/bridge/tc358767.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index 5c26488e7a2d..12a35f9c3adc 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -1325,11 +1325,7 @@ static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id) tc->bridge.funcs = &tc_bridge_funcs; tc->bridge.of_node = dev->of_node; - ret = drm_bridge_add(&tc->bridge); - if (ret) { - dev_err(dev, "Failed to add drm_bridge: %d\n", ret); - goto err_unregister_aux; - } + drm_bridge_add(&tc->bridge); i2c_set_clientdata(client, tc); -- cgit v1.2.3 From f74c527591b02a296e34d94c181b423587523f9e Mon Sep 17 00:00:00 2001 From: Inki Dae Date: Mon, 3 Jul 2017 17:42:27 +0900 Subject: drm/bridge: ti-tfp410: clean up drm_bridge_add call This patch removes unnecessary checking of return value. Signed-off-by: Inki Dae Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/1499071350-25168-12-git-send-email-inki.dae@samsung.com --- drivers/gpu/drm/bridge/ti-tfp410.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c index eee4efda829e..7ea2a15e8807 100644 --- a/drivers/gpu/drm/bridge/ti-tfp410.c +++ b/drivers/gpu/drm/bridge/ti-tfp410.c @@ -237,11 +237,7 @@ static int tfp410_init(struct device *dev) } } - ret = drm_bridge_add(&dvi->bridge); - if (ret) { - dev_err(dev, "drm_bridge_add() failed: %d\n", ret); - goto fail; - } + drm_bridge_add(&dvi->bridge); return 0; fail: -- cgit v1.2.3 From 0a7a0986559d85c9926cbe5b1570212e09008a7c Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Mon, 3 Jul 2017 16:38:25 +0530 Subject: drm: i915: sysfs: constify attribute_group structures. attribute_groups are not supposed to change at runtime. All functions working with attribute_groups provided by work with const attribute_group. So mark the non-const structs as const. File size before: text data bss dec hex filename 4028 1088 0 5116 13fc drivers/gpu/drm/i915/i915_sysfs.o File size After adding 'const': text data bss dec hex filename 4196 928 0 5124 1404 drivers/gpu/drm/i915/i915_sysfs.o Signed-off-by: Arvind Yadav Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/13b5c875e677c10e6257be4fac31b2b6c77a494f.1499079914.git.arvind.yadav.cs@gmail.com --- drivers/gpu/drm/i915/i915_sysfs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index 3a481062f219..3736c9f79197 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -96,7 +96,7 @@ static struct attribute *rc6_attrs[] = { NULL }; -static struct attribute_group rc6_attr_group = { +static const struct attribute_group rc6_attr_group = { .name = power_group_name, .attrs = rc6_attrs }; @@ -107,7 +107,7 @@ static struct attribute *rc6p_attrs[] = { NULL }; -static struct attribute_group rc6p_attr_group = { +static const struct attribute_group rc6p_attr_group = { .name = power_group_name, .attrs = rc6p_attrs }; @@ -117,7 +117,7 @@ static struct attribute *media_rc6_attrs[] = { NULL }; -static struct attribute_group media_rc6_attr_group = { +static const struct attribute_group media_rc6_attr_group = { .name = power_group_name, .attrs = media_rc6_attrs }; -- cgit v1.2.3 From 817aef5d86f124e94bfc871ecd6fb2afa4f55417 Mon Sep 17 00:00:00 2001 From: Xiong Zhang Date: Thu, 15 Jun 2017 11:11:45 +0800 Subject: drm/i915: Setting pch_id for HSW/BDW in virtual environment In a IGD passthrough environment, the real ISA bridge may doesn't exist. then pch_id couldn't be correctly gotten from ISA bridge, but pch_id is used to identify LPT_H and LPT_LP. Currently i915 treat all LPT pch as LPT_H,then errors occur when i915 runs on LPT_LP machines with igd passthrough. This patch set pch_id for HSW/BDW according to IGD type and isn't fully correct. But it solves such issue on HSW/BDW ult/ulx machines. QA CI system is blocked by this issue for a long time, it's better that we could merge it to unblock QA CI system. We know the root cause is in device model of virtual passthrough, and will resolve it in the future with several parts cooperation in kernel, qemu and xen. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=99938 Signed-off-by: Xiong Zhang Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1497496305-5364-1-git-send-email-xiong.y.zhang@intel.com --- drivers/gpu/drm/i915/i915_drv.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index a6bef9ee8703..6f750efe9c3d 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -135,6 +135,10 @@ static enum intel_pch intel_virt_detect_pch(struct drm_i915_private *dev_priv) DRM_DEBUG_KMS("Assuming CougarPoint PCH\n"); } else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { ret = PCH_LPT; + if (IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv)) + dev_priv->pch_id = INTEL_PCH_LPT_LP_DEVICE_ID_TYPE; + else + dev_priv->pch_id = INTEL_PCH_LPT_DEVICE_ID_TYPE; DRM_DEBUG_KMS("Assuming LynxPoint PCH\n"); } else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { ret = PCH_SPT; -- cgit v1.2.3 From e4d5dc218c4a1d1f555448825f5a8d7b1ac82959 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 5 Jul 2017 15:26:31 +0100 Subject: drm/i915: Check new context against kernel_context after reporting an error Avoid any pointer dereference in inspecting a potential PTR_ERR by checking for the error pointer before checking for an invalid context. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20170705142634.18554-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_context.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 2eb5d8203999..98d2ce98f467 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -571,14 +571,13 @@ int i915_gem_context_open(struct drm_i915_private *i915, mutex_lock(&i915->drm.struct_mutex); ctx = i915_gem_create_context(i915, file_priv); mutex_unlock(&i915->drm.struct_mutex); - - GEM_BUG_ON(i915_gem_context_is_kernel(ctx)); - if (IS_ERR(ctx)) { idr_destroy(&file_priv->context_idr); return PTR_ERR(ctx); } + GEM_BUG_ON(i915_gem_context_is_kernel(ctx)); + return 0; } -- cgit v1.2.3 From ddfc925851b4f0ae36b21a5b545e4002c4259c42 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 5 Jul 2017 15:26:32 +0100 Subject: drm/i915: Move stale context reaping to common i915_gem_context_create We need to reap the stale contexts for all new contexts, be they created by user in i915_gem_context_ioctl or from opening a new file in i915_gem_context_open. Both paths may be called very frequently accumulating many stale contexts before any worker has a chance to run and free their memory. Fixes: 1acfc104cdf8 ("drm/i915: Enable rcu-only context lookups") Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20170705142634.18554-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_context.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 98d2ce98f467..c58a95c33c25 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -383,6 +383,10 @@ i915_gem_create_context(struct drm_i915_private *dev_priv, lockdep_assert_held(&dev_priv->drm.struct_mutex); + /* Reap stale contexts */ + i915_gem_retire_requests(dev_priv); + contexts_free(dev_priv); + ctx = __create_hw_context(dev_priv, file_priv); if (IS_ERR(ctx)) return ctx; @@ -989,10 +993,6 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, if (ret) return ret; - /* Reap stale contexts */ - i915_gem_retire_requests(dev_priv); - contexts_free(dev_priv); - ctx = i915_gem_create_context(dev_priv, file_priv); mutex_unlock(&dev->struct_mutex); if (IS_ERR(ctx)) -- cgit v1.2.3 From 6b6573d114050ee4ee1c54a60a92ae1b68ce1b6e Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 5 Jul 2017 15:26:33 +0100 Subject: drm/i915: Drop request retirement before reaping stale contexts Before we create a new context, we try and reap all the stale contexts (i.e. those that are freed but waiting for a worker to come and return their allocations to the system). Before we do this, we retire all requests so that we clear any inflight no longer used contexts (who are only being kept alived by those inflght requests). However, any context that is finally unreferenced by this retirement is put onto an RCU list and not available for immediately reaping, we stall for no immediate benefit. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20170705142634.18554-3-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_gem_context.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index c58a95c33c25..4f6773ea7d85 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -384,7 +384,6 @@ i915_gem_create_context(struct drm_i915_private *dev_priv, lockdep_assert_held(&dev_priv->drm.struct_mutex); /* Reap stale contexts */ - i915_gem_retire_requests(dev_priv); contexts_free(dev_priv); ctx = __create_hw_context(dev_priv, file_priv); -- cgit v1.2.3 From cb0aeaa81842948e32f39838f0ec113e3bb52291 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 5 Jul 2017 15:26:34 +0100 Subject: drm/i915: Only free the oldest stale context before allocating Currently, we move all unreferenced contexts to an RCU free list and then onto a worker for eventual reaping. To compensate against this growing into a long list with frequent allocations starving the system of available memory, before we allocate a new context we reap all the stale contexts. This puts all the cost of destroying the context into the next allocator, which is presumably more sensitive to syscall latency and unfair. We can limit the number of contexts being freed by the new allocator to both keep the list trimmed and to allow the allocator to be reasonably fast. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20170705142634.18554-4-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_gem_context.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 4f6773ea7d85..1a87d04e7937 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -201,6 +201,21 @@ static void contexts_free(struct drm_i915_private *i915) i915_gem_context_free(ctx); } +static void contexts_free_first(struct drm_i915_private *i915) +{ + struct i915_gem_context *ctx; + struct llist_node *freed; + + lockdep_assert_held(&i915->drm.struct_mutex); + + freed = llist_del_first(&i915->contexts.free_list); + if (!freed) + return; + + ctx = container_of(freed, typeof(*ctx), free_link); + i915_gem_context_free(ctx); +} + static void contexts_free_worker(struct work_struct *work) { struct drm_i915_private *i915 = @@ -383,8 +398,8 @@ i915_gem_create_context(struct drm_i915_private *dev_priv, lockdep_assert_held(&dev_priv->drm.struct_mutex); - /* Reap stale contexts */ - contexts_free(dev_priv); + /* Reap the most stale context */ + contexts_free_first(dev_priv); ctx = __create_hw_context(dev_priv, file_priv); if (IS_ERR(ctx)) -- cgit v1.2.3 From 5784f87df16619f6a55255aa827faba431a6ee7a Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Thu, 6 Jul 2017 09:42:20 +0300 Subject: ath10k: fix indenting in ath10k_wmi_update_noa() Commit 59ae1d127ac0 ("networking: introduce and use skb_put_data()") introduced a new checkpatch warning: drivers/net/wireless/ath/ath10k/wmi.c:3308: code indent should use tabs where possible Fix that. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 3efb404b83c0..96cd1ebd6a7e 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -3305,7 +3305,7 @@ static void ath10k_wmi_update_noa(struct ath10k *ar, struct ath10k_vif *arvif, if (arvif->u.ap.noa_data) if (!pskb_expand_head(bcn, 0, arvif->u.ap.noa_len, GFP_ATOMIC)) skb_put_data(bcn, arvif->u.ap.noa_data, - arvif->u.ap.noa_len); + arvif->u.ap.noa_len); } static int ath10k_wmi_op_pull_swba_ev(struct ath10k *ar, struct sk_buff *skb, -- cgit v1.2.3 From 641fe28ad30544991253d8ca172aaa0fa12bd1e7 Mon Sep 17 00:00:00 2001 From: Govind Singh Date: Wed, 28 Jun 2017 10:18:26 +0530 Subject: ath10k: make CE layer bus agnostic Remove bus specific dependencies from CE layer to have common CE layer across multiple targets. This is required for adding support for WCN3990 chipset support as WCN3990 chipset uses SNOC bus interface with Copy Engine endpoint. Signed-off-by: Govind Singh Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ahb.c | 3 +- drivers/net/wireless/ath/ath10k/ce.c | 299 ++++++++++++++++++--------------- drivers/net/wireless/ath/ath10k/ce.h | 30 +++- drivers/net/wireless/ath/ath10k/core.h | 2 + drivers/net/wireless/ath/ath10k/pci.c | 51 +++--- drivers/net/wireless/ath/ath10k/pci.h | 14 +- 6 files changed, 224 insertions(+), 175 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c index da770af83036..b36dd792fbb2 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.c +++ b/drivers/net/wireless/ath/ath10k/ahb.c @@ -787,8 +787,9 @@ static int ath10k_ahb_probe(struct platform_device *pdev) ar_pci->mem = ar_ahb->mem; ar_pci->mem_len = ar_ahb->mem_len; ar_pci->ar = ar; - ar_pci->bus_ops = &ath10k_ahb_bus_ops; + ar_pci->ce.bus_ops = &ath10k_ahb_bus_ops; ar_pci->targ_cpu_to_ce_addr = ath10k_ahb_qca4019_targ_cpu_to_ce_addr; + ar->ce_priv = &ar_pci->ce; ret = ath10k_pci_setup_resource(ar); if (ret) { diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index 08b84c8c3614..a8afd690290f 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -16,7 +16,6 @@ */ #include "hif.h" -#include "pci.h" #include "ce.h" #include "debug.h" @@ -33,7 +32,7 @@ * Each ring consists of a number of descriptors which specify * an address, length, and meta-data. * - * Typically, one side of the PCIe interconnect (Host or Target) + * Typically, one side of the PCIe/AHB/SNOC interconnect (Host or Target) * controls one ring and the other side controls the other ring. * The source side chooses when to initiate a transfer and it * chooses what to send (buffer address, length). The destination @@ -73,57 +72,71 @@ ath10k_get_ring_byte(unsigned int offset, return ((offset & addr_map->mask) >> (addr_map->lsb)); } +static inline u32 ath10k_ce_read32(struct ath10k *ar, u32 offset) +{ + struct ath10k_ce *ce = ath10k_ce_priv(ar); + + return ce->bus_ops->read32(ar, offset); +} + +static inline void ath10k_ce_write32(struct ath10k *ar, u32 offset, u32 value) +{ + struct ath10k_ce *ce = ath10k_ce_priv(ar); + + ce->bus_ops->write32(ar, offset, value); +} + static inline void ath10k_ce_dest_ring_write_index_set(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int n) { - ath10k_pci_write32(ar, ce_ctrl_addr + - ar->hw_ce_regs->dst_wr_index_addr, n); + ath10k_ce_write32(ar, ce_ctrl_addr + + ar->hw_ce_regs->dst_wr_index_addr, n); } static inline u32 ath10k_ce_dest_ring_write_index_get(struct ath10k *ar, u32 ce_ctrl_addr) { - return ath10k_pci_read32(ar, ce_ctrl_addr + - ar->hw_ce_regs->dst_wr_index_addr); + return ath10k_ce_read32(ar, ce_ctrl_addr + + ar->hw_ce_regs->dst_wr_index_addr); } static inline void ath10k_ce_src_ring_write_index_set(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int n) { - ath10k_pci_write32(ar, ce_ctrl_addr + - ar->hw_ce_regs->sr_wr_index_addr, n); + ath10k_ce_write32(ar, ce_ctrl_addr + + ar->hw_ce_regs->sr_wr_index_addr, n); } static inline u32 ath10k_ce_src_ring_write_index_get(struct ath10k *ar, u32 ce_ctrl_addr) { - return ath10k_pci_read32(ar, ce_ctrl_addr + - ar->hw_ce_regs->sr_wr_index_addr); + return ath10k_ce_read32(ar, ce_ctrl_addr + + ar->hw_ce_regs->sr_wr_index_addr); } static inline u32 ath10k_ce_src_ring_read_index_get(struct ath10k *ar, u32 ce_ctrl_addr) { - return ath10k_pci_read32(ar, ce_ctrl_addr + - ar->hw_ce_regs->current_srri_addr); + return ath10k_ce_read32(ar, ce_ctrl_addr + + ar->hw_ce_regs->current_srri_addr); } static inline void ath10k_ce_src_ring_base_addr_set(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int addr) { - ath10k_pci_write32(ar, ce_ctrl_addr + - ar->hw_ce_regs->sr_base_addr, addr); + ath10k_ce_write32(ar, ce_ctrl_addr + + ar->hw_ce_regs->sr_base_addr, addr); } static inline void ath10k_ce_src_ring_size_set(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int n) { - ath10k_pci_write32(ar, ce_ctrl_addr + - ar->hw_ce_regs->sr_size_addr, n); + ath10k_ce_write32(ar, ce_ctrl_addr + + ar->hw_ce_regs->sr_size_addr, n); } static inline void ath10k_ce_src_ring_dmax_set(struct ath10k *ar, @@ -131,12 +144,13 @@ static inline void ath10k_ce_src_ring_dmax_set(struct ath10k *ar, unsigned int n) { struct ath10k_hw_ce_ctrl1 *ctrl_regs = ar->hw_ce_regs->ctrl1_regs; - u32 ctrl1_addr = ath10k_pci_read32(ar, - ce_ctrl_addr + ctrl_regs->addr); - ath10k_pci_write32(ar, ce_ctrl_addr + ctrl_regs->addr, - (ctrl1_addr & ~(ctrl_regs->dmax->mask)) | - ath10k_set_ring_byte(n, ctrl_regs->dmax)); + u32 ctrl1_addr = ath10k_ce_read32(ar, ce_ctrl_addr + + ctrl_regs->addr); + + ath10k_ce_write32(ar, ce_ctrl_addr + ctrl_regs->addr, + (ctrl1_addr & ~(ctrl_regs->dmax->mask)) | + ath10k_set_ring_byte(n, ctrl_regs->dmax)); } static inline void ath10k_ce_src_ring_byte_swap_set(struct ath10k *ar, @@ -144,11 +158,13 @@ static inline void ath10k_ce_src_ring_byte_swap_set(struct ath10k *ar, unsigned int n) { struct ath10k_hw_ce_ctrl1 *ctrl_regs = ar->hw_ce_regs->ctrl1_regs; - u32 ctrl1_addr = ath10k_pci_read32(ar, ce_ctrl_addr + ctrl_regs->addr); - ath10k_pci_write32(ar, ce_ctrl_addr + ctrl_regs->addr, - (ctrl1_addr & ~(ctrl_regs->src_ring->mask)) | - ath10k_set_ring_byte(n, ctrl_regs->src_ring)); + u32 ctrl1_addr = ath10k_ce_read32(ar, ce_ctrl_addr + + ctrl_regs->addr); + + ath10k_ce_write32(ar, ce_ctrl_addr + ctrl_regs->addr, + (ctrl1_addr & ~(ctrl_regs->src_ring->mask)) | + ath10k_set_ring_byte(n, ctrl_regs->src_ring)); } static inline void ath10k_ce_dest_ring_byte_swap_set(struct ath10k *ar, @@ -156,34 +172,36 @@ static inline void ath10k_ce_dest_ring_byte_swap_set(struct ath10k *ar, unsigned int n) { struct ath10k_hw_ce_ctrl1 *ctrl_regs = ar->hw_ce_regs->ctrl1_regs; - u32 ctrl1_addr = ath10k_pci_read32(ar, ce_ctrl_addr + ctrl_regs->addr); - ath10k_pci_write32(ar, ce_ctrl_addr + ctrl_regs->addr, - (ctrl1_addr & ~(ctrl_regs->dst_ring->mask)) | - ath10k_set_ring_byte(n, ctrl_regs->dst_ring)); + u32 ctrl1_addr = ath10k_ce_read32(ar, ce_ctrl_addr + + ctrl_regs->addr); + + ath10k_ce_write32(ar, ce_ctrl_addr + ctrl_regs->addr, + (ctrl1_addr & ~(ctrl_regs->dst_ring->mask)) | + ath10k_set_ring_byte(n, ctrl_regs->dst_ring)); } static inline u32 ath10k_ce_dest_ring_read_index_get(struct ath10k *ar, u32 ce_ctrl_addr) { - return ath10k_pci_read32(ar, ce_ctrl_addr + - ar->hw_ce_regs->current_drri_addr); + return ath10k_ce_read32(ar, ce_ctrl_addr + + ar->hw_ce_regs->current_drri_addr); } static inline void ath10k_ce_dest_ring_base_addr_set(struct ath10k *ar, u32 ce_ctrl_addr, u32 addr) { - ath10k_pci_write32(ar, ce_ctrl_addr + - ar->hw_ce_regs->dr_base_addr, addr); + ath10k_ce_write32(ar, ce_ctrl_addr + + ar->hw_ce_regs->dr_base_addr, addr); } static inline void ath10k_ce_dest_ring_size_set(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int n) { - ath10k_pci_write32(ar, ce_ctrl_addr + - ar->hw_ce_regs->dr_size_addr, n); + ath10k_ce_write32(ar, ce_ctrl_addr + + ar->hw_ce_regs->dr_size_addr, n); } static inline void ath10k_ce_src_ring_highmark_set(struct ath10k *ar, @@ -191,11 +209,11 @@ static inline void ath10k_ce_src_ring_highmark_set(struct ath10k *ar, unsigned int n) { struct ath10k_hw_ce_dst_src_wm_regs *srcr_wm = ar->hw_ce_regs->wm_srcr; - u32 addr = ath10k_pci_read32(ar, ce_ctrl_addr + srcr_wm->addr); + u32 addr = ath10k_ce_read32(ar, ce_ctrl_addr + srcr_wm->addr); - ath10k_pci_write32(ar, ce_ctrl_addr + srcr_wm->addr, - (addr & ~(srcr_wm->wm_high->mask)) | - (ath10k_set_ring_byte(n, srcr_wm->wm_high))); + ath10k_ce_write32(ar, ce_ctrl_addr + srcr_wm->addr, + (addr & ~(srcr_wm->wm_high->mask)) | + (ath10k_set_ring_byte(n, srcr_wm->wm_high))); } static inline void ath10k_ce_src_ring_lowmark_set(struct ath10k *ar, @@ -203,11 +221,11 @@ static inline void ath10k_ce_src_ring_lowmark_set(struct ath10k *ar, unsigned int n) { struct ath10k_hw_ce_dst_src_wm_regs *srcr_wm = ar->hw_ce_regs->wm_srcr; - u32 addr = ath10k_pci_read32(ar, ce_ctrl_addr + srcr_wm->addr); + u32 addr = ath10k_ce_read32(ar, ce_ctrl_addr + srcr_wm->addr); - ath10k_pci_write32(ar, ce_ctrl_addr + srcr_wm->addr, - (addr & ~(srcr_wm->wm_low->mask)) | - (ath10k_set_ring_byte(n, srcr_wm->wm_low))); + ath10k_ce_write32(ar, ce_ctrl_addr + srcr_wm->addr, + (addr & ~(srcr_wm->wm_low->mask)) | + (ath10k_set_ring_byte(n, srcr_wm->wm_low))); } static inline void ath10k_ce_dest_ring_highmark_set(struct ath10k *ar, @@ -215,11 +233,11 @@ static inline void ath10k_ce_dest_ring_highmark_set(struct ath10k *ar, unsigned int n) { struct ath10k_hw_ce_dst_src_wm_regs *dstr_wm = ar->hw_ce_regs->wm_dstr; - u32 addr = ath10k_pci_read32(ar, ce_ctrl_addr + dstr_wm->addr); + u32 addr = ath10k_ce_read32(ar, ce_ctrl_addr + dstr_wm->addr); - ath10k_pci_write32(ar, ce_ctrl_addr + dstr_wm->addr, - (addr & ~(dstr_wm->wm_high->mask)) | - (ath10k_set_ring_byte(n, dstr_wm->wm_high))); + ath10k_ce_write32(ar, ce_ctrl_addr + dstr_wm->addr, + (addr & ~(dstr_wm->wm_high->mask)) | + (ath10k_set_ring_byte(n, dstr_wm->wm_high))); } static inline void ath10k_ce_dest_ring_lowmark_set(struct ath10k *ar, @@ -227,66 +245,73 @@ static inline void ath10k_ce_dest_ring_lowmark_set(struct ath10k *ar, unsigned int n) { struct ath10k_hw_ce_dst_src_wm_regs *dstr_wm = ar->hw_ce_regs->wm_dstr; - u32 addr = ath10k_pci_read32(ar, ce_ctrl_addr + dstr_wm->addr); + u32 addr = ath10k_ce_read32(ar, ce_ctrl_addr + dstr_wm->addr); - ath10k_pci_write32(ar, ce_ctrl_addr + dstr_wm->addr, - (addr & ~(dstr_wm->wm_low->mask)) | - (ath10k_set_ring_byte(n, dstr_wm->wm_low))); + ath10k_ce_write32(ar, ce_ctrl_addr + dstr_wm->addr, + (addr & ~(dstr_wm->wm_low->mask)) | + (ath10k_set_ring_byte(n, dstr_wm->wm_low))); } static inline void ath10k_ce_copy_complete_inter_enable(struct ath10k *ar, u32 ce_ctrl_addr) { struct ath10k_hw_ce_host_ie *host_ie = ar->hw_ce_regs->host_ie; - u32 host_ie_addr = ath10k_pci_read32(ar, ce_ctrl_addr + - ar->hw_ce_regs->host_ie_addr); - ath10k_pci_write32(ar, ce_ctrl_addr + ar->hw_ce_regs->host_ie_addr, - host_ie_addr | host_ie->copy_complete->mask); + u32 host_ie_addr = ath10k_ce_read32(ar, ce_ctrl_addr + + ar->hw_ce_regs->host_ie_addr); + + ath10k_ce_write32(ar, ce_ctrl_addr + ar->hw_ce_regs->host_ie_addr, + host_ie_addr | host_ie->copy_complete->mask); } static inline void ath10k_ce_copy_complete_intr_disable(struct ath10k *ar, u32 ce_ctrl_addr) { struct ath10k_hw_ce_host_ie *host_ie = ar->hw_ce_regs->host_ie; - u32 host_ie_addr = ath10k_pci_read32(ar, ce_ctrl_addr + - ar->hw_ce_regs->host_ie_addr); - ath10k_pci_write32(ar, ce_ctrl_addr + ar->hw_ce_regs->host_ie_addr, - host_ie_addr & ~(host_ie->copy_complete->mask)); + u32 host_ie_addr = ath10k_ce_read32(ar, ce_ctrl_addr + + ar->hw_ce_regs->host_ie_addr); + + ath10k_ce_write32(ar, ce_ctrl_addr + ar->hw_ce_regs->host_ie_addr, + host_ie_addr & ~(host_ie->copy_complete->mask)); } static inline void ath10k_ce_watermark_intr_disable(struct ath10k *ar, u32 ce_ctrl_addr) { struct ath10k_hw_ce_host_wm_regs *wm_regs = ar->hw_ce_regs->wm_regs; - u32 host_ie_addr = ath10k_pci_read32(ar, ce_ctrl_addr + - ar->hw_ce_regs->host_ie_addr); - ath10k_pci_write32(ar, ce_ctrl_addr + ar->hw_ce_regs->host_ie_addr, - host_ie_addr & ~(wm_regs->wm_mask)); + u32 host_ie_addr = ath10k_ce_read32(ar, ce_ctrl_addr + + ar->hw_ce_regs->host_ie_addr); + + ath10k_ce_write32(ar, ce_ctrl_addr + ar->hw_ce_regs->host_ie_addr, + host_ie_addr & ~(wm_regs->wm_mask)); } static inline void ath10k_ce_error_intr_enable(struct ath10k *ar, u32 ce_ctrl_addr) { struct ath10k_hw_ce_misc_regs *misc_regs = ar->hw_ce_regs->misc_regs; - u32 misc_ie_addr = ath10k_pci_read32(ar, ce_ctrl_addr + - ar->hw_ce_regs->misc_ie_addr); - ath10k_pci_write32(ar, ce_ctrl_addr + ar->hw_ce_regs->misc_ie_addr, - misc_ie_addr | misc_regs->err_mask); + u32 misc_ie_addr = ath10k_ce_read32(ar, ce_ctrl_addr + + ar->hw_ce_regs->misc_ie_addr); + + ath10k_ce_write32(ar, + ce_ctrl_addr + ar->hw_ce_regs->misc_ie_addr, + misc_ie_addr | misc_regs->err_mask); } static inline void ath10k_ce_error_intr_disable(struct ath10k *ar, u32 ce_ctrl_addr) { struct ath10k_hw_ce_misc_regs *misc_regs = ar->hw_ce_regs->misc_regs; - u32 misc_ie_addr = ath10k_pci_read32(ar, ce_ctrl_addr + - ar->hw_ce_regs->misc_ie_addr); - ath10k_pci_write32(ar, ce_ctrl_addr + ar->hw_ce_regs->misc_ie_addr, - misc_ie_addr & ~(misc_regs->err_mask)); + u32 misc_ie_addr = ath10k_ce_read32(ar, + ce_ctrl_addr + ar->hw_ce_regs->misc_ie_addr); + + ath10k_ce_write32(ar, + ce_ctrl_addr + ar->hw_ce_regs->misc_ie_addr, + misc_ie_addr & ~(misc_regs->err_mask)); } static inline void ath10k_ce_engine_int_status_clear(struct ath10k *ar, @@ -295,7 +320,7 @@ static inline void ath10k_ce_engine_int_status_clear(struct ath10k *ar, { struct ath10k_hw_ce_host_wm_regs *wm_regs = ar->hw_ce_regs->wm_regs; - ath10k_pci_write32(ar, ce_ctrl_addr + wm_regs->addr, mask); + ath10k_ce_write32(ar, ce_ctrl_addr + wm_regs->addr, mask); } /* @@ -362,11 +387,11 @@ exit: void __ath10k_ce_send_revert(struct ath10k_ce_pipe *pipe) { struct ath10k *ar = pipe->ar; - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ath10k_ce *ce = ath10k_ce_priv(ar); struct ath10k_ce_ring *src_ring = pipe->src_ring; u32 ctrl_addr = pipe->ctrl_addr; - lockdep_assert_held(&ar_pci->ce_lock); + lockdep_assert_held(&ce->ce_lock); /* * This function must be called only if there is an incomplete @@ -394,13 +419,13 @@ int ath10k_ce_send(struct ath10k_ce_pipe *ce_state, unsigned int flags) { struct ath10k *ar = ce_state->ar; - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ath10k_ce *ce = ath10k_ce_priv(ar); int ret; - spin_lock_bh(&ar_pci->ce_lock); + spin_lock_bh(&ce->ce_lock); ret = ath10k_ce_send_nolock(ce_state, per_transfer_context, buffer, nbytes, transfer_id, flags); - spin_unlock_bh(&ar_pci->ce_lock); + spin_unlock_bh(&ce->ce_lock); return ret; } @@ -408,14 +433,14 @@ int ath10k_ce_send(struct ath10k_ce_pipe *ce_state, int ath10k_ce_num_free_src_entries(struct ath10k_ce_pipe *pipe) { struct ath10k *ar = pipe->ar; - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ath10k_ce *ce = ath10k_ce_priv(ar); int delta; - spin_lock_bh(&ar_pci->ce_lock); + spin_lock_bh(&ce->ce_lock); delta = CE_RING_DELTA(pipe->src_ring->nentries_mask, pipe->src_ring->write_index, pipe->src_ring->sw_index - 1); - spin_unlock_bh(&ar_pci->ce_lock); + spin_unlock_bh(&ce->ce_lock); return delta; } @@ -423,13 +448,13 @@ int ath10k_ce_num_free_src_entries(struct ath10k_ce_pipe *pipe) int __ath10k_ce_rx_num_free_bufs(struct ath10k_ce_pipe *pipe) { struct ath10k *ar = pipe->ar; - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ath10k_ce *ce = ath10k_ce_priv(ar); struct ath10k_ce_ring *dest_ring = pipe->dest_ring; unsigned int nentries_mask = dest_ring->nentries_mask; unsigned int write_index = dest_ring->write_index; unsigned int sw_index = dest_ring->sw_index; - lockdep_assert_held(&ar_pci->ce_lock); + lockdep_assert_held(&ce->ce_lock); return CE_RING_DELTA(nentries_mask, write_index, sw_index - 1); } @@ -437,7 +462,7 @@ int __ath10k_ce_rx_num_free_bufs(struct ath10k_ce_pipe *pipe) int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr) { struct ath10k *ar = pipe->ar; - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ath10k_ce *ce = ath10k_ce_priv(ar); struct ath10k_ce_ring *dest_ring = pipe->dest_ring; unsigned int nentries_mask = dest_ring->nentries_mask; unsigned int write_index = dest_ring->write_index; @@ -446,7 +471,7 @@ int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr) struct ce_desc *desc = CE_DEST_RING_TO_DESC(base, write_index); u32 ctrl_addr = pipe->ctrl_addr; - lockdep_assert_held(&ar_pci->ce_lock); + lockdep_assert_held(&ce->ce_lock); if ((pipe->id != 5) && CE_RING_DELTA(nentries_mask, write_index, sw_index - 1) == 0) @@ -486,12 +511,12 @@ void ath10k_ce_rx_update_write_idx(struct ath10k_ce_pipe *pipe, u32 nentries) int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr) { struct ath10k *ar = pipe->ar; - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ath10k_ce *ce = ath10k_ce_priv(ar); int ret; - spin_lock_bh(&ar_pci->ce_lock); + spin_lock_bh(&ce->ce_lock); ret = __ath10k_ce_rx_post_buf(pipe, ctx, paddr); - spin_unlock_bh(&ar_pci->ce_lock); + spin_unlock_bh(&ce->ce_lock); return ret; } @@ -554,14 +579,14 @@ int ath10k_ce_completed_recv_next(struct ath10k_ce_pipe *ce_state, unsigned int *nbytesp) { struct ath10k *ar = ce_state->ar; - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ath10k_ce *ce = ath10k_ce_priv(ar); int ret; - spin_lock_bh(&ar_pci->ce_lock); + spin_lock_bh(&ce->ce_lock); ret = ath10k_ce_completed_recv_next_nolock(ce_state, per_transfer_contextp, nbytesp); - spin_unlock_bh(&ar_pci->ce_lock); + spin_unlock_bh(&ce->ce_lock); return ret; } @@ -576,7 +601,7 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state, unsigned int write_index; int ret; struct ath10k *ar; - struct ath10k_pci *ar_pci; + struct ath10k_ce *ce; dest_ring = ce_state->dest_ring; @@ -584,9 +609,9 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state, return -EIO; ar = ce_state->ar; - ar_pci = ath10k_pci_priv(ar); + ce = ath10k_ce_priv(ar); - spin_lock_bh(&ar_pci->ce_lock); + spin_lock_bh(&ce->ce_lock); nentries_mask = dest_ring->nentries_mask; sw_index = dest_ring->sw_index; @@ -614,7 +639,7 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state, ret = -EIO; } - spin_unlock_bh(&ar_pci->ce_lock); + spin_unlock_bh(&ce->ce_lock); return ret; } @@ -686,7 +711,7 @@ int ath10k_ce_cancel_send_next(struct ath10k_ce_pipe *ce_state, unsigned int write_index; int ret; struct ath10k *ar; - struct ath10k_pci *ar_pci; + struct ath10k_ce *ce; src_ring = ce_state->src_ring; @@ -694,9 +719,9 @@ int ath10k_ce_cancel_send_next(struct ath10k_ce_pipe *ce_state, return -EIO; ar = ce_state->ar; - ar_pci = ath10k_pci_priv(ar); + ce = ath10k_ce_priv(ar); - spin_lock_bh(&ar_pci->ce_lock); + spin_lock_bh(&ce->ce_lock); nentries_mask = src_ring->nentries_mask; sw_index = src_ring->sw_index; @@ -727,7 +752,7 @@ int ath10k_ce_cancel_send_next(struct ath10k_ce_pipe *ce_state, ret = -EIO; } - spin_unlock_bh(&ar_pci->ce_lock); + spin_unlock_bh(&ce->ce_lock); return ret; } @@ -736,13 +761,13 @@ int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state, void **per_transfer_contextp) { struct ath10k *ar = ce_state->ar; - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ath10k_ce *ce = ath10k_ce_priv(ar); int ret; - spin_lock_bh(&ar_pci->ce_lock); + spin_lock_bh(&ce->ce_lock); ret = ath10k_ce_completed_send_next_nolock(ce_state, per_transfer_contextp); - spin_unlock_bh(&ar_pci->ce_lock); + spin_unlock_bh(&ce->ce_lock); return ret; } @@ -755,17 +780,18 @@ int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state, */ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id) { - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; + struct ath10k_ce *ce = ath10k_ce_priv(ar); + struct ath10k_ce_pipe *ce_state = &ce->ce_states[ce_id]; struct ath10k_hw_ce_host_wm_regs *wm_regs = ar->hw_ce_regs->wm_regs; u32 ctrl_addr = ce_state->ctrl_addr; - spin_lock_bh(&ar_pci->ce_lock); + spin_lock_bh(&ce->ce_lock); /* Clear the copy-complete interrupts that will be handled here. */ - ath10k_ce_engine_int_status_clear(ar, ctrl_addr, wm_regs->cc_mask); + ath10k_ce_engine_int_status_clear(ar, ctrl_addr, + wm_regs->cc_mask); - spin_unlock_bh(&ar_pci->ce_lock); + spin_unlock_bh(&ce->ce_lock); if (ce_state->recv_cb) ce_state->recv_cb(ce_state); @@ -773,7 +799,7 @@ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id) if (ce_state->send_cb) ce_state->send_cb(ce_state); - spin_lock_bh(&ar_pci->ce_lock); + spin_lock_bh(&ce->ce_lock); /* * Misc CE interrupts are not being handled, but still need @@ -781,7 +807,7 @@ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id) */ ath10k_ce_engine_int_status_clear(ar, ctrl_addr, wm_regs->wm_mask); - spin_unlock_bh(&ar_pci->ce_lock); + spin_unlock_bh(&ce->ce_lock); } /* @@ -795,7 +821,7 @@ void ath10k_ce_per_engine_service_any(struct ath10k *ar) int ce_id; u32 intr_summary; - intr_summary = CE_INTERRUPT_SUMMARY(ar); + intr_summary = ath10k_ce_interrupt_summary(ar); for (ce_id = 0; intr_summary && (ce_id < CE_COUNT); ce_id++) { if (intr_summary & (1 << ce_id)) @@ -847,22 +873,25 @@ int ath10k_ce_disable_interrupts(struct ath10k *ar) void ath10k_ce_enable_interrupts(struct ath10k *ar) { - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ath10k_ce *ce = ath10k_ce_priv(ar); int ce_id; + struct ath10k_ce_pipe *ce_state; /* Skip the last copy engine, CE7 the diagnostic window, as that * uses polling and isn't initialized for interrupts. */ - for (ce_id = 0; ce_id < CE_COUNT - 1; ce_id++) - ath10k_ce_per_engine_handler_adjust(&ar_pci->ce_states[ce_id]); + for (ce_id = 0; ce_id < CE_COUNT - 1; ce_id++) { + ce_state = &ce->ce_states[ce_id]; + ath10k_ce_per_engine_handler_adjust(ce_state); + } } static int ath10k_ce_init_src_ring(struct ath10k *ar, unsigned int ce_id, const struct ce_attr *attr) { - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; + struct ath10k_ce *ce = ath10k_ce_priv(ar); + struct ath10k_ce_pipe *ce_state = &ce->ce_states[ce_id]; struct ath10k_ce_ring *src_ring = ce_state->src_ring; u32 nentries, ctrl_addr = ath10k_ce_base_address(ar, ce_id); @@ -898,8 +927,8 @@ static int ath10k_ce_init_dest_ring(struct ath10k *ar, unsigned int ce_id, const struct ce_attr *attr) { - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; + struct ath10k_ce *ce = ath10k_ce_priv(ar); + struct ath10k_ce_pipe *ce_state = &ce->ce_states[ce_id]; struct ath10k_ce_ring *dest_ring = ce_state->dest_ring; u32 nentries, ctrl_addr = ath10k_ce_base_address(ar, ce_id); @@ -1081,8 +1110,8 @@ void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id) int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, const struct ce_attr *attr) { - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; + struct ath10k_ce *ce = ath10k_ce_priv(ar); + struct ath10k_ce_pipe *ce_state = &ce->ce_states[ce_id]; int ret; /* @@ -1138,8 +1167,8 @@ int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id) { - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; + struct ath10k_ce *ce = ath10k_ce_priv(ar); + struct ath10k_ce_pipe *ce_state = &ce->ce_states[ce_id]; if (ce_state->src_ring) { dma_free_coherent(ar->dev, @@ -1168,38 +1197,38 @@ void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id) void ath10k_ce_dump_registers(struct ath10k *ar, struct ath10k_fw_crash_data *crash_data) { - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - struct ath10k_ce_crash_data ce; + struct ath10k_ce *ce = ath10k_ce_priv(ar); + struct ath10k_ce_crash_data ce_data; u32 addr, id; lockdep_assert_held(&ar->data_lock); ath10k_err(ar, "Copy Engine register dump:\n"); - spin_lock_bh(&ar_pci->ce_lock); + spin_lock_bh(&ce->ce_lock); for (id = 0; id < CE_COUNT; id++) { addr = ath10k_ce_base_address(ar, id); - ce.base_addr = cpu_to_le32(addr); + ce_data.base_addr = cpu_to_le32(addr); - ce.src_wr_idx = + ce_data.src_wr_idx = cpu_to_le32(ath10k_ce_src_ring_write_index_get(ar, addr)); - ce.src_r_idx = + ce_data.src_r_idx = cpu_to_le32(ath10k_ce_src_ring_read_index_get(ar, addr)); - ce.dst_wr_idx = + ce_data.dst_wr_idx = cpu_to_le32(ath10k_ce_dest_ring_write_index_get(ar, addr)); - ce.dst_r_idx = + ce_data.dst_r_idx = cpu_to_le32(ath10k_ce_dest_ring_read_index_get(ar, addr)); if (crash_data) - crash_data->ce_crash_data[id] = ce; + crash_data->ce_crash_data[id] = ce_data; ath10k_err(ar, "[%02d]: 0x%08x %3u %3u %3u %3u", id, - le32_to_cpu(ce.base_addr), - le32_to_cpu(ce.src_wr_idx), - le32_to_cpu(ce.src_r_idx), - le32_to_cpu(ce.dst_wr_idx), - le32_to_cpu(ce.dst_r_idx)); + le32_to_cpu(ce_data.base_addr), + le32_to_cpu(ce_data.src_wr_idx), + le32_to_cpu(ce_data.src_r_idx), + le32_to_cpu(ce_data.dst_wr_idx), + le32_to_cpu(ce_data.dst_r_idx)); } - spin_unlock_bh(&ar_pci->ce_lock); + spin_unlock_bh(&ce->ce_lock); } diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index 95743a57525d..bdec794704d9 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h @@ -122,6 +122,24 @@ struct ath10k_ce_pipe { /* Copy Engine settable attributes */ struct ce_attr; +struct ath10k_bus_ops { + u32 (*read32)(struct ath10k *ar, u32 offset); + void (*write32)(struct ath10k *ar, u32 offset, u32 value); + int (*get_num_banks)(struct ath10k *ar); +}; + +static inline struct ath10k_ce *ath10k_ce_priv(struct ath10k *ar) +{ + return (struct ath10k_ce *)ar->ce_priv; +} + +struct ath10k_ce { + /* protects CE info */ + spinlock_t ce_lock; + const struct ath10k_bus_ops *bus_ops; + struct ath10k_ce_pipe ce_states[CE_COUNT_MAX]; +}; + /*==================Send====================*/ /* ath10k_ce_send flags */ @@ -291,9 +309,13 @@ static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id) CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB) #define CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS 0x0000 -#define CE_INTERRUPT_SUMMARY(ar) \ - CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_GET( \ - ath10k_pci_read32((ar), CE_WRAPPER_BASE_ADDRESS + \ - CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS)) +static inline u32 ath10k_ce_interrupt_summary(struct ath10k *ar) +{ + struct ath10k_ce *ce = ath10k_ce_priv(ar); + + return CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_GET( + ce->bus_ops->read32((ar), CE_WRAPPER_BASE_ADDRESS + + CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS)); +} #endif /* _CE_H_ */ diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 1aa5cf12fce0..2b499af722ad 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -993,6 +993,8 @@ struct ath10k { u32 reg_ack_cts_timeout_orig; } fw_coverage; + void *ce_priv; + /* must be last */ u8 drv_priv[0] __aligned(sizeof(void *)); }; diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 7ebfc409018d..6a91276ce4d7 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -672,16 +672,16 @@ static u32 ath10k_bus_pci_read32(struct ath10k *ar, u32 offset) inline void ath10k_pci_write32(struct ath10k *ar, u32 offset, u32 value) { - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ath10k_ce *ce = ath10k_ce_priv(ar); - ar_pci->bus_ops->write32(ar, offset, value); + ce->bus_ops->write32(ar, offset, value); } inline u32 ath10k_pci_read32(struct ath10k *ar, u32 offset) { - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ath10k_ce *ce = ath10k_ce_priv(ar); - return ar_pci->bus_ops->read32(ar, offset); + return ce->bus_ops->read32(ar, offset); } u32 ath10k_pci_soc_read32(struct ath10k *ar, u32 addr) @@ -761,7 +761,7 @@ static inline const char *ath10k_pci_get_irq_method(struct ath10k *ar) static int __ath10k_pci_rx_post_buf(struct ath10k_pci_pipe *pipe) { struct ath10k *ar = pipe->hif_ce_state; - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ath10k_ce *ce = ath10k_ce_priv(ar); struct ath10k_ce_pipe *ce_pipe = pipe->ce_hdl; struct sk_buff *skb; dma_addr_t paddr; @@ -784,9 +784,9 @@ static int __ath10k_pci_rx_post_buf(struct ath10k_pci_pipe *pipe) ATH10K_SKB_RXCB(skb)->paddr = paddr; - spin_lock_bh(&ar_pci->ce_lock); + spin_lock_bh(&ce->ce_lock); ret = __ath10k_ce_rx_post_buf(ce_pipe, skb, paddr); - spin_unlock_bh(&ar_pci->ce_lock); + spin_unlock_bh(&ce->ce_lock); if (ret) { dma_unmap_single(ar->dev, paddr, skb->len + skb_tailroom(skb), DMA_FROM_DEVICE); @@ -801,6 +801,7 @@ static void ath10k_pci_rx_post_pipe(struct ath10k_pci_pipe *pipe) { struct ath10k *ar = pipe->hif_ce_state; struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ath10k_ce *ce = ath10k_ce_priv(ar); struct ath10k_ce_pipe *ce_pipe = pipe->ce_hdl; int ret, num; @@ -810,9 +811,9 @@ static void ath10k_pci_rx_post_pipe(struct ath10k_pci_pipe *pipe) if (!ce_pipe->dest_ring) return; - spin_lock_bh(&ar_pci->ce_lock); + spin_lock_bh(&ce->ce_lock); num = __ath10k_ce_rx_num_free_bufs(ce_pipe); - spin_unlock_bh(&ar_pci->ce_lock); + spin_unlock_bh(&ce->ce_lock); while (num >= 0) { ret = __ath10k_pci_rx_post_buf(pipe); @@ -882,6 +883,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, int nbytes) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ath10k_ce *ce = ath10k_ce_priv(ar); int ret = 0; u32 *buf; unsigned int completed_nbytes, alloc_nbytes, remaining_bytes; @@ -892,7 +894,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, void *data_buf = NULL; int i; - spin_lock_bh(&ar_pci->ce_lock); + spin_lock_bh(&ce->ce_lock); ce_diag = ar_pci->ce_diag; @@ -986,7 +988,7 @@ done: dma_free_coherent(ar->dev, alloc_nbytes, data_buf, ce_data_base); - spin_unlock_bh(&ar_pci->ce_lock); + spin_unlock_bh(&ce->ce_lock); return ret; } @@ -1034,6 +1036,7 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, const void *data, int nbytes) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ath10k_ce *ce = ath10k_ce_priv(ar); int ret = 0; u32 *buf; unsigned int completed_nbytes, orig_nbytes, remaining_bytes; @@ -1043,7 +1046,7 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, dma_addr_t ce_data_base = 0; int i; - spin_lock_bh(&ar_pci->ce_lock); + spin_lock_bh(&ce->ce_lock); ce_diag = ar_pci->ce_diag; @@ -1147,7 +1150,7 @@ done: ath10k_warn(ar, "failed to write diag value at 0x%x: %d\n", address, ret); - spin_unlock_bh(&ar_pci->ce_lock); + spin_unlock_bh(&ce->ce_lock); return ret; } @@ -1342,6 +1345,7 @@ int ath10k_pci_hif_tx_sg(struct ath10k *ar, u8 pipe_id, struct ath10k_hif_sg_item *items, int n_items) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ath10k_ce *ce = ath10k_ce_priv(ar); struct ath10k_pci_pipe *pci_pipe = &ar_pci->pipe_info[pipe_id]; struct ath10k_ce_pipe *ce_pipe = pci_pipe->ce_hdl; struct ath10k_ce_ring *src_ring = ce_pipe->src_ring; @@ -1350,7 +1354,7 @@ int ath10k_pci_hif_tx_sg(struct ath10k *ar, u8 pipe_id, unsigned int write_index; int err, i = 0; - spin_lock_bh(&ar_pci->ce_lock); + spin_lock_bh(&ce->ce_lock); nentries_mask = src_ring->nentries_mask; sw_index = src_ring->sw_index; @@ -1396,14 +1400,14 @@ int ath10k_pci_hif_tx_sg(struct ath10k *ar, u8 pipe_id, if (err) goto err; - spin_unlock_bh(&ar_pci->ce_lock); + spin_unlock_bh(&ce->ce_lock); return 0; err: for (; i > 0; i--) __ath10k_ce_send_revert(ce_pipe); - spin_unlock_bh(&ar_pci->ce_lock); + spin_unlock_bh(&ce->ce_lock); return err; } @@ -2000,9 +2004,9 @@ static int ath10k_pci_get_num_banks(struct ath10k *ar) static int ath10k_bus_get_num_banks(struct ath10k *ar) { - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ath10k_ce *ce = ath10k_ce_priv(ar); - return ar_pci->bus_ops->get_num_banks(ar); + return ce->bus_ops->get_num_banks(ar); } int ath10k_pci_init_config(struct ath10k *ar) @@ -2173,11 +2177,12 @@ int ath10k_pci_alloc_pipes(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_pci_pipe *pipe; + struct ath10k_ce *ce = ath10k_ce_priv(ar); int i, ret; for (i = 0; i < CE_COUNT; i++) { pipe = &ar_pci->pipe_info[i]; - pipe->ce_hdl = &ar_pci->ce_states[i]; + pipe->ce_hdl = &ce->ce_states[i]; pipe->pipe_num = i; pipe->hif_ce_state = ar; @@ -2825,7 +2830,7 @@ static int ath10k_pci_napi_poll(struct napi_struct *ctx, int budget) * interrupts safer to check for pending interrupts for * immediate servicing. */ - if (CE_INTERRUPT_SUMMARY(ar)) { + if (ath10k_ce_interrupt_summary(ar)) { napi_reschedule(ctx); goto out; } @@ -3142,9 +3147,10 @@ static bool ath10k_pci_chip_is_supported(u32 dev_id, u32 chip_id) int ath10k_pci_setup_resource(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ath10k_ce *ce = ath10k_ce_priv(ar); int ret; - spin_lock_init(&ar_pci->ce_lock); + spin_lock_init(&ce->ce_lock); spin_lock_init(&ar_pci->ps_lock); setup_timer(&ar_pci->rx_post_retry, ath10k_pci_rx_replenish_retry, @@ -3263,10 +3269,11 @@ static int ath10k_pci_probe(struct pci_dev *pdev, ar_pci->ar = ar; ar->dev_id = pci_dev->device; ar_pci->pci_ps = pci_ps; - ar_pci->bus_ops = &ath10k_pci_bus_ops; + ar_pci->ce.bus_ops = &ath10k_pci_bus_ops; ar_pci->pci_soft_reset = pci_soft_reset; ar_pci->pci_hard_reset = pci_hard_reset; ar_pci->targ_cpu_to_ce_addr = targ_cpu_to_ce_addr; + ar->ce_priv = &ar_pci->ce; ar->id.vendor = pdev->vendor; ar->id.device = pdev->device; diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index c1e08ad63940..424ff323b2dc 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -150,12 +150,6 @@ struct ath10k_pci_supp_chip { u32 rev_id; }; -struct ath10k_bus_ops { - u32 (*read32)(struct ath10k *ar, u32 offset); - void (*write32)(struct ath10k *ar, u32 offset, u32 value); - int (*get_num_banks)(struct ath10k *ar); -}; - enum ath10k_pci_irq_mode { ATH10K_PCI_IRQ_AUTO = 0, ATH10K_PCI_IRQ_LEGACY = 1, @@ -177,11 +171,7 @@ struct ath10k_pci { /* Copy Engine used for Diagnostic Accesses */ struct ath10k_ce_pipe *ce_diag; - /* FIXME: document what this really protects */ - spinlock_t ce_lock; - - /* Map CE id to ce_state */ - struct ath10k_ce_pipe ce_states[CE_COUNT_MAX]; + struct ath10k_ce ce; struct timer_list rx_post_retry; /* Due to HW quirks it is recommended to disable ASPM during device @@ -225,8 +215,6 @@ struct ath10k_pci { */ bool pci_ps; - const struct ath10k_bus_ops *bus_ops; - /* Chip specific pci reset routine used to do a safe reset */ int (*pci_soft_reset)(struct ath10k *ar); -- cgit v1.2.3 From f9e18304544e7fbabe9e4b5da8c7a052542000ca Mon Sep 17 00:00:00 2001 From: Govind Singh Date: Wed, 28 Jun 2017 10:18:36 +0530 Subject: ath10k: add copy engine register MAP for wcn3990 target Copy engine is a host to target communication interface between wlan firmware and wlan wcn3990 platform driver. Add copy engine register map for wcn3990 wlan module. This add support for the copy engine source/destination ring configuration for wcn3990 chipset. Signed-off-by: Govind Singh Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 5 ++ drivers/net/wireless/ath/ath10k/hw.c | 150 +++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/hw.h | 9 ++ drivers/net/wireless/ath/ath10k/pci.c | 4 + 4 files changed, 168 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 75c5c903c8a6..8ff47458207c 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -2516,6 +2516,11 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, ar->hw_ce_regs = &qcax_ce_regs; ar->hw_values = &qca4019_values; break; + case ATH10K_HW_WCN3990: + ar->regs = &wcn3990_regs; + ar->hw_ce_regs = &wcn3990_ce_regs; + ar->hw_values = &wcn3990_values; + break; default: ath10k_err(ar, "unsupported core hardware revision %d\n", hw_rev); diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c index afb0c01cbb55..a860691d635d 100644 --- a/drivers/net/wireless/ath/ath10k/hw.c +++ b/drivers/net/wireless/ath/ath10k/hw.c @@ -192,6 +192,156 @@ const struct ath10k_hw_values qca4019_values = { .ce_desc_meta_data_lsb = 4, }; +const struct ath10k_hw_regs wcn3990_regs = { + .rtc_soc_base_address = 0x00000000, + .rtc_wmac_base_address = 0x00000000, + .soc_core_base_address = 0x00000000, + .ce_wrapper_base_address = 0x0024C000, + .ce0_base_address = 0x00240000, + .ce1_base_address = 0x00241000, + .ce2_base_address = 0x00242000, + .ce3_base_address = 0x00243000, + .ce4_base_address = 0x00244000, + .ce5_base_address = 0x00245000, + .ce6_base_address = 0x00246000, + .ce7_base_address = 0x00247000, + .ce8_base_address = 0x00248000, + .ce9_base_address = 0x00249000, + .ce10_base_address = 0x0024A000, + .ce11_base_address = 0x0024B000, + .soc_chip_id_address = 0x000000f0, + .soc_reset_control_si0_rst_mask = 0x00000001, + .soc_reset_control_ce_rst_mask = 0x00000100, + .ce_wrap_intr_sum_host_msi_lsb = 0x0000000c, + .ce_wrap_intr_sum_host_msi_mask = 0x00fff000, + .pcie_intr_fw_mask = 0x00100000, +}; + +static struct ath10k_hw_ce_regs_addr_map wcn3990_src_ring = { + .msb = 0x00000010, + .lsb = 0x00000010, + .mask = GENMASK(17, 17), +}; + +static struct ath10k_hw_ce_regs_addr_map wcn3990_dst_ring = { + .msb = 0x00000012, + .lsb = 0x00000012, + .mask = GENMASK(18, 18), +}; + +static struct ath10k_hw_ce_regs_addr_map wcn3990_dmax = { + .msb = 0x00000000, + .lsb = 0x00000000, + .mask = GENMASK(15, 0), +}; + +static struct ath10k_hw_ce_ctrl1 wcn3990_ctrl1 = { + .addr = 0x00000018, + .src_ring = &wcn3990_src_ring, + .dst_ring = &wcn3990_dst_ring, + .dmax = &wcn3990_dmax, +}; + +static struct ath10k_hw_ce_regs_addr_map wcn3990_host_ie_cc = { + .mask = GENMASK(0, 0), +}; + +static struct ath10k_hw_ce_host_ie wcn3990_host_ie = { + .copy_complete = &wcn3990_host_ie_cc, +}; + +static struct ath10k_hw_ce_host_wm_regs wcn3990_wm_reg = { + .dstr_lmask = 0x00000010, + .dstr_hmask = 0x00000008, + .srcr_lmask = 0x00000004, + .srcr_hmask = 0x00000002, + .cc_mask = 0x00000001, + .wm_mask = 0x0000001E, + .addr = 0x00000030, +}; + +static struct ath10k_hw_ce_misc_regs wcn3990_misc_reg = { + .axi_err = 0x00000100, + .dstr_add_err = 0x00000200, + .srcr_len_err = 0x00000100, + .dstr_mlen_vio = 0x00000080, + .dstr_overflow = 0x00000040, + .srcr_overflow = 0x00000020, + .err_mask = 0x000003E0, + .addr = 0x00000038, +}; + +static struct ath10k_hw_ce_regs_addr_map wcn3990_src_wm_low = { + .msb = 0x00000000, + .lsb = 0x00000010, + .mask = GENMASK(31, 16), +}; + +static struct ath10k_hw_ce_regs_addr_map wcn3990_src_wm_high = { + .msb = 0x0000000f, + .lsb = 0x00000000, + .mask = GENMASK(15, 0), +}; + +static struct ath10k_hw_ce_dst_src_wm_regs wcn3990_wm_src_ring = { + .addr = 0x0000004c, + .low_rst = 0x00000000, + .high_rst = 0x00000000, + .wm_low = &wcn3990_src_wm_low, + .wm_high = &wcn3990_src_wm_high, +}; + +static struct ath10k_hw_ce_regs_addr_map wcn3990_dst_wm_low = { + .lsb = 0x00000010, + .mask = GENMASK(31, 16), +}; + +static struct ath10k_hw_ce_regs_addr_map wcn3990_dst_wm_high = { + .msb = 0x0000000f, + .lsb = 0x00000000, + .mask = GENMASK(15, 0), +}; + +static struct ath10k_hw_ce_dst_src_wm_regs wcn3990_wm_dst_ring = { + .addr = 0x00000050, + .low_rst = 0x00000000, + .high_rst = 0x00000000, + .wm_low = &wcn3990_dst_wm_low, + .wm_high = &wcn3990_dst_wm_high, +}; + +struct ath10k_hw_ce_regs wcn3990_ce_regs = { + .sr_base_addr = 0x00000000, + .sr_size_addr = 0x00000008, + .dr_base_addr = 0x0000000c, + .dr_size_addr = 0x00000014, + .misc_ie_addr = 0x00000034, + .sr_wr_index_addr = 0x0000003c, + .dst_wr_index_addr = 0x00000040, + .current_srri_addr = 0x00000044, + .current_drri_addr = 0x00000048, + .ddr_addr_for_rri_low = 0x00000004, + .ddr_addr_for_rri_high = 0x00000008, + .ce_rri_low = 0x0024C004, + .ce_rri_high = 0x0024C008, + .host_ie_addr = 0x0000002c, + .ctrl1_regs = &wcn3990_ctrl1, + .host_ie = &wcn3990_host_ie, + .wm_regs = &wcn3990_wm_reg, + .misc_regs = &wcn3990_misc_reg, + .wm_srcr = &wcn3990_wm_src_ring, + .wm_dstr = &wcn3990_wm_dst_ring, +}; + +const struct ath10k_hw_values wcn3990_values = { + .rtc_state_val_on = 5, + .ce_count = 12, + .msi_assign_ce_max = 12, + .num_target_ce_config_wlan = 12, + .ce_desc_meta_data_mask = 0xFFF0, + .ce_desc_meta_data_lsb = 4, +}; + static struct ath10k_hw_ce_regs_addr_map qcax_src_ring = { .msb = 0x00000010, .lsb = 0x00000010, diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 97dc1479f44e..19e43512af50 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -231,6 +231,7 @@ enum ath10k_hw_rev { ATH10K_HW_QCA9377, ATH10K_HW_QCA4019, ATH10K_HW_QCA9887, + ATH10K_HW_WCN3990, }; struct ath10k_hw_regs { @@ -247,6 +248,10 @@ struct ath10k_hw_regs { u32 ce5_base_address; u32 ce6_base_address; u32 ce7_base_address; + u32 ce8_base_address; + u32 ce9_base_address; + u32 ce10_base_address; + u32 ce11_base_address; u32 soc_reset_control_si0_rst_mask; u32 soc_reset_control_ce_rst_mask; u32 soc_chip_id_address; @@ -267,6 +272,7 @@ extern const struct ath10k_hw_regs qca988x_regs; extern const struct ath10k_hw_regs qca6174_regs; extern const struct ath10k_hw_regs qca99x0_regs; extern const struct ath10k_hw_regs qca4019_regs; +extern const struct ath10k_hw_regs wcn3990_regs; struct ath10k_hw_ce_regs_addr_map { u32 msb; @@ -362,6 +368,8 @@ extern const struct ath10k_hw_values qca6174_values; extern const struct ath10k_hw_values qca99x0_values; extern const struct ath10k_hw_values qca9888_values; extern const struct ath10k_hw_values qca4019_values; +extern const struct ath10k_hw_values wcn3990_values; +extern struct ath10k_hw_ce_regs wcn3990_ce_regs; extern struct ath10k_hw_ce_regs qcax_ce_regs; void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey, @@ -375,6 +383,7 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey, #define QCA_REV_9984(ar) ((ar)->hw_rev == ATH10K_HW_QCA9984) #define QCA_REV_9377(ar) ((ar)->hw_rev == ATH10K_HW_QCA9377) #define QCA_REV_40XX(ar) ((ar)->hw_rev == ATH10K_HW_QCA4019) +#define QCA_REV_WCN3990(ar) ((ar)->hw_rev == ATH10K_HW_WCN3990) /* Known peculiarities: * - raw appears in nwifi decap, raw and nwifi appear in ethernet decap diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 6a91276ce4d7..a697caec6579 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -1597,6 +1597,8 @@ void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar) * to mask irq/MSI. */ break; + case ATH10K_HW_WCN3990: + break; } } @@ -1623,6 +1625,8 @@ static void ath10k_pci_irq_msi_fw_unmask(struct ath10k *ar) * to unmask irq/MSI. */ break; + case ATH10K_HW_WCN3990: + break; } } -- cgit v1.2.3 From 75e0dde2abf6ae8561b133c4069c473641d50c12 Mon Sep 17 00:00:00 2001 From: Tamizh chelvam Date: Mon, 3 Jul 2017 11:02:36 +0530 Subject: ath10k: increase buffer len to print all wmi services All wmi_services are not printing when we give below command. cat /sys/kernel/debug/ieee80211/phyX/ath10k/wmi_services This patch increases the buffer_len to 8192 to print all the wmi_services. Signed-off-by: Tamizh chelvam Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 389fcb7a9fd0..56404fe4e8f5 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -237,7 +237,7 @@ static ssize_t ath10k_read_wmi_services(struct file *file, { struct ath10k *ar = file->private_data; char *buf; - size_t len = 0, buf_len = 4096; + size_t len = 0, buf_len = 8192; const char *name; ssize_t ret_cnt; bool enabled; -- cgit v1.2.3 From 846c6b26d38e56e5004f1d71d4c13226d2514750 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Thu, 29 Jun 2017 18:36:58 +0300 Subject: drm/i915/gen9+: Add 10 us delay after power well 1/AUX IO pw disabling Bspec requires a 10 us delay after disabling power well 1 and - if not toggled on-demand - the AUX IO power wells during display uninit. Signed-off-by: Imre Deak Reviewed-by: Rodrigo Vivi Link: http://patchwork.freedesktop.org/patch/msgid/1498750622-14023-2-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/intel_runtime_pm.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index efe80ed5fd4d..fd59016191ff 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -2701,6 +2701,8 @@ static void skl_display_core_uninit(struct drm_i915_private *dev_priv) intel_power_well_disable(dev_priv, well); mutex_unlock(&power_domains->lock); + + usleep_range(10, 30); /* 10 us delay per Bspec */ } void bxt_display_core_init(struct drm_i915_private *dev_priv, @@ -2758,6 +2760,8 @@ void bxt_display_core_uninit(struct drm_i915_private *dev_priv) intel_power_well_disable(dev_priv, well); mutex_unlock(&power_domains->lock); + + usleep_range(10, 30); /* 10 us delay per Bspec */ } #define CNL_PROCMON_IDX(val) \ @@ -2859,6 +2863,8 @@ static void cnl_display_core_uninit(struct drm_i915_private *dev_priv) intel_power_well_disable(dev_priv, well); mutex_unlock(&power_domains->lock); + usleep_range(10, 30); /* 10 us delay per Bspec */ + /* 5. Disable Comp */ val = I915_READ(CHICKEN_MISC_2); val |= COMP_PWR_DOWN; -- cgit v1.2.3 From edfda8e37ae9ec530434c3a014c8f0155a72acbd Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Thu, 29 Jun 2017 18:36:59 +0300 Subject: drm/i915/skl: Don't disable misc IO power well during display uninit Bspec requires leaving the misc IO power well enabled during display uninit, so align the code accordingly. Signed-off-by: Imre Deak Reviewed-by: Rodrigo Vivi Link: http://patchwork.freedesktop.org/patch/msgid/1498750622-14023-3-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/intel_runtime_pm.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index fd59016191ff..8418879c287a 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -2694,9 +2694,10 @@ static void skl_display_core_uninit(struct drm_i915_private *dev_priv) mutex_lock(&power_domains->lock); - well = lookup_power_well(dev_priv, SKL_DISP_PW_MISC_IO); - intel_power_well_disable(dev_priv, well); - + /* + * BSpec says to keep the MISC IO power well enabled here, only + * remove our request for power well 1. + */ well = lookup_power_well(dev_priv, SKL_DISP_PW_1); intel_power_well_disable(dev_priv, well); -- cgit v1.2.3 From e8a3a2a3d7f7a194e0f0ad92c5dd636f908e7601 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Thu, 29 Jun 2017 18:37:00 +0300 Subject: drm/i915/bxt, glk: Fix assert on conditions for DC9 enabling What we want to assert based on the conditions required by Bspec is that power well 2 is disabled, so no need to check for other power wells. In addition we can only check if the driver's request is removed, the actual state depends on whether the other request bits are set or not (BIOS, KVMR, DEBUG). So check only the driver's request bit. Signed-off-by: Imre Deak Reviewed-by: Rodrigo Vivi Link: http://patchwork.freedesktop.org/patch/msgid/1498750622-14023-4-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/intel_runtime_pm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 8418879c287a..1fc75e6769bc 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -549,7 +549,9 @@ static void assert_can_enable_dc9(struct drm_i915_private *dev_priv) "DC9 already programmed to be enabled.\n"); WARN_ONCE(I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5, "DC5 still not disabled to enable DC9.\n"); - WARN_ONCE(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on.\n"); + WARN_ONCE(I915_READ(HSW_PWR_WELL_DRIVER) & + SKL_POWER_WELL_REQ(SKL_DISP_PW_2), + "Power well 2 on.\n"); WARN_ONCE(intel_irqs_enabled(dev_priv), "Interrupts not disabled yet.\n"); -- cgit v1.2.3 From 42d9366d41a992631abaa15f5a881ae1235a8203 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Thu, 29 Jun 2017 18:37:01 +0300 Subject: drm/i915/gen9+: Don't remove secondary power well requests So far in an attempt to make sure all power wells get disabled during display uninitialization the driver removed any secondary request bits (BIOS, KVMR, DEBUG) that were set for a given power well. The known source for these requests was DMC's request on power well 1 and the misc IO power well. Since DMC is inactive (DC states are disabled) at the point we disable these power wells, there shouldn't be any reason to leave them on. However there are two problems with the above assumption: Bspec requires that the misc IO power well stays enabled (without providing a reason) and there can be KVMR requests that we can't remove anyway (the KVMR request register is R/O). Atm, a KVMR request can trigger a timeout WARN when trying to disable power wells. To make the code aligned to Bspec and to get rid of the KVMR WARN, don't try to remove the secondary requests, only detect them and stop polling for the power well disabled state when any one is set. Also add a comment about the timeout values required by Bspec when enabling power wells and the fact that waiting for them to get disabled is not required by Bspec. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=98564 Signed-off-by: Imre Deak Reviewed-by: Rodrigo Vivi Link: http://patchwork.freedesktop.org/patch/msgid/1498750622-14023-5-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/intel_runtime_pm.c | 109 ++++++++++++++++++-------------- 1 file changed, 63 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 1fc75e6769bc..2fe715b25f9e 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -341,6 +341,59 @@ static void skl_power_well_pre_disable(struct drm_i915_private *dev_priv, 1 << PIPE_C | 1 << PIPE_B); } +static void gen9_wait_for_power_well_enable(struct drm_i915_private *dev_priv, + struct i915_power_well *power_well) +{ + int id = power_well->id; + + /* Timeout for PW1:10 us, AUX:not specified, other PWs:20 us. */ + WARN_ON(intel_wait_for_register(dev_priv, + HSW_PWR_WELL_DRIVER, + SKL_POWER_WELL_STATE(id), + SKL_POWER_WELL_STATE(id), + 1)); +} + +static u32 gen9_power_well_requesters(struct drm_i915_private *dev_priv, int id) +{ + u32 req_mask = SKL_POWER_WELL_REQ(id); + u32 ret; + + ret = I915_READ(HSW_PWR_WELL_BIOS) & req_mask ? 1 : 0; + ret |= I915_READ(HSW_PWR_WELL_DRIVER) & req_mask ? 2 : 0; + ret |= I915_READ(HSW_PWR_WELL_KVMR) & req_mask ? 4 : 0; + ret |= I915_READ(HSW_PWR_WELL_DEBUG) & req_mask ? 8 : 0; + + return ret; +} + +static void gen9_wait_for_power_well_disable(struct drm_i915_private *dev_priv, + struct i915_power_well *power_well) +{ + int id = power_well->id; + bool disabled; + u32 reqs; + + /* + * Bspec doesn't require waiting for PWs to get disabled, but still do + * this for paranoia. The known cases where a PW will be forced on: + * - a KVMR request on any power well via the KVMR request register + * - a DMC request on PW1 and MISC_IO power wells via the BIOS and + * DEBUG request registers + * Skip the wait in case any of the request bits are set and print a + * diagnostic message. + */ + wait_for((disabled = !(I915_READ(HSW_PWR_WELL_DRIVER) & + SKL_POWER_WELL_STATE(id))) || + (reqs = gen9_power_well_requesters(dev_priv, id)), 1); + if (disabled) + return; + + DRM_DEBUG_KMS("%s forced on (bios:%d driver:%d kvmr:%d debug:%d)\n", + power_well->name, + !!(reqs & 1), !!(reqs & 2), !!(reqs & 4), !!(reqs & 8)); +} + static void hsw_set_power_well(struct drm_i915_private *dev_priv, struct i915_power_well *power_well, bool enable) { @@ -746,45 +799,6 @@ void skl_disable_dc6(struct drm_i915_private *dev_priv) gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); } -static void -gen9_sanitize_power_well_requests(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well) -{ - enum skl_disp_power_wells power_well_id = power_well->id; - u32 val; - u32 mask; - - mask = SKL_POWER_WELL_REQ(power_well_id); - - val = I915_READ(HSW_PWR_WELL_KVMR); - if (WARN_ONCE(val & mask, "Clearing unexpected KVMR request for %s\n", - power_well->name)) - I915_WRITE(HSW_PWR_WELL_KVMR, val & ~mask); - - val = I915_READ(HSW_PWR_WELL_BIOS); - val |= I915_READ(HSW_PWR_WELL_DEBUG); - - if (!(val & mask)) - return; - - /* - * DMC is known to force on the request bits for power well 1 on SKL - * and BXT and the misc IO power well on SKL but we don't expect any - * other request bits to be set, so WARN for those. - */ - if (power_well_id == SKL_DISP_PW_1 || - (IS_GEN9_BC(dev_priv) && - power_well_id == SKL_DISP_PW_MISC_IO)) - DRM_DEBUG_DRIVER("Clearing auxiliary requests for %s forced on " - "by DMC\n", power_well->name); - else - WARN_ONCE(1, "Clearing unexpected auxiliary requests for %s\n", - power_well->name); - - I915_WRITE(HSW_PWR_WELL_BIOS, val & ~mask); - I915_WRITE(HSW_PWR_WELL_DEBUG, val & ~mask); -} - static void skl_set_power_well(struct drm_i915_private *dev_priv, struct i915_power_well *power_well, bool enable) { @@ -848,6 +862,8 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv, DRM_DEBUG_KMS("Enabling %s\n", power_well->name); check_fuse_status = true; } + + gen9_wait_for_power_well_enable(dev_priv, power_well); } else { if (enable_requested) { I915_WRITE(HSW_PWR_WELL_DRIVER, tmp & ~req_mask); @@ -855,14 +871,9 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv, DRM_DEBUG_KMS("Disabling %s\n", power_well->name); } - gen9_sanitize_power_well_requests(dev_priv, power_well); + gen9_wait_for_power_well_disable(dev_priv, power_well); } - if (wait_for(!!(I915_READ(HSW_PWR_WELL_DRIVER) & state_mask) == enable, - 1)) - DRM_ERROR("%s %s timeout\n", - power_well->name, enable ? "enable" : "disable"); - if (check_fuse_status) { if (power_well->id == SKL_DISP_PW_1) { if (intel_wait_for_register(dev_priv, @@ -2699,6 +2710,8 @@ static void skl_display_core_uninit(struct drm_i915_private *dev_priv) /* * BSpec says to keep the MISC IO power well enabled here, only * remove our request for power well 1. + * Note that even though the driver's request is removed power well 1 + * may stay enabled after this due to DMC's own request on it. */ well = lookup_power_well(dev_priv, SKL_DISP_PW_1); intel_power_well_disable(dev_priv, well); @@ -2756,7 +2769,11 @@ void bxt_display_core_uninit(struct drm_i915_private *dev_priv) /* The spec doesn't call for removing the reset handshake flag */ - /* Disable PG1 */ + /* + * Disable PW1 (PG1). + * Note that even though the driver's request is removed power well 1 + * may stay enabled after this due to DMC's own request on it. + */ mutex_lock(&power_domains->lock); well = lookup_power_well(dev_priv, SKL_DISP_PW_1); -- cgit v1.2.3 From b38131fbcba5e16e94db7f0a6334446ffd157204 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Thu, 29 Jun 2017 18:37:02 +0300 Subject: drm/i915/cnl: Fix comment about AUX IO power well enable/disable The comments match an earlier version of the patch, fix them to match the current state. Signed-off-by: Imre Deak Reviewed-by: Rodrigo Vivi Link: http://patchwork.freedesktop.org/patch/msgid/1498750622-14023-6-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/intel_runtime_pm.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 2fe715b25f9e..5eb9c5ec9c85 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -2845,7 +2845,10 @@ static void cnl_display_core_init(struct drm_i915_private *dev_priv, bool resume val |= CL_POWER_DOWN_ENABLE; I915_WRITE(CNL_PORT_CL1CM_DW5, val); - /* 4. Enable Power Well 1 (PG1) and Aux IO Power */ + /* + * 4. Enable Power Well 1 (PG1). + * The AUX IO power wells will be enabled on demand. + */ mutex_lock(&power_domains->lock); well = lookup_power_well(dev_priv, SKL_DISP_PW_1); intel_power_well_enable(dev_priv, well); @@ -2877,7 +2880,11 @@ static void cnl_display_core_uninit(struct drm_i915_private *dev_priv) /* 3. Disable CD clock */ cnl_uninit_cdclk(dev_priv); - /* 4. Disable Power Well 1 (PG1) and Aux IO Power */ + /* + * 4. Disable Power Well 1 (PG1). + * The AUX IO power wells are toggled on demand, so they are already + * disabled at this point. + */ mutex_lock(&power_domains->lock); well = lookup_power_well(dev_priv, SKL_DISP_PW_1); intel_power_well_disable(dev_priv, well); -- cgit v1.2.3 From eed3089fb28d9afc252821ca2913ca84b53e17e7 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 5 Jul 2017 03:25:58 -0700 Subject: iio: pressure: zpa2326: Add newlines to logging macros Add newlines to the macro definitions and use a more common style. Signed-off-by: Joe Perches Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/zpa2326.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/pressure/zpa2326.c b/drivers/iio/pressure/zpa2326.c index c92a95f9f52c..ebfb1de7377f 100644 --- a/drivers/iio/pressure/zpa2326.c +++ b/drivers/iio/pressure/zpa2326.c @@ -141,14 +141,14 @@ struct zpa2326_private { struct regulator *vdd; }; -#define zpa2326_err(_idev, _format, _arg...) \ - dev_err(_idev->dev.parent, _format, ##_arg) +#define zpa2326_err(idev, fmt, ...) \ + dev_err(idev->dev.parent, fmt "\n", ##__VA_ARGS__) -#define zpa2326_warn(_idev, _format, _arg...) \ - dev_warn(_idev->dev.parent, _format, ##_arg) +#define zpa2326_warn(idev, fmt, ...) \ + dev_warn(idev->dev.parent, fmt "\n", ##__VA_ARGS__) -#define zpa2326_dbg(_idev, _format, _arg...) \ - dev_dbg(_idev->dev.parent, _format, ##_arg) +#define zpa2326_dbg(idev, fmt, ...) \ + dev_dbg(idev->dev.parent, fmt "\n", ##__VA_ARGS__) bool zpa2326_isreg_writeable(struct device *dev, unsigned int reg) { -- cgit v1.2.3 From a7b8829d242b1a58107e9c02b09e93aec446d55c Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 5 Jul 2017 20:30:01 +0200 Subject: iio: accel: st_accel: add SPI-3wire support Add SPI Serial Interface Mode (SIM) register information in st_sensor_settings look up table to support devices (like LSM303AGR accel sensor) that allow just SPI-3wire communication mode. SIM mode has to be configured before any other operation since it is not enabled by default and the driver is not able to read without that configuration Whilst a fairly substantial patch, the actual logic is simple and it is better to have the generic fix than a band aid. Fixes: ddc05fa28606 (iio: st-accel: add support for lsm303agr accel) Signed-off-by: Lorenzo Bianconi Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/accel/st_accel_core.c | 32 +++++++++++++++++++++++++ drivers/iio/common/st_sensors/st_sensors_core.c | 29 ++++++++++++++++++++++ include/linux/iio/common/st_sensors.h | 7 ++++++ include/linux/platform_data/st_sensors_pdata.h | 2 ++ 4 files changed, 70 insertions(+) (limited to 'drivers') diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c index 784670e2736b..2ee3ae11eb2a 100644 --- a/drivers/iio/accel/st_accel_core.c +++ b/drivers/iio/accel/st_accel_core.c @@ -166,6 +166,10 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .mask_ihl = 0x02, .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, }, + .sim = { + .addr = 0x23, + .value = BIT(0), + }, .multi_read_bit = true, .bootime = 2, }, @@ -234,6 +238,10 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .mask_od = 0x40, .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, }, + .sim = { + .addr = 0x23, + .value = BIT(0), + }, .multi_read_bit = true, .bootime = 2, }, @@ -316,6 +324,10 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .en_mask = 0x08, }, }, + .sim = { + .addr = 0x24, + .value = BIT(0), + }, .multi_read_bit = false, .bootime = 2, }, @@ -379,6 +391,10 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .mask_int1 = 0x04, .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, }, + .sim = { + .addr = 0x21, + .value = BIT(1), + }, .multi_read_bit = true, .bootime = 2, /* guess */ }, @@ -437,6 +453,10 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .mask_od = 0x40, .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, }, + .sim = { + .addr = 0x21, + .value = BIT(7), + }, .multi_read_bit = false, .bootime = 2, /* guess */ }, @@ -499,6 +519,10 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .addr_ihl = 0x22, .mask_ihl = 0x80, }, + .sim = { + .addr = 0x23, + .value = BIT(0), + }, .multi_read_bit = true, .bootime = 2, }, @@ -547,6 +571,10 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .mask_int1 = 0x04, .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, }, + .sim = { + .addr = 0x21, + .value = BIT(1), + }, .multi_read_bit = false, .bootime = 2, }, @@ -614,6 +642,10 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .mask_ihl = 0x02, .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, }, + .sim = { + .addr = 0x23, + .value = BIT(0), + }, .multi_read_bit = true, .bootime = 2, }, diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c index 79c8c7cd70d5..6e6a1ecc99dd 100644 --- a/drivers/iio/common/st_sensors/st_sensors_core.c +++ b/drivers/iio/common/st_sensors/st_sensors_core.c @@ -550,6 +550,31 @@ out: } EXPORT_SYMBOL(st_sensors_read_info_raw); +static int st_sensors_init_interface_mode(struct iio_dev *indio_dev, + const struct st_sensor_settings *sensor_settings) +{ + struct st_sensor_data *sdata = iio_priv(indio_dev); + struct device_node *np = sdata->dev->of_node; + struct st_sensors_platform_data *pdata; + + pdata = (struct st_sensors_platform_data *)sdata->dev->platform_data; + if (((np && of_property_read_bool(np, "spi-3wire")) || + (pdata && pdata->spi_3wire)) && sensor_settings->sim.addr) { + int err; + + err = sdata->tf->write_byte(&sdata->tb, sdata->dev, + sensor_settings->sim.addr, + sensor_settings->sim.value); + if (err < 0) { + dev_err(&indio_dev->dev, + "failed to init interface mode\n"); + return err; + } + } + + return 0; +} + int st_sensors_check_device_support(struct iio_dev *indio_dev, int num_sensors_list, const struct st_sensor_settings *sensor_settings) @@ -574,6 +599,10 @@ int st_sensors_check_device_support(struct iio_dev *indio_dev, return -ENODEV; } + err = st_sensors_init_interface_mode(indio_dev, &sensor_settings[i]); + if (err < 0) + return err; + if (sensor_settings[i].wai_addr) { err = sdata->tf->read_byte(&sdata->tb, sdata->dev, sensor_settings[i].wai_addr, &wai); diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h index 497f2b3a5a62..97f1b465d04f 100644 --- a/include/linux/iio/common/st_sensors.h +++ b/include/linux/iio/common/st_sensors.h @@ -105,6 +105,11 @@ struct st_sensor_fullscale { struct st_sensor_fullscale_avl fs_avl[ST_SENSORS_FULLSCALE_AVL_MAX]; }; +struct st_sensor_sim { + u8 addr; + u8 value; +}; + /** * struct st_sensor_bdu - ST sensor device block data update * @addr: address of the register. @@ -197,6 +202,7 @@ struct st_sensor_transfer_function { * @bdu: Block data update register. * @das: Data Alignment Selection register. * @drdy_irq: Data ready register of the sensor. + * @sim: SPI serial interface mode register of the sensor. * @multi_read_bit: Use or not particular bit for [I2C/SPI] multi-read. * @bootime: samples to discard when sensor passing from power-down to power-up. */ @@ -213,6 +219,7 @@ struct st_sensor_settings { struct st_sensor_bdu bdu; struct st_sensor_das das; struct st_sensor_data_ready_irq drdy_irq; + struct st_sensor_sim sim; bool multi_read_bit; unsigned int bootime; }; diff --git a/include/linux/platform_data/st_sensors_pdata.h b/include/linux/platform_data/st_sensors_pdata.h index 79b0e4cdb814..f8274b0c6888 100644 --- a/include/linux/platform_data/st_sensors_pdata.h +++ b/include/linux/platform_data/st_sensors_pdata.h @@ -17,10 +17,12 @@ * Available only for accelerometer and pressure sensors. * Accelerometer DRDY on LSM330 available only on pin 1 (see datasheet). * @open_drain: set the interrupt line to be open drain if possible. + * @spi_3wire: enable spi-3wire mode. */ struct st_sensors_platform_data { u8 drdy_int_pin; bool open_drain; + bool spi_3wire; }; #endif /* ST_SENSORS_PDATA_H */ -- cgit v1.2.3 From d466d3c1217406b14b834335b5b4b33c0d45bd09 Mon Sep 17 00:00:00 2001 From: Stefan-Gabriel Mirea Date: Thu, 6 Jul 2017 10:06:41 +0100 Subject: iio: adc: vf610_adc: Fix VALT selection value for REFSEL bits In order to select the alternate voltage reference pair (VALTH/VALTL), the right value for the REFSEL field in the ADCx_CFG register is "01", leading to 0x800 as register mask. See section 8.2.6.4 in the reference manual[1]. [1] http://www.nxp.com/docs/en/reference-manual/VFXXXRM.pdf Fixes: a775427632fd ("iio:adc:imx: add Freescale Vybrid vf610 adc driver") Signed-off-by: Stefan-Gabriel Mirea Signed-off-by: Jonathan Cameron --- drivers/iio/adc/vf610_adc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c index 01fc76f7d660..c168e0db329a 100644 --- a/drivers/iio/adc/vf610_adc.c +++ b/drivers/iio/adc/vf610_adc.c @@ -77,7 +77,7 @@ #define VF610_ADC_ADSTS_MASK 0x300 #define VF610_ADC_ADLPC_EN 0x80 #define VF610_ADC_ADHSC_EN 0x400 -#define VF610_ADC_REFSEL_VALT 0x100 +#define VF610_ADC_REFSEL_VALT 0x800 #define VF610_ADC_REFSEL_VBG 0x1000 #define VF610_ADC_ADTRG_HARD 0x2000 #define VF610_ADC_AVGS_8 0x4000 -- cgit v1.2.3 From 3d16ca58908312a1d837972123217ee12bdbda24 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Wed, 5 Jul 2017 18:00:31 -0700 Subject: drm/i915/cnl: Add force wake for gen10+. By spec there is no change on force wake registers for Cannonlake. Let's reuse gen9 one. v2: Adding missing case for the write part. (Tvrtko) v3: Rebase on recent tree. v4: Make it for gen9+ instead adding gen10 only. (by Joonas). Cc: Tvrtko Ursulin Signed-off-by: Rodrigo Vivi Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/1499302831-17773-1-git-send-email-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/intel_uncore.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 1ed3dd8df850..deb4430541cf 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -643,7 +643,7 @@ find_fw_domain(struct drm_i915_private *dev_priv, u32 offset) { .start = (s), .end = (e), .domains = (d) } #define HAS_FWTABLE(dev_priv) \ - (IS_GEN9(dev_priv) || \ + (INTEL_GEN(dev_priv) >= 9 || \ IS_CHERRYVIEW(dev_priv) || \ IS_VALLEYVIEW(dev_priv)) @@ -1072,7 +1072,7 @@ static void intel_uncore_fw_domains_init(struct drm_i915_private *dev_priv) dev_priv->uncore.fw_clear = _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL); } - if (IS_GEN9(dev_priv)) { + if (INTEL_GEN(dev_priv) >= 9) { dev_priv->uncore.funcs.force_wake_get = fw_domains_get; dev_priv->uncore.funcs.force_wake_put = fw_domains_put; fw_domain_init(dev_priv, FW_DOMAIN_ID_RENDER, -- cgit v1.2.3 From 6602be0e2c6163bd747d490d8875ef0812c11560 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Thu, 6 Jul 2017 14:01:13 -0700 Subject: drm/i915/cnl: Cannonlake color init. Cannonlake has same color setup as Geminilake. Legacy color load luts doesn't work anymore on Cannonlake+. Cc: Clint Taylor Cc: Ander Conselvan de Oliveira Signed-off-by: Rodrigo Vivi Reviewed-by: Clinton Taylor Link: http://patchwork.freedesktop.org/patch/msgid/1499374873-2454-1-git-send-email-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/i915_pci.c | 1 + drivers/gpu/drm/i915/intel_color.c | 2 +- drivers/gpu/drm/i915/intel_display.c | 4 ++-- drivers/gpu/drm/i915/intel_sprite.c | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 04aaf553e3fa..a1e6b696bcfa 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -449,6 +449,7 @@ static const struct intel_device_info intel_cannonlake_info = { .gen = 10, .ddb_size = 1024, .has_csr = 1, + .color = { .degamma_lut_size = 0, .gamma_lut_size = 1024 } }; /* diff --git a/drivers/gpu/drm/i915/intel_color.c b/drivers/gpu/drm/i915/intel_color.c index 306c6b06b330..f85d57555957 100644 --- a/drivers/gpu/drm/i915/intel_color.c +++ b/drivers/gpu/drm/i915/intel_color.c @@ -615,7 +615,7 @@ void intel_color_init(struct drm_crtc *crtc) IS_BROXTON(dev_priv)) { dev_priv->display.load_csc_matrix = i9xx_load_csc_matrix; dev_priv->display.load_luts = broadwell_load_luts; - } else if (IS_GEMINILAKE(dev_priv)) { + } else if (IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) { dev_priv->display.load_csc_matrix = i9xx_load_csc_matrix; dev_priv->display.load_luts = glk_load_luts; } else { diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ede3c6c02ec5..9a3919b19413 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3311,7 +3311,7 @@ u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state, plane_ctl = PLANE_CTL_ENABLE; - if (!IS_GEMINILAKE(dev_priv)) { + if (!IS_GEMINILAKE(dev_priv) && !IS_CANNONLAKE(dev_priv)) { plane_ctl |= PLANE_CTL_PIPE_GAMMA_ENABLE | PLANE_CTL_PIPE_CSC_ENABLE | @@ -3367,7 +3367,7 @@ static void skylake_update_primary_plane(struct intel_plane *plane, spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - if (IS_GEMINILAKE(dev_priv)) { + if (IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) { I915_WRITE_FW(PLANE_COLOR_CTL(pipe, plane_id), PLANE_COLOR_PIPE_GAMMA_ENABLE | PLANE_COLOR_PIPE_CSC_ENABLE | diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 0c650c2cbca8..94f9a1332dbf 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -262,7 +262,7 @@ skl_update_plane(struct intel_plane *plane, spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - if (IS_GEMINILAKE(dev_priv)) { + if (IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) { I915_WRITE_FW(PLANE_COLOR_CTL(pipe, plane_id), PLANE_COLOR_PIPE_GAMMA_ENABLE | PLANE_COLOR_PIPE_CSC_ENABLE | -- cgit v1.2.3 From 17369ba08c065967b7b8c48253f20b73acc0b9f5 Mon Sep 17 00:00:00 2001 From: Chuanxiao Dong Date: Fri, 7 Jul 2017 17:50:59 +0800 Subject: drm/i915: Fix the kernel panic when using aliasing ppgtt The ppgtt should be get directly from i915_address_space *vm instead of vma->vm. v2: - add one more fix for bxt. (Chris) Fixes: 4a234c5fae16 ("drm/i915: pass the vma to insert_entries") Bugzilla:https://bugs.freedesktop.org/show_bug.cgi?id=101713 Signed-off-by: Chuanxiao Dong Reviewed-by: Matthew Auld v1 Cc: Matthew Auld Cc: Chris Wilson Cc: Zhenyu Wang Link: http://patchwork.freedesktop.org/patch/msgid/1499421059-18262-1-git-send-email-chuanxiao.dong@intel.com Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_gem_gtt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index de67084d5fcf..10aa7762d9a6 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -910,7 +910,7 @@ static void gen8_ppgtt_insert_3lvl(struct i915_address_space *vm, enum i915_cache_level cache_level, u32 unused) { - struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vma->vm); + struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm); struct sgt_dma iter = { .sg = vma->pages->sgl, .dma = sg_dma_address(iter.sg), @@ -2242,7 +2242,7 @@ static void bxt_vtd_ggtt_insert_entries__BKL(struct i915_address_space *vm, enum i915_cache_level level, u32 unused) { - struct insert_entries arg = { vma->vm, vma, level }; + struct insert_entries arg = { vm, vma, level }; stop_machine(bxt_vtd_ggtt_insert_entries__cb, &arg, NULL); } -- cgit v1.2.3 From 2f2472baa66ef9a6aa25124cb07679bbe613ceff Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 7 Jul 2017 00:29:58 -0500 Subject: regulator: qcom_rpm-regulator: add NULL check on of_match_device() return value Check return value from call to of_match_device() in order to prevent a NULL pointer dereference. In case of NULL print error message and return. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- drivers/regulator/qcom_rpm-regulator.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/regulator/qcom_rpm-regulator.c b/drivers/regulator/qcom_rpm-regulator.c index 1b2acc43fea1..88dc0b0f003c 100644 --- a/drivers/regulator/qcom_rpm-regulator.c +++ b/drivers/regulator/qcom_rpm-regulator.c @@ -959,6 +959,11 @@ static int rpm_reg_probe(struct platform_device *pdev) } match = of_match_device(rpm_of_match, &pdev->dev); + if (!match) { + dev_err(&pdev->dev, "failed to match device\n"); + return -ENODEV; + } + for (reg = match->data; reg->name; reg++) { vreg = devm_kmalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL); if (!vreg) -- cgit v1.2.3 From e3b53b8a465133ce57f9722aab5617b8e0f9657f Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 7 Jul 2017 00:36:10 -0500 Subject: regulator: qcom_smd: add NULL check on of_match_device() return value Check return value from call to of_match_device() in order to prevent a NULL pointer dereference. In case of NULL print error message and return. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- drivers/regulator/qcom_smd-regulator.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/regulator/qcom_smd-regulator.c b/drivers/regulator/qcom_smd-regulator.c index f35994a2a5be..940fe1b78411 100644 --- a/drivers/regulator/qcom_smd-regulator.c +++ b/drivers/regulator/qcom_smd-regulator.c @@ -570,6 +570,11 @@ static int rpm_reg_probe(struct platform_device *pdev) } match = of_match_device(rpm_of_match, &pdev->dev); + if (!match) { + dev_err(&pdev->dev, "failed to match device\n"); + return -ENODEV; + } + for (reg = match->data; reg->name; reg++) { vreg = devm_kzalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL); if (!vreg) -- cgit v1.2.3 From da2629684822091bf15c6c14d8e33b75dfce8637 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 6 Jul 2017 16:49:18 -0500 Subject: regulator: axp20x: add NULL check on devm_kzalloc() return value Check return value from call to devm_kzalloc() in order to prevent a NULL pointer dereference. This issue was detected using Coccinelle and the following semantic patch: @@ expression x; identifier fld; @@ * x = devm_kzalloc(...); ... when != x == NULL x->fld Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- drivers/regulator/axp20x-regulator.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c index e2608fe770b9..f18b36dd57dd 100644 --- a/drivers/regulator/axp20x-regulator.c +++ b/drivers/regulator/axp20x-regulator.c @@ -691,6 +691,9 @@ static int axp20x_regulator_probe(struct platform_device *pdev) (regulators == axp809_regulators && i == AXP809_DC1SW)) { new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL); + if (!new_desc) + return -ENOMEM; + *new_desc = regulators[i]; new_desc->supply_name = dcdc1_name; desc = new_desc; @@ -700,6 +703,9 @@ static int axp20x_regulator_probe(struct platform_device *pdev) (regulators == axp809_regulators && i == AXP809_DC5LDO)) { new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL); + if (!new_desc) + return -ENOMEM; + *new_desc = regulators[i]; new_desc->supply_name = dcdc5_name; desc = new_desc; -- cgit v1.2.3 From 75be7756bc21ac1f9f3082850deff809ac3c5d0c Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Thu, 6 Jul 2017 14:08:15 -0700 Subject: drm/i915/cnl: Don't trust VBT's alternate pin for port D for now. Cannon Lake's VBT that is currently available for B0 stepping states that port D uses alternate pin 3 messing up with the default pin-port mapping table. Using that information we cannot get HDMI working properly. So for now we don't relly on VBT for this information. Cc: Clint Taylor Signed-off-by: Rodrigo Vivi Reviewed-by: Clinton Taylor Link: http://patchwork.freedesktop.org/patch/msgid/1499375295-6454-1-git-send-email-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/intel_bios.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 639d45c1dd2e..82b144cdfa1d 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -1187,6 +1187,15 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, if (is_dvi) { info->alternate_ddc_pin = ddc_pin; + /* + * All VBTs that we got so far for B Stepping has this + * information wrong for Port D. So, let's just ignore for now. + */ + if (IS_CNL_REVID(dev_priv, CNL_REVID_B0, CNL_REVID_B0) && + port == PORT_D) { + info->alternate_ddc_pin = 0; + } + sanitize_ddc_pin(dev_priv, port); } -- cgit v1.2.3 From f65f84178999c2c0227f9ae7dafd8af62c0ce5ad Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Thu, 6 Jul 2017 14:06:24 -0700 Subject: drm/i915/cnl: Gen10 render context size. No change on render context size is required for Gen10. So this patch doesn't change the default behaviour, but only avoid the missing_case message. Cc: Ben Widawsky Signed-off-by: Rodrigo Vivi Reviewed-by: Ben Widawsky Link: http://patchwork.freedesktop.org/patch/msgid/1499375184-5725-1-git-send-email-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/intel_engine_cs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index a55cd72aeeff..24db316e0fd1 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -149,6 +149,7 @@ __intel_engine_context_size(struct drm_i915_private *dev_priv, u8 class) switch (INTEL_GEN(dev_priv)) { default: MISSING_CASE(INTEL_GEN(dev_priv)); + case 10: case 9: return GEN9_LR_CONTEXT_RENDER_SIZE; case 8: -- cgit v1.2.3 From 35ceabf3cdb557b23bbc09f0b6f7bb2b545185b1 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Thu, 6 Jul 2017 13:41:13 -0700 Subject: drm/i915/cnl: Inherit RPS stuff from previous platforms. Apparently no change on RPS stuff from previous platforms. v2: Merging to rps related patches in one and also adding missed cases. Cc: David Weinehall Signed-off-by: Rodrigo Vivi Reviewed-by: David Weinehall Link: http://patchwork.freedesktop.org/patch/msgid/1499373673-25066-1-git-send-email-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/i915_debugfs.c | 20 ++++++++++++-------- drivers/gpu/drm/i915/i915_reg.h | 4 ++-- drivers/gpu/drm/i915/i915_sysfs.c | 2 +- drivers/gpu/drm/i915/intel_pm.c | 18 +++++++++--------- 4 files changed, 24 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 643f56b8b87c..ca2e34b1c798 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1159,7 +1159,7 @@ static int i915_frequency_info(struct seq_file *m, void *unused) intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); reqf = I915_READ(GEN6_RPNSWREQ); - if (IS_GEN9(dev_priv)) + if (INTEL_GEN(dev_priv) >= 9) reqf >>= 23; else { reqf &= ~GEN6_TURBO_DISABLE; @@ -1181,7 +1181,7 @@ static int i915_frequency_info(struct seq_file *m, void *unused) rpdownei = I915_READ(GEN6_RP_CUR_DOWN_EI) & GEN6_CURIAVG_MASK; rpcurdown = I915_READ(GEN6_RP_CUR_DOWN) & GEN6_CURBSYTAVG_MASK; rpprevdown = I915_READ(GEN6_RP_PREV_DOWN) & GEN6_CURBSYTAVG_MASK; - if (IS_GEN9(dev_priv)) + if (INTEL_GEN(dev_priv) >= 9) cagf = (rpstat & GEN9_CAGF_MASK) >> GEN9_CAGF_SHIFT; else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) cagf = (rpstat & HSW_CAGF_MASK) >> HSW_CAGF_SHIFT; @@ -1210,7 +1210,7 @@ static int i915_frequency_info(struct seq_file *m, void *unused) dev_priv->rps.pm_intrmsk_mbz); seq_printf(m, "GT_PERF_STATUS: 0x%08x\n", gt_perf_status); seq_printf(m, "Render p-state ratio: %d\n", - (gt_perf_status & (IS_GEN9(dev_priv) ? 0x1ff00 : 0xff00)) >> 8); + (gt_perf_status & (INTEL_GEN(dev_priv) >= 9 ? 0x1ff00 : 0xff00)) >> 8); seq_printf(m, "Render p-state VID: %d\n", gt_perf_status & 0xff); seq_printf(m, "Render p-state limit: %d\n", @@ -1241,18 +1241,21 @@ static int i915_frequency_info(struct seq_file *m, void *unused) max_freq = (IS_GEN9_LP(dev_priv) ? rp_state_cap >> 0 : rp_state_cap >> 16) & 0xff; - max_freq *= (IS_GEN9_BC(dev_priv) ? GEN9_FREQ_SCALER : 1); + max_freq *= (IS_GEN9_BC(dev_priv) || + IS_CANNONLAKE(dev_priv) ? GEN9_FREQ_SCALER : 1); seq_printf(m, "Lowest (RPN) frequency: %dMHz\n", intel_gpu_freq(dev_priv, max_freq)); max_freq = (rp_state_cap & 0xff00) >> 8; - max_freq *= (IS_GEN9_BC(dev_priv) ? GEN9_FREQ_SCALER : 1); + max_freq *= (IS_GEN9_BC(dev_priv) || + IS_CANNONLAKE(dev_priv) ? GEN9_FREQ_SCALER : 1); seq_printf(m, "Nominal (RP1) frequency: %dMHz\n", intel_gpu_freq(dev_priv, max_freq)); max_freq = (IS_GEN9_LP(dev_priv) ? rp_state_cap >> 16 : rp_state_cap >> 0) & 0xff; - max_freq *= (IS_GEN9_BC(dev_priv) ? GEN9_FREQ_SCALER : 1); + max_freq *= (IS_GEN9_BC(dev_priv) || + IS_CANNONLAKE(dev_priv) ? GEN9_FREQ_SCALER : 1); seq_printf(m, "Max non-overclocked (RP0) frequency: %dMHz\n", intel_gpu_freq(dev_priv, max_freq)); seq_printf(m, "Max overclocked frequency: %dMHz\n", @@ -1855,7 +1858,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused) if (ret) goto out; - if (IS_GEN9_BC(dev_priv)) { + if (IS_GEN9_BC(dev_priv) || IS_CANNONLAKE(dev_priv)) { /* Convert GT frequency to 50 HZ units */ min_gpu_freq = dev_priv->rps.min_freq_softlimit / GEN9_FREQ_SCALER; @@ -1875,7 +1878,8 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused) &ia_freq); seq_printf(m, "%d\t\t%d\t\t\t\t%d\n", intel_gpu_freq(dev_priv, (gpu_freq * - (IS_GEN9_BC(dev_priv) ? + (IS_GEN9_BC(dev_priv) || + IS_CANNONLAKE(dev_priv) ? GEN9_FREQ_SCALER : 1))), ((ia_freq >> 0) & 0xff) * 100, ((ia_freq >> 8) & 0xff) * 100); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 64cc674b652a..21ab12f4e72a 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3522,7 +3522,7 @@ enum skl_disp_power_wells { #define INTERVAL_1_28_US(us) roundup(((us) * 100) >> 7, 25) #define INTERVAL_1_33_US(us) (((us) * 3) >> 2) #define INTERVAL_0_833_US(us) (((us) * 6) / 5) -#define GT_INTERVAL_FROM_US(dev_priv, us) (IS_GEN9(dev_priv) ? \ +#define GT_INTERVAL_FROM_US(dev_priv, us) (INTEL_GEN(dev_priv) >= 9 ? \ (IS_GEN9_LP(dev_priv) ? \ INTERVAL_0_833_US(us) : \ INTERVAL_1_33_US(us)) : \ @@ -3531,7 +3531,7 @@ enum skl_disp_power_wells { #define INTERVAL_1_28_TO_US(interval) (((interval) << 7) / 100) #define INTERVAL_1_33_TO_US(interval) (((interval) << 2) / 3) #define INTERVAL_0_833_TO_US(interval) (((interval) * 5) / 6) -#define GT_PM_INTERVAL_TO_US(dev_priv, interval) (IS_GEN9(dev_priv) ? \ +#define GT_PM_INTERVAL_TO_US(dev_priv, interval) (INTEL_GEN(dev_priv) >= 9 ? \ (IS_GEN9_LP(dev_priv) ? \ INTERVAL_0_833_TO_US(interval) : \ INTERVAL_1_33_TO_US(interval)) : \ diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index 3736c9f79197..7fcf00622c4c 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -253,7 +253,7 @@ static ssize_t gt_act_freq_mhz_show(struct device *kdev, ret = intel_gpu_freq(dev_priv, (freq >> 8) & 0xff); } else { u32 rpstat = I915_READ(GEN6_RPSTAT1); - if (IS_GEN9(dev_priv)) + if (INTEL_GEN(dev_priv) >= 9) ret = (rpstat & GEN9_CAGF_MASK) >> GEN9_CAGF_SHIFT; else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) ret = (rpstat & HSW_CAGF_MASK) >> HSW_CAGF_SHIFT; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index c3fcadfa0ae7..6db833e6dcbd 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5852,7 +5852,7 @@ static u32 intel_rps_limits(struct drm_i915_private *dev_priv, u8 val) * the hw runs at the minimal clock before selecting the desired * frequency, if the down threshold expires in that window we will not * receive a down interrupt. */ - if (IS_GEN9(dev_priv)) { + if (INTEL_GEN(dev_priv) >= 9) { limits = (dev_priv->rps.max_freq_softlimit) << 23; if (val <= dev_priv->rps.min_freq_softlimit) limits |= (dev_priv->rps.min_freq_softlimit) << 14; @@ -5994,7 +5994,7 @@ static int gen6_set_rps(struct drm_i915_private *dev_priv, u8 val) if (val != dev_priv->rps.cur_freq) { gen6_set_rps_thresholds(dev_priv, val); - if (IS_GEN9(dev_priv)) + if (INTEL_GEN(dev_priv) >= 9) I915_WRITE(GEN6_RPNSWREQ, GEN9_FREQUENCY(val)); else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) @@ -6353,7 +6353,7 @@ static void gen6_init_rps_frequencies(struct drm_i915_private *dev_priv) dev_priv->rps.efficient_freq = dev_priv->rps.rp1_freq; if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv) || - IS_GEN9_BC(dev_priv)) { + IS_GEN9_BC(dev_priv) || IS_CANNONLAKE(dev_priv)) { u32 ddcc_status = 0; if (sandybridge_pcode_read(dev_priv, @@ -6366,7 +6366,7 @@ static void gen6_init_rps_frequencies(struct drm_i915_private *dev_priv) dev_priv->rps.max_freq); } - if (IS_GEN9_BC(dev_priv)) { + if (IS_GEN9_BC(dev_priv) || IS_CANNONLAKE(dev_priv)) { /* Store the frequency values in 16.66 MHZ units, which is * the natural hardware unit for SKL */ @@ -6672,7 +6672,7 @@ static void gen6_update_ring_freq(struct drm_i915_private *dev_priv) /* convert DDR frequency from units of 266.6MHz to bandwidth */ min_ring_freq = mult_frac(min_ring_freq, 8, 3); - if (IS_GEN9_BC(dev_priv)) { + if (IS_GEN9_BC(dev_priv) || IS_CANNONLAKE(dev_priv)) { /* Convert GT frequency to 50 HZ units */ min_gpu_freq = dev_priv->rps.min_freq / GEN9_FREQ_SCALER; max_gpu_freq = dev_priv->rps.max_freq / GEN9_FREQ_SCALER; @@ -6690,7 +6690,7 @@ static void gen6_update_ring_freq(struct drm_i915_private *dev_priv) int diff = max_gpu_freq - gpu_freq; unsigned int ia_freq = 0, ring_freq = 0; - if (IS_GEN9_BC(dev_priv)) { + if (IS_GEN9_BC(dev_priv) || IS_CANNONLAKE(dev_priv)) { /* * ring_freq = 2 * GT. ring_freq is in 100MHz units * No floor required for ring frequency on SKL. @@ -7821,7 +7821,7 @@ void intel_enable_gt_powersave(struct drm_i915_private *dev_priv) } else if (INTEL_GEN(dev_priv) >= 9) { gen9_enable_rc6(dev_priv); gen9_enable_rps(dev_priv); - if (IS_GEN9_BC(dev_priv)) + if (IS_GEN9_BC(dev_priv) || IS_CANNONLAKE(dev_priv)) gen6_update_ring_freq(dev_priv); } else if (IS_BROADWELL(dev_priv)) { gen8_enable_rps(dev_priv); @@ -9066,7 +9066,7 @@ static int chv_freq_opcode(struct drm_i915_private *dev_priv, int val) int intel_gpu_freq(struct drm_i915_private *dev_priv, int val) { - if (IS_GEN9(dev_priv)) + if (INTEL_GEN(dev_priv) >= 9) return DIV_ROUND_CLOSEST(val * GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER); else if (IS_CHERRYVIEW(dev_priv)) @@ -9079,7 +9079,7 @@ int intel_gpu_freq(struct drm_i915_private *dev_priv, int val) int intel_freq_opcode(struct drm_i915_private *dev_priv, int val) { - if (IS_GEN9(dev_priv)) + if (INTEL_GEN(dev_priv) >= 9) return DIV_ROUND_CLOSEST(val * GEN9_FREQ_SCALER, GT_FREQUENCY_MULTIPLIER); else if (IS_CHERRYVIEW(dev_priv)) -- cgit v1.2.3 From a9701a897067db118f1a0fcf59ce8391e3612687 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Thu, 6 Jul 2017 13:52:01 -0700 Subject: drm/i915/cnl: Get DDI clock based on PLLs. PLLs are the source clocks for the DDIs so in order to determine the ddi clock we need to check the PLL configuration. v2: Mika pointed out that 24 was hardcoded while it should consider ref clock that can be either 24KHz or 19.2KHz on CNL. Reviewed-by: Mika Kahola Signed-off-by: Rodrigo Vivi Link: http://patchwork.freedesktop.org/patch/msgid/1499374321-31152-1-git-send-email-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/i915_reg.h | 2 + drivers/gpu/drm/i915/intel_ddi.c | 111 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 21ab12f4e72a..c712d01f92ab 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -8343,6 +8343,7 @@ enum { #define DPLL_CFGCR0_LINK_RATE_3240 (6 << 25) #define DPLL_CFGCR0_LINK_RATE_4050 (7 << 25) #define DPLL_CFGCR0_DCO_FRACTION_MASK (0x7fff << 10) +#define DPLL_CFGCR0_DCO_FRAC_SHIFT (10) #define DPLL_CFGCR0_DCO_FRACTION(x) ((x) << 10) #define DPLL_CFGCR0_DCO_INTEGER_MASK (0x3ff) #define CNL_DPLL_CFGCR0(pll) _MMIO_PLL(pll, _CNL_DPLL0_CFGCR0, _CNL_DPLL1_CFGCR0) @@ -8350,6 +8351,7 @@ enum { #define _CNL_DPLL0_CFGCR1 0x6C004 #define _CNL_DPLL1_CFGCR1 0x6C084 #define DPLL_CFGCR1_QDIV_RATIO_MASK (0xff << 10) +#define DPLL_CFGCR1_QDIV_RATIO_SHIFT (10) #define DPLL_CFGCR1_QDIV_RATIO(x) ((x) << 10) #define DPLL_CFGCR1_QDIV_MODE(x) ((x) << 9) #define DPLL_CFGCR1_KDIV_MASK (7 << 6) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 80e96f1f49d2..241decf2a7d9 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1103,6 +1103,62 @@ static int skl_calc_wrpll_link(struct drm_i915_private *dev_priv, return dco_freq / (p0 * p1 * p2 * 5); } +static int cnl_calc_wrpll_link(struct drm_i915_private *dev_priv, + uint32_t pll_id) +{ + uint32_t cfgcr0, cfgcr1; + uint32_t p0, p1, p2, dco_freq, ref_clock; + + cfgcr0 = I915_READ(CNL_DPLL_CFGCR0(pll_id)); + cfgcr1 = I915_READ(CNL_DPLL_CFGCR1(pll_id)); + + p0 = cfgcr1 & DPLL_CFGCR1_PDIV_MASK; + p2 = cfgcr1 & DPLL_CFGCR1_KDIV_MASK; + + if (cfgcr1 & DPLL_CFGCR1_QDIV_MODE(1)) + p1 = (cfgcr1 & DPLL_CFGCR1_QDIV_RATIO_MASK) >> + DPLL_CFGCR1_QDIV_RATIO_SHIFT; + else + p1 = 1; + + + switch (p0) { + case DPLL_CFGCR1_PDIV_2: + p0 = 2; + break; + case DPLL_CFGCR1_PDIV_3: + p0 = 3; + break; + case DPLL_CFGCR1_PDIV_5: + p0 = 5; + break; + case DPLL_CFGCR1_PDIV_7: + p0 = 7; + break; + } + + switch (p2) { + case DPLL_CFGCR1_KDIV_1: + p2 = 1; + break; + case DPLL_CFGCR1_KDIV_2: + p2 = 2; + break; + case DPLL_CFGCR1_KDIV_4: + p2 = 4; + break; + } + + ref_clock = dev_priv->cdclk.hw.ref; + + dco_freq = (cfgcr0 & DPLL_CFGCR0_DCO_INTEGER_MASK) * ref_clock; + + dco_freq += (((cfgcr0 & DPLL_CFGCR0_DCO_FRACTION_MASK) >> + DPLL_CFGCR0_DCO_FRAC_SHIFT) * ref_clock) / 0x8000; + + return dco_freq / (p0 * p1 * p2 * 5); +} + static void ddi_dotclock_get(struct intel_crtc_state *pipe_config) { int dotclock; @@ -1124,6 +1180,59 @@ static void ddi_dotclock_get(struct intel_crtc_state *pipe_config) pipe_config->base.adjusted_mode.crtc_clock = dotclock; } +static void cnl_ddi_clock_get(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + int link_clock = 0; + uint32_t cfgcr0, pll_id; + + pll_id = intel_get_shared_dpll_id(dev_priv, pipe_config->shared_dpll); + + cfgcr0 = I915_READ(CNL_DPLL_CFGCR0(pll_id)); + + if (cfgcr0 & DPLL_CFGCR0_HDMI_MODE) { + link_clock = cnl_calc_wrpll_link(dev_priv, pll_id); + } else { + link_clock = cfgcr0 & DPLL_CFGCR0_LINK_RATE_MASK; + + switch (link_clock) { + case DPLL_CFGCR0_LINK_RATE_810: + link_clock = 81000; + break; + case DPLL_CFGCR0_LINK_RATE_1080: + link_clock = 108000; + break; + case DPLL_CFGCR0_LINK_RATE_1350: + link_clock = 135000; + break; + case DPLL_CFGCR0_LINK_RATE_1620: + link_clock = 162000; + break; + case DPLL_CFGCR0_LINK_RATE_2160: + link_clock = 216000; + break; + case DPLL_CFGCR0_LINK_RATE_2700: + link_clock = 270000; + break; + case DPLL_CFGCR0_LINK_RATE_3240: + link_clock = 324000; + break; + case DPLL_CFGCR0_LINK_RATE_4050: + link_clock = 405000; + break; + default: + WARN(1, "Unsupported link rate\n"); + break; + } + link_clock *= 2; + } + + pipe_config->port_clock = link_clock; + + ddi_dotclock_get(pipe_config); +} + static void skl_ddi_clock_get(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) { @@ -1267,6 +1376,8 @@ void intel_ddi_clock_get(struct intel_encoder *encoder, skl_ddi_clock_get(encoder, pipe_config); else if (IS_GEN9_LP(dev_priv)) bxt_ddi_clock_get(encoder, pipe_config); + else if (IS_CANNONLAKE(dev_priv)) + cnl_ddi_clock_get(encoder, pipe_config); } void intel_ddi_set_pipe_settings(const struct intel_crtc_state *crtc_state) -- cgit v1.2.3 From 7c0299e879dd3c3fe0885fc07233b28f6007add3 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Thu, 6 Jul 2017 12:39:33 -1000 Subject: iio: adc: Add support for DLN2 ADC This patch adds support for Diolan DLN2 ADC via IIO's ADC interface. ADC is the fourth and final component of the DLN2 for the kernel. Signed-off-by: Jack Andersen Signed-off-by: Jonathan Cameron --- drivers/iio/adc/Kconfig | 9 + drivers/iio/adc/Makefile | 1 + drivers/iio/adc/dln2-adc.c | 722 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 732 insertions(+) create mode 100644 drivers/iio/adc/dln2-adc.c (limited to 'drivers') diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 8a6edf5bb1e5..17e61c5e9ffd 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -239,6 +239,15 @@ config DA9150_GPADC To compile this driver as a module, choose M here: the module will be called berlin2-adc. +config DLN2_ADC + tristate "Diolan DLN-2 ADC driver support" + depends on MFD_DLN2 + help + Say yes here to build support for Diolan DLN-2 ADC. + + This driver can also be built as a module. If so, the module will be + called adc_dln2. + config ENVELOPE_DETECTOR tristate "Envelope detector using a DAC and a comparator" depends on OF diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 73c206209f1f..4abb7af9e5bb 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_BERLIN2_ADC) += berlin2-adc.o obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o obj-$(CONFIG_CPCAP_ADC) += cpcap-adc.o obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o +obj-$(CONFIG_DLN2_ADC) += dln2-adc.o obj-$(CONFIG_ENVELOPE_DETECTOR) += envelope-detector.o obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o obj-$(CONFIG_FSL_MX25_ADC) += fsl-imx25-gcq.o diff --git a/drivers/iio/adc/dln2-adc.c b/drivers/iio/adc/dln2-adc.c new file mode 100644 index 000000000000..ab8d6aed5085 --- /dev/null +++ b/drivers/iio/adc/dln2-adc.c @@ -0,0 +1,722 @@ +/* + * Driver for the Diolan DLN-2 USB-ADC adapter + * + * Copyright (c) 2017 Jack Andersen + * + * 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, version 2. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define DLN2_ADC_MOD_NAME "dln2-adc" + +#define DLN2_ADC_ID 0x06 + +#define DLN2_ADC_GET_CHANNEL_COUNT DLN2_CMD(0x01, DLN2_ADC_ID) +#define DLN2_ADC_ENABLE DLN2_CMD(0x02, DLN2_ADC_ID) +#define DLN2_ADC_DISABLE DLN2_CMD(0x03, DLN2_ADC_ID) +#define DLN2_ADC_CHANNEL_ENABLE DLN2_CMD(0x05, DLN2_ADC_ID) +#define DLN2_ADC_CHANNEL_DISABLE DLN2_CMD(0x06, DLN2_ADC_ID) +#define DLN2_ADC_SET_RESOLUTION DLN2_CMD(0x08, DLN2_ADC_ID) +#define DLN2_ADC_CHANNEL_GET_VAL DLN2_CMD(0x0A, DLN2_ADC_ID) +#define DLN2_ADC_CHANNEL_GET_ALL_VAL DLN2_CMD(0x0B, DLN2_ADC_ID) +#define DLN2_ADC_CHANNEL_SET_CFG DLN2_CMD(0x0C, DLN2_ADC_ID) +#define DLN2_ADC_CHANNEL_GET_CFG DLN2_CMD(0x0D, DLN2_ADC_ID) +#define DLN2_ADC_CONDITION_MET_EV DLN2_CMD(0x10, DLN2_ADC_ID) + +#define DLN2_ADC_EVENT_NONE 0 +#define DLN2_ADC_EVENT_BELOW 1 +#define DLN2_ADC_EVENT_LEVEL_ABOVE 2 +#define DLN2_ADC_EVENT_OUTSIDE 3 +#define DLN2_ADC_EVENT_INSIDE 4 +#define DLN2_ADC_EVENT_ALWAYS 5 + +#define DLN2_ADC_MAX_CHANNELS 8 +#define DLN2_ADC_DATA_BITS 10 + +/* + * Plays similar role to iio_demux_table in subsystem core; except allocated + * in a fixed 8-element array. + */ +struct dln2_adc_demux_table { + unsigned int from; + unsigned int to; + unsigned int length; +}; + +struct dln2_adc { + struct platform_device *pdev; + struct iio_chan_spec iio_channels[DLN2_ADC_MAX_CHANNELS + 1]; + int port, trigger_chan; + struct iio_trigger *trig; + struct mutex mutex; + /* Cached sample period in milliseconds */ + unsigned int sample_period; + /* Demux table */ + unsigned int demux_count; + struct dln2_adc_demux_table demux[DLN2_ADC_MAX_CHANNELS]; + /* Precomputed timestamp padding offset and length */ + unsigned int ts_pad_offset, ts_pad_length; +}; + +struct dln2_adc_port_chan { + u8 port; + u8 chan; +}; + +struct dln2_adc_get_all_vals { + __le16 channel_mask; + __le16 values[DLN2_ADC_MAX_CHANNELS]; +}; + +static void dln2_adc_add_demux(struct dln2_adc *dln2, + unsigned int in_loc, unsigned int out_loc, + unsigned int length) +{ + struct dln2_adc_demux_table *p = dln2->demux_count ? + &dln2->demux[dln2->demux_count - 1] : NULL; + + if (p && p->from + p->length == in_loc && + p->to + p->length == out_loc) { + p->length += length; + } else if (dln2->demux_count < DLN2_ADC_MAX_CHANNELS) { + p = &dln2->demux[dln2->demux_count++]; + p->from = in_loc; + p->to = out_loc; + p->length = length; + } +} + +static void dln2_adc_update_demux(struct dln2_adc *dln2) +{ + int in_ind = -1, out_ind; + unsigned int in_loc = 0, out_loc = 0; + struct iio_dev *indio_dev = platform_get_drvdata(dln2->pdev); + + /* Clear out any old demux */ + dln2->demux_count = 0; + + /* Optimize all 8-channels case */ + if (indio_dev->masklength && + (*indio_dev->active_scan_mask & 0xff) == 0xff) { + dln2_adc_add_demux(dln2, 0, 0, 16); + dln2->ts_pad_offset = 0; + dln2->ts_pad_length = 0; + return; + } + + /* Build demux table from fixed 8-channels to active_scan_mask */ + for_each_set_bit(out_ind, + indio_dev->active_scan_mask, + indio_dev->masklength) { + /* Handle timestamp separately */ + if (out_ind == DLN2_ADC_MAX_CHANNELS) + break; + for (++in_ind; in_ind != out_ind; ++in_ind) + in_loc += 2; + dln2_adc_add_demux(dln2, in_loc, out_loc, 2); + out_loc += 2; + in_loc += 2; + } + + if (indio_dev->scan_timestamp) { + size_t ts_offset = indio_dev->scan_bytes / sizeof(int64_t) - 1; + + dln2->ts_pad_offset = out_loc; + dln2->ts_pad_length = ts_offset * sizeof(int64_t) - out_loc; + } else { + dln2->ts_pad_offset = 0; + dln2->ts_pad_length = 0; + } +} + +static int dln2_adc_get_chan_count(struct dln2_adc *dln2) +{ + int ret; + u8 port = dln2->port; + u8 count; + int olen = sizeof(count); + + ret = dln2_transfer(dln2->pdev, DLN2_ADC_GET_CHANNEL_COUNT, + &port, sizeof(port), &count, &olen); + if (ret < 0) { + dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__); + return ret; + } + if (olen < sizeof(count)) + return -EPROTO; + + return count; +} + +static int dln2_adc_set_port_resolution(struct dln2_adc *dln2) +{ + int ret; + struct dln2_adc_port_chan port_chan = { + .port = dln2->port, + .chan = DLN2_ADC_DATA_BITS, + }; + + ret = dln2_transfer_tx(dln2->pdev, DLN2_ADC_SET_RESOLUTION, + &port_chan, sizeof(port_chan)); + if (ret < 0) + dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__); + + return ret; +} + +static int dln2_adc_set_chan_enabled(struct dln2_adc *dln2, + int channel, bool enable) +{ + int ret; + struct dln2_adc_port_chan port_chan = { + .port = dln2->port, + .chan = channel, + }; + u16 cmd = enable ? DLN2_ADC_CHANNEL_ENABLE : DLN2_ADC_CHANNEL_DISABLE; + + ret = dln2_transfer_tx(dln2->pdev, cmd, &port_chan, sizeof(port_chan)); + if (ret < 0) + dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__); + + return ret; +} + +static int dln2_adc_set_port_enabled(struct dln2_adc *dln2, bool enable, + u16 *conflict_out) +{ + int ret; + u8 port = dln2->port; + __le16 conflict; + int olen = sizeof(conflict); + u16 cmd = enable ? DLN2_ADC_ENABLE : DLN2_ADC_DISABLE; + + if (conflict_out) + *conflict_out = 0; + + ret = dln2_transfer(dln2->pdev, cmd, &port, sizeof(port), + &conflict, &olen); + if (ret < 0) { + dev_dbg(&dln2->pdev->dev, "Problem in %s(%d)\n", + __func__, (int)enable); + if (conflict_out && enable && olen >= sizeof(conflict)) + *conflict_out = le16_to_cpu(conflict); + return ret; + } + if (enable && olen < sizeof(conflict)) + return -EPROTO; + + return ret; +} + +static int dln2_adc_set_chan_period(struct dln2_adc *dln2, + unsigned int channel, unsigned int period) +{ + int ret; + struct { + struct dln2_adc_port_chan port_chan; + __u8 type; + __le16 period; + __le16 low; + __le16 high; + } __packed set_cfg = { + .port_chan.port = dln2->port, + .port_chan.chan = channel, + .type = period ? DLN2_ADC_EVENT_ALWAYS : DLN2_ADC_EVENT_NONE, + .period = cpu_to_le16(period) + }; + + ret = dln2_transfer_tx(dln2->pdev, DLN2_ADC_CHANNEL_SET_CFG, + &set_cfg, sizeof(set_cfg)); + if (ret < 0) + dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__); + + return ret; +} + +static int dln2_adc_read(struct dln2_adc *dln2, unsigned int channel) +{ + int ret, i; + struct iio_dev *indio_dev = platform_get_drvdata(dln2->pdev); + u16 conflict; + __le16 value; + int olen = sizeof(value); + struct dln2_adc_port_chan port_chan = { + .port = dln2->port, + .chan = channel, + }; + + ret = iio_device_claim_direct_mode(indio_dev); + if (ret < 0) + return ret; + + ret = dln2_adc_set_chan_enabled(dln2, channel, true); + if (ret < 0) + goto release_direct; + + ret = dln2_adc_set_port_enabled(dln2, true, &conflict); + if (ret < 0) { + if (conflict) { + dev_err(&dln2->pdev->dev, + "ADC pins conflict with mask %04X\n", + (int)conflict); + ret = -EBUSY; + } + goto disable_chan; + } + + /* + * Call GET_VAL twice due to initial zero-return immediately after + * enabling channel. + */ + for (i = 0; i < 2; ++i) { + ret = dln2_transfer(dln2->pdev, DLN2_ADC_CHANNEL_GET_VAL, + &port_chan, sizeof(port_chan), + &value, &olen); + if (ret < 0) { + dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__); + goto disable_port; + } + if (olen < sizeof(value)) { + ret = -EPROTO; + goto disable_port; + } + } + + ret = le16_to_cpu(value); + +disable_port: + dln2_adc_set_port_enabled(dln2, false, NULL); +disable_chan: + dln2_adc_set_chan_enabled(dln2, channel, false); +release_direct: + iio_device_release_direct_mode(indio_dev); + + return ret; +} + +static int dln2_adc_read_all(struct dln2_adc *dln2, + struct dln2_adc_get_all_vals *get_all_vals) +{ + int ret; + __u8 port = dln2->port; + int olen = sizeof(*get_all_vals); + + ret = dln2_transfer(dln2->pdev, DLN2_ADC_CHANNEL_GET_ALL_VAL, + &port, sizeof(port), get_all_vals, &olen); + if (ret < 0) { + dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__); + return ret; + } + if (olen < sizeof(*get_all_vals)) + return -EPROTO; + + return ret; +} + +static int dln2_adc_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long mask) +{ + int ret; + unsigned int microhertz; + struct dln2_adc *dln2 = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + mutex_lock(&dln2->mutex); + ret = dln2_adc_read(dln2, chan->channel); + mutex_unlock(&dln2->mutex); + + if (ret < 0) + return ret; + + *val = ret; + return IIO_VAL_INT; + + case IIO_CHAN_INFO_SCALE: + /* + * Voltage reference is fixed at 3.3v + * 3.3 / (1 << 10) * 1000000000 + */ + *val = 0; + *val2 = 3222656; + return IIO_VAL_INT_PLUS_NANO; + + case IIO_CHAN_INFO_SAMP_FREQ: + if (dln2->sample_period) { + microhertz = 1000000000 / dln2->sample_period; + *val = microhertz / 1000000; + *val2 = microhertz % 1000000; + } else { + *val = 0; + *val2 = 0; + } + + return IIO_VAL_INT_PLUS_MICRO; + + default: + return -EINVAL; + } +} + +static int dln2_adc_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + int ret; + unsigned int microhertz; + struct dln2_adc *dln2 = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + microhertz = 1000000 * val + val2; + + mutex_lock(&dln2->mutex); + + dln2->sample_period = + microhertz ? 1000000000 / microhertz : UINT_MAX; + if (dln2->sample_period > 65535) { + dln2->sample_period = 65535; + dev_warn(&dln2->pdev->dev, + "clamping period to 65535ms\n"); + } + + /* + * The first requested channel is arbitrated as a shared + * trigger source, so only one event is registered with the + * DLN. The event handler will then read all enabled channel + * values using DLN2_ADC_CHANNEL_GET_ALL_VAL to maintain + * synchronization between ADC readings. + */ + if (dln2->trigger_chan != -1) + ret = dln2_adc_set_chan_period(dln2, + dln2->trigger_chan, dln2->sample_period); + else + ret = 0; + + mutex_unlock(&dln2->mutex); + + return ret; + + default: + return -EINVAL; + } +} + +static int dln2_update_scan_mode(struct iio_dev *indio_dev, + const unsigned long *scan_mask) +{ + struct dln2_adc *dln2 = iio_priv(indio_dev); + int chan_count = indio_dev->num_channels - 1; + int ret, i, j; + + mutex_lock(&dln2->mutex); + + for (i = 0; i < chan_count; ++i) { + ret = dln2_adc_set_chan_enabled(dln2, i, + test_bit(i, scan_mask)); + if (ret < 0) { + for (j = 0; j < i; ++j) + dln2_adc_set_chan_enabled(dln2, j, false); + mutex_unlock(&dln2->mutex); + dev_err(&dln2->pdev->dev, + "Unable to enable ADC channel %d\n", i); + return -EBUSY; + } + } + + dln2_adc_update_demux(dln2); + + mutex_unlock(&dln2->mutex); + + return 0; +} + +#define DLN2_ADC_CHAN(lval, idx) { \ + lval.type = IIO_VOLTAGE; \ + lval.channel = idx; \ + lval.indexed = 1; \ + lval.info_mask_separate = BIT(IIO_CHAN_INFO_RAW); \ + lval.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_SAMP_FREQ); \ + lval.scan_index = idx; \ + lval.scan_type.sign = 'u'; \ + lval.scan_type.realbits = DLN2_ADC_DATA_BITS; \ + lval.scan_type.storagebits = 16; \ + lval.scan_type.endianness = IIO_LE; \ +} + +/* Assignment version of IIO_CHAN_SOFT_TIMESTAMP */ +#define IIO_CHAN_SOFT_TIMESTAMP_ASSIGN(lval, _si) { \ + lval.type = IIO_TIMESTAMP; \ + lval.channel = -1; \ + lval.scan_index = _si; \ + lval.scan_type.sign = 's'; \ + lval.scan_type.realbits = 64; \ + lval.scan_type.storagebits = 64; \ +} + +static const struct iio_info dln2_adc_info = { + .read_raw = dln2_adc_read_raw, + .write_raw = dln2_adc_write_raw, + .update_scan_mode = dln2_update_scan_mode, + .driver_module = THIS_MODULE, +}; + +static irqreturn_t dln2_adc_trigger_h(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct { + __le16 values[DLN2_ADC_MAX_CHANNELS]; + int64_t timestamp_space; + } data; + struct dln2_adc_get_all_vals dev_data; + struct dln2_adc *dln2 = iio_priv(indio_dev); + const struct dln2_adc_demux_table *t; + int ret, i; + + mutex_lock(&dln2->mutex); + ret = dln2_adc_read_all(dln2, &dev_data); + mutex_unlock(&dln2->mutex); + if (ret < 0) + goto done; + + /* Demux operation */ + for (i = 0; i < dln2->demux_count; ++i) { + t = &dln2->demux[i]; + memcpy((void *)data.values + t->to, + (void *)dev_data.values + t->from, t->length); + } + + /* Zero padding space between values and timestamp */ + if (dln2->ts_pad_length) + memset((void *)data.values + dln2->ts_pad_offset, + 0, dln2->ts_pad_length); + + iio_push_to_buffers_with_timestamp(indio_dev, &data, + iio_get_time_ns(indio_dev)); + +done: + iio_trigger_notify_done(indio_dev->trig); + return IRQ_HANDLED; +} + +static int dln2_adc_triggered_buffer_postenable(struct iio_dev *indio_dev) +{ + int ret; + struct dln2_adc *dln2 = iio_priv(indio_dev); + u16 conflict; + unsigned int trigger_chan; + + mutex_lock(&dln2->mutex); + + /* Enable ADC */ + ret = dln2_adc_set_port_enabled(dln2, true, &conflict); + if (ret < 0) { + mutex_unlock(&dln2->mutex); + dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__); + if (conflict) { + dev_err(&dln2->pdev->dev, + "ADC pins conflict with mask %04X\n", + (int)conflict); + ret = -EBUSY; + } + return ret; + } + + /* Assign trigger channel based on first enabled channel */ + trigger_chan = find_first_bit(indio_dev->active_scan_mask, + indio_dev->masklength); + if (trigger_chan < DLN2_ADC_MAX_CHANNELS) { + dln2->trigger_chan = trigger_chan; + ret = dln2_adc_set_chan_period(dln2, dln2->trigger_chan, + dln2->sample_period); + mutex_unlock(&dln2->mutex); + if (ret < 0) { + dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__); + return ret; + } + } else { + dln2->trigger_chan = -1; + mutex_unlock(&dln2->mutex); + } + + return iio_triggered_buffer_postenable(indio_dev); +} + +static int dln2_adc_triggered_buffer_predisable(struct iio_dev *indio_dev) +{ + int ret; + struct dln2_adc *dln2 = iio_priv(indio_dev); + + mutex_lock(&dln2->mutex); + + /* Disable trigger channel */ + if (dln2->trigger_chan != -1) { + dln2_adc_set_chan_period(dln2, dln2->trigger_chan, 0); + dln2->trigger_chan = -1; + } + + /* Disable ADC */ + ret = dln2_adc_set_port_enabled(dln2, false, NULL); + + mutex_unlock(&dln2->mutex); + if (ret < 0) { + dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__); + return ret; + } + + return iio_triggered_buffer_predisable(indio_dev); +} + +static const struct iio_buffer_setup_ops dln2_adc_buffer_setup_ops = { + .postenable = dln2_adc_triggered_buffer_postenable, + .predisable = dln2_adc_triggered_buffer_predisable, +}; + +static void dln2_adc_event(struct platform_device *pdev, u16 echo, + const void *data, int len) +{ + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct dln2_adc *dln2 = iio_priv(indio_dev); + + /* Called via URB completion handler */ + iio_trigger_poll(dln2->trig); +} + +static const struct iio_trigger_ops dln2_adc_trigger_ops = { + .owner = THIS_MODULE, +}; + +static int dln2_adc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct dln2_adc *dln2; + struct dln2_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct iio_dev *indio_dev; + int i, ret, chans; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*dln2)); + if (!indio_dev) { + dev_err(dev, "failed allocating iio device\n"); + return -ENOMEM; + } + + dln2 = iio_priv(indio_dev); + dln2->pdev = pdev; + dln2->port = pdata->port; + dln2->trigger_chan = -1; + mutex_init(&dln2->mutex); + + platform_set_drvdata(pdev, indio_dev); + + ret = dln2_adc_set_port_resolution(dln2); + if (ret < 0) { + dev_err(dev, "failed to set ADC resolution to 10 bits\n"); + return ret; + } + + chans = dln2_adc_get_chan_count(dln2); + if (chans < 0) { + dev_err(dev, "failed to get channel count: %d\n", chans); + return chans; + } + if (chans > DLN2_ADC_MAX_CHANNELS) { + chans = DLN2_ADC_MAX_CHANNELS; + dev_warn(dev, "clamping channels to %d\n", + DLN2_ADC_MAX_CHANNELS); + } + + for (i = 0; i < chans; ++i) + DLN2_ADC_CHAN(dln2->iio_channels[i], i) + IIO_CHAN_SOFT_TIMESTAMP_ASSIGN(dln2->iio_channels[i], i); + + indio_dev->name = DLN2_ADC_MOD_NAME; + indio_dev->dev.parent = dev; + indio_dev->info = &dln2_adc_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = dln2->iio_channels; + indio_dev->num_channels = chans + 1; + indio_dev->setup_ops = &dln2_adc_buffer_setup_ops; + + dln2->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", + indio_dev->name, indio_dev->id); + if (!dln2->trig) { + dev_err(dev, "failed to allocate trigger\n"); + return -ENOMEM; + } + dln2->trig->ops = &dln2_adc_trigger_ops; + iio_trigger_set_drvdata(dln2->trig, dln2); + devm_iio_trigger_register(dev, dln2->trig); + iio_trigger_set_immutable(indio_dev, dln2->trig); + + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, + dln2_adc_trigger_h, + &dln2_adc_buffer_setup_ops); + if (ret) { + dev_err(dev, "failed to allocate triggered buffer: %d\n", ret); + return ret; + } + + ret = dln2_register_event_cb(pdev, DLN2_ADC_CONDITION_MET_EV, + dln2_adc_event); + if (ret) { + dev_err(dev, "failed to setup DLN2 periodic event: %d\n", ret); + return ret; + } + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(dev, "failed to register iio device: %d\n", ret); + goto unregister_event; + } + + return ret; + +unregister_event: + dln2_unregister_event_cb(pdev, DLN2_ADC_CONDITION_MET_EV); + + return ret; +} + +static int dln2_adc_remove(struct platform_device *pdev) +{ + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + + iio_device_unregister(indio_dev); + dln2_unregister_event_cb(pdev, DLN2_ADC_CONDITION_MET_EV); + return 0; +} + +static struct platform_driver dln2_adc_driver = { + .driver.name = DLN2_ADC_MOD_NAME, + .probe = dln2_adc_probe, + .remove = dln2_adc_remove, +}; + +module_platform_driver(dln2_adc_driver); + +MODULE_AUTHOR("Jack Andersen Date: Thu, 6 Jul 2017 18:56:18 -0400 Subject: staging: iio: tsl2x7x: add of_match table for device tree support Add device tree support for the tsl2x7x IIO driver with no custom properties. The device tree documentation is in a separate commit so that the changes to trivial-devices.txt can go in via the device tree subsystem. Signed-off-by: Brian Masney CC: Rob Herring CC: Mark Rutland CC: devicetree@vger.kernel.org Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/tsl2x7x.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/iio/light/tsl2x7x.c b/drivers/staging/iio/light/tsl2x7x.c index 146719928fb3..8148986b2049 100644 --- a/drivers/staging/iio/light/tsl2x7x.c +++ b/drivers/staging/iio/light/tsl2x7x.c @@ -2026,6 +2026,21 @@ static struct i2c_device_id tsl2x7x_idtable[] = { MODULE_DEVICE_TABLE(i2c, tsl2x7x_idtable); +static const struct of_device_id tsl2x7x_of_match[] = { + { .compatible = "amstaos,tsl2571" }, + { .compatible = "amstaos,tsl2671" }, + { .compatible = "amstaos,tmd2671" }, + { .compatible = "amstaos,tsl2771" }, + { .compatible = "amstaos,tmd2771" }, + { .compatible = "amstaos,tsl2572" }, + { .compatible = "amstaos,tsl2672" }, + { .compatible = "amstaos,tmd2672" }, + { .compatible = "amstaos,tsl2772" }, + { .compatible = "amstaos,tmd2772" }, + {} +}; +MODULE_DEVICE_TABLE(of, tsl2x7x_of_match); + static const struct dev_pm_ops tsl2x7x_pm_ops = { .suspend = tsl2x7x_suspend, .resume = tsl2x7x_resume, @@ -2035,6 +2050,7 @@ static const struct dev_pm_ops tsl2x7x_pm_ops = { static struct i2c_driver tsl2x7x_driver = { .driver = { .name = "tsl2x7x", + .of_match_table = tsl2x7x_of_match, .pm = &tsl2x7x_pm_ops, }, .id_table = tsl2x7x_idtable, -- cgit v1.2.3 From 8ea6134c234ee142f6be0361afd6369d13440f72 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 6 Jul 2017 18:56:20 -0400 Subject: staging: iio: tsl2x7x: remove redundant power_state sysfs attribute The TSL2X7X driver has a custom power_state sysfs attribute. Remove this attribute since the runtime power management code provides a sysfs attribute to control the power state of the device. Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/tsl2x7x.c | 34 ---------------------------------- 1 file changed, 34 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/tsl2x7x.c b/drivers/staging/iio/light/tsl2x7x.c index 8148986b2049..95ed7cc6cd8a 100644 --- a/drivers/staging/iio/light/tsl2x7x.c +++ b/drivers/staging/iio/light/tsl2x7x.c @@ -915,33 +915,6 @@ static void tsl2x7x_prox_cal(struct iio_dev *indio_dev) tsl2x7x_chip_on(indio_dev); } -static ssize_t power_state_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct tsl2X7X_chip *chip = iio_priv(dev_to_iio_dev(dev)); - - return snprintf(buf, PAGE_SIZE, "%d\n", chip->tsl2x7x_chip_status); -} - -static ssize_t power_state_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - bool value; - - if (strtobool(buf, &value)) - return -EINVAL; - - if (value) - tsl2x7x_chip_on(indio_dev); - else - tsl2x7x_chip_off(indio_dev); - - return len; -} - static ssize_t in_illuminance0_calibscale_available_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -1494,8 +1467,6 @@ static int tsl2x7x_write_raw(struct iio_dev *indio_dev, return 0; } -static DEVICE_ATTR_RW(power_state); - static DEVICE_ATTR_RO(in_proximity0_calibscale_available); static DEVICE_ATTR_RO(in_illuminance0_calibscale_available); @@ -1580,7 +1551,6 @@ static irqreturn_t tsl2x7x_event_handler(int irq, void *private) } static struct attribute *tsl2x7x_ALS_device_attrs[] = { - &dev_attr_power_state.attr, &dev_attr_in_illuminance0_calibscale_available.attr, &dev_attr_in_illuminance0_integration_time.attr, &iio_const_attr_in_illuminance0_integration_time_available.dev_attr.attr, @@ -1591,13 +1561,11 @@ static struct attribute *tsl2x7x_ALS_device_attrs[] = { }; static struct attribute *tsl2x7x_PRX_device_attrs[] = { - &dev_attr_power_state.attr, &dev_attr_in_proximity0_calibrate.attr, NULL }; static struct attribute *tsl2x7x_ALSPRX_device_attrs[] = { - &dev_attr_power_state.attr, &dev_attr_in_illuminance0_calibscale_available.attr, &dev_attr_in_illuminance0_integration_time.attr, &iio_const_attr_in_illuminance0_integration_time_available.dev_attr.attr, @@ -1609,14 +1577,12 @@ static struct attribute *tsl2x7x_ALSPRX_device_attrs[] = { }; static struct attribute *tsl2x7x_PRX2_device_attrs[] = { - &dev_attr_power_state.attr, &dev_attr_in_proximity0_calibrate.attr, &dev_attr_in_proximity0_calibscale_available.attr, NULL }; static struct attribute *tsl2x7x_ALSPRX2_device_attrs[] = { - &dev_attr_power_state.attr, &dev_attr_in_illuminance0_calibscale_available.attr, &dev_attr_in_illuminance0_integration_time.attr, &iio_const_attr_in_illuminance0_integration_time_available.dev_attr.attr, -- cgit v1.2.3 From d2f46f56b8ecd32ab0734b4a6d8a14de88d9894f Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 6 Jul 2017 18:56:21 -0400 Subject: staging: iio: tsl2x7x: remove tsl2x7x_i2c_read() tsl2x7x_i2c_read() would call i2c_smbus_write_byte() and i2c_smbus_read_byte(). These two i2c functions can be replaced with a single call to i2c_smbus_read_byte_data(). This patch removes the tsl2x7x_i2c_read() function and replaces all occurrences with a call to i2c_smbus_read_byte_data(). Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/tsl2x7x.c | 71 ++++++++++++------------------------- 1 file changed, 22 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/tsl2x7x.c b/drivers/staging/iio/light/tsl2x7x.c index 95ed7cc6cd8a..6c9f06bd65ad 100644 --- a/drivers/staging/iio/light/tsl2x7x.c +++ b/drivers/staging/iio/light/tsl2x7x.c @@ -284,35 +284,6 @@ static const u8 device_channel_config[] = { ALSPRX2 }; -/** - * tsl2x7x_i2c_read() - Read a byte from a register. - * @client: i2c client - * @reg: device register to read from - * @*val: pointer to location to store register contents. - * - */ -static int -tsl2x7x_i2c_read(struct i2c_client *client, u8 reg, u8 *val) -{ - int ret; - - /* select register to write */ - ret = i2c_smbus_write_byte(client, (TSL2X7X_CMD_REG | reg)); - if (ret < 0) { - dev_err(&client->dev, "failed to write register %x\n", reg); - return ret; - } - - /* read the data */ - ret = i2c_smbus_read_byte(client); - if (ret >= 0) - *val = (u8)ret; - else - dev_err(&client->dev, "failed to read register %x\n", reg); - - return ret; -} - /** * tsl2x7x_get_lux() - Reads and calculates current lux value. * @indio_dev: pointer to IIO device @@ -352,15 +323,15 @@ static int tsl2x7x_get_lux(struct iio_dev *indio_dev) goto out_unlock; } - ret = tsl2x7x_i2c_read(chip->client, - (TSL2X7X_CMD_REG | TSL2X7X_STATUS), &buf[0]); + ret = i2c_smbus_read_byte_data(chip->client, + TSL2X7X_CMD_REG | TSL2X7X_STATUS); if (ret < 0) { dev_err(&chip->client->dev, "%s: Failed to read STATUS Reg\n", __func__); goto out_unlock; } /* is data new & valid */ - if (!(buf[0] & TSL2X7X_STA_ADC_VALID)) { + if (!(ret & TSL2X7X_STA_ADC_VALID)) { dev_err(&chip->client->dev, "%s: data not valid yet\n", __func__); ret = chip->als_cur_info.lux; /* return LAST VALUE */ @@ -368,14 +339,16 @@ static int tsl2x7x_get_lux(struct iio_dev *indio_dev) } for (i = 0; i < 4; i++) { - ret = tsl2x7x_i2c_read(chip->client, - (TSL2X7X_CMD_REG | - (TSL2X7X_ALS_CHAN0LO + i)), &buf[i]); + int reg = TSL2X7X_CMD_REG | (TSL2X7X_ALS_CHAN0LO + i); + + ret = i2c_smbus_read_byte_data(chip->client, reg); if (ret < 0) { dev_err(&chip->client->dev, "failed to read. err=%x\n", ret); goto out_unlock; } + + buf[i] = ret; } /* clear any existing interrupt status */ @@ -475,7 +448,6 @@ static int tsl2x7x_get_prox(struct iio_dev *indio_dev) { int i; int ret; - u8 status; u8 chdata[2]; struct tsl2X7X_chip *chip = iio_priv(indio_dev); @@ -485,8 +457,8 @@ static int tsl2x7x_get_prox(struct iio_dev *indio_dev) return -EBUSY; } - ret = tsl2x7x_i2c_read(chip->client, - (TSL2X7X_CMD_REG | TSL2X7X_STATUS), &status); + ret = i2c_smbus_read_byte_data(chip->client, + TSL2X7X_CMD_REG | TSL2X7X_STATUS); if (ret < 0) { dev_err(&chip->client->dev, "i2c err=%d\n", ret); goto prox_poll_err; @@ -498,7 +470,7 @@ static int tsl2x7x_get_prox(struct iio_dev *indio_dev) case tmd2671: case tsl2771: case tmd2771: - if (!(status & TSL2X7X_STA_ADC_VALID)) + if (!(ret & TSL2X7X_STA_ADC_VALID)) goto prox_poll_err; break; case tsl2572: @@ -506,17 +478,19 @@ static int tsl2x7x_get_prox(struct iio_dev *indio_dev) case tmd2672: case tsl2772: case tmd2772: - if (!(status & TSL2X7X_STA_PRX_VALID)) + if (!(ret & TSL2X7X_STA_PRX_VALID)) goto prox_poll_err; break; } for (i = 0; i < 2; i++) { - ret = tsl2x7x_i2c_read(chip->client, - (TSL2X7X_CMD_REG | - (TSL2X7X_PRX_LO + i)), &chdata[i]); + int reg = TSL2X7X_CMD_REG | (TSL2X7X_PRX_LO + i); + + ret = i2c_smbus_read_byte_data(chip->client, reg); if (ret < 0) goto prox_poll_err; + + chdata[i] = ret; } chip->prox_data = @@ -1486,7 +1460,7 @@ static DEVICE_ATTR_RW(in_intensity0_thresh_period); static DEVICE_ATTR_RW(in_proximity0_thresh_period); /* Use the default register values to identify the Taos device */ -static int tsl2x7x_device_id(unsigned char *id, int target) +static int tsl2x7x_device_id(int *id, int target) { switch (target) { case tsl2571: @@ -1843,7 +1817,6 @@ static int tsl2x7x_probe(struct i2c_client *clientp, const struct i2c_device_id *id) { int ret; - unsigned char device_id; struct iio_dev *indio_dev; struct tsl2X7X_chip *chip; @@ -1855,13 +1828,13 @@ static int tsl2x7x_probe(struct i2c_client *clientp, chip->client = clientp; i2c_set_clientdata(clientp, indio_dev); - ret = tsl2x7x_i2c_read(chip->client, - TSL2X7X_CHIPID, &device_id); + ret = i2c_smbus_read_byte_data(chip->client, + TSL2X7X_CMD_REG | TSL2X7X_CHIPID); if (ret < 0) return ret; - if ((!tsl2x7x_device_id(&device_id, id->driver_data)) || - (tsl2x7x_device_id(&device_id, id->driver_data) == -EINVAL)) { + if ((!tsl2x7x_device_id(&ret, id->driver_data)) || + (tsl2x7x_device_id(&ret, id->driver_data) == -EINVAL)) { dev_info(&chip->client->dev, "%s: i2c device found does not match expected id\n", __func__); -- cgit v1.2.3 From 1b4cbe2ef00e5d055bb310030ed3eac9bc1d3e3d Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 6 Jul 2017 18:56:22 -0400 Subject: staging: iio: tsl2x7x: cleaned up i2c calls in tsl2x7x_als_calibrate() The calibration function calls i2c_smbus_write_byte() and i2c_smbus_read_byte(). These two function calls are replaced with a single call to i2c_smbus_read_byte_data() by this patch. This patch also removes an unnecessary call that reads the CNTRL register a second time. One of the error paths returned -1 if the ADC was not enabled and this patch changes that return value to -EINVAL. Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/tsl2x7x.c | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/tsl2x7x.c b/drivers/staging/iio/light/tsl2x7x.c index 6c9f06bd65ad..57346287da62 100644 --- a/drivers/staging/iio/light/tsl2x7x.c +++ b/drivers/staging/iio/light/tsl2x7x.c @@ -542,39 +542,29 @@ static void tsl2x7x_defaults(struct tsl2X7X_chip *chip) static int tsl2x7x_als_calibrate(struct iio_dev *indio_dev) { struct tsl2X7X_chip *chip = iio_priv(indio_dev); - u8 reg_val; int gain_trim_val; int ret; int lux_val; - ret = i2c_smbus_write_byte(chip->client, - (TSL2X7X_CMD_REG | TSL2X7X_CNTRL)); + ret = i2c_smbus_read_byte_data(chip->client, + TSL2X7X_CMD_REG | TSL2X7X_CNTRL); if (ret < 0) { dev_err(&chip->client->dev, - "failed to write CNTRL register, ret=%d\n", ret); + "%s: failed to read from the CNTRL register\n", + __func__); return ret; } - reg_val = i2c_smbus_read_byte(chip->client); - if ((reg_val & (TSL2X7X_CNTL_ADC_ENBL | TSL2X7X_CNTL_PWR_ON)) - != (TSL2X7X_CNTL_ADC_ENBL | TSL2X7X_CNTL_PWR_ON)) { - dev_err(&chip->client->dev, - "%s: failed: ADC not enabled\n", __func__); - return -1; - } - - ret = i2c_smbus_write_byte(chip->client, - (TSL2X7X_CMD_REG | TSL2X7X_CNTRL)); - if (ret < 0) { + if ((ret & (TSL2X7X_CNTL_ADC_ENBL | TSL2X7X_CNTL_PWR_ON)) + != (TSL2X7X_CNTL_ADC_ENBL | TSL2X7X_CNTL_PWR_ON)) { dev_err(&chip->client->dev, - "failed to write ctrl reg: ret=%d\n", ret); - return ret; - } - - reg_val = i2c_smbus_read_byte(chip->client); - if ((reg_val & TSL2X7X_STA_ADC_VALID) != TSL2X7X_STA_ADC_VALID) { + "%s: Device is not powered on and/or ADC is not enabled\n", + __func__); + return -EINVAL; + } else if ((ret & TSL2X7X_STA_ADC_VALID) != TSL2X7X_STA_ADC_VALID) { dev_err(&chip->client->dev, - "%s: failed: STATUS - ADC not valid.\n", __func__); + "%s: The two ADC channels have not completed an integration cycle\n", + __func__); return -ENODATA; } -- cgit v1.2.3 From be78f70ce0d11aa5767a859e1abdc522c1748c44 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 6 Jul 2017 18:56:23 -0400 Subject: staging: iio: tsl2x7x: refactor {read,write}_event_value to allow handling multiple iio_event_infos tsl2x7x_read_thresh() and tsl2x7x_write_thresh() currently assumes that IIO_EV_INFO_VALUE is the only iio_event_info that will be passed in. This patch refactors these two functions so that additional iio_event_infos can be passed in. The functions are renamed from tsl2x7x_{read,write}_thresh() to tsl2x7x_{read,write}_event_value(). This patch also adds the missing return value check to tsl2x7x_invoke_change() since this was previously missing. This patch is in preparation for moving the in_intensity0_thresh_period and in_proximity0_thresh_period sysfs attributes to be created by iio_event_spec. Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/tsl2x7x.c | 157 +++++++++++++++++++++--------------- 1 file changed, 90 insertions(+), 67 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/tsl2x7x.c b/drivers/staging/iio/light/tsl2x7x.c index 57346287da62..d80f5dcb5c37 100644 --- a/drivers/staging/iio/light/tsl2x7x.c +++ b/drivers/staging/iio/light/tsl2x7x.c @@ -1218,78 +1218,101 @@ static int tsl2x7x_write_interrupt_config(struct iio_dev *indio_dev, return 0; } -static int tsl2x7x_write_thresh(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, - enum iio_event_type type, - enum iio_event_direction dir, - enum iio_event_info info, - int val, int val2) +static int tsl2x7x_write_event_value(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int val, int val2) { struct tsl2X7X_chip *chip = iio_priv(indio_dev); + int ret = -EINVAL; - if (chan->type == IIO_INTENSITY) { - switch (dir) { - case IIO_EV_DIR_RISING: - chip->tsl2x7x_settings.als_thresh_high = val; - break; - case IIO_EV_DIR_FALLING: - chip->tsl2x7x_settings.als_thresh_low = val; - break; - default: - return -EINVAL; - } - } else { - switch (dir) { - case IIO_EV_DIR_RISING: - chip->tsl2x7x_settings.prox_thres_high = val; - break; - case IIO_EV_DIR_FALLING: - chip->tsl2x7x_settings.prox_thres_low = val; - break; - default: - return -EINVAL; + switch (info) { + case IIO_EV_INFO_VALUE: + if (chan->type == IIO_INTENSITY) { + switch (dir) { + case IIO_EV_DIR_RISING: + chip->tsl2x7x_settings.als_thresh_high = val; + ret = 0; + break; + case IIO_EV_DIR_FALLING: + chip->tsl2x7x_settings.als_thresh_low = val; + ret = 0; + break; + default: + break; + } + } else { + switch (dir) { + case IIO_EV_DIR_RISING: + chip->tsl2x7x_settings.prox_thres_high = val; + ret = 0; + break; + case IIO_EV_DIR_FALLING: + chip->tsl2x7x_settings.prox_thres_low = val; + ret = 0; + break; + default: + break; + } } + break; + default: + break; } - tsl2x7x_invoke_change(indio_dev); + if (ret < 0) + return ret; - return 0; + return tsl2x7x_invoke_change(indio_dev); } -static int tsl2x7x_read_thresh(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, - enum iio_event_type type, - enum iio_event_direction dir, - enum iio_event_info info, - int *val, int *val2) +static int tsl2x7x_read_event_value(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int *val, int *val2) { struct tsl2X7X_chip *chip = iio_priv(indio_dev); + int ret = -EINVAL; - if (chan->type == IIO_INTENSITY) { - switch (dir) { - case IIO_EV_DIR_RISING: - *val = chip->tsl2x7x_settings.als_thresh_high; - break; - case IIO_EV_DIR_FALLING: - *val = chip->tsl2x7x_settings.als_thresh_low; - break; - default: - return -EINVAL; - } - } else { - switch (dir) { - case IIO_EV_DIR_RISING: - *val = chip->tsl2x7x_settings.prox_thres_high; - break; - case IIO_EV_DIR_FALLING: - *val = chip->tsl2x7x_settings.prox_thres_low; - break; - default: - return -EINVAL; + switch (info) { + case IIO_EV_INFO_VALUE: + if (chan->type == IIO_INTENSITY) { + switch (dir) { + case IIO_EV_DIR_RISING: + *val = chip->tsl2x7x_settings.als_thresh_high; + ret = IIO_VAL_INT; + break; + case IIO_EV_DIR_FALLING: + *val = chip->tsl2x7x_settings.als_thresh_low; + ret = IIO_VAL_INT; + break; + default: + break; + } + } else { + switch (dir) { + case IIO_EV_DIR_RISING: + *val = chip->tsl2x7x_settings.prox_thres_high; + ret = IIO_VAL_INT; + break; + case IIO_EV_DIR_FALLING: + *val = chip->tsl2x7x_settings.prox_thres_low; + ret = IIO_VAL_INT; + break; + default: + break; + } } + break; + default: + break; } - return IIO_VAL_INT; + return ret; } static int tsl2x7x_read_raw(struct iio_dev *indio_dev, @@ -1614,8 +1637,8 @@ static const struct iio_info tsl2X7X_device_info[] = { .driver_module = THIS_MODULE, .read_raw = &tsl2x7x_read_raw, .write_raw = &tsl2x7x_write_raw, - .read_event_value = &tsl2x7x_read_thresh, - .write_event_value = &tsl2x7x_write_thresh, + .read_event_value = &tsl2x7x_read_event_value, + .write_event_value = &tsl2x7x_write_event_value, .read_event_config = &tsl2x7x_read_interrupt_config, .write_event_config = &tsl2x7x_write_interrupt_config, }, @@ -1625,8 +1648,8 @@ static const struct iio_info tsl2X7X_device_info[] = { .driver_module = THIS_MODULE, .read_raw = &tsl2x7x_read_raw, .write_raw = &tsl2x7x_write_raw, - .read_event_value = &tsl2x7x_read_thresh, - .write_event_value = &tsl2x7x_write_thresh, + .read_event_value = &tsl2x7x_read_event_value, + .write_event_value = &tsl2x7x_write_event_value, .read_event_config = &tsl2x7x_read_interrupt_config, .write_event_config = &tsl2x7x_write_interrupt_config, }, @@ -1636,8 +1659,8 @@ static const struct iio_info tsl2X7X_device_info[] = { .driver_module = THIS_MODULE, .read_raw = &tsl2x7x_read_raw, .write_raw = &tsl2x7x_write_raw, - .read_event_value = &tsl2x7x_read_thresh, - .write_event_value = &tsl2x7x_write_thresh, + .read_event_value = &tsl2x7x_read_event_value, + .write_event_value = &tsl2x7x_write_event_value, .read_event_config = &tsl2x7x_read_interrupt_config, .write_event_config = &tsl2x7x_write_interrupt_config, }, @@ -1647,8 +1670,8 @@ static const struct iio_info tsl2X7X_device_info[] = { .driver_module = THIS_MODULE, .read_raw = &tsl2x7x_read_raw, .write_raw = &tsl2x7x_write_raw, - .read_event_value = &tsl2x7x_read_thresh, - .write_event_value = &tsl2x7x_write_thresh, + .read_event_value = &tsl2x7x_read_event_value, + .write_event_value = &tsl2x7x_write_event_value, .read_event_config = &tsl2x7x_read_interrupt_config, .write_event_config = &tsl2x7x_write_interrupt_config, }, @@ -1658,8 +1681,8 @@ static const struct iio_info tsl2X7X_device_info[] = { .driver_module = THIS_MODULE, .read_raw = &tsl2x7x_read_raw, .write_raw = &tsl2x7x_write_raw, - .read_event_value = &tsl2x7x_read_thresh, - .write_event_value = &tsl2x7x_write_thresh, + .read_event_value = &tsl2x7x_read_event_value, + .write_event_value = &tsl2x7x_write_event_value, .read_event_config = &tsl2x7x_read_interrupt_config, .write_event_config = &tsl2x7x_write_interrupt_config, }, -- cgit v1.2.3 From 36a28e4a613bba376959a1b698ae0e1b23d52b59 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 6 Jul 2017 18:56:24 -0400 Subject: staging: iio: tsl2x7x: use usleep_range() instead of mdelay() This driver in some cases can busy wait for upwards of 15ms. Since the kernel at this point is not running in atomic context, and is running in process context, we can safely use usleep_range() instead. This patch changes the two occurrences of mdelay() to usleep_range(). Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/tsl2x7x.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/tsl2x7x.c b/drivers/staging/iio/light/tsl2x7x.c index d80f5dcb5c37..c38bd6404726 100644 --- a/drivers/staging/iio/light/tsl2x7x.c +++ b/drivers/staging/iio/light/tsl2x7x.c @@ -686,7 +686,8 @@ static int tsl2x7x_chip_on(struct iio_dev *indio_dev) } } - mdelay(3); /* Power-on settling time */ + /* Power-on settling time */ + usleep_range(3000, 3500); /* * NOW enable the ADC @@ -853,7 +854,7 @@ static void tsl2x7x_prox_cal(struct iio_dev *indio_dev) /*gather the samples*/ for (i = 0; i < chip->tsl2x7x_settings.prox_max_samples_cal; i++) { - mdelay(15); + usleep_range(15000, 17500); tsl2x7x_get_prox(indio_dev); prox_history[i] = chip->prox_data; dev_info(&chip->client->dev, "2 i=%d prox data= %d\n", -- cgit v1.2.3 From 0503deb820b19ffdefa5b0cc6557b2d2a7fdfc5c Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 6 Jul 2017 18:56:26 -0400 Subject: staging: iio: tsl2x7x: check return value from tsl2x7x_invoke_change() The return value from tsl2x7x_invoke_change() was not checked in most places in the driver. This patch adds the proper error checks. The return values inside tsl2x7x_invoke_change() are now checked by this patch as well. Previously, if there was an error turning the chip back on, then the driver would attempt to turn the chip off and incorrectly return success. The code to power off the chip is removed by this patch since we should fail fast. Signed-off-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/tsl2x7x.c | 55 +++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/tsl2x7x.c b/drivers/staging/iio/light/tsl2x7x.c index c38bd6404726..786e93f16ce9 100644 --- a/drivers/staging/iio/light/tsl2x7x.c +++ b/drivers/staging/iio/light/tsl2x7x.c @@ -771,22 +771,24 @@ int tsl2x7x_invoke_change(struct iio_dev *indio_dev) { struct tsl2X7X_chip *chip = iio_priv(indio_dev); int device_status = chip->tsl2x7x_chip_status; + int ret; mutex_lock(&chip->als_mutex); mutex_lock(&chip->prox_mutex); - if (device_status == TSL2X7X_CHIP_WORKING) - tsl2x7x_chip_off(indio_dev); - - tsl2x7x_chip_on(indio_dev); + if (device_status == TSL2X7X_CHIP_WORKING) { + ret = tsl2x7x_chip_off(indio_dev); + if (ret < 0) + goto unlock; + } - if (device_status != TSL2X7X_CHIP_WORKING) - tsl2x7x_chip_off(indio_dev); + ret = tsl2x7x_chip_on(indio_dev); +unlock: mutex_unlock(&chip->prox_mutex); mutex_unlock(&chip->als_mutex); - return 0; + return ret; } static @@ -965,6 +967,7 @@ static ssize_t in_illuminance0_target_input_store(struct device *dev, struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct tsl2X7X_chip *chip = iio_priv(indio_dev); unsigned long value; + int ret; if (kstrtoul(buf, 0, &value)) return -EINVAL; @@ -972,7 +975,9 @@ static ssize_t in_illuminance0_target_input_store(struct device *dev, if (value) chip->tsl2x7x_settings.als_cal_target = value; - tsl2x7x_invoke_change(indio_dev); + ret = tsl2x7x_invoke_change(indio_dev); + if (ret < 0) + return ret; return len; } @@ -1021,7 +1026,9 @@ static ssize_t in_intensity0_thresh_period_store(struct device *dev, dev_info(&chip->client->dev, "%s: als persistence = %d", __func__, filter_delay); - tsl2x7x_invoke_change(indio_dev); + ret = tsl2x7x_invoke_change(indio_dev); + if (ret < 0) + return ret; return IIO_VAL_INT_PLUS_MICRO; } @@ -1069,7 +1076,10 @@ static ssize_t in_proximity0_thresh_period_store(struct device *dev, dev_info(&chip->client->dev, "%s: prox persistence = %d", __func__, filter_delay); - tsl2x7x_invoke_change(indio_dev); + ret = tsl2x7x_invoke_change(indio_dev); + if (ret < 0) + return ret; + return IIO_VAL_INT_PLUS_MICRO; } @@ -1080,6 +1090,7 @@ static ssize_t in_illuminance0_calibrate_store(struct device *dev, { struct iio_dev *indio_dev = dev_to_iio_dev(dev); bool value; + int ret; if (strtobool(buf, &value)) return -EINVAL; @@ -1087,7 +1098,9 @@ static ssize_t in_illuminance0_calibrate_store(struct device *dev, if (value) tsl2x7x_als_calibrate(indio_dev); - tsl2x7x_invoke_change(indio_dev); + ret = tsl2x7x_invoke_change(indio_dev); + if (ret < 0) + return ret; return len; } @@ -1127,7 +1140,7 @@ static ssize_t in_illuminance0_lux_table_store(struct device *dev, struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct tsl2X7X_chip *chip = iio_priv(indio_dev); int value[ARRAY_SIZE(chip->tsl2x7x_device_lux) * 3 + 1]; - int n; + int n, ret; get_options(buf, ARRAY_SIZE(value), value); @@ -1155,7 +1168,9 @@ static ssize_t in_illuminance0_lux_table_store(struct device *dev, memset(chip->tsl2x7x_device_lux, 0, sizeof(chip->tsl2x7x_device_lux)); memcpy(chip->tsl2x7x_device_lux, &value[1], (value[0] * 4)); - tsl2x7x_invoke_change(indio_dev); + ret = tsl2x7x_invoke_change(indio_dev); + if (ret < 0) + return ret; return len; } @@ -1166,6 +1181,7 @@ static ssize_t in_proximity0_calibrate_store(struct device *dev, { struct iio_dev *indio_dev = dev_to_iio_dev(dev); bool value; + int ret; if (strtobool(buf, &value)) return -EINVAL; @@ -1173,7 +1189,9 @@ static ssize_t in_proximity0_calibrate_store(struct device *dev, if (value) tsl2x7x_prox_cal(indio_dev); - tsl2x7x_invoke_change(indio_dev); + ret = tsl2x7x_invoke_change(indio_dev); + if (ret < 0) + return ret; return len; } @@ -1201,6 +1219,7 @@ static int tsl2x7x_write_interrupt_config(struct iio_dev *indio_dev, int val) { struct tsl2X7X_chip *chip = iio_priv(indio_dev); + int ret; if (chan->type == IIO_INTENSITY) { if (val) @@ -1214,7 +1233,9 @@ static int tsl2x7x_write_interrupt_config(struct iio_dev *indio_dev, chip->tsl2x7x_settings.interrupts_en &= 0x10; } - tsl2x7x_invoke_change(indio_dev); + ret = tsl2x7x_invoke_change(indio_dev); + if (ret < 0) + return ret; return 0; } @@ -1450,9 +1471,7 @@ static int tsl2x7x_write_raw(struct iio_dev *indio_dev, return -EINVAL; } - tsl2x7x_invoke_change(indio_dev); - - return 0; + return tsl2x7x_invoke_change(indio_dev); } static DEVICE_ATTR_RO(in_proximity0_calibscale_available); -- cgit v1.2.3 From 2f9aeeed92a2911e8f1ec89cf7f5c16b8d054fe5 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 7 Jul 2017 01:46:30 -0500 Subject: iio: adc: meson-saradc: add NULL check on of_match_device() return value Check return value from call to of_match_device() in order to prevent a NULL pointer dereference. In case of NULL print error message and return -ENODEV Signed-off-by: Gustavo A. R. Silva Acked-by: Martin Blumenstingl Signed-off-by: Jonathan Cameron --- drivers/iio/adc/meson_saradc.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c index 83da50ed73ab..c4e904bbf168 100644 --- a/drivers/iio/adc/meson_saradc.c +++ b/drivers/iio/adc/meson_saradc.c @@ -915,6 +915,11 @@ static int meson_sar_adc_probe(struct platform_device *pdev) init_completion(&priv->done); match = of_match_device(meson_sar_adc_of_match, &pdev->dev); + if (!match) { + dev_err(&pdev->dev, "failed to match device\n"); + return -ENODEV; + } + priv->data = match->data; indio_dev->name = priv->data->name; -- cgit v1.2.3 From 36d311bc1663f004529d2f870c1fc939d00c49f0 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 7 Jul 2017 01:51:31 -0500 Subject: iio: adc: rockchip_saradc: add NULL check on of_match_device() return value Check return value from call to of_match_device() in order to prevent a NULL pointer dereference. In case of NULL print error message and return -ENODEV Signed-off-by: Gustavo A. R. Silva Signed-off-by: Jonathan Cameron --- drivers/iio/adc/rockchip_saradc.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c index ae6d3324f518..2bf2ed15a870 100644 --- a/drivers/iio/adc/rockchip_saradc.c +++ b/drivers/iio/adc/rockchip_saradc.c @@ -224,6 +224,11 @@ static int rockchip_saradc_probe(struct platform_device *pdev) info = iio_priv(indio_dev); match = of_match_device(rockchip_saradc_match, &pdev->dev); + if (!match) { + dev_err(&pdev->dev, "failed to match device\n"); + return -ENODEV; + } + info->data = match->data; mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- cgit v1.2.3 From 72e36017eee0ffcbcf1630074f122916ed104269 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 7 Jul 2017 16:55:19 +0100 Subject: iio: accel: make array init_data static to reduce code size Making the const array init_data static rather having it on the stack saves us a couple hundreds of bytes: Before: text data bss dec hex filename 3175 848 0 4023 fb7 drivers/iio/accel/da311.o After: text data bss dec hex filename 2860 936 0 3796 ed4 drivers/iio/accel/da311.o Signed-off-by: Colin Ian King Signed-off-by: Jonathan Cameron --- drivers/iio/accel/da311.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/accel/da311.c b/drivers/iio/accel/da311.c index 537cfa8b6edf..c0c1620d2a2f 100644 --- a/drivers/iio/accel/da311.c +++ b/drivers/iio/accel/da311.c @@ -139,7 +139,7 @@ static int da311_register_mask_write(struct i2c_client *client, u16 addr, /* Init sequence taken from the android driver */ static int da311_reset(struct i2c_client *client) { - const struct { + static const struct { u16 addr; u8 mask; u8 data; -- cgit v1.2.3 From 2df331cfe38d8aac4e787110279e00d12d0b2b25 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 7 Jul 2017 17:08:35 +0100 Subject: iio:adc:at91-sama5d2: make array startup_lookup static to reduce code size Making the const array startup_lookup static rather having it on the stack saves 69 bytes. Add in missing int specifier to clean up a checkpatch warning. Before: text data bss dec hex filename 10297 2800 128 13225 33a9 drivers/iio/adc/at91-sama5d2_adc.o After: text data bss dec hex filename 10140 2888 128 13156 3364 drivers/iio/adc/at91-sama5d2_adc.o Signed-off-by: Colin Ian King Signed-off-by: Jonathan Cameron --- drivers/iio/adc/at91-sama5d2_adc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c index 57e1eb23c45d..bc5b38e3a147 100644 --- a/drivers/iio/adc/at91-sama5d2_adc.c +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -411,7 +411,7 @@ static int at91_adc_buffer_init(struct iio_dev *indio) static unsigned at91_adc_startup_time(unsigned startup_time_min, unsigned adc_clk_khz) { - const unsigned startup_lookup[] = { + static const unsigned int startup_lookup[] = { 0, 8, 16, 24, 64, 80, 96, 112, 512, 576, 640, 704, -- cgit v1.2.3 From 6011208d8ad794e9c30e9e4c95669c977b1e274b Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 8 Jul 2017 13:00:16 +0200 Subject: iio: accel: st_accel_i2c: fix i2c_device_id table Add H3LIS331DL, LIS331DL and LIS3LV02DL entries in st_accel_id_table Fixes: 1e52fefc9b0c (iio: accel: Add support for the h3lis331dl accel) Fixes: bbf5f037fad4 (iio: st_accel: support the LIS331DL sensor) Fixes: 3acddf74f807 (iio: st-sensors: add support for lis3lv02d accel) Signed-off-by: Lorenzo Bianconi Signed-off-by: Jonathan Cameron --- drivers/iio/accel/st_accel.h | 3 +++ drivers/iio/accel/st_accel_i2c.c | 3 +++ 2 files changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/iio/accel/st_accel.h b/drivers/iio/accel/st_accel.h index 3ad44ce7ae82..fe3864f0f146 100644 --- a/drivers/iio/accel/st_accel.h +++ b/drivers/iio/accel/st_accel.h @@ -29,6 +29,9 @@ enum st_accel_type { LIS2DH12, LIS3L02DQ, LNG2DM, + H3LIS331DL, + LIS331DL, + LIS3LV02DL, ST_ACCEL_MAX, }; diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c index ac67826135be..1b22c5714e89 100644 --- a/drivers/iio/accel/st_accel_i2c.c +++ b/drivers/iio/accel/st_accel_i2c.c @@ -126,6 +126,9 @@ static const struct i2c_device_id st_accel_id_table[] = { { LIS2DH12_ACCEL_DEV_NAME, LIS2DH12 }, { LIS3L02DQ_ACCEL_DEV_NAME, LIS3L02DQ }, { LNG2DM_ACCEL_DEV_NAME, LNG2DM }, + { H3LIS331DL_DRIVER_NAME, H3LIS331DL }, + { LIS331DL_ACCEL_DEV_NAME, LIS331DL }, + { LIS3LV02DL_ACCEL_DEV_NAME, LIS3LV02DL }, {}, }; MODULE_DEVICE_TABLE(i2c, st_accel_id_table); -- cgit v1.2.3 From 2b96d66c205b23b55324118ff31905d7152cb1cc Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 8 Jul 2017 13:00:17 +0200 Subject: iio: accel: st_accel_spi: add support to H3LIS331DL, LIS331DL, LIS3LV02DL Signed-off-by: Lorenzo Bianconi Signed-off-by: Jonathan Cameron --- drivers/iio/accel/st_accel_spi.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/iio/accel/st_accel_spi.c b/drivers/iio/accel/st_accel_spi.c index 6b2eafa45cbb..7a2a0384b42d 100644 --- a/drivers/iio/accel/st_accel_spi.c +++ b/drivers/iio/accel/st_accel_spi.c @@ -30,6 +30,10 @@ static const struct of_device_id st_accel_of_match[] = { .compatible = "st,lis302dl-spi", .data = LIS3LV02DL_ACCEL_DEV_NAME, }, + { + .compatible = "st,lis3lv02dl-accel", + .data = LIS3LV02DL_ACCEL_DEV_NAME, + }, { .compatible = "st,lis3dh-accel", .data = LIS3DH_ACCEL_DEV_NAME, @@ -70,6 +74,14 @@ static const struct of_device_id st_accel_of_match[] = { .compatible = "st,lng2dm-accel", .data = LNG2DM_ACCEL_DEV_NAME, }, + { + .compatible = "st,h3lis331dl-accel", + .data = H3LIS331DL_DRIVER_NAME, + }, + { + .compatible = "st,lis331dl-accel", + .data = LIS331DL_ACCEL_DEV_NAME, + }, {} }; MODULE_DEVICE_TABLE(of, st_accel_of_match); @@ -118,6 +130,9 @@ static const struct spi_device_id st_accel_id_table[] = { { LIS2DH12_ACCEL_DEV_NAME }, { LIS3L02DQ_ACCEL_DEV_NAME }, { LNG2DM_ACCEL_DEV_NAME }, + { H3LIS331DL_DRIVER_NAME }, + { LIS331DL_ACCEL_DEV_NAME }, + { LIS3LV02DL_ACCEL_DEV_NAME }, {}, }; MODULE_DEVICE_TABLE(spi, st_accel_id_table); -- cgit v1.2.3 From b30f1593678efe786234e12a86e321391ff9407c Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 8 Jul 2017 13:00:18 +0200 Subject: iio: accel: st_accel: rename H3LIS331DL_DRIVER_NAME in H3LIS331DL_ACCEL_DEV_NAME In order to use the standard name convention rename H3LIS331DL_DRIVER_NAME macro in H3LIS331DL_ACCEL_DEV_NAME Signed-off-by: Lorenzo Bianconi Signed-off-by: Jonathan Cameron --- drivers/iio/accel/st_accel.h | 2 +- drivers/iio/accel/st_accel_core.c | 2 +- drivers/iio/accel/st_accel_i2c.c | 4 ++-- drivers/iio/accel/st_accel_spi.c | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/accel/st_accel.h b/drivers/iio/accel/st_accel.h index fe3864f0f146..0fe521609a3a 100644 --- a/drivers/iio/accel/st_accel.h +++ b/drivers/iio/accel/st_accel.h @@ -35,7 +35,7 @@ enum st_accel_type { ST_ACCEL_MAX, }; -#define H3LIS331DL_DRIVER_NAME "h3lis331dl_accel" +#define H3LIS331DL_ACCEL_DEV_NAME "h3lis331dl_accel" #define LIS3LV02DL_ACCEL_DEV_NAME "lis3lv02dl_accel" #define LSM303DLHC_ACCEL_DEV_NAME "lsm303dlhc_accel" #define LIS3DH_ACCEL_DEV_NAME "lis3dh" diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c index 07d1489cd457..c7709494bed3 100644 --- a/drivers/iio/accel/st_accel_core.c +++ b/drivers/iio/accel/st_accel_core.c @@ -444,7 +444,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .wai = 0x32, .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, .sensors_supported = { - [0] = H3LIS331DL_DRIVER_NAME, + [0] = H3LIS331DL_ACCEL_DEV_NAME, }, .ch = (struct iio_chan_spec *)st_accel_12bit_channels, .odr = { diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c index 1b22c5714e89..18cafb9f2468 100644 --- a/drivers/iio/accel/st_accel_i2c.c +++ b/drivers/iio/accel/st_accel_i2c.c @@ -84,7 +84,7 @@ static const struct of_device_id st_accel_of_match[] = { }, { .compatible = "st,h3lis331dl-accel", - .data = H3LIS331DL_DRIVER_NAME, + .data = H3LIS331DL_ACCEL_DEV_NAME, }, { .compatible = "st,lis3l02dq", @@ -126,7 +126,7 @@ static const struct i2c_device_id st_accel_id_table[] = { { LIS2DH12_ACCEL_DEV_NAME, LIS2DH12 }, { LIS3L02DQ_ACCEL_DEV_NAME, LIS3L02DQ }, { LNG2DM_ACCEL_DEV_NAME, LNG2DM }, - { H3LIS331DL_DRIVER_NAME, H3LIS331DL }, + { H3LIS331DL_ACCEL_DEV_NAME, H3LIS331DL }, { LIS331DL_ACCEL_DEV_NAME, LIS331DL }, { LIS3LV02DL_ACCEL_DEV_NAME, LIS3LV02DL }, {}, diff --git a/drivers/iio/accel/st_accel_spi.c b/drivers/iio/accel/st_accel_spi.c index 7a2a0384b42d..915fa49085f7 100644 --- a/drivers/iio/accel/st_accel_spi.c +++ b/drivers/iio/accel/st_accel_spi.c @@ -76,7 +76,7 @@ static const struct of_device_id st_accel_of_match[] = { }, { .compatible = "st,h3lis331dl-accel", - .data = H3LIS331DL_DRIVER_NAME, + .data = H3LIS331DL_ACCEL_DEV_NAME, }, { .compatible = "st,lis331dl-accel", @@ -130,7 +130,7 @@ static const struct spi_device_id st_accel_id_table[] = { { LIS2DH12_ACCEL_DEV_NAME }, { LIS3L02DQ_ACCEL_DEV_NAME }, { LNG2DM_ACCEL_DEV_NAME }, - { H3LIS331DL_DRIVER_NAME }, + { H3LIS331DL_ACCEL_DEV_NAME }, { LIS331DL_ACCEL_DEV_NAME }, { LIS3LV02DL_ACCEL_DEV_NAME }, {}, -- cgit v1.2.3 From 3091141d7803608950adc001518ffb544a4e3308 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 8 Jul 2017 15:11:57 +0200 Subject: iio: adc: axp288: Fix the GPADC pin reading often wrongly returning 0 I noticed in its DSDT that one of my tablets actually is using the GPADC pin for temperature monitoring. The whole axp288_adc_set_ts() function is a bit weird, in the past it was removed because it seems to make no sense, then this was reverted because of regressions. So I decided to test the special GPADC pin handling on this tablet. Conclusion: not only is axp288_adc_set_ts() necessary, we need to sleep a bit after making the AXP288_ADC_TS_PIN_CTRL changes before sampling the GPADC, otherwise it will often (about 80% of the time) read 0 instead of its actual value. It seems that there is only 1 bias current source and to be able to use it for the GPIO0 pin in GPADC mode it must be temporarily turned off for the TS pin, but the datasheet does not mention this. This commit adds a sleep after disabling the TS pin bias current, fixing the GPADC more often then not wrongly returning 0. Signed-off-by: Hans de Goede Signed-off-by: Jonathan Cameron --- drivers/iio/adc/axp288_adc.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/adc/axp288_adc.c b/drivers/iio/adc/axp288_adc.c index 7fd24949c0c1..462a99c13e7a 100644 --- a/drivers/iio/adc/axp288_adc.c +++ b/drivers/iio/adc/axp288_adc.c @@ -126,11 +126,21 @@ static int axp288_adc_read_channel(int *val, unsigned long address, static int axp288_adc_set_ts(struct regmap *regmap, unsigned int mode, unsigned long address) { + int ret; + /* channels other than GPADC do not need to switch TS pin */ if (address != AXP288_GP_ADC_H) return 0; - return regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, mode); + ret = regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, mode); + if (ret) + return ret; + + /* When switching to the GPADC pin give things some time to settle */ + if (mode == AXP288_ADC_TS_PIN_GPADC) + usleep_range(6000, 10000); + + return 0; } static int axp288_adc_read_raw(struct iio_dev *indio_dev, -- cgit v1.2.3 From 77d1f615c78a73a04254fa2bff07ee9fa27145d9 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Mon, 26 Jun 2017 10:33:49 +0200 Subject: drm/i915: Make DP-MST connector info work Commit 9a148a96fc3a ("drm/i915/debugfs: add dp mst info") adds support for DP-MST to intel_connector_info, but forgot to remove the early return for DP-MST. Remove it, and print out MST connectors directly. Fixes: 9a148a96fc3a ("drm/i915/debugfs: add dp mst info") Cc: # v4.11+ Cc: Dhinakaran Pandiyan Cc: Libin Yang Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/20170626083349.24389-1-maarten.lankhorst@linux.intel.com Reviewed-by: Dhinakaran Pandiyan --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index ca2e34b1c798..620c9218d1c1 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -3108,7 +3108,7 @@ static void intel_connector_info(struct seq_file *m, connector->display_info.cea_rev); } - if (!intel_encoder || intel_encoder->type == INTEL_OUTPUT_DP_MST) + if (!intel_encoder) return; switch (connector->connector_type) { -- cgit v1.2.3 From 4ebb9d7f901027e1740f69829cf10af0193e8e17 Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Mon, 10 Jul 2017 16:33:39 +0200 Subject: regulator: cpcap: Fix standby mode The original patch from Tony uses standby mode bit inverted, which is not correct. This fixes all instances in the driver code for get & set mode. This did not yet make problems, since mode has not been changed by any mainline driver so far. Fixes: 0ad4c07edd41 ("regulator: cpcap: Add basic regulator support") Acked-by: Tony Lindgren Signed-off-by: Sebastian Reichel Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- drivers/regulator/cpcap-regulator.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/regulator/cpcap-regulator.c b/drivers/regulator/cpcap-regulator.c index cc98aceed1c1..ce1cab320f6f 100644 --- a/drivers/regulator/cpcap-regulator.c +++ b/drivers/regulator/cpcap-regulator.c @@ -77,6 +77,8 @@ #define CPCAP_BIT_VAUDIO_MODE0 BIT(1) #define CPCAP_BIT_V_AUDIO_EN BIT(0) +#define CPCAP_BIT_AUDIO_NORMAL_MODE 0x00 + /* * Off mode configuration bit. Used currently only by SW5 on omap4. There's * the following comment in Motorola Linux kernel tree for it: @@ -217,7 +219,7 @@ static unsigned int cpcap_regulator_get_mode(struct regulator_dev *rdev) regmap_read(rdev->regmap, rdev->desc->enable_reg, &value); - if (!(value & CPCAP_BIT_AUDIO_LOW_PWR)) + if (value & CPCAP_BIT_AUDIO_LOW_PWR) return REGULATOR_MODE_STANDBY; return REGULATOR_MODE_NORMAL; @@ -230,10 +232,10 @@ static int cpcap_regulator_set_mode(struct regulator_dev *rdev, switch (mode) { case REGULATOR_MODE_NORMAL: - value = CPCAP_BIT_AUDIO_LOW_PWR; + value = CPCAP_BIT_AUDIO_NORMAL_MODE; break; case REGULATOR_MODE_STANDBY: - value = 0; + value = CPCAP_BIT_AUDIO_LOW_PWR; break; default: return -EINVAL; -- cgit v1.2.3 From 6d6a89708188823d676c9b84e7e2534b822465e3 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Thu, 6 Jul 2017 13:45:08 -0700 Subject: drm/i915/cnl: Add max allowed Cannonlake DC. This is a follow-up after enabling DC states with commit: "drm/i915/DMC/CNL: Load DMC on CNL". Cc: Anusha Srivatsa Cc: Imre Deak Signed-off-by: Rodrigo Vivi Reviewed-by: Imre Deak Link: http://patchwork.freedesktop.org/patch/msgid/1499373908-26761-1-git-send-email-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/intel_runtime_pm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 5eb9c5ec9c85..f630d632a976 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -2492,7 +2492,7 @@ static uint32_t get_allowed_dc_mask(const struct drm_i915_private *dev_priv, int requested_dc; int max_dc; - if (IS_GEN9_BC(dev_priv)) { + if (IS_GEN9_BC(dev_priv) || IS_CANNONLAKE(dev_priv)) { max_dc = 2; mask = 0; } else if (IS_GEN9_LP(dev_priv)) { -- cgit v1.2.3 From 5b4e17c9c45a93bae226fdaa2985c8b521f45bd4 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 10 Jul 2017 18:46:54 +0100 Subject: iio: adc: at91: make array startup_lookup static Don't populate array startup_lookup on the stack but instead make it static. Makes the object code smaller. Before: text data bss dec hex filename 21754 5440 128 27322 6aba drivers/iio/adc/at91_adc.o After: text data bss dec hex filename 21613 5496 128 27237 6a65 drivers/iio/adc/at91_adc.o Signed-off-by: Colin Ian King Signed-off-by: Jonathan Cameron --- drivers/iio/adc/at91_adc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 34b928cefeed..15109728cae7 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -799,7 +799,7 @@ static u32 calc_startup_ticks_9x5(u32 startup_time, u32 adc_clk_khz) * For sama5d3x and at91sam9x5, the formula changes to: * Startup Time = / ADC Clock */ - const int startup_lookup[] = { + static const int startup_lookup[] = { 0, 8, 16, 24, 64, 80, 96, 112, 512, 576, 640, 704, -- cgit v1.2.3 From 371c2279aa705c32730e738b3f173fb2e62b33e7 Mon Sep 17 00:00:00 2001 From: Alexandru Moise <00moses.alexander00@gmail.com> Date: Sat, 8 Jul 2017 23:43:52 +0200 Subject: drm: inhibit drm drivers register to uninitialized drm core If the DRM core fails to init for whatever reason, ensure that no driver ever calls drm_dev_register(). This is best done at drm_dev_init() as it covers drivers that call drm_dev_alloc() as well as drivers that prefer to embed struct drm_device into their own device struct and call drm_dev_init() themselves. In my case I had so many dynamic device majors used that the major number for DRM (226) was stolen, causing DRM core init to fail after failing to register a chrdev, and ultimately calling debugfs_remove() on drm_debugfs_root in drm_core_exit(). After drm core failed to init, VGEM was still calling drm_dev_register(), ultimately leading to drm_debugfs_init(), with drm_debugfs_root passed as the root for the new debugfs dir at debugfs_create_dir(). This led to a kernel panic once we were either derefencing root->d_inode while it was NULL or calling root->d_inode->i_op->lookup() while it was NULL in debugfs at inode_lock() or lookup_*(). Signed-off-by: Alexandru Moise <00moses.alexander00@gmail.com> Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170708214352.GA27205@gmail.com --- drivers/gpu/drm/drm_drv.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 37b8ad3e30d8..2ed2d919beae 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -63,6 +63,15 @@ module_param_named(debug, drm_debug, int, 0600); static DEFINE_SPINLOCK(drm_minor_lock); static struct idr drm_minors_idr; +/* + * If the drm core fails to init for whatever reason, + * we should prevent any drivers from registering with it. + * It's best to check this at drm_dev_init(), as some drivers + * prefer to embed struct drm_device into their own device + * structure and call drm_dev_init() themselves. + */ +static bool drm_core_init_complete = false; + static struct dentry *drm_debugfs_root; #define DRM_PRINTK_FMT "[" DRM_NAME ":%s]%s %pV" @@ -484,6 +493,11 @@ int drm_dev_init(struct drm_device *dev, { int ret; + if (!drm_core_init_complete) { + DRM_ERROR("DRM core is not initialized\n"); + return -ENODEV; + } + kref_init(&dev->ref); dev->dev = parent; dev->driver = driver; @@ -966,6 +980,8 @@ static int __init drm_core_init(void) if (ret < 0) goto error; + drm_core_init_complete = true; + DRM_DEBUG("Initialized\n"); return 0; -- cgit v1.2.3 From 61f3e7704897188d85e5698980316f2929a7c753 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Mon, 10 Jul 2017 13:58:52 -0700 Subject: drm/i915/cnl: Add missing type case. Paulo had noticed that inside cnl_ddi_vswing_program the case was handling voltage but with no indication of type where a missing type could also take us to that path. So my first attempt was to add a message to let clear who trigger that path. However DK had a better idea that is to handle the missed type sooner before it might take to that path. So this v2 here uses his approach. v2: Handle missed type sooner. Cc: Dhinakaran Pandiyan Cc: Paulo Zanoni Signed-off-by: Rodrigo Vivi Reviewed-by: Dhinakaran Pandiyan Link: http://patchwork.freedesktop.org/patch/msgid/20170710205852.28352-1-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/intel_ddi.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 241decf2a7d9..efb13582dc73 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1979,9 +1979,12 @@ static void cnl_ddi_vswing_sequence(struct intel_encoder *encoder, u32 level) if ((intel_dp) && (type == INTEL_OUTPUT_EDP || type == INTEL_OUTPUT_DP)) { width = intel_dp->lane_count; rate = intel_dp->link_rate; - } else { + } else if (type == INTEL_OUTPUT_HDMI) { width = 4; /* Rate is always < than 6GHz for HDMI */ + } else { + MISSING_CASE(type); + return; } /* -- cgit v1.2.3 From 672647afabf5bafd3d855724ee5829e2a9cbd65b Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Tue, 11 Jul 2017 15:46:38 +0530 Subject: bus: omap-ocp2scp: Fix error handling in omap_ocp2scp_probe The error handling code in omap_ocp2scp_probe fails to invoke pm_runtime_disable and fails to initialize return value in certain cases. Fix it here. Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Sekhar Nori Signed-off-by: Tony Lindgren --- drivers/bus/omap-ocp2scp.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/bus/omap-ocp2scp.c b/drivers/bus/omap-ocp2scp.c index bf500e0e7362..77791f3dcfc6 100644 --- a/drivers/bus/omap-ocp2scp.c +++ b/drivers/bus/omap-ocp2scp.c @@ -70,8 +70,10 @@ static int omap_ocp2scp_probe(struct platform_device *pdev) if (!of_device_is_compatible(np, "ti,am437x-ocp2scp")) { res = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(regs)) - goto err0; + if (IS_ERR(regs)) { + ret = PTR_ERR(regs); + goto err1; + } pm_runtime_get_sync(&pdev->dev); reg = readl_relaxed(regs + OCP2SCP_TIMING); @@ -83,6 +85,9 @@ static int omap_ocp2scp_probe(struct platform_device *pdev) return 0; +err1: + pm_runtime_disable(&pdev->dev); + err0: device_for_each_child(&pdev->dev, NULL, ocp2scp_remove_devices); -- cgit v1.2.3 From 547a915d379be9f41c73357892b38a1b326d2a1f Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Mon, 10 Jul 2017 20:14:59 -0700 Subject: Input: serio - constify attribute_group structures attribute_groups are not supposed to change at runtime. All functions working with attribute_groups provided by work with const attribute_group. So mark the non-const structs as const. File size before: text data bss dec hex filename 6862 1008 4 7874 1ec2 drivers/input/serio/serio.o File size After adding 'const': text data bss dec hex filename 6990 880 4 7874 1ec2 drivers/input/serio/serio.o Signed-off-by: Arvind Yadav Signed-off-by: Dmitry Torokhov --- drivers/input/serio/serio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 30d6230d48f7..24a90c8db5b3 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -469,7 +469,7 @@ static struct attribute *serio_device_id_attrs[] = { NULL }; -static struct attribute_group serio_id_attr_group = { +static const struct attribute_group serio_id_attr_group = { .name = "id", .attrs = serio_device_id_attrs, }; @@ -489,7 +489,7 @@ static struct attribute *serio_device_attrs[] = { NULL }; -static struct attribute_group serio_device_attr_group = { +static const struct attribute_group serio_device_attr_group = { .attrs = serio_device_attrs, }; -- cgit v1.2.3 From c4043b57c867a548f888530351505cc1f86dbfb3 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Mon, 10 Jul 2017 20:15:30 -0700 Subject: Input: aiptek - constify attribute_group structures attribute_groups are not supposed to change at runtime. All functions working with attribute_groups provided by work with const attribute_group. So mark the non-const structs as const. File size before: text data bss dec hex filename 9941 1560 0 11501 2ced drivers/input/tablet/aiptek.o File size After adding 'const': text data bss dec hex filename 10005 1496 0 11501 2ced drivers/input/tablet/aiptek.o Signed-off-by: Arvind Yadav Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/aiptek.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c index d67547bded3e..0b55e1f375b3 100644 --- a/drivers/input/tablet/aiptek.c +++ b/drivers/input/tablet/aiptek.c @@ -1676,7 +1676,7 @@ static struct attribute *aiptek_attributes[] = { NULL }; -static struct attribute_group aiptek_attribute_group = { +static const struct attribute_group aiptek_attribute_group = { .attrs = aiptek_attributes, }; -- cgit v1.2.3 From 5e895b74169a00d865a80536a424ddd918f1c6c0 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Mon, 10 Jul 2017 20:15:49 -0700 Subject: Input: constify attribute_group structures attribute_groups are not supposed to change at runtime. All functions working with attribute_groups provided by work with const attribute_group. So mark the non-const structs as const. File size before: text data bss dec hex filename 17755 1312 16 19083 4a8b drivers/input/input.o File size After adding 'const': text data bss dec hex filename 17947 1120 16 19083 4a8b drivers/input/input.o Signed-off-by: Arvind Yadav Signed-off-by: Dmitry Torokhov --- drivers/input/input.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/input/input.c b/drivers/input/input.c index 7e6842bd525c..d268fdc23c64 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -1398,7 +1398,7 @@ static struct attribute *input_dev_attrs[] = { NULL }; -static struct attribute_group input_dev_attr_group = { +static const struct attribute_group input_dev_attr_group = { .attrs = input_dev_attrs, }; @@ -1425,7 +1425,7 @@ static struct attribute *input_dev_id_attrs[] = { NULL }; -static struct attribute_group input_dev_id_attr_group = { +static const struct attribute_group input_dev_id_attr_group = { .name = "id", .attrs = input_dev_id_attrs, }; @@ -1495,7 +1495,7 @@ static struct attribute *input_dev_caps_attrs[] = { NULL }; -static struct attribute_group input_dev_caps_attr_group = { +static const struct attribute_group input_dev_caps_attr_group = { .name = "capabilities", .attrs = input_dev_caps_attrs, }; -- cgit v1.2.3 From fab2f5e0f3b79d9d2de2c375f9a5ad9a5ced826e Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Mon, 10 Jul 2017 20:16:07 -0700 Subject: Input: synaptics-rmi4 - constify attribute_group structures in F34 attribute_groups are not supposed to change at runtime. All functions working with attribute_groups provided by work with const attribute_group. So mark the non-const structs as const. File size before: text data bss dec hex filename 5287 448 0 5735 1667 drivers/input/rmi4/rmi_f34.o File size After adding 'const': text data bss dec hex filename 5339 384 0 5723 165b drivers/input/rmi4/rmi_f34.o Signed-off-by: Arvind Yadav Signed-off-by: Dmitry Torokhov --- drivers/input/rmi4/rmi_f34.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/rmi4/rmi_f34.c b/drivers/input/rmi4/rmi_f34.c index b8ee78e0d61f..4cfe9703a8e7 100644 --- a/drivers/input/rmi4/rmi_f34.c +++ b/drivers/input/rmi4/rmi_f34.c @@ -516,7 +516,7 @@ static struct attribute *rmi_firmware_attrs[] = { NULL }; -static struct attribute_group rmi_firmware_attr_group = { +static const struct attribute_group rmi_firmware_attr_group = { .attrs = rmi_firmware_attrs, }; -- cgit v1.2.3 From 0d4b8e36b9861d678c454d6bb4c4849827071ebd Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Mon, 10 Jul 2017 20:17:05 -0700 Subject: Input: synaptics-rmi4 - constify attribute_group structures in F01 attribute_groups are not supposed to change at runtime. All functions working with attribute_groups provided by work with const attribute_group. So mark the non-const structs as const. File size before: text data bss dec hex filename 4777 480 0 5257 1489 drivers/input/rmi4/rmi_f01.o File size After adding 'const': text data bss dec hex filename 4817 416 0 5233 1471 drivers/input/rmi4/rmi_f01.o Signed-off-by: Arvind Yadav Signed-off-by: Dmitry Torokhov --- drivers/input/rmi4/rmi_f01.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/rmi4/rmi_f01.c b/drivers/input/rmi4/rmi_f01.c index 7f7e9176f7ea..aa1aabfdbe7c 100644 --- a/drivers/input/rmi4/rmi_f01.c +++ b/drivers/input/rmi4/rmi_f01.c @@ -334,7 +334,7 @@ static struct attribute *rmi_f01_attrs[] = { NULL }; -static struct attribute_group rmi_f01_attr_group = { +static const struct attribute_group rmi_f01_attr_group = { .attrs = rmi_f01_attrs, }; -- cgit v1.2.3 From b06ae14803a264a61fa4c9fbb6a2304c78851bac Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Mon, 10 Jul 2017 20:18:03 -0700 Subject: Input: ims-pcu - constify attribute_group structures attribute_groups are not supposed to change at runtime. All functions working with attribute_groups provided by work with const attribute_group. So mark the non-const structs as const. File size before: text data bss dec hex filename 13547 1600 0 15147 3b2b drivers/input/misc/ims-pcu.o File size After adding 'const': text data bss dec hex filename 13675 1472 0 15147 3b2b drivers/input/misc/ims-pcu.o Signed-off-by: Arvind Yadav Signed-off-by: Dmitry Torokhov --- drivers/input/misc/ims-pcu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c index f4e8fbec6a94..6bf82ea8c918 100644 --- a/drivers/input/misc/ims-pcu.c +++ b/drivers/input/misc/ims-pcu.c @@ -1261,7 +1261,7 @@ static umode_t ims_pcu_is_attr_visible(struct kobject *kobj, return mode; } -static struct attribute_group ims_pcu_attr_group = { +static const struct attribute_group ims_pcu_attr_group = { .is_visible = ims_pcu_is_attr_visible, .attrs = ims_pcu_attrs, }; @@ -1480,7 +1480,7 @@ static struct attribute *ims_pcu_ofn_attrs[] = { NULL }; -static struct attribute_group ims_pcu_ofn_attr_group = { +static const struct attribute_group ims_pcu_ofn_attr_group = { .name = "ofn", .attrs = ims_pcu_ofn_attrs, }; -- cgit v1.2.3 From aa3350718a2662a87742b923b80c5925ac9b5c43 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Mon, 10 Jul 2017 20:21:06 -0700 Subject: Input: yealink - constify attribute_group structures attribute_groups are not supposed to change at runtime. All functions working with attribute_groups provided by work with const attribute_group. So mark the non-const structs as const. File size before: text data bss dec hex filename 6039 944 0 6983 1b47 drivers/input/misc/yealink.o File size After adding 'const': text data bss dec hex filename 6103 880 0 6983 1b47 drivers/input/misc/yealink.o Signed-off-by: Arvind Yadav Signed-off-by: Henk Vergonet Signed-off-by: Dmitry Torokhov --- drivers/input/misc/yealink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/misc/yealink.c b/drivers/input/misc/yealink.c index 6e7ff9561d92..a1e0ff59d2f2 100644 --- a/drivers/input/misc/yealink.c +++ b/drivers/input/misc/yealink.c @@ -798,7 +798,7 @@ static struct attribute *yld_attributes[] = { NULL }; -static struct attribute_group yld_attr_group = { +static const struct attribute_group yld_attr_group = { .attrs = yld_attributes }; -- cgit v1.2.3 From 21563a7eaba9720e53fc1a56d0b89bf69afca6bd Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Mon, 10 Jul 2017 20:22:20 -0700 Subject: Input: gpio_keys - constify attribute_group structures attribute_groups are not supposed to change at runtime. All functions working with attribute_groups provided by work with const attribute_group. So mark the non-const structs as const. File size before: text data bss dec hex filename 5693 464 0 6157 180d drivers/input/keyboard/gpio_keys.o File size After adding 'const': text data bss dec hex filename 5749 400 0 6149 1805 drivers/input/keyboard/gpio_keys.o Signed-off-by: Arvind Yadav Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/gpio_keys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index a047b9af8369..f52812db91bc 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -353,7 +353,7 @@ static struct attribute *gpio_keys_attrs[] = { NULL, }; -static struct attribute_group gpio_keys_attr_group = { +static const struct attribute_group gpio_keys_attr_group = { .attrs = gpio_keys_attrs, }; -- cgit v1.2.3 From 579994334df06372ca57c5418edcb79e2c8864f8 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Mon, 10 Jul 2017 20:22:40 -0700 Subject: Input: elantech - constify attribute_group structures attribute_groups are not supposed to change at runtime. All functions working with attribute_groups provided by work with const attribute_group. So mark the non-const structs as const. File size before: text data bss dec hex filename 16815 1424 0 18239 473f drivers/input/mouse/elantech.o File size After adding 'const': text data bss dec hex filename 16879 1360 0 18239 473f drivers/input/mouse/elantech.o Signed-off-by: Arvind Yadav Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elantech.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index e8cc223373ae..65c9de3f516c 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -1375,7 +1375,7 @@ static struct attribute *elantech_attrs[] = { NULL }; -static struct attribute_group elantech_attr_group = { +static const struct attribute_group elantech_attr_group = { .attrs = elantech_attrs, }; -- cgit v1.2.3 From ebc6a3709e5272405afe75e3cab10dbec82b6bca Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Mon, 10 Jul 2017 20:22:54 -0700 Subject: Input: psmouse - constify attribute_group structures attribute_groups are not supposed to change at runtime. All functions working with attribute_groups provided by work with const attribute_group. So mark the non-const structs as const. File size before: text data bss dec hex filename 12850 740 12 13602 3522 drivers/input/mouse/psmouse-base.o File size After adding 'const': text data bss dec hex filename 12914 676 12 13602 3522 drivers/input/mouse/psmouse-base.o Signed-off-by: Arvind Yadav Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/psmouse-base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index f73b47b8c578..6a5649e52eed 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -101,7 +101,7 @@ static struct attribute *psmouse_attributes[] = { NULL }; -static struct attribute_group psmouse_attribute_group = { +static const struct attribute_group psmouse_attribute_group = { .attrs = psmouse_attributes, }; -- cgit v1.2.3 From d653386da19cfd5ca4d00ca0f83b16ccf94d355f Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Mon, 10 Jul 2017 20:23:06 -0700 Subject: Input: raydium_i2c_ts - constify attribute_group structures attribute_groups are not supposed to change at runtime. All functions working with attribute_groups provided by work with const attribute_group. So mark the non-const structs as const. File size before: text data bss dec hex filename 7801 560 0 8361 20a9 drivers/input/touchscreen/raydium_i2c_ts.o File size After adding 'const': text data bss dec hex filename 7849 496 0 8345 2099 drivers/input/touchscreen/raydium_i2c_ts.o Signed-off-by: Arvind Yadav Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/raydium_i2c_ts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/raydium_i2c_ts.c b/drivers/input/touchscreen/raydium_i2c_ts.c index 1252e49ccfa1..4f1d3fd5d412 100644 --- a/drivers/input/touchscreen/raydium_i2c_ts.c +++ b/drivers/input/touchscreen/raydium_i2c_ts.c @@ -939,7 +939,7 @@ static struct attribute *raydium_i2c_attributes[] = { NULL }; -static struct attribute_group raydium_i2c_attribute_group = { +static const struct attribute_group raydium_i2c_attribute_group = { .attrs = raydium_i2c_attributes, }; -- cgit v1.2.3 From 48f960ddd79235e7840fd07f75766c160296d91c Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Mon, 10 Jul 2017 20:23:18 -0700 Subject: Input: elants_i2c - constify attribute_group structures attribute_groups are not supposed to change at runtime. All functions working with attribute_groups provided by work with const attribute_group. So mark the non-const structs as const. File size before: text data bss dec hex filename 9448 1008 0 10456 28d8 drivers/input/touchscreen/elants_i2c.o File size After adding 'const': text data bss dec hex filename 9496 944 0 10440 28c8 drivers/input/touchscreen/elants_i2c.o Signed-off-by: Arvind Yadav Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/elants_i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c index 872750eeca93..0f4cda7282a2 100644 --- a/drivers/input/touchscreen/elants_i2c.c +++ b/drivers/input/touchscreen/elants_i2c.c @@ -1066,7 +1066,7 @@ static struct attribute *elants_attributes[] = { NULL }; -static struct attribute_group elants_attribute_group = { +static const struct attribute_group elants_attribute_group = { .attrs = elants_attributes, }; -- cgit v1.2.3 From 9e938deceaea1496af4dda420e8f854691d4321f Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Mon, 10 Jul 2017 20:23:34 -0700 Subject: Input: ads7846 - constify attribute_group structures attribute_groups are not supposed to change at runtime. All functions working with attribute_groups provided by work with const attribute_group. So mark the non-const structs as const. File size before: text data bss dec hex filename 9086 624 0 9710 25ee drivers/input/touchscreen/ads7846.o File size After adding 'const': text data bss dec hex filename 9198 496 0 9694 25de drivers/input/touchscreen/ads7846.o Signed-off-by: Arvind Yadav Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ads7846.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 735a0be1ad95..a2f45aefce08 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -499,7 +499,7 @@ static struct attribute *ads7846_attributes[] = { NULL, }; -static struct attribute_group ads7846_attr_group = { +static const struct attribute_group ads7846_attr_group = { .attrs = ads7846_attributes, .is_visible = ads7846_is_visible, }; @@ -599,7 +599,7 @@ static struct attribute *ads784x_attributes[] = { NULL, }; -static struct attribute_group ads784x_attr_group = { +static const struct attribute_group ads784x_attr_group = { .attrs = ads784x_attributes, }; -- cgit v1.2.3 From 435915eae2d796f1141cb1c3280c4388f852bd98 Mon Sep 17 00:00:00 2001 From: Florian Echtler Date: Mon, 10 Jul 2017 10:39:27 -0700 Subject: Input: sur40 - add additional reverse-engineered information Due to recent reverse engineering efforts, a lot more information is now available about the internals of the SUR40. We document this in the kernel driver for future use. Signed-off-by: Martin Kaltenbrunner Signed-off-by: Florian Echtler Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/sur40.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c index 128e5bd74720..259aef505042 100644 --- a/drivers/input/touchscreen/sur40.c +++ b/drivers/input/touchscreen/sur40.c @@ -59,7 +59,7 @@ struct sur40_blob { __le16 blob_id; u8 action; /* 0x02 = enter/exit, 0x03 = update (?) */ - u8 unknown; /* always 0x01 or 0x02 (no idea what this is?) */ + u8 type; /* bitmask (0x01 blob, 0x02 touch, 0x04 tag) */ __le16 bb_pos_x; /* upper left corner of bounding box */ __le16 bb_pos_y; @@ -133,12 +133,19 @@ struct sur40_image_header { /* control commands */ #define SUR40_GET_VERSION 0xb0 /* 12 bytes string */ -#define SUR40_UNKNOWN1 0xb3 /* 5 bytes */ -#define SUR40_UNKNOWN2 0xc1 /* 24 bytes */ +#define SUR40_ACCEL_CAPS 0xb3 /* 5 bytes */ +#define SUR40_SENSOR_CAPS 0xc1 /* 24 bytes */ + +#define SUR40_POKE 0xc5 /* poke register byte */ +#define SUR40_PEEK 0xc4 /* 48 bytes registers */ #define SUR40_GET_STATE 0xc5 /* 4 bytes state (?) */ #define SUR40_GET_SENSORS 0xb1 /* 8 bytes sensors */ +#define SUR40_BLOB 0x01 +#define SUR40_TOUCH 0x02 +#define SUR40_TAG 0x04 + static const struct v4l2_pix_format sur40_pix_format[] = { { .pixelformat = V4L2_TCH_FMT_TU08, @@ -238,11 +245,11 @@ static int sur40_init(struct sur40_state *dev) if (result < 0) goto error; - result = sur40_command(dev, SUR40_UNKNOWN2, 0x00, buffer, 24); + result = sur40_command(dev, SUR40_SENSOR_CAPS, 0x00, buffer, 24); if (result < 0) goto error; - result = sur40_command(dev, SUR40_UNKNOWN1, 0x00, buffer, 5); + result = sur40_command(dev, SUR40_ACCEL_CAPS, 0x00, buffer, 5); if (result < 0) goto error; -- cgit v1.2.3 From 335abaea7a27b8a2dfb1ae4573f25019b5d6f68e Mon Sep 17 00:00:00 2001 From: Florian Echtler Date: Mon, 10 Jul 2017 10:39:48 -0700 Subject: Input: sur40 - silence unnecessary noisy debug output This information is unneccessary, even as debug output. Leave commented out as documentation of the packet ID quirk. Signed-off-by: Martin Kaltenbrunner Signed-off-by: Florian Echtler Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/sur40.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c index 259aef505042..f04adeaa45b3 100644 --- a/drivers/input/touchscreen/sur40.c +++ b/drivers/input/touchscreen/sur40.c @@ -374,10 +374,13 @@ static void sur40_poll(struct input_polled_dev *polldev) /* * Sanity check. when video data is also being retrieved, the * packet ID will usually increase in the middle of a series - * instead of at the end. - */ + * instead of at the end. However, the data is still consistent, + * so the packet ID is probably just valid for the first packet + * in a series. + if (packet_id != le32_to_cpu(header->packet_id)) dev_dbg(sur40->dev, "packet ID mismatch\n"); + */ packet_blobs = result / sizeof(struct sur40_blob); dev_dbg(sur40->dev, "received %d blobs\n", packet_blobs); -- cgit v1.2.3 From 4323418d62fefe48ee5019f2c744c918be06ec69 Mon Sep 17 00:00:00 2001 From: Florian Echtler Date: Mon, 10 Jul 2017 10:40:28 -0700 Subject: Input: sur40 - skip all blobs that are not touches The SUR40 labels all reported blobs as touch, token, or generic blob. Previously, all blobs were reported as touch regardless of type, causing lots of false positives. Present patch fixes this. Signed-off-by: Martin Kaltenbrunner Signed-off-by: Florian Echtler Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/sur40.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c index f04adeaa45b3..f16f8358c70a 100644 --- a/drivers/input/touchscreen/sur40.c +++ b/drivers/input/touchscreen/sur40.c @@ -296,20 +296,24 @@ static void sur40_close(struct input_polled_dev *polldev) static void sur40_report_blob(struct sur40_blob *blob, struct input_dev *input) { int wide, major, minor; + int bb_size_x, bb_size_y, pos_x, pos_y, ctr_x, ctr_y, slotnum; - int bb_size_x = le16_to_cpu(blob->bb_size_x); - int bb_size_y = le16_to_cpu(blob->bb_size_y); - - int pos_x = le16_to_cpu(blob->pos_x); - int pos_y = le16_to_cpu(blob->pos_y); - - int ctr_x = le16_to_cpu(blob->ctr_x); - int ctr_y = le16_to_cpu(blob->ctr_y); + if (blob->type != SUR40_TOUCH) + return; - int slotnum = input_mt_get_slot_by_key(input, blob->blob_id); + slotnum = input_mt_get_slot_by_key(input, blob->blob_id); if (slotnum < 0 || slotnum >= MAX_CONTACTS) return; + bb_size_x = le16_to_cpu(blob->bb_size_x); + bb_size_y = le16_to_cpu(blob->bb_size_y); + + pos_x = le16_to_cpu(blob->pos_x); + pos_y = le16_to_cpu(blob->pos_y); + + ctr_x = le16_to_cpu(blob->ctr_x); + ctr_y = le16_to_cpu(blob->ctr_y); + input_mt_slot(input, slotnum); input_mt_report_slot_state(input, MT_TOOL_FINGER, 1); wide = (bb_size_x > bb_size_y); -- cgit v1.2.3 From 765831dc27ab141b3a0be1ab55b922b012427902 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 12 Jul 2017 10:13:29 +0200 Subject: drm/simple-kms-helper: Fix the check for the mismatch between plane and CRTC enabled. You can enable the CRTC and without adding the plane to the state and it will succeed. This should be prevented in the crtc check instead of the plane check, because the plane check may never run for atomic enable, but the crtc check always will. This is based on a similar check in vmwgfx. Signed-off-by: Maarten Lankhorst Cc: Daniel Vetter Cc: Jani Nikula Cc: Sean Paul Cc: David Airlie Link: http://patchwork.freedesktop.org/patch/msgid/20170712081344.25495-2-maarten.lankhorst@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/drm_simple_kms_helper.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c index 98250854af75..39c203ad59db 100644 --- a/drivers/gpu/drm/drm_simple_kms_helper.c +++ b/drivers/gpu/drm/drm_simple_kms_helper.c @@ -37,6 +37,13 @@ static const struct drm_encoder_funcs drm_simple_kms_encoder_funcs = { static int drm_simple_kms_crtc_check(struct drm_crtc *crtc, struct drm_crtc_state *state) { + bool has_primary = state->plane_mask & + BIT(drm_plane_index(crtc->primary)); + + /* We always want to have an active plane with an active CRTC */ + if (has_primary != state->enable) + return -EINVAL; + return drm_atomic_add_affected_planes(state->state, crtc); } @@ -90,9 +97,6 @@ static int drm_simple_kms_plane_atomic_check(struct drm_plane *plane, pipe = container_of(plane, struct drm_simple_display_pipe, plane); crtc_state = drm_atomic_get_new_crtc_state(plane_state->state, &pipe->crtc); - if (crtc_state->enable != !!plane_state->crtc) - return -EINVAL; /* plane must match crtc enable state */ - if (!crtc_state->enable) return 0; /* nothing to check when disabling or disabled */ -- cgit v1.2.3 From 0c3eb12324277eac3334ef04c9780b9e734f6f27 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 12 Jul 2017 10:13:30 +0200 Subject: drm/atomic: Use the correct iterator macro in atomic_remove_fb for_each_obj_in_state will be removed, so use the new state here. Signed-off-by: Maarten Lankhorst Cc: Daniel Vetter Cc: Jani Nikula Cc: Sean Paul Cc: David Airlie Link: http://patchwork.freedesktop.org/patch/msgid/20170712081344.25495-3-maarten.lankhorst@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/drm_framebuffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c index fc8ef42203ec..607ef3a97c42 100644 --- a/drivers/gpu/drm/drm_framebuffer.c +++ b/drivers/gpu/drm/drm_framebuffer.c @@ -817,7 +817,7 @@ retry: plane->old_fb = plane->fb; } - for_each_connector_in_state(state, conn, conn_state, i) { + for_each_new_connector_in_state(state, conn, conn_state, i) { ret = drm_atomic_set_crtc_for_connector(conn_state, NULL); if (ret) -- cgit v1.2.3 From dfb8bb3bd4bbb6c525ee1baa202eae01aa305109 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 12 Jul 2017 10:13:31 +0200 Subject: drm/atomic: Use the new helpers in drm_atomic_helper_disable_all() for_each_obj_in_state will be removed, so don't use it here. Signed-off-by: Maarten Lankhorst Cc: Daniel Vetter Cc: Jani Nikula Cc: Sean Paul Cc: David Airlie Link: http://patchwork.freedesktop.org/patch/msgid/20170712081344.25495-4-maarten.lankhorst@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic_helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 667ec97d4efb..391cd887f922 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -2715,13 +2715,13 @@ int drm_atomic_helper_disable_all(struct drm_device *dev, goto free; } - for_each_connector_in_state(state, conn, conn_state, i) { + for_each_new_connector_in_state(state, conn, conn_state, i) { ret = drm_atomic_set_crtc_for_connector(conn_state, NULL); if (ret < 0) goto free; } - for_each_plane_in_state(state, plane, plane_state, i) { + for_each_new_plane_in_state(state, plane, plane_state, i) { ret = drm_atomic_set_crtc_for_plane(plane_state, NULL); if (ret < 0) goto free; -- cgit v1.2.3 From 2d705c0b367622d382d80c38240b3069c19f4eeb Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 12 Jul 2017 10:13:32 +0200 Subject: drm/atomic: Use new iterator macros in drm_atomic_helper_wait_for_flip_done for_each_obj_in_state is about to be removed, so use the correct new iterator macro. Signed-off-by: Maarten Lankhorst Cc: Daniel Vetter Cc: Jani Nikula Cc: Sean Paul Cc: David Airlie Link: http://patchwork.freedesktop.org/patch/msgid/20170712081344.25495-5-maarten.lankhorst@linux.intel.com [mlankhorst: Based on danvet's feedback, only apply first hunk and rename crtc_state variable to unused] Reviewed-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic_helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 391cd887f922..0fed20692df4 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1266,11 +1266,11 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_vblanks); void drm_atomic_helper_wait_for_flip_done(struct drm_device *dev, struct drm_atomic_state *old_state) { - struct drm_crtc_state *crtc_state; + struct drm_crtc_state *unused; struct drm_crtc *crtc; int i; - for_each_crtc_in_state(old_state, crtc, crtc_state, i) { + for_each_crtc_in_state(old_state, crtc, unused, i) { struct drm_crtc_commit *commit = old_state->crtcs[i].commit; int ret; -- cgit v1.2.3 From bdc362f631e2ac140e2b5ddfe5ba9705a5b1a6a0 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 12 Jul 2017 10:13:33 +0200 Subject: drm/vmwgfx: Make check_modeset() use the new atomic iterator macros. I don't think the checking of resources in this function is very atomic-like, but it should definitely not use a macro that's about to be removed. Signed-off-by: Maarten Lankhorst Cc: VMware Graphics Cc: Sinclair Yeh Cc: Thomas Hellstrom Link: http://patchwork.freedesktop.org/patch/msgid/20170712081344.25495-6-maarten.lankhorst@linux.intel.com Reviewed-by: Sinclair Yeh Reviewed-by: Daniel Vetter [mlankhorst: Make function static (danvet)] --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 1cd67b10a0d9..620180df1303 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1527,7 +1527,7 @@ err_out: * RETURNS * Zero for success or -errno */ -int +static int vmw_kms_atomic_check_modeset(struct drm_device *dev, struct drm_atomic_state *state) { @@ -1536,8 +1536,7 @@ vmw_kms_atomic_check_modeset(struct drm_device *dev, struct vmw_private *dev_priv = vmw_priv(dev); int i; - - for_each_crtc_in_state(state, crtc, crtc_state, i) { + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { unsigned long requested_bb_mem = 0; if (dev_priv->active_display_unit == vmw_du_screen_target) { -- cgit v1.2.3 From fe5f6b1fa02fbee34d95578db41f8e7117469b41 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 12 Jul 2017 10:13:34 +0200 Subject: drm/i915: Use correct iterator macro for_each_connector_in_state will be removed, so use the right state here. Signed-off-by: Maarten Lankhorst Cc: Daniel Vetter Cc: Jani Nikula Cc: intel-gfx@lists.freedesktop.org Link: http://patchwork.freedesktop.org/patch/msgid/20170712081344.25495-7-maarten.lankhorst@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_hdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index ec0779a52d53..916340f03882 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1321,7 +1321,7 @@ static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state) if (crtc_state->output_types != 1 << INTEL_OUTPUT_HDMI) return false; - for_each_connector_in_state(state, connector, connector_state, i) { + for_each_new_connector_in_state(state, connector, connector_state, i) { const struct drm_display_info *info = &connector->display_info; if (connector_state->crtc != crtc_state->base.crtc) -- cgit v1.2.3 From d57da16f57f44d3cdf26a9b233287057866d4979 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 12 Jul 2017 10:13:36 +0200 Subject: drm/atmel-hlcdec: Use for_each_new_connector_in_state for_each_obj_in_state is about to be removed, so use the new iterator macros. Signed-off-by: Maarten Lankhorst Cc: Boris Brezillon Link: http://patchwork.freedesktop.org/patch/msgid/20170712081344.25495-9-maarten.lankhorst@linux.intel.com Reviewed-by: Daniel Vetter Acked-by: Boris Brezillon --- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c index 441769c5bcd4..4fbbeab5c5d4 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c @@ -237,7 +237,7 @@ static int atmel_hlcdc_crtc_select_output_mode(struct drm_crtc_state *state) crtc = drm_crtc_to_atmel_hlcdc_crtc(state->crtc); - for_each_connector_in_state(state->state, connector, cstate, i) { + for_each_new_connector_in_state(state->state, connector, cstate, i) { struct drm_display_info *info = &connector->display_info; unsigned int supported_fmts = 0; int j; -- cgit v1.2.3 From e741f2b182e6d6203dfbf294affdfb9eb1009ddf Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 12 Jul 2017 10:13:37 +0200 Subject: drm/rockchip: Use for_each_oldnew_plane_in_state in vop_crtc_atomic_flush for_each_obj_in_state is about to be removed, so use the new atomic iterator macros. Signed-off-by: Maarten Lankhorst Cc: Mark Yao Cc: Heiko Stuebner Cc: linux-arm-kernel@lists.infradead.org Cc: linux-rockchip@lists.infradead.org Link: http://patchwork.freedesktop.org/patch/msgid/20170712081344.25495-10-maarten.lankhorst@linux.intel.com Reviewed-by: Daniel Vetter Acked-by: Mark Yao --- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index ee876a9631f0..f90088b1a247 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -1029,7 +1029,7 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state) { struct drm_atomic_state *old_state = old_crtc_state->state; - struct drm_plane_state *old_plane_state; + struct drm_plane_state *old_plane_state, *new_plane_state; struct vop *vop = to_vop(crtc); struct drm_plane *plane; int i; @@ -1060,11 +1060,12 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc, } spin_unlock_irq(&crtc->dev->event_lock); - for_each_plane_in_state(old_state, plane, old_plane_state, i) { + for_each_oldnew_plane_in_state(old_state, plane, old_plane_state, + new_plane_state, i) { if (!old_plane_state->fb) continue; - if (old_plane_state->fb == plane->state->fb) + if (old_plane_state->fb == new_plane_state->fb) continue; drm_framebuffer_reference(old_plane_state->fb); -- cgit v1.2.3 From a8e3fb5508fe559c2318c2b6966867110e4de98c Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 12 Jul 2017 10:13:39 +0200 Subject: drm/mali: Use new atomic iterator macros for_each_obj_in_state is about to be removed, so use the new iterator macros. Signed-off-by: Maarten Lankhorst Cc: Liviu Dudau Cc: Brian Starkey Cc: Mali DP Maintainers Link: http://patchwork.freedesktop.org/patch/msgid/20170712081344.25495-12-maarten.lankhorst@linux.intel.com Reviewed-by: Daniel Vetter Acked-by: Liviu Dudau --- drivers/gpu/drm/arm/malidp_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c index 01b13d219917..a6a05a768dd1 100644 --- a/drivers/gpu/drm/arm/malidp_drv.c +++ b/drivers/gpu/drm/arm/malidp_drv.c @@ -225,7 +225,7 @@ static void malidp_atomic_commit_tail(struct drm_atomic_state *state) drm_atomic_helper_commit_modeset_disables(drm, state); - for_each_crtc_in_state(state, crtc, old_crtc_state, i) { + for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) { malidp_atomic_commit_update_gamma(crtc, old_crtc_state); malidp_atomic_commit_update_coloradj(crtc, old_crtc_state); malidp_atomic_commit_se_config(crtc, old_crtc_state); -- cgit v1.2.3 From 30ea752146e147c5a1f0367aa5303929f7bfd697 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 12 Jul 2017 10:13:40 +0200 Subject: drm/imx: Use atomic iterator macros for_each_obj_in_state is about to be removed, so use the new atomic iterator macros. Signed-off-by: Maarten Lankhorst Cc: Philipp Zabel Link: http://patchwork.freedesktop.org/patch/msgid/20170712081344.25495-13-maarten.lankhorst@linux.intel.com Reviewed-by: Daniel Vetter Reviewed-by: Philipp Zabel Tested-by: Philipp Zabel --- drivers/gpu/drm/imx/imx-drm-core.c | 8 ++++---- drivers/gpu/drm/imx/ipuv3-plane.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c index 95e2181963d9..f5c621219113 100644 --- a/drivers/gpu/drm/imx/imx-drm-core.c +++ b/drivers/gpu/drm/imx/imx-drm-core.c @@ -115,7 +115,7 @@ static void imx_drm_atomic_commit_tail(struct drm_atomic_state *state) { struct drm_device *dev = state->dev; struct drm_plane *plane; - struct drm_plane_state *old_plane_state; + struct drm_plane_state *old_plane_state, *new_plane_state; bool plane_disabling = false; int i; @@ -127,15 +127,15 @@ static void imx_drm_atomic_commit_tail(struct drm_atomic_state *state) drm_atomic_helper_commit_modeset_enables(dev, state); - for_each_plane_in_state(state, plane, old_plane_state, i) { - if (drm_atomic_plane_disabling(old_plane_state, plane->state)) + for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { + if (drm_atomic_plane_disabling(old_plane_state, new_plane_state)) plane_disabling = true; } if (plane_disabling) { drm_atomic_helper_wait_for_vblanks(dev, state); - for_each_plane_in_state(state, plane, old_plane_state, i) + for_each_old_plane_in_state(state, plane, old_plane_state, i) ipu_plane_disable_deferred(plane); } diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index 49546222c6d3..ff53c8dec633 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -675,7 +675,7 @@ int ipu_planes_assign_pre(struct drm_device *dev, int available_pres = ipu_prg_max_active_channels(); int i; - for_each_plane_in_state(state, plane, plane_state, i) { + for_each_new_plane_in_state(state, plane, plane_state, i) { struct ipu_plane_state *ipu_state = to_ipu_plane_state(plane_state); struct ipu_plane *ipu_plane = to_ipu_plane(plane); -- cgit v1.2.3 From e27986853a168b31c9801359a7a70a5226b558c3 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 12 Jul 2017 10:13:41 +0200 Subject: drm/mediatek: Convert to new iterator macros for_each_obj_in_state is about to be removed, so use the new atomic iterator macros. Signed-off-by: Maarten Lankhorst Cc: CK Hu Cc: Philipp Zabel Cc: Matthias Brugger Cc: linux-arm-kernel@lists.infradead.org Cc: linux-mediatek@lists.infradead.org Link: http://patchwork.freedesktop.org/patch/msgid/20170712081344.25495-14-maarten.lankhorst@linux.intel.com Reviewed-by: Daniel Vetter Acked-by: Philipp Zabel --- drivers/gpu/drm/mediatek/mtk_drm_drv.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index 56f802d0a51c..be0741638f94 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -48,11 +48,11 @@ static void mtk_atomic_schedule(struct mtk_drm_private *private, static void mtk_atomic_wait_for_fences(struct drm_atomic_state *state) { struct drm_plane *plane; - struct drm_plane_state *plane_state; + struct drm_plane_state *new_plane_state; int i; - for_each_plane_in_state(state, plane, plane_state, i) - mtk_fb_wait(plane->state->fb); + for_each_new_plane_in_state(state, plane, new_plane_state, i) + mtk_fb_wait(new_plane_state->fb); } static void mtk_atomic_complete(struct mtk_drm_private *private, -- cgit v1.2.3 From 07ab976d1971a91a7ac25d4782dc8985a2314b87 Mon Sep 17 00:00:00 2001 From: "Kumar, Mahesh" Date: Wed, 5 Jul 2017 20:01:44 +0530 Subject: drm/i915: take-out common clamping code of fixed16 wrappers This patch creates a new function for clamping u64 to fixed16. And make use of this function in other fixed16 wrappers. Signed-off-by: Mahesh Kumar Reviewed-by: Maarten Lankhorst Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/20170705143154.32132-2-mahesh1.kumar@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 5e70f5711fc8..1b525051bf5f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -160,6 +160,14 @@ static inline uint_fixed_16_16_t max_fixed_16_16(uint_fixed_16_16_t max1, return max; } +static inline uint_fixed_16_16_t clamp_u64_to_fixed16(uint64_t val) +{ + uint_fixed_16_16_t fp; + WARN_ON(val >> 32); + fp.val = clamp_t(uint32_t, val, 0, ~0); + return fp; +} + static inline uint32_t div_round_up_fixed16(uint_fixed_16_16_t val, uint_fixed_16_16_t d) { @@ -170,26 +178,21 @@ static inline uint32_t mul_round_up_u32_fixed16(uint32_t val, uint_fixed_16_16_t mul) { uint64_t intermediate_val; - uint32_t result; intermediate_val = (uint64_t) val * mul.val; intermediate_val = DIV_ROUND_UP_ULL(intermediate_val, 1 << 16); WARN_ON(intermediate_val >> 32); - result = clamp_t(uint32_t, intermediate_val, 0, ~0); - return result; + return clamp_t(uint32_t, intermediate_val, 0, ~0); } static inline uint_fixed_16_16_t mul_fixed16(uint_fixed_16_16_t val, uint_fixed_16_16_t mul) { uint64_t intermediate_val; - uint_fixed_16_16_t fp; intermediate_val = (uint64_t) val.val * mul.val; intermediate_val = intermediate_val >> 16; - WARN_ON(intermediate_val >> 32); - fp.val = clamp_t(uint32_t, intermediate_val, 0, ~0); - return fp; + return clamp_u64_to_fixed16(intermediate_val); } static inline uint_fixed_16_16_t fixed_16_16_div(uint32_t val, uint32_t d) @@ -203,15 +206,11 @@ static inline uint_fixed_16_16_t fixed_16_16_div(uint32_t val, uint32_t d) static inline uint_fixed_16_16_t fixed_16_16_div_u64(uint32_t val, uint32_t d) { - uint_fixed_16_16_t res; uint64_t interm_val; interm_val = (uint64_t)val << 16; interm_val = DIV_ROUND_UP_ULL(interm_val, d); - WARN_ON(interm_val >> 32); - res.val = (uint32_t) interm_val; - - return res; + return clamp_u64_to_fixed16(interm_val); } static inline uint32_t div_round_up_u32_fixed16(uint32_t val, @@ -229,12 +228,9 @@ static inline uint_fixed_16_16_t mul_u32_fixed_16_16(uint32_t val, uint_fixed_16_16_t mul) { uint64_t intermediate_val; - uint_fixed_16_16_t fp; intermediate_val = (uint64_t) val * mul.val; - WARN_ON(intermediate_val >> 32); - fp.val = (uint32_t) intermediate_val; - return fp; + return clamp_u64_to_fixed16(intermediate_val); } static inline const char *yesno(bool v) -- cgit v1.2.3 From eed02a7b53131abb796ba8a8cf2886cee366a89f Mon Sep 17 00:00:00 2001 From: "Kumar, Mahesh" Date: Wed, 5 Jul 2017 20:01:45 +0530 Subject: drm/i915: Always perform internal fixed16 division in 64 bits This patch combines fixed_16_16_div & fixed_16_16_div_u64 wrappers. And new fixed_16_16_div wrapper always performs division operation in u64 internally, to avoid any data loss which was happening in earlier version of wrapper. earlier wrapper was converting u32 to fixed16 in 32 bit so we were losing 16-MSB data. Signed-off-by: Mahesh Kumar Reviewed-by: Maarten Lankhorst Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/20170705143154.32132-3-mahesh1.kumar@intel.com [mlankhorst: Fix typo in commit message.] --- drivers/gpu/drm/i915/i915_drv.h | 9 --------- drivers/gpu/drm/i915/intel_pm.c | 4 ++-- 2 files changed, 2 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1b525051bf5f..95d5328a26e9 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -196,15 +196,6 @@ static inline uint_fixed_16_16_t mul_fixed16(uint_fixed_16_16_t val, } static inline uint_fixed_16_16_t fixed_16_16_div(uint32_t val, uint32_t d) -{ - uint_fixed_16_16_t fp, res; - - fp = u32_to_fixed_16_16(val); - res.val = DIV_ROUND_UP(fp.val, d); - return res; -} - -static inline uint_fixed_16_16_t fixed_16_16_div_u64(uint32_t val, uint32_t d) { uint64_t interm_val; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 6db833e6dcbd..05eabadaa23d 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4276,7 +4276,7 @@ static uint_fixed_16_16_t skl_wm_method1(uint32_t pixel_rate, uint8_t cpp, return FP_16_16_MAX; wm_intermediate_val = latency * pixel_rate * cpp; - ret = fixed_16_16_div_u64(wm_intermediate_val, 1000 * 512); + ret = fixed_16_16_div(wm_intermediate_val, 1000 * 512); return ret; } @@ -4314,7 +4314,7 @@ intel_get_linetime_us(struct intel_crtc_state *cstate) return u32_to_fixed_16_16(0); crtc_htotal = cstate->base.adjusted_mode.crtc_htotal; - linetime_us = fixed_16_16_div_u64(crtc_htotal * 1000, pixel_rate); + linetime_us = fixed_16_16_div(crtc_htotal * 1000, pixel_rate); return linetime_us; } -- cgit v1.2.3 From eac2cb81fb87223198c2be93bfd49357d71be669 Mon Sep 17 00:00:00 2001 From: "Kumar, Mahesh" Date: Wed, 5 Jul 2017 20:01:46 +0530 Subject: drm/i915: cleanup fixed-point wrappers naming This patch make naming of fixed-point wrappers consistent operation__<1st operand>_<2nd operand> also shorten the name for fixed_16_16 to fixed16 s/u32_to_fixed_16_16/u32_to_fixed16 s/fixed_16_16_to_u32/fixed16_to_u32 s/fixed_16_16_to_u32_round_up/fixed16_to_u32_round_up s/min_fixed_16_16/min_fixed16 s/max_fixed_16_16/max_fixed16 s/mul_u32_fixed_16_16/mul_u32_fixed16 s/fixed_16_16_div/div_fixed16 Changes Since V1: - Split the patch in more logical patches (Maarten) Changes Since V2: - Rebase Signed-off-by: Mahesh Kumar Reviewed-by: Maarten Lankhorst Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/20170705143154.32132-4-mahesh1.kumar@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 14 ++++----- drivers/gpu/drm/i915/intel_pm.c | 63 ++++++++++++++++++++--------------------- 2 files changed, 38 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 95d5328a26e9..1fc25bd5c904 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -122,7 +122,7 @@ static inline bool is_fixed16_zero(uint_fixed_16_16_t val) return false; } -static inline uint_fixed_16_16_t u32_to_fixed_16_16(uint32_t val) +static inline uint_fixed_16_16_t u32_to_fixed16(uint32_t val) { uint_fixed_16_16_t fp; @@ -132,17 +132,17 @@ static inline uint_fixed_16_16_t u32_to_fixed_16_16(uint32_t val) return fp; } -static inline uint32_t fixed_16_16_to_u32_round_up(uint_fixed_16_16_t fp) +static inline uint32_t fixed16_to_u32_round_up(uint_fixed_16_16_t fp) { return DIV_ROUND_UP(fp.val, 1 << 16); } -static inline uint32_t fixed_16_16_to_u32(uint_fixed_16_16_t fp) +static inline uint32_t fixed16_to_u32(uint_fixed_16_16_t fp) { return fp.val >> 16; } -static inline uint_fixed_16_16_t min_fixed_16_16(uint_fixed_16_16_t min1, +static inline uint_fixed_16_16_t min_fixed16(uint_fixed_16_16_t min1, uint_fixed_16_16_t min2) { uint_fixed_16_16_t min; @@ -151,7 +151,7 @@ static inline uint_fixed_16_16_t min_fixed_16_16(uint_fixed_16_16_t min1, return min; } -static inline uint_fixed_16_16_t max_fixed_16_16(uint_fixed_16_16_t max1, +static inline uint_fixed_16_16_t max_fixed16(uint_fixed_16_16_t max1, uint_fixed_16_16_t max2) { uint_fixed_16_16_t max; @@ -195,7 +195,7 @@ static inline uint_fixed_16_16_t mul_fixed16(uint_fixed_16_16_t val, return clamp_u64_to_fixed16(intermediate_val); } -static inline uint_fixed_16_16_t fixed_16_16_div(uint32_t val, uint32_t d) +static inline uint_fixed_16_16_t div_fixed16(uint32_t val, uint32_t d) { uint64_t interm_val; @@ -215,7 +215,7 @@ static inline uint32_t div_round_up_u32_fixed16(uint32_t val, return clamp_t(uint32_t, interm_val, 0, ~0); } -static inline uint_fixed_16_16_t mul_u32_fixed_16_16(uint32_t val, +static inline uint_fixed_16_16_t mul_u32_fixed16(uint32_t val, uint_fixed_16_16_t mul) { uint64_t intermediate_val; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 05eabadaa23d..2603df15b4e1 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3837,7 +3837,7 @@ skl_plane_downscale_amount(const struct intel_crtc_state *cstate, uint_fixed_16_16_t downscale_h, downscale_w; if (WARN_ON(!intel_wm_plane_visible(cstate, pstate))) - return u32_to_fixed_16_16(0); + return u32_to_fixed16(0); /* n.b., src is 16.16 fixed point, dst is whole integer */ if (plane->id == PLANE_CURSOR) { @@ -3861,10 +3861,10 @@ skl_plane_downscale_amount(const struct intel_crtc_state *cstate, dst_h = drm_rect_height(&pstate->base.dst); } - fp_w_ratio = fixed_16_16_div(src_w, dst_w); - fp_h_ratio = fixed_16_16_div(src_h, dst_h); - downscale_w = max_fixed_16_16(fp_w_ratio, u32_to_fixed_16_16(1)); - downscale_h = max_fixed_16_16(fp_h_ratio, u32_to_fixed_16_16(1)); + fp_w_ratio = div_fixed16(src_w, dst_w); + fp_h_ratio = div_fixed16(src_h, dst_h); + downscale_w = max_fixed16(fp_w_ratio, u32_to_fixed16(1)); + downscale_h = max_fixed16(fp_h_ratio, u32_to_fixed16(1)); return mul_fixed16(downscale_w, downscale_h); } @@ -3872,7 +3872,7 @@ skl_plane_downscale_amount(const struct intel_crtc_state *cstate, static uint_fixed_16_16_t skl_pipe_downscale_amount(const struct intel_crtc_state *crtc_state) { - uint_fixed_16_16_t pipe_downscale = u32_to_fixed_16_16(1); + uint_fixed_16_16_t pipe_downscale = u32_to_fixed16(1); if (!crtc_state->base.enable) return pipe_downscale; @@ -3891,10 +3891,10 @@ skl_pipe_downscale_amount(const struct intel_crtc_state *crtc_state) if (!dst_w || !dst_h) return pipe_downscale; - fp_w_ratio = fixed_16_16_div(src_w, dst_w); - fp_h_ratio = fixed_16_16_div(src_h, dst_h); - downscale_w = max_fixed_16_16(fp_w_ratio, u32_to_fixed_16_16(1)); - downscale_h = max_fixed_16_16(fp_h_ratio, u32_to_fixed_16_16(1)); + fp_w_ratio = div_fixed16(src_w, dst_w); + fp_h_ratio = div_fixed16(src_h, dst_h); + downscale_w = max_fixed16(fp_w_ratio, u32_to_fixed16(1)); + downscale_h = max_fixed16(fp_h_ratio, u32_to_fixed16(1)); pipe_downscale = mul_fixed16(downscale_w, downscale_h); } @@ -3913,14 +3913,14 @@ int skl_check_pipe_max_pixel_rate(struct intel_crtc *intel_crtc, int crtc_clock, dotclk; uint32_t pipe_max_pixel_rate; uint_fixed_16_16_t pipe_downscale; - uint_fixed_16_16_t max_downscale = u32_to_fixed_16_16(1); + uint_fixed_16_16_t max_downscale = u32_to_fixed16(1); if (!cstate->base.enable) return 0; drm_atomic_crtc_state_for_each_plane_state(plane, pstate, crtc_state) { uint_fixed_16_16_t plane_downscale; - uint_fixed_16_16_t fp_9_div_8 = fixed_16_16_div(9, 8); + uint_fixed_16_16_t fp_9_div_8 = div_fixed16(9, 8); int bpp; if (!intel_wm_plane_visible(cstate, @@ -3938,7 +3938,7 @@ int skl_check_pipe_max_pixel_rate(struct intel_crtc *intel_crtc, plane_downscale = mul_fixed16(plane_downscale, fp_9_div_8); - max_downscale = max_fixed_16_16(plane_downscale, max_downscale); + max_downscale = max_fixed16(plane_downscale, max_downscale); } pipe_downscale = skl_pipe_downscale_amount(cstate); @@ -4276,7 +4276,7 @@ static uint_fixed_16_16_t skl_wm_method1(uint32_t pixel_rate, uint8_t cpp, return FP_16_16_MAX; wm_intermediate_val = latency * pixel_rate * cpp; - ret = fixed_16_16_div(wm_intermediate_val, 1000 * 512); + ret = div_fixed16(wm_intermediate_val, 1000 * 512); return ret; } @@ -4294,7 +4294,7 @@ static uint_fixed_16_16_t skl_wm_method2(uint32_t pixel_rate, wm_intermediate_val = latency * pixel_rate; wm_intermediate_val = DIV_ROUND_UP(wm_intermediate_val, pipe_htotal * 1000); - ret = mul_u32_fixed_16_16(wm_intermediate_val, plane_blocks_per_line); + ret = mul_u32_fixed16(wm_intermediate_val, plane_blocks_per_line); return ret; } @@ -4306,15 +4306,15 @@ intel_get_linetime_us(struct intel_crtc_state *cstate) uint_fixed_16_16_t linetime_us; if (!cstate->base.active) - return u32_to_fixed_16_16(0); + return u32_to_fixed16(0); pixel_rate = cstate->pixel_rate; if (WARN_ON(pixel_rate == 0)) - return u32_to_fixed_16_16(0); + return u32_to_fixed16(0); crtc_htotal = cstate->base.adjusted_mode.crtc_htotal; - linetime_us = fixed_16_16_div(crtc_htotal * 1000, pixel_rate); + linetime_us = div_fixed16(crtc_htotal * 1000, pixel_rate); return linetime_us; } @@ -4434,14 +4434,14 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, if (y_tiled) { interm_pbpl = DIV_ROUND_UP(plane_bytes_per_line * y_min_scanlines, 512); - plane_blocks_per_line = fixed_16_16_div(interm_pbpl, + plane_blocks_per_line = div_fixed16(interm_pbpl, y_min_scanlines); } else if (x_tiled) { interm_pbpl = DIV_ROUND_UP(plane_bytes_per_line, 512); - plane_blocks_per_line = u32_to_fixed_16_16(interm_pbpl); + plane_blocks_per_line = u32_to_fixed16(interm_pbpl); } else { interm_pbpl = DIV_ROUND_UP(plane_bytes_per_line, 512) + 1; - plane_blocks_per_line = u32_to_fixed_16_16(interm_pbpl); + plane_blocks_per_line = u32_to_fixed16(interm_pbpl); } method1 = skl_wm_method1(plane_pixel_rate, cpp, latency); @@ -4450,35 +4450,35 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, latency, plane_blocks_per_line); - y_tile_minimum = mul_u32_fixed_16_16(y_min_scanlines, - plane_blocks_per_line); + y_tile_minimum = mul_u32_fixed16(y_min_scanlines, + plane_blocks_per_line); if (y_tiled) { - selected_result = max_fixed_16_16(method2, y_tile_minimum); + selected_result = max_fixed16(method2, y_tile_minimum); } else { uint32_t linetime_us; - linetime_us = fixed_16_16_to_u32_round_up( + linetime_us = fixed16_to_u32_round_up( intel_get_linetime_us(cstate)); if ((cpp * cstate->base.adjusted_mode.crtc_htotal / 512 < 1) && (plane_bytes_per_line / 512 < 1)) selected_result = method2; else if ((ddb_allocation && ddb_allocation / - fixed_16_16_to_u32_round_up(plane_blocks_per_line)) >= 1) - selected_result = min_fixed_16_16(method1, method2); + fixed16_to_u32_round_up(plane_blocks_per_line)) >= 1) + selected_result = min_fixed16(method1, method2); else if (latency >= linetime_us) - selected_result = min_fixed_16_16(method1, method2); + selected_result = min_fixed16(method1, method2); else selected_result = method1; } - res_blocks = fixed_16_16_to_u32_round_up(selected_result) + 1; + res_blocks = fixed16_to_u32_round_up(selected_result) + 1; res_lines = div_round_up_fixed16(selected_result, plane_blocks_per_line); if (level >= 1 && level <= 7) { if (y_tiled) { - res_blocks += fixed_16_16_to_u32_round_up(y_tile_minimum); + res_blocks += fixed16_to_u32_round_up(y_tile_minimum); res_lines += y_min_scanlines; } else { res_blocks++; @@ -4563,8 +4563,7 @@ skl_compute_linetime_wm(struct intel_crtc_state *cstate) if (is_fixed16_zero(linetime_us)) return 0; - linetime_wm = fixed_16_16_to_u32_round_up(mul_u32_fixed_16_16(8, - linetime_us)); + linetime_wm = fixed16_to_u32_round_up(mul_u32_fixed16(8, linetime_us)); /* Display WA #1135: bxt. */ if (IS_BROXTON(dev_priv) && dev_priv->ipc_enabled) -- cgit v1.2.3 From 6ea593c029d8f7c847fd68392eeb5a284ee96bd7 Mon Sep 17 00:00:00 2001 From: "Kumar, Mahesh" Date: Wed, 5 Jul 2017 20:01:47 +0530 Subject: drm/i915: Addition wrapper for fixed16.16 operation This patch introduce addition wrapper for fixed point 16.16 operations. Which will be used by later patches to avoid direct member variables access of fixed_16_16_t structure. add_fixed16 : takes 2 fixed_16_16_t variable & returns fixed_16_16_t add_fixed16_u32 : takes fixed_16_16_t & u32 variable & returns fixed_16_16_t Signed-off-by: Mahesh Kumar Reviewed-by: Maarten Lankhorst Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/20170705143154.32132-5-mahesh1.kumar@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1fc25bd5c904..b4716ce32ca2 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -224,6 +224,25 @@ static inline uint_fixed_16_16_t mul_u32_fixed16(uint32_t val, return clamp_u64_to_fixed16(intermediate_val); } +static inline uint_fixed_16_16_t add_fixed16(uint_fixed_16_16_t add1, + uint_fixed_16_16_t add2) +{ + uint64_t interm_sum; + + interm_sum = (uint64_t) add1.val + add2.val; + return clamp_u64_to_fixed16(interm_sum); +} + +static inline uint_fixed_16_16_t add_fixed16_u32(uint_fixed_16_16_t add1, + uint32_t add2) +{ + uint64_t interm_sum; + uint_fixed_16_16_t interm_add2 = u32_to_fixed16(add2); + + interm_sum = (uint64_t) add1.val + interm_add2.val; + return clamp_u64_to_fixed16(interm_sum); +} + static inline const char *yesno(bool v) { return v ? "yes" : "no"; -- cgit v1.2.3 From 129eaa957dd5a717edd70cfaf0626c143c03e54e Mon Sep 17 00:00:00 2001 From: "Kumar, Mahesh" Date: Wed, 5 Jul 2017 20:01:48 +0530 Subject: drm/i915/skl+: WM calculation don't require height height of plane was require to swap width/height in case of 90/270 rotation. Now src structure contains already swapped values, So we don't have to calculate height of the plane. Signed-off-by: Mahesh Kumar Reviewed-by: Maarten Lankhorst Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/20170705143154.32132-6-mahesh1.kumar@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 2603df15b4e1..81e77f073d8c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4361,7 +4361,7 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, uint32_t plane_bytes_per_line; uint32_t res_blocks, res_lines; uint8_t cpp; - uint32_t width = 0, height = 0; + uint32_t width = 0; uint32_t plane_pixel_rate; uint_fixed_16_16_t y_tile_minimum; uint32_t y_min_scanlines; @@ -4390,7 +4390,6 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, if (plane->id == PLANE_CURSOR) { width = intel_pstate->base.crtc_w; - height = intel_pstate->base.crtc_h; } else { /* * Src coordinates are already rotated by 270 degrees for @@ -4398,7 +4397,6 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, * GTT mapping), hence no need to account for rotation here. */ width = drm_rect_width(&intel_pstate->base.src) >> 16; - height = drm_rect_height(&intel_pstate->base.src) >> 16; } cpp = fb->format->cpp[0]; -- cgit v1.2.3 From b064be0784530d2a98b589b40793e3d421fb93ba Mon Sep 17 00:00:00 2001 From: "Kumar, Mahesh" Date: Wed, 5 Jul 2017 20:01:49 +0530 Subject: drm/i915/skl+: unify cpp value in WM calculation use same cpp value in different phase of plane WM caluclation. Signed-off-by: Mahesh Kumar Reviewed-by: Maarten Lankhorst Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/20170705143154.32132-7-mahesh1.kumar@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 81e77f073d8c..ee2a349cfe68 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4399,13 +4399,11 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, width = drm_rect_width(&intel_pstate->base.src) >> 16; } - cpp = fb->format->cpp[0]; + cpp = (fb->format->format == DRM_FORMAT_NV12) ? fb->format->cpp[1] : + fb->format->cpp[0]; plane_pixel_rate = skl_adjusted_plane_pixel_rate(cstate, intel_pstate); if (drm_rotation_90_or_270(pstate->rotation)) { - int cpp = (fb->format->format == DRM_FORMAT_NV12) ? - fb->format->cpp[1] : - fb->format->cpp[0]; switch (cpp) { case 1: -- cgit v1.2.3 From 56a91c4932bd038f3d1f6555ddc349ca4e6933b0 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 12 Jul 2017 18:51:00 +0300 Subject: drm/dp/mst: Handle errors from drm_atomic_get_private_obj_state() correctly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On failure drm_atomic_get_private_obj_state() returns and error pointer instead of NULL. Adjust the checks in the callers to match. Cc: stable@vger.kernel.org Cc: Dhinakaran Pandiyan Cc: Harry Wentland Cc: Maarten Lankhorst Fixes: edb1ed1ab7d3 ("drm/dp: Add DP MST helpers to atomically find and release vcpi slots") Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/20170712155102.26276-1-ville.syrjala@linux.intel.com Reviewed-by: Dhinakaran Pandiyan --- drivers/gpu/drm/drm_dp_mst_topology.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index bfd237c15e76..18cecd94acb6 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -2515,8 +2515,8 @@ int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state, int req_slots; topology_state = drm_atomic_get_mst_topology_state(state, mgr); - if (topology_state == NULL) - return -ENOMEM; + if (IS_ERR(topology_state)) + return PTR_ERR(topology_state); port = drm_dp_get_validated_port_ref(mgr, port); if (port == NULL) @@ -2555,8 +2555,8 @@ int drm_dp_atomic_release_vcpi_slots(struct drm_atomic_state *state, struct drm_dp_mst_topology_state *topology_state; topology_state = drm_atomic_get_mst_topology_state(state, mgr); - if (topology_state == NULL) - return -ENOMEM; + if (IS_ERR(topology_state)) + return PTR_ERR(topology_state); /* We cannot rely on port->vcpi.num_slots to update * topology_state->avail_slots as the port may not exist if the parent -- cgit v1.2.3 From 178e32c224d2772d3862828dc6f81e4d8953b2f2 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 12 Jul 2017 18:51:01 +0300 Subject: drm/atomic: Remove pointless private object NULL state check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We will never add private objects with a NULL state into the atomic state, hence checking for that is pointless. Cc: Dhinakaran Pandiyan Reviewed-by: Daniel Vetter Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/20170712155102.26276-2-ville.syrjala@linux.intel.com --- drivers/gpu/drm/drm_atomic.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 09ca662fcd35..f0482247b31f 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -1013,8 +1013,7 @@ drm_atomic_get_private_obj_state(struct drm_atomic_state *state, void *obj, struct __drm_private_objs_state *arr; for (i = 0; i < state->num_private_objs; i++) - if (obj == state->private_objs[i].obj && - state->private_objs[i].obj_state) + if (obj == state->private_objs[i].obj) return state->private_objs[i].obj_state; num_objs = state->num_private_objs + 1; -- cgit v1.2.3 From a4370c777406c2810e37fafd166ccddecdb2a60c Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 12 Jul 2017 18:51:02 +0300 Subject: drm/atomic: Make private objs proper objects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the atomic private object stuff less special by introducing proper base classes for the object and its state. Drivers can embed these in their own appropriate objects, after which these things will work exactly like the plane/crtc/connector states during atomic operations. v2: Reorder to not depend on drm_dynarray (Daniel) Cc: Dhinakaran Pandiyan Cc: Daniel Vetter Reviewed-by: Daniel Vetter #v1 Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/20170712155102.26276-3-ville.syrjala@linux.intel.com --- drivers/gpu/drm/drm_atomic.c | 78 ++++++++++++++++------ drivers/gpu/drm/drm_atomic_helper.c | 30 +++++++-- drivers/gpu/drm/drm_dp_mst_topology.c | 63 +++++++++--------- include/drm/drm_atomic.h | 120 +++++++++++++++++++++------------- include/drm/drm_atomic_helper.h | 4 ++ include/drm/drm_dp_mst_helper.h | 10 +++ 6 files changed, 203 insertions(+), 102 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index f0482247b31f..b59fd33c5786 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -187,12 +187,15 @@ void drm_atomic_state_default_clear(struct drm_atomic_state *state) } for (i = 0; i < state->num_private_objs; i++) { - void *obj_state = state->private_objs[i].obj_state; + struct drm_private_obj *obj = state->private_objs[i].ptr; - state->private_objs[i].funcs->destroy_state(obj_state); - state->private_objs[i].obj = NULL; - state->private_objs[i].obj_state = NULL; - state->private_objs[i].funcs = NULL; + if (!obj) + continue; + + obj->funcs->atomic_destroy_state(obj, + state->private_objs[i].state); + state->private_objs[i].ptr = NULL; + state->private_objs[i].state = NULL; } state->num_private_objs = 0; @@ -989,12 +992,45 @@ static void drm_atomic_plane_print_state(struct drm_printer *p, plane->funcs->atomic_print_state(p, state); } +/** + * drm_atomic_private_obj_init - initialize private object + * @obj: private object + * @state: initial private object state + * @funcs: pointer to the struct of function pointers that identify the object + * type + * + * Initialize the private object, which can be embedded into any + * driver private object that needs its own atomic state. + */ +void +drm_atomic_private_obj_init(struct drm_private_obj *obj, + struct drm_private_state *state, + const struct drm_private_state_funcs *funcs) +{ + memset(obj, 0, sizeof(*obj)); + + obj->state = state; + obj->funcs = funcs; +} +EXPORT_SYMBOL(drm_atomic_private_obj_init); + +/** + * drm_atomic_private_obj_fini - finalize private object + * @obj: private object + * + * Finalize the private object. + */ +void +drm_atomic_private_obj_fini(struct drm_private_obj *obj) +{ + obj->funcs->atomic_destroy_state(obj, obj->state); +} +EXPORT_SYMBOL(drm_atomic_private_obj_fini); + /** * drm_atomic_get_private_obj_state - get private object state * @state: global atomic state * @obj: private object to get the state for - * @funcs: pointer to the struct of function pointers that identify the object - * type * * This function returns the private object state for the given private object, * allocating the state if needed. It does not grab any locks as the caller is @@ -1004,17 +1040,18 @@ static void drm_atomic_plane_print_state(struct drm_printer *p, * * Either the allocated state or the error code encoded into a pointer. */ -void * -drm_atomic_get_private_obj_state(struct drm_atomic_state *state, void *obj, - const struct drm_private_state_funcs *funcs) +struct drm_private_state * +drm_atomic_get_private_obj_state(struct drm_atomic_state *state, + struct drm_private_obj *obj) { int index, num_objs, i; size_t size; struct __drm_private_objs_state *arr; + struct drm_private_state *obj_state; for (i = 0; i < state->num_private_objs; i++) - if (obj == state->private_objs[i].obj) - return state->private_objs[i].obj_state; + if (obj == state->private_objs[i].ptr) + return state->private_objs[i].state; num_objs = state->num_private_objs + 1; size = sizeof(*state->private_objs) * num_objs; @@ -1026,18 +1063,21 @@ drm_atomic_get_private_obj_state(struct drm_atomic_state *state, void *obj, index = state->num_private_objs; memset(&state->private_objs[index], 0, sizeof(*state->private_objs)); - state->private_objs[index].obj_state = funcs->duplicate_state(state, obj); - if (!state->private_objs[index].obj_state) + obj_state = obj->funcs->atomic_duplicate_state(obj); + if (!obj_state) return ERR_PTR(-ENOMEM); - state->private_objs[index].obj = obj; - state->private_objs[index].funcs = funcs; + state->private_objs[index].state = obj_state; + state->private_objs[index].old_state = obj->state; + state->private_objs[index].new_state = obj_state; + state->private_objs[index].ptr = obj; + state->num_private_objs = num_objs; - DRM_DEBUG_ATOMIC("Added new private object state %p to %p\n", - state->private_objs[index].obj_state, state); + DRM_DEBUG_ATOMIC("Added new private object %p state %p to %p\n", + obj, obj_state, state); - return state->private_objs[index].obj_state; + return obj_state; } EXPORT_SYMBOL(drm_atomic_get_private_obj_state); diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 0fed20692df4..fa64b31ae579 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -2267,8 +2267,8 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state, struct drm_plane *plane; struct drm_plane_state *old_plane_state, *new_plane_state; struct drm_crtc_commit *commit; - void *obj, *obj_state; - const struct drm_private_state_funcs *funcs; + struct drm_private_obj *obj; + struct drm_private_state *old_obj_state, *new_obj_state; if (stall) { for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { @@ -2330,8 +2330,15 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state, plane->state = new_plane_state; } - __for_each_private_obj(state, obj, obj_state, i, funcs) - funcs->swap_state(obj, &state->private_objs[i].obj_state); + for_each_oldnew_private_obj_in_state(state, obj, old_obj_state, new_obj_state, i) { + WARN_ON(obj->state != old_obj_state); + + old_obj_state->state = state; + new_obj_state->state = NULL; + + state->private_objs[i].state = old_obj_state; + obj->state = new_obj_state; + } } EXPORT_SYMBOL(drm_atomic_helper_swap_state); @@ -3828,3 +3835,18 @@ fail: return ret; } EXPORT_SYMBOL(drm_atomic_helper_legacy_gamma_set); + +/** + * __drm_atomic_helper_private_duplicate_state - copy atomic private state + * @obj: CRTC object + * @state: new private object state + * + * Copies atomic state from a private objects's current state and resets inferred values. + * This is useful for drivers that subclass the private state. + */ +void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj, + struct drm_private_state *state) +{ + memcpy(state, obj->state, sizeof(*state)); +} +EXPORT_SYMBOL(__drm_atomic_helper_private_obj_duplicate_state); diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 18cecd94acb6..552e71d5aa5f 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -31,6 +31,8 @@ #include #include +#include +#include /** * DOC: dp mst helper @@ -2992,41 +2994,32 @@ static void drm_dp_destroy_connector_work(struct work_struct *work) (*mgr->cbs->hotplug)(mgr); } -void *drm_dp_mst_duplicate_state(struct drm_atomic_state *state, void *obj) +static struct drm_private_state * +drm_dp_mst_duplicate_state(struct drm_private_obj *obj) { - struct drm_dp_mst_topology_mgr *mgr = obj; - struct drm_dp_mst_topology_state *new_mst_state; + struct drm_dp_mst_topology_state *state; - if (WARN_ON(!mgr->state)) + state = kmemdup(obj->state, sizeof(*state), GFP_KERNEL); + if (!state) return NULL; - new_mst_state = kmemdup(mgr->state, sizeof(*new_mst_state), GFP_KERNEL); - if (new_mst_state) - new_mst_state->state = state; - return new_mst_state; -} - -void drm_dp_mst_swap_state(void *obj, void **obj_state_ptr) -{ - struct drm_dp_mst_topology_mgr *mgr = obj; - struct drm_dp_mst_topology_state **topology_state_ptr; - - topology_state_ptr = (struct drm_dp_mst_topology_state **)obj_state_ptr; + __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base); - mgr->state->state = (*topology_state_ptr)->state; - swap(*topology_state_ptr, mgr->state); - mgr->state->state = NULL; + return &state->base; } -void drm_dp_mst_destroy_state(void *obj_state) +static void drm_dp_mst_destroy_state(struct drm_private_obj *obj, + struct drm_private_state *state) { - kfree(obj_state); + struct drm_dp_mst_topology_state *mst_state = + to_dp_mst_topology_state(state); + + kfree(mst_state); } static const struct drm_private_state_funcs mst_state_funcs = { - .duplicate_state = drm_dp_mst_duplicate_state, - .swap_state = drm_dp_mst_swap_state, - .destroy_state = drm_dp_mst_destroy_state, + .atomic_duplicate_state = drm_dp_mst_duplicate_state, + .atomic_destroy_state = drm_dp_mst_destroy_state, }; /** @@ -3050,8 +3043,7 @@ struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_a struct drm_device *dev = mgr->dev; WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); - return drm_atomic_get_private_obj_state(state, mgr, - &mst_state_funcs); + return to_dp_mst_topology_state(drm_atomic_get_private_obj_state(state, &mgr->base)); } EXPORT_SYMBOL(drm_atomic_get_mst_topology_state); @@ -3071,6 +3063,8 @@ int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr, int max_dpcd_transaction_bytes, int max_payloads, int conn_base_id) { + struct drm_dp_mst_topology_state *mst_state; + mutex_init(&mgr->lock); mutex_init(&mgr->qlock); mutex_init(&mgr->payload_lock); @@ -3099,14 +3093,18 @@ int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr, if (test_calc_pbn_mode() < 0) DRM_ERROR("MST PBN self-test failed\n"); - mgr->state = kzalloc(sizeof(*mgr->state), GFP_KERNEL); - if (mgr->state == NULL) + mst_state = kzalloc(sizeof(*mst_state), GFP_KERNEL); + if (mst_state == NULL) return -ENOMEM; - mgr->state->mgr = mgr; + + mst_state->mgr = mgr; /* max. time slots - one slot for MTP header */ - mgr->state->avail_slots = 63; - mgr->funcs = &mst_state_funcs; + mst_state->avail_slots = 63; + + drm_atomic_private_obj_init(&mgr->base, + &mst_state->base, + &mst_state_funcs); return 0; } @@ -3128,8 +3126,7 @@ void drm_dp_mst_topology_mgr_destroy(struct drm_dp_mst_topology_mgr *mgr) mutex_unlock(&mgr->payload_lock); mgr->dev = NULL; mgr->aux = NULL; - kfree(mgr->state); - mgr->state = NULL; + drm_atomic_private_obj_fini(&mgr->base); mgr->funcs = NULL; } EXPORT_SYMBOL(drm_dp_mst_topology_mgr_destroy); diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index dcc8e0cdb7ff..7cd0f303f5a3 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -154,6 +154,9 @@ struct __drm_connnectors_state { struct drm_connector_state *state, *old_state, *new_state; }; +struct drm_private_obj; +struct drm_private_state; + /** * struct drm_private_state_funcs - atomic state functions for private objects * @@ -166,7 +169,7 @@ struct __drm_connnectors_state { */ struct drm_private_state_funcs { /** - * @duplicate_state: + * @atomic_duplicate_state: * * Duplicate the current state of the private object and return it. It * is an error to call this before obj->state has been initialized. @@ -176,29 +179,30 @@ struct drm_private_state_funcs { * Duplicated atomic state or NULL when obj->state is not * initialized or allocation failed. */ - void *(*duplicate_state)(struct drm_atomic_state *state, void *obj); + struct drm_private_state *(*atomic_duplicate_state)(struct drm_private_obj *obj); /** - * @swap_state: + * @atomic_destroy_state: * - * This function swaps the existing state of a private object @obj with - * it's newly created state, the pointer to which is passed as - * @obj_state_ptr. + * Frees the private object state created with @atomic_duplicate_state. */ - void (*swap_state)(void *obj, void **obj_state_ptr); + void (*atomic_destroy_state)(struct drm_private_obj *obj, + struct drm_private_state *state); +}; - /** - * @destroy_state: - * - * Frees the private object state created with @duplicate_state. - */ - void (*destroy_state)(void *obj_state); +struct drm_private_obj { + struct drm_private_state *state; + + const struct drm_private_state_funcs *funcs; +}; + +struct drm_private_state { + struct drm_atomic_state *state; }; struct __drm_private_objs_state { - void *obj; - void *obj_state; - const struct drm_private_state_funcs *funcs; + struct drm_private_obj *ptr; + struct drm_private_state *state, *old_state, *new_state; }; /** @@ -321,10 +325,14 @@ int drm_atomic_connector_set_property(struct drm_connector *connector, struct drm_connector_state *state, struct drm_property *property, uint64_t val); -void * __must_check +void drm_atomic_private_obj_init(struct drm_private_obj *obj, + struct drm_private_state *state, + const struct drm_private_state_funcs *funcs); +void drm_atomic_private_obj_fini(struct drm_private_obj *obj); + +struct drm_private_state * __must_check drm_atomic_get_private_obj_state(struct drm_atomic_state *state, - void *obj, - const struct drm_private_state_funcs *funcs); + struct drm_private_obj *obj); /** * drm_atomic_get_existing_crtc_state - get crtc state, if it exists @@ -811,43 +819,63 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); for_each_if (plane) /** - * __for_each_private_obj - iterate over all private objects + * for_each_oldnew_private_obj_in_state - iterate over all private objects in an atomic update * @__state: &struct drm_atomic_state pointer - * @obj: private object iteration cursor - * @obj_state: private object state iteration cursor + * @obj: &struct drm_private_obj iteration cursor + * @old_obj_state: &struct drm_private_state iteration cursor for the old state + * @new_obj_state: &struct drm_private_state iteration cursor for the new state * @__i: int iteration cursor, for macro-internal use - * @__funcs: &struct drm_private_state_funcs iteration cursor * - * This macro iterates over the array containing private object data in atomic - * state + * This iterates over all private objects in an atomic update, tracking both + * old and new state. This is useful in places where the state delta needs + * to be considered, for example in atomic check functions. */ -#define __for_each_private_obj(__state, obj, obj_state, __i, __funcs) \ - for ((__i) = 0; \ - (__i) < (__state)->num_private_objs && \ - ((obj) = (__state)->private_objs[__i].obj, \ - (__funcs) = (__state)->private_objs[__i].funcs, \ - (obj_state) = (__state)->private_objs[__i].obj_state, \ - 1); \ - (__i)++) \ +#define for_each_oldnew_private_obj_in_state(__state, obj, old_obj_state, new_obj_state, __i) \ + for ((__i) = 0; \ + (__i) < (__state)->num_private_objs && \ + ((obj) = (__state)->private_objs[__i].ptr, \ + (old_obj_state) = (__state)->private_objs[__i].old_state, \ + (new_obj_state) = (__state)->private_objs[__i].new_state, 1); \ + (__i)++) \ + for_each_if (obj) + +/** + * for_each_old_private_obj_in_state - iterate over all private objects in an atomic update + * @__state: &struct drm_atomic_state pointer + * @obj: &struct drm_private_obj iteration cursor + * @old_obj_state: &struct drm_private_state iteration cursor for the old state + * @__i: int iteration cursor, for macro-internal use + * + * This iterates over all private objects in an atomic update, tracking only + * the old state. This is useful in disable functions, where we need the old + * state the hardware is still in. + */ +#define for_each_old_private_obj_in_state(__state, obj, old_obj_state, __i) \ + for ((__i) = 0; \ + (__i) < (__state)->num_private_objs && \ + ((obj) = (__state)->private_objs[__i].ptr, \ + (old_obj_state) = (__state)->private_objs[__i].old_state, 1); \ + (__i)++) \ + for_each_if (obj) /** - * for_each_private_obj - iterate over a specify type of private object + * for_each_new_private_obj_in_state - iterate over all private objects in an atomic update * @__state: &struct drm_atomic_state pointer - * @obj_funcs: &struct drm_private_state_funcs function table to filter - * private objects - * @obj: private object iteration cursor - * @obj_state: private object state iteration cursor + * @obj: &struct drm_private_obj iteration cursor + * @new_obj_state: &struct drm_private_state iteration cursor for the new state * @__i: int iteration cursor, for macro-internal use - * @__funcs: &struct drm_private_state_funcs iteration cursor * - * This macro iterates over the private objects state array while filtering the - * objects based on the vfunc table that is passed as @obj_funcs. New macros - * can be created by passing in the vfunc table associated with a specific - * private object. + * This iterates over all private objects in an atomic update, tracking only + * the new state. This is useful in enable functions, where we need the new state the + * hardware should be in when the atomic commit operation has completed. */ -#define for_each_private_obj(__state, obj_funcs, obj, obj_state, __i, __funcs) \ - __for_each_private_obj(__state, obj, obj_state, __i, __funcs) \ - for_each_if (__funcs == obj_funcs) +#define for_each_new_private_obj_in_state(__state, obj, new_obj_state, __i) \ + for ((__i) = 0; \ + (__i) < (__state)->num_private_objs && \ + ((obj) = (__state)->private_objs[__i].ptr, \ + (new_obj_state) = (__state)->private_objs[__i].new_state, 1); \ + (__i)++) \ + for_each_if (obj) /** * drm_atomic_crtc_needs_modeset - compute combined modeset need diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index dd196cc0afd7..7db3438ff735 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -33,6 +33,8 @@ #include struct drm_atomic_state; +struct drm_private_obj; +struct drm_private_state; int drm_atomic_helper_check_modeset(struct drm_device *dev, struct drm_atomic_state *state); @@ -185,6 +187,8 @@ int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue, uint32_t size, struct drm_modeset_acquire_ctx *ctx); +void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj, + struct drm_private_state *state); /** * drm_atomic_crtc_for_each_plane - iterate over planes currently attached to CRTC diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h index 177ab6f86855..d55abb75f29a 100644 --- a/include/drm/drm_dp_mst_helper.h +++ b/include/drm/drm_dp_mst_helper.h @@ -404,12 +404,17 @@ struct drm_dp_payload { int vcpi; }; +#define to_dp_mst_topology_state(x) container_of(x, struct drm_dp_mst_topology_state, base) + struct drm_dp_mst_topology_state { + struct drm_private_state base; int avail_slots; struct drm_atomic_state *state; struct drm_dp_mst_topology_mgr *mgr; }; +#define to_dp_mst_topology_mgr(x) container_of(x, struct drm_dp_mst_topology_mgr, base) + /** * struct drm_dp_mst_topology_mgr - DisplayPort MST manager * @@ -418,6 +423,11 @@ struct drm_dp_mst_topology_state { * on the GPU. */ struct drm_dp_mst_topology_mgr { + /** + * @base: Base private object for atomic + */ + struct drm_private_obj base; + /** * @dev: device pointer for adding i2c devices etc. */ -- cgit v1.2.3 From e38e12895022d7148220fc35782b5bd6461f1736 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 12 Jul 2017 18:52:54 +0300 Subject: drm/dp/mst: Use memchr_inv() instead of memcmp() against a zeroed array MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have memch_inv(), so no need to memcmp() against a zeroed temp array. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/20170712155254.26455-1-ville.syrjala@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/drm_dp_mst_topology.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 552e71d5aa5f..f7e292bf2baf 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -1337,15 +1337,17 @@ static void drm_dp_mst_link_probe_work(struct work_struct *work) static bool drm_dp_validate_guid(struct drm_dp_mst_topology_mgr *mgr, u8 *guid) { - static u8 zero_guid[16]; + u64 salt; - if (!memcmp(guid, zero_guid, 16)) { - u64 salt = get_jiffies_64(); - memcpy(&guid[0], &salt, sizeof(u64)); - memcpy(&guid[8], &salt, sizeof(u64)); - return false; - } - return true; + if (memchr_inv(guid, 0, 16)) + return true; + + salt = get_jiffies_64(); + + memcpy(&guid[0], &salt, sizeof(u64)); + memcpy(&guid[8], &salt, sizeof(u64)); + + return false; } #if 0 -- cgit v1.2.3 From 88be58be886f1215cc73dc8c273c985eecd7385c Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 6 Jul 2017 15:00:19 +0200 Subject: drm/i915/fbdev: Always forward hotplug events With deferred fbdev setup we always need to forward hotplug events, even if fbdev isn't fully set up yet. Otherwise the deferred setup will neer happen. Originally this check was added in commit c45eb4fed12d278d3619f1904885bd0d7bcbf036 (tag: drm-intel-next-fixes-2016-08-05) Author: Chris Wilson Date: Wed Jul 13 18:34:45 2016 +0100 drm/i915/fbdev: Check for the framebuffer before use But the specific case of the hotplug function blowing up was fixed in commit 50c3dc970a09b3b60422a58934cc27a413288bab Author: Daniel Vetter Date: Fri Jun 27 17:19:22 2014 +0200 drm/fb-helper: Fix hpd vs. initial config races Cc: Maarten Lankhorst Cc: Mika Kuoppala Cc: Chris Wilson Reviewed-by: Maarten Lankhorst Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170706130023.28417-1-daniel.vetter@ffwll.ch --- drivers/gpu/drm/i915/intel_fbdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index 0c4cde6b2e6f..ee1a5b937590 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -813,7 +813,7 @@ void intel_fbdev_output_poll_changed(struct drm_device *dev) { struct intel_fbdev *ifbdev = to_i915(dev)->fbdev; - if (ifbdev && ifbdev->vma) + if (ifbdev) drm_fb_helper_hotplug_event(&ifbdev->helper); } -- cgit v1.2.3 From 346fb4e0b9660e2fe888f870608d287e1980f665 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 6 Jul 2017 15:00:20 +0200 Subject: drm/i915: Protect against deferred fbdev setup We could probably hit this already with our current async fbdev init, but it's much easier to hit this with the new deferred fbdev setup that I'm working on polishing. Cc: Maarten Lankhorst Reported-by: Maarten Lankhorst Reviewed-by: Maarten Lankhorst Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170706130023.28417-2-daniel.vetter@ffwll.ch --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 620c9218d1c1..2ef75c1a6119 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1935,7 +1935,7 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data) return ret; #ifdef CONFIG_DRM_FBDEV_EMULATION - if (dev_priv->fbdev) { + if (dev_priv->fbdev && dev_priv->fbdev->helper.fb) { fbdev_fb = to_intel_framebuffer(dev_priv->fbdev->helper.fb); seq_printf(m, "fbcon size: %d x %d, depth %d, %d bpp, modifier 0x%llx, refcount %d, obj ", -- cgit v1.2.3 From 5f057ffd6da26c939dff976a2acc76233bbe4467 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Thu, 13 Jul 2017 18:25:25 +0200 Subject: drm: rename, adjust and export drm_atomic_replace_property_blob The function has little to do with atomic, it's just where it has so far been needed. So, rename it to drm_property_replace_blob, move it to drm_property.c and export it. Change the semantics to return whether the blob was replaced instead of using an extra argument for that. Signed-off-by: Peter Rosin Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170713162538.22788-2-peda@axentia.se --- drivers/gpu/drm/drm_atomic.c | 30 +----------------------------- drivers/gpu/drm/drm_property.c | 23 +++++++++++++++++++++++ include/drm/drm_property.h | 2 ++ 3 files changed, 26 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index b59fd33c5786..01192dd3ed79 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -411,34 +411,6 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state, } EXPORT_SYMBOL(drm_atomic_set_mode_prop_for_crtc); -/** - * drm_atomic_replace_property_blob - replace a blob property - * @blob: a pointer to the member blob to be replaced - * @new_blob: the new blob to replace with - * @replaced: whether the blob has been replaced - * - * RETURNS: - * Zero on success, error code on failure - */ -static void -drm_atomic_replace_property_blob(struct drm_property_blob **blob, - struct drm_property_blob *new_blob, - bool *replaced) -{ - struct drm_property_blob *old_blob = *blob; - - if (old_blob == new_blob) - return; - - drm_property_blob_put(old_blob); - if (new_blob) - drm_property_blob_get(new_blob); - *blob = new_blob; - *replaced = true; - - return; -} - static int drm_atomic_replace_property_blob_from_id(struct drm_device *dev, struct drm_property_blob **blob, @@ -459,7 +431,7 @@ drm_atomic_replace_property_blob_from_id(struct drm_device *dev, } } - drm_atomic_replace_property_blob(blob, new_blob, replaced); + *replaced |= drm_property_replace_blob(blob, new_blob); drm_property_blob_put(new_blob); return 0; diff --git a/drivers/gpu/drm/drm_property.c b/drivers/gpu/drm/drm_property.c index 3e88fa24eab3..bc5128203056 100644 --- a/drivers/gpu/drm/drm_property.c +++ b/drivers/gpu/drm/drm_property.c @@ -709,6 +709,29 @@ err_created: } EXPORT_SYMBOL(drm_property_replace_global_blob); +/** + * drm_property_replace_blob - replace a blob property + * @blob: a pointer to the member blob to be replaced + * @new_blob: the new blob to replace with + * + * Return: true if the blob was in fact replaced. + */ +bool drm_property_replace_blob(struct drm_property_blob **blob, + struct drm_property_blob *new_blob) +{ + struct drm_property_blob *old_blob = *blob; + + if (old_blob == new_blob) + return false; + + drm_property_blob_put(old_blob); + if (new_blob) + drm_property_blob_get(new_blob); + *blob = new_blob; + return true; +} +EXPORT_SYMBOL(drm_property_replace_blob); + int drm_mode_getblob_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { diff --git a/include/drm/drm_property.h b/include/drm/drm_property.h index 619868dc08d8..37355c623e6c 100644 --- a/include/drm/drm_property.h +++ b/include/drm/drm_property.h @@ -273,6 +273,8 @@ int drm_property_replace_global_blob(struct drm_device *dev, const void *data, struct drm_mode_object *obj_holds_id, struct drm_property *prop_holds_id); +bool drm_property_replace_blob(struct drm_property_blob **blob, + struct drm_property_blob *new_blob); struct drm_property_blob *drm_property_blob_get(struct drm_property_blob *blob); void drm_property_blob_put(struct drm_property_blob *blob); -- cgit v1.2.3 From e2b9dd304aed9e1415d4e001b81a10e2a6aeef7b Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Thu, 13 Jul 2017 18:25:26 +0200 Subject: drm/atomic-helper: update lut props directly in ..._legacy_gamma_set Do not waste cycles looking up the property id when we have the actual property already. Signed-off-by: Peter Rosin Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170713162538.22788-3-peda@axentia.se --- drivers/gpu/drm/drm_atomic_helper.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index fa64b31ae579..2f675112e225 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -3776,12 +3776,12 @@ int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc, struct drm_modeset_acquire_ctx *ctx) { struct drm_device *dev = crtc->dev; - struct drm_mode_config *config = &dev->mode_config; struct drm_atomic_state *state; struct drm_crtc_state *crtc_state; struct drm_property_blob *blob = NULL; struct drm_color_lut *blob_data; int i, ret = 0; + bool replaced; state = drm_atomic_state_alloc(crtc->dev); if (!state) @@ -3812,20 +3812,10 @@ int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc, } /* Reset DEGAMMA_LUT and CTM properties. */ - ret = drm_atomic_crtc_set_property(crtc, crtc_state, - config->degamma_lut_property, 0); - if (ret) - goto fail; - - ret = drm_atomic_crtc_set_property(crtc, crtc_state, - config->ctm_property, 0); - if (ret) - goto fail; - - ret = drm_atomic_crtc_set_property(crtc, crtc_state, - config->gamma_lut_property, blob->base.id); - if (ret) - goto fail; + replaced = drm_property_replace_blob(&crtc_state->degamma_lut, NULL); + replaced |= drm_property_replace_blob(&crtc_state->ctm, NULL); + replaced |= drm_property_replace_blob(&crtc_state->gamma_lut, blob); + crtc_state->color_mgmt_changed |= replaced; ret = drm_atomic_commit(state); -- cgit v1.2.3 From 964c60063bff6ae7631eb4d9c0bac3913749ca9f Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Thu, 13 Jul 2017 18:25:27 +0200 Subject: drm/fb-helper: separate the fb_setcmap helper into atomic and legacy paths The legacy path implements setcmap in terms of crtc .gamma_set. The atomic path implements setcmap by directly updating the crtc gamma_lut property. This has a couple of benefits: - it makes the redundant fb helpers .load_lut, .gamma_set and .gamma_get completely obsolete. They are now unused and subject for removal. - atomic drivers that support clut modes get fbdev support for those from the drm core. This includes atmel-hlcdc, but perhaps others as well? Signed-off-by: Peter Rosin Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170713162538.22788-4-peda@axentia.se --- drivers/gpu/drm/drm_fb_helper.c | 231 ++++++++++++++++++++++++++++------------ 1 file changed, 160 insertions(+), 71 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 721511da4de6..42090fe00ef9 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1195,27 +1195,6 @@ void drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper, } EXPORT_SYMBOL(drm_fb_helper_set_suspend_unlocked); -static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green, - u16 blue, u16 regno, struct fb_info *info) -{ - struct drm_fb_helper *fb_helper = info->par; - struct drm_framebuffer *fb = fb_helper->fb; - - /* - * The driver really shouldn't advertise pseudo/directcolor - * visuals if it can't deal with the palette. - */ - if (WARN_ON(!fb_helper->funcs->gamma_set || - !fb_helper->funcs->gamma_get)) - return -EINVAL; - - WARN_ON(fb->format->cpp[0] != 1); - - fb_helper->funcs->gamma_set(crtc, red, green, blue, regno); - - return 0; -} - static int setcmap_pseudo_palette(struct fb_cmap *cmap, struct fb_info *info) { u32 *palette = (u32 *)info->pseudo_palette; @@ -1248,57 +1227,138 @@ static int setcmap_pseudo_palette(struct fb_cmap *cmap, struct fb_info *info) return 0; } -/** - * drm_fb_helper_setcmap - implementation for &fb_ops.fb_setcmap - * @cmap: cmap to set - * @info: fbdev registered by the helper - */ -int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) +static int setcmap_legacy(struct fb_cmap *cmap, struct fb_info *info) { struct drm_fb_helper *fb_helper = info->par; - struct drm_device *dev = fb_helper->dev; - const struct drm_crtc_helper_funcs *crtc_funcs; - u16 *red, *green, *blue, *transp; struct drm_crtc *crtc; u16 *r, *g, *b; - int i, j, rc = 0; - int start; + int i, ret = 0; - if (oops_in_progress) - return -EBUSY; + drm_modeset_lock_all(fb_helper->dev); + for (i = 0; i < fb_helper->crtc_count; i++) { + crtc = fb_helper->crtc_info[i].mode_set.crtc; + if (!crtc->funcs->gamma_set || !crtc->gamma_size) + return -EINVAL; - mutex_lock(&fb_helper->lock); - if (!drm_fb_helper_is_bound(fb_helper)) { - mutex_unlock(&fb_helper->lock); - return -EBUSY; + if (cmap->start + cmap->len > crtc->gamma_size) + return -EINVAL; + + r = crtc->gamma_store; + g = r + crtc->gamma_size; + b = g + crtc->gamma_size; + + memcpy(r + cmap->start, cmap->red, cmap->len * sizeof(*r)); + memcpy(g + cmap->start, cmap->green, cmap->len * sizeof(*g)); + memcpy(b + cmap->start, cmap->blue, cmap->len * sizeof(*b)); + + ret = crtc->funcs->gamma_set(crtc, r, g, b, + crtc->gamma_size, NULL); + if (ret) + return ret; } + drm_modeset_unlock_all(fb_helper->dev); - drm_modeset_lock_all(dev); - if (info->fix.visual == FB_VISUAL_TRUECOLOR) { - rc = setcmap_pseudo_palette(cmap, info); - goto out; + return ret; +} + +static struct drm_property_blob *setcmap_new_gamma_lut(struct drm_crtc *crtc, + struct fb_cmap *cmap) +{ + struct drm_device *dev = crtc->dev; + struct drm_property_blob *gamma_lut; + struct drm_color_lut *lut; + int size = crtc->gamma_size; + int i; + + if (!size || cmap->start + cmap->len > size) + return ERR_PTR(-EINVAL); + + gamma_lut = drm_property_create_blob(dev, sizeof(*lut) * size, NULL); + if (IS_ERR(gamma_lut)) + return gamma_lut; + + lut = (struct drm_color_lut *)gamma_lut->data; + if (cmap->start || cmap->len != size) { + u16 *r = crtc->gamma_store; + u16 *g = r + crtc->gamma_size; + u16 *b = g + crtc->gamma_size; + + for (i = 0; i < cmap->start; i++) { + lut[i].red = r[i]; + lut[i].green = g[i]; + lut[i].blue = b[i]; + } + for (i = cmap->start + cmap->len; i < size; i++) { + lut[i].red = r[i]; + lut[i].green = g[i]; + lut[i].blue = b[i]; + } + } + + for (i = 0; i < cmap->len; i++) { + lut[cmap->start + i].red = cmap->red[i]; + lut[cmap->start + i].green = cmap->green[i]; + lut[cmap->start + i].blue = cmap->blue[i]; + } + + return gamma_lut; +} + +static int setcmap_atomic(struct fb_cmap *cmap, struct fb_info *info) +{ + struct drm_fb_helper *fb_helper = info->par; + struct drm_device *dev = fb_helper->dev; + struct drm_property_blob *gamma_lut = NULL; + struct drm_modeset_acquire_ctx ctx; + struct drm_crtc_state *crtc_state; + struct drm_atomic_state *state; + struct drm_crtc *crtc; + u16 *r, *g, *b; + int i, ret = 0; + bool replaced; + + drm_modeset_acquire_init(&ctx, 0); + + state = drm_atomic_state_alloc(dev); + if (!state) { + ret = -ENOMEM; + goto out_ctx; } + state->acquire_ctx = &ctx; +retry: for (i = 0; i < fb_helper->crtc_count; i++) { crtc = fb_helper->crtc_info[i].mode_set.crtc; - crtc_funcs = crtc->helper_private; - red = cmap->red; - green = cmap->green; - blue = cmap->blue; - transp = cmap->transp; - start = cmap->start; - - if (!crtc->gamma_size) { - rc = -EINVAL; - goto out; + if (!gamma_lut) + gamma_lut = setcmap_new_gamma_lut(crtc, cmap); + if (IS_ERR(gamma_lut)) { + ret = PTR_ERR(gamma_lut); + gamma_lut = NULL; + goto out_state; } - if (cmap->start + cmap->len > crtc->gamma_size) { - rc = -EINVAL; - goto out; + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (IS_ERR(crtc_state)) { + ret = PTR_ERR(crtc_state); + goto out_state; } + replaced = drm_property_replace_blob(&crtc_state->degamma_lut, + NULL); + replaced |= drm_property_replace_blob(&crtc_state->ctm, NULL); + replaced |= drm_property_replace_blob(&crtc_state->gamma_lut, + gamma_lut); + crtc_state->color_mgmt_changed |= replaced; + } + + ret = drm_atomic_commit(state); + if (ret) + goto out_state; + + for (i = 0; i < fb_helper->crtc_count; i++) { + crtc = fb_helper->crtc_info[i].mode_set.crtc; + r = crtc->gamma_store; g = r + crtc->gamma_size; b = g + crtc->gamma_size; @@ -1306,28 +1366,57 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) memcpy(r + cmap->start, cmap->red, cmap->len * sizeof(*r)); memcpy(g + cmap->start, cmap->green, cmap->len * sizeof(*g)); memcpy(b + cmap->start, cmap->blue, cmap->len * sizeof(*b)); + } + +out_state: + if (ret == -EDEADLK) + goto backoff; + + drm_property_blob_put(gamma_lut); + drm_atomic_state_put(state); +out_ctx: + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); - for (j = 0; j < cmap->len; j++) { - u16 hred, hgreen, hblue, htransp = 0xffff; + return ret; - hred = *red++; - hgreen = *green++; - hblue = *blue++; +backoff: + drm_atomic_state_clear(state); + drm_modeset_backoff(&ctx); + goto retry; +} - if (transp) - htransp = *transp++; +/** + * drm_fb_helper_setcmap - implementation for &fb_ops.fb_setcmap + * @cmap: cmap to set + * @info: fbdev registered by the helper + */ +int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) +{ + struct drm_fb_helper *fb_helper = info->par; + int ret; - rc = setcolreg(crtc, hred, hgreen, hblue, start++, info); - if (rc) - goto out; - } - if (crtc_funcs->load_lut) - crtc_funcs->load_lut(crtc); + if (oops_in_progress) + return -EBUSY; + + mutex_lock(&fb_helper->lock); + + if (!drm_fb_helper_is_bound(fb_helper)) { + ret = -EBUSY; + goto out; } - out: - drm_modeset_unlock_all(dev); + + if (info->fix.visual == FB_VISUAL_TRUECOLOR) + ret = setcmap_pseudo_palette(cmap, info); + else if (drm_drv_uses_atomic_modeset(fb_helper->dev)) + ret = setcmap_atomic(cmap, info); + else + ret = setcmap_legacy(cmap, info); + +out: mutex_unlock(&fb_helper->lock); - return rc; + + return ret; } EXPORT_SYMBOL(drm_fb_helper_setcmap); -- cgit v1.2.3 From 7611750784664db46d0db95631e322aeb263dde7 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 21 Jun 2017 12:31:41 -0400 Subject: drm/amdgpu: use kernel is_power_of_2 rather than local version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the kernel provided version. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 2fe1e0a20c17..f3811f6197e0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1031,19 +1031,6 @@ static unsigned int amdgpu_vga_set_decode(void *cookie, bool state) return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; } -/** - * amdgpu_check_pot_argument - check that argument is a power of two - * - * @arg: value to check - * - * Validates that a certain argument is a power of two (all asics). - * Returns true if argument is valid. - */ -static bool amdgpu_check_pot_argument(int arg) -{ - return (arg & (arg - 1)) == 0; -} - static void amdgpu_check_block_size(struct amdgpu_device *adev) { /* defines number of bits in page table versus page directory, @@ -1077,7 +1064,7 @@ static void amdgpu_check_vm_size(struct amdgpu_device *adev) if (amdgpu_vm_size == -1) return; - if (!amdgpu_check_pot_argument(amdgpu_vm_size)) { + if (!is_power_of_2(amdgpu_vm_size)) { dev_warn(adev->dev, "VM size (%d) must be a power of 2\n", amdgpu_vm_size); goto def_value; @@ -1118,7 +1105,7 @@ static void amdgpu_check_arguments(struct amdgpu_device *adev) dev_warn(adev->dev, "sched jobs (%d) must be at least 4\n", amdgpu_sched_jobs); amdgpu_sched_jobs = 4; - } else if (!amdgpu_check_pot_argument(amdgpu_sched_jobs)){ + } else if (!is_power_of_2(amdgpu_sched_jobs)){ dev_warn(adev->dev, "sched jobs (%d) must be a power of 2\n", amdgpu_sched_jobs); amdgpu_sched_jobs = roundup_pow_of_two(amdgpu_sched_jobs); @@ -1138,7 +1125,7 @@ static void amdgpu_check_arguments(struct amdgpu_device *adev) amdgpu_check_block_size(adev); if (amdgpu_vram_page_split != -1 && (amdgpu_vram_page_split < 16 || - !amdgpu_check_pot_argument(amdgpu_vram_page_split))) { + !is_power_of_2(amdgpu_vram_page_split))) { dev_warn(adev->dev, "invalid VRAM page split (%d)\n", amdgpu_vram_page_split); amdgpu_vram_page_split = 1024; -- cgit v1.2.3 From fd66560b803e32c873164105a0864fdfc1163633 Mon Sep 17 00:00:00 2001 From: Hawking Zhang Date: Thu, 22 Jun 2017 13:09:43 +0800 Subject: drm/amdgpu: enable 4 level page table on raven (v3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v1: enable 4 level-page table on raven v2: add back legacy 2 level page table on raven v3: set num_level in initial switch statement Signed-off-by: Hawking Zhang Reviewed-by: Alex Deucher Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 175ba5f9691c..c6394ea69f96 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -537,10 +537,20 @@ static int gmc_v9_0_sw_init(void *handle) spin_lock_init(&adev->mc.invalidate_lock); - if (adev->flags & AMD_IS_APU) { + switch (adev->asic_type) { + case CHIP_RAVEN: adev->mc.vram_type = AMDGPU_VRAM_TYPE_UNKNOWN; - amdgpu_vm_adjust_size(adev, 64); - } else { + if (adev->rev_id == 0x0 || adev->rev_id == 0x1) { + adev->vm_manager.vm_size = 1U << 18; + adev->vm_manager.block_size = 9; + adev->vm_manager.num_level = 3; + } else { + /* vm_size is 64GB for legacy 2-level page support*/ + amdgpu_vm_adjust_size(adev, 64); + adev->vm_manager.num_level = 1; + } + break; + case CHIP_VEGA10: /* XXX Don't know how to get VRAM type yet. */ adev->mc.vram_type = AMDGPU_VRAM_TYPE_HBM; /* @@ -550,11 +560,16 @@ static int gmc_v9_0_sw_init(void *handle) */ adev->vm_manager.vm_size = 1U << 18; adev->vm_manager.block_size = 9; - DRM_INFO("vm size is %llu GB, block size is %u-bit\n", - adev->vm_manager.vm_size, - adev->vm_manager.block_size); + adev->vm_manager.num_level = 3; + break; + default: + break; } + DRM_INFO("vm size is %llu GB, block size is %u-bit\n", + adev->vm_manager.vm_size, + adev->vm_manager.block_size); + /* This interrupt is VMC page fault.*/ r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_VMC, 0, &adev->mc.vm_fault); @@ -619,11 +634,6 @@ static int gmc_v9_0_sw_init(void *handle) adev->vm_manager.id_mgr[AMDGPU_GFXHUB].num_ids = AMDGPU_NUM_OF_VMIDS; adev->vm_manager.id_mgr[AMDGPU_MMHUB].num_ids = AMDGPU_NUM_OF_VMIDS; - /* TODO: fix num_level for APU when updating vm size and block size */ - if (adev->flags & AMD_IS_APU) - adev->vm_manager.num_level = 1; - else - adev->vm_manager.num_level = 3; amdgpu_vm_manager_init(adev); return 0; -- cgit v1.2.3 From dd0792c1be56843b12008ccc625dc7bad8efd7ab Mon Sep 17 00:00:00 2001 From: Christian König Date: Tue, 27 Jun 2017 14:48:15 -0400 Subject: drm/amdgpu: simplify VM shadow handling v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that we don't join PTE updates any more we don't need to call the update function twice for this. v2: rebased Signed-off-by: Christian König Reviewed-by: Chunming Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 5795f81369f0..cda9e5d8b831 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -77,8 +77,6 @@ struct amdgpu_pte_update_params { void (*func)(struct amdgpu_pte_update_params *params, uint64_t pe, uint64_t addr, unsigned count, uint32_t incr, uint64_t flags); - /* indicate update pt or its shadow */ - bool shadow; /* The next two are used during VM update by CPU * DMA addresses to use for mapping * Kernel pointer of PD/PT BO that needs to be updated @@ -1299,16 +1297,6 @@ static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params, return -EINVAL; } - if (params->shadow) { - if (WARN_ONCE(use_cpu_update, - "CPU VM update doesn't suuport shadow pages")) - return 0; - - if (!pt->shadow) - return 0; - pt = pt->shadow; - } - if ((addr & ~mask) == (end & ~mask)) nptes = end - addr; else @@ -1318,11 +1306,20 @@ static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params, r = amdgpu_bo_kmap(pt, (void *)&pe_start); if (r) return r; - } else + + WARN_ONCE(pt->shadow, + "CPU VM update doesn't support shadow pages"); + } else { + if (pt->shadow) { + pe_start = amdgpu_bo_gpu_offset(pt->shadow); + pe_start += (addr & mask) * 8; + params->func(params, pe_start, dst, nptes, + AMDGPU_GPU_PAGE_SIZE, flags); + } pe_start = amdgpu_bo_gpu_offset(pt); + } pe_start += (addr & mask) * 8; - params->func(params, pe_start, dst, nptes, AMDGPU_GPU_PAGE_SIZE, flags); @@ -1459,7 +1456,6 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, params.func = amdgpu_vm_cpu_set_ptes; params.pages_addr = pages_addr; - params.shadow = false; return amdgpu_vm_frag_ptes(¶ms, start, last + 1, addr, flags); } @@ -1542,11 +1538,6 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, if (r) goto error_free; - params.shadow = true; - r = amdgpu_vm_frag_ptes(¶ms, start, last + 1, addr, flags); - if (r) - goto error_free; - params.shadow = false; r = amdgpu_vm_frag_ptes(¶ms, start, last + 1, addr, flags); if (r) goto error_free; -- cgit v1.2.3 From 84b5d3d10d6c7b8ff53e756217405a535691ff7d Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 19 Jun 2017 17:00:38 -0400 Subject: drm/amdgpu: disable vga render in dce hw_init This got dropped accidently with the fb location changes, but for some reason, this doesn't seem to cause an issue on all cards which is why I never saw it despite extensive testing. I suspect it may only be an issue on systems with a legacy sbios that enables vga. Tested-by: Andres Rodriguez Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/dce_v10_0.c | 2 ++ drivers/gpu/drm/amd/amdgpu/dce_v11_0.c | 2 ++ drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 2 ++ drivers/gpu/drm/amd/amdgpu/dce_v8_0.c | 2 ++ 4 files changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index 9f78c03a2e31..9bda363e02be 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c @@ -3025,6 +3025,8 @@ static int dce_v10_0_hw_init(void *handle) dce_v10_0_init_golden_registers(adev); + /* disable vga render */ + dce_v10_0_set_vga_render_state(adev, false); /* init dig PHYs, disp eng pll */ amdgpu_atombios_encoder_init_dig(adev); amdgpu_atombios_crtc_set_disp_eng_pll(adev, adev->clock.default_dispclk); diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index 4bcf01dc567a..c02c7fb75c63 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c @@ -3086,6 +3086,8 @@ static int dce_v11_0_hw_init(void *handle) dce_v11_0_init_golden_registers(adev); + /* disable vga render */ + dce_v11_0_set_vga_render_state(adev, false); /* init dig PHYs, disp eng pll */ amdgpu_atombios_crtc_powergate_init(adev); amdgpu_atombios_encoder_init_dig(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index fd134a4629d7..0a8ad0fc13ea 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -2873,6 +2873,8 @@ static int dce_v6_0_hw_init(void *handle) int i; struct amdgpu_device *adev = (struct amdgpu_device *)handle; + /* disable vga render */ + dce_v6_0_set_vga_render_state(adev, false); /* init dig PHYs, disp eng pll */ amdgpu_atombios_encoder_init_dig(adev); amdgpu_atombios_crtc_set_disp_eng_pll(adev, adev->clock.default_dispclk); diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c index a9e869554627..7e06c36b6ee9 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c @@ -2870,6 +2870,8 @@ static int dce_v8_0_hw_init(void *handle) int i; struct amdgpu_device *adev = (struct amdgpu_device *)handle; + /* disable vga render */ + dce_v8_0_set_vga_render_state(adev, false); /* init dig PHYs, disp eng pll */ amdgpu_atombios_encoder_init_dig(adev); amdgpu_atombios_crtc_set_disp_eng_pll(adev, adev->clock.default_dispclk); -- cgit v1.2.3 From 9081c4cf7d4ea40cf7e77e8efe3c2bedb924b830 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 1 Nov 2016 13:08:33 -0400 Subject: drm/amdgpu/gmc8: use the vram location programmed by the vbios MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes mc programming much simpler in future patches. Since evergreen, the vbios has been programming the fb location to the proper vram size. The only reason to reprogram it would be to change the location. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index cc9f88057cd5..1c8c0f536aed 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -404,13 +404,16 @@ static int gmc_v8_0_polaris_mc_load_microcode(struct amdgpu_device *adev) static void gmc_v8_0_vram_gtt_location(struct amdgpu_device *adev, struct amdgpu_mc *mc) { + u64 base = RREG32(mmMC_VM_FB_LOCATION) & 0xFFFF; + base <<= 24; + if (mc->mc_vram_size > 0xFFC0000000ULL) { /* leave room for at least 1024M GTT */ dev_warn(adev->dev, "limiting VRAM\n"); mc->real_vram_size = 0xFFC0000000ULL; mc->mc_vram_size = 0xFFC0000000ULL; } - amdgpu_vram_location(adev, &adev->mc, 0); + amdgpu_vram_location(adev, &adev->mc, base); adev->mc.gtt_base_align = 0; amdgpu_gtt_location(adev, mc); } -- cgit v1.2.3 From e0205a7156a62bfcaa3f3f2ed556faf3c9b38aad Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 1 Nov 2016 13:14:45 -0400 Subject: drm/amdgpu/gmc7: use the vram location programmed by the vbios MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes mc programming much simpler in future patches. Since evergreen, the vbios has been programming the fb location to the proper vram size. The only reason to reprogram it would be to change the location. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c index 7e9ea53edf8b..0fc7d31176a5 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c @@ -242,13 +242,16 @@ static int gmc_v7_0_mc_load_microcode(struct amdgpu_device *adev) static void gmc_v7_0_vram_gtt_location(struct amdgpu_device *adev, struct amdgpu_mc *mc) { + u64 base = RREG32(mmMC_VM_FB_LOCATION) & 0xFFFF; + base <<= 24; + if (mc->mc_vram_size > 0xFFC0000000ULL) { /* leave room for at least 1024M GTT */ dev_warn(adev->dev, "limiting VRAM\n"); mc->real_vram_size = 0xFFC0000000ULL; mc->mc_vram_size = 0xFFC0000000ULL; } - amdgpu_vram_location(adev, &adev->mc, 0); + amdgpu_vram_location(adev, &adev->mc, base); adev->mc.gtt_base_align = 0; amdgpu_gtt_location(adev, mc); } -- cgit v1.2.3 From ba3a5b83dd9b7490fcab098c875709c03cf439ef Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 1 Nov 2016 13:15:29 -0400 Subject: drm/amdgpu/gmc6: use the vram location programmed by the vbios MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes mc programming much simpler in future patches. Since evergreen, the vbios has been programming the fb location to the proper vram size. The only reason to reprogram it would be to change the location. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c index d0214d942bfc..224b6935c885 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c @@ -228,12 +228,15 @@ static int gmc_v6_0_mc_load_microcode(struct amdgpu_device *adev) static void gmc_v6_0_vram_gtt_location(struct amdgpu_device *adev, struct amdgpu_mc *mc) { + u64 base = RREG32(mmMC_VM_FB_LOCATION) & 0xFFFF; + base <<= 24; + if (mc->mc_vram_size > 0xFFC0000000ULL) { dev_warn(adev->dev, "limiting VRAM\n"); mc->real_vram_size = 0xFFC0000000ULL; mc->mc_vram_size = 0xFFC0000000ULL; } - amdgpu_vram_location(adev, &adev->mc, 0); + amdgpu_vram_location(adev, &adev->mc, base); adev->mc.gtt_base_align = 0; amdgpu_gtt_location(adev, mc); } -- cgit v1.2.3 From cad81e34a8d268146fda82d2379eafb0ce9ea775 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 1 Nov 2016 13:33:28 -0400 Subject: drm/amdgpu/gmc8: drop fb location programming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No need to do this as the vbios does this for us. As such we no longer need to stop the mc during init. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index 1c8c0f536aed..72ab2d04f048 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -428,7 +428,6 @@ static void gmc_v8_0_vram_gtt_location(struct amdgpu_device *adev, */ static void gmc_v8_0_mc_program(struct amdgpu_device *adev) { - struct amdgpu_mode_mc_save save; u32 tmp; int i, j; @@ -442,10 +441,6 @@ static void gmc_v8_0_mc_program(struct amdgpu_device *adev) } WREG32(mmHDP_REG_COHERENCY_FLUSH_CNTL, 0); - if (adev->mode_info.num_crtc) - amdgpu_display_set_vga_render_state(adev, false); - - gmc_v8_0_mc_stop(adev, &save); if (gmc_v8_0_wait_for_idle((void *)adev)) { dev_warn(adev->dev, "Wait for MC idle timedout !\n"); } @@ -456,20 +451,12 @@ static void gmc_v8_0_mc_program(struct amdgpu_device *adev) adev->mc.vram_end >> 12); WREG32(mmMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, adev->vram_scratch.gpu_addr >> 12); - tmp = ((adev->mc.vram_end >> 24) & 0xFFFF) << 16; - tmp |= ((adev->mc.vram_start >> 24) & 0xFFFF); - WREG32(mmMC_VM_FB_LOCATION, tmp); - /* XXX double check these! */ - WREG32(mmHDP_NONSURFACE_BASE, (adev->mc.vram_start >> 8)); - WREG32(mmHDP_NONSURFACE_INFO, (2 << 7) | (1 << 30)); - WREG32(mmHDP_NONSURFACE_SIZE, 0x3FFFFFFF); WREG32(mmMC_VM_AGP_BASE, 0); WREG32(mmMC_VM_AGP_TOP, 0x0FFFFFFF); WREG32(mmMC_VM_AGP_BOT, 0x0FFFFFFF); if (gmc_v8_0_wait_for_idle((void *)adev)) { dev_warn(adev->dev, "Wait for MC idle timedout !\n"); } - gmc_v8_0_mc_resume(adev, &save); WREG32(mmBIF_FB_EN, BIF_FB_EN__FB_READ_EN_MASK | BIF_FB_EN__FB_WRITE_EN_MASK); -- cgit v1.2.3 From 219611db30573bab37ff46f4e36571eba0bbd6a5 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 1 Nov 2016 13:39:10 -0400 Subject: drm/amdgpu/gmc7: drop fb location programming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No need to do this as the vbios does this for us. As such we no longer need to stop the mc during init. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c index 0fc7d31176a5..31ad68a68c77 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c @@ -266,7 +266,6 @@ static void gmc_v7_0_vram_gtt_location(struct amdgpu_device *adev, */ static void gmc_v7_0_mc_program(struct amdgpu_device *adev) { - struct amdgpu_mode_mc_save save; u32 tmp; int i, j; @@ -280,10 +279,6 @@ static void gmc_v7_0_mc_program(struct amdgpu_device *adev) } WREG32(mmHDP_REG_COHERENCY_FLUSH_CNTL, 0); - if (adev->mode_info.num_crtc) - amdgpu_display_set_vga_render_state(adev, false); - - gmc_v7_0_mc_stop(adev, &save); if (gmc_v7_0_wait_for_idle((void *)adev)) { dev_warn(adev->dev, "Wait for MC idle timedout !\n"); } @@ -294,20 +289,12 @@ static void gmc_v7_0_mc_program(struct amdgpu_device *adev) adev->mc.vram_end >> 12); WREG32(mmMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, adev->vram_scratch.gpu_addr >> 12); - tmp = ((adev->mc.vram_end >> 24) & 0xFFFF) << 16; - tmp |= ((adev->mc.vram_start >> 24) & 0xFFFF); - WREG32(mmMC_VM_FB_LOCATION, tmp); - /* XXX double check these! */ - WREG32(mmHDP_NONSURFACE_BASE, (adev->mc.vram_start >> 8)); - WREG32(mmHDP_NONSURFACE_INFO, (2 << 7) | (1 << 30)); - WREG32(mmHDP_NONSURFACE_SIZE, 0x3FFFFFFF); WREG32(mmMC_VM_AGP_BASE, 0); WREG32(mmMC_VM_AGP_TOP, 0x0FFFFFFF); WREG32(mmMC_VM_AGP_BOT, 0x0FFFFFFF); if (gmc_v7_0_wait_for_idle((void *)adev)) { dev_warn(adev->dev, "Wait for MC idle timedout !\n"); } - gmc_v7_0_mc_resume(adev, &save); WREG32(mmBIF_FB_EN, BIF_FB_EN__FB_READ_EN_MASK | BIF_FB_EN__FB_WRITE_EN_MASK); -- cgit v1.2.3 From 71086a3e8470eee3e54a454d276e6f214be28fdc Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 15 Nov 2016 17:37:41 -0500 Subject: drm/amdgpu/gmc6: drop fb location programming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No need to do this as the vbios does this for us. As such we no longer need to stop the mc during init. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c index 224b6935c885..a652fbaa7b8c 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c @@ -243,8 +243,6 @@ static void gmc_v6_0_vram_gtt_location(struct amdgpu_device *adev, static void gmc_v6_0_mc_program(struct amdgpu_device *adev) { - struct amdgpu_mode_mc_save save; - u32 tmp; int i, j; /* Initialize HDP */ @@ -257,11 +255,6 @@ static void gmc_v6_0_mc_program(struct amdgpu_device *adev) } WREG32(mmHDP_REG_COHERENCY_FLUSH_CNTL, 0); - if (adev->mode_info.num_crtc) - amdgpu_display_set_vga_render_state(adev, false); - - gmc_v6_0_mc_stop(adev, &save); - if (gmc_v6_0_wait_for_idle((void *)adev)) { dev_warn(adev->dev, "Wait for MC idle timedout !\n"); } @@ -274,13 +267,6 @@ static void gmc_v6_0_mc_program(struct amdgpu_device *adev) adev->mc.vram_end >> 12); WREG32(mmMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, adev->vram_scratch.gpu_addr >> 12); - tmp = ((adev->mc.vram_end >> 24) & 0xFFFF) << 16; - tmp |= ((adev->mc.vram_start >> 24) & 0xFFFF); - WREG32(mmMC_VM_FB_LOCATION, tmp); - /* XXX double check these! */ - WREG32(mmHDP_NONSURFACE_BASE, (adev->mc.vram_start >> 8)); - WREG32(mmHDP_NONSURFACE_INFO, (2 << 7) | (1 << 30)); - WREG32(mmHDP_NONSURFACE_SIZE, 0x3FFFFFFF); WREG32(mmMC_VM_AGP_BASE, 0); WREG32(mmMC_VM_AGP_TOP, 0x0FFFFFFF); WREG32(mmMC_VM_AGP_BOT, 0x0FFFFFFF); @@ -288,7 +274,6 @@ static void gmc_v6_0_mc_program(struct amdgpu_device *adev) if (gmc_v6_0_wait_for_idle((void *)adev)) { dev_warn(adev->dev, "Wait for MC idle timedout !\n"); } - gmc_v6_0_mc_resume(adev, &save); } static int gmc_v6_0_mc_init(struct amdgpu_device *adev) -- cgit v1.2.3 From b3fba8ad9d4be15cdf9aedb52b6a1262b213a1f4 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 22 Nov 2016 18:09:47 -0500 Subject: drm/amdgpu: drop set_vga_render_state from display funcs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Not used. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 - drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 2 -- drivers/gpu/drm/amd/amdgpu/dce_v10_0.c | 1 - drivers/gpu/drm/amd/amdgpu/dce_v11_0.c | 1 - drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 1 - drivers/gpu/drm/amd/amdgpu/dce_v8_0.c | 1 - drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 7 ------- 7 files changed, 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index ff7bf1a9f967..407b6c6736ec 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1898,7 +1898,6 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring) #define amdgpu_ih_get_wptr(adev) (adev)->irq.ih_funcs->get_wptr((adev)) #define amdgpu_ih_decode_iv(adev, iv) (adev)->irq.ih_funcs->decode_iv((adev), (iv)) #define amdgpu_ih_set_rptr(adev) (adev)->irq.ih_funcs->set_rptr((adev)) -#define amdgpu_display_set_vga_render_state(adev, r) (adev)->mode_info.funcs->set_vga_render_state((adev), (r)) #define amdgpu_display_vblank_get_counter(adev, crtc) (adev)->mode_info.funcs->vblank_get_counter((adev), (crtc)) #define amdgpu_display_vblank_wait(adev, crtc) (adev)->mode_info.funcs->vblank_wait((adev), (crtc)) #define amdgpu_display_backlight_set_level(adev, e, l) (adev)->mode_info.funcs->backlight_set_level((e), (l)) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 43a9d3aec6c4..35bd93cb0c19 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -264,8 +264,6 @@ struct amdgpu_mode_mc_save { }; struct amdgpu_display_funcs { - /* vga render */ - void (*set_vga_render_state)(struct amdgpu_device *adev, bool render); /* display watermarks */ void (*bandwidth_update)(struct amdgpu_device *adev); /* get frame count */ diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index 9bda363e02be..fba084dc43a2 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c @@ -3739,7 +3739,6 @@ static void dce_v10_0_encoder_add(struct amdgpu_device *adev, } static const struct amdgpu_display_funcs dce_v10_0_display_funcs = { - .set_vga_render_state = &dce_v10_0_set_vga_render_state, .bandwidth_update = &dce_v10_0_bandwidth_update, .vblank_get_counter = &dce_v10_0_vblank_get_counter, .vblank_wait = &dce_v10_0_vblank_wait, diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index c02c7fb75c63..4eb3b90903ac 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c @@ -3808,7 +3808,6 @@ static void dce_v11_0_encoder_add(struct amdgpu_device *adev, } static const struct amdgpu_display_funcs dce_v11_0_display_funcs = { - .set_vga_render_state = &dce_v11_0_set_vga_render_state, .bandwidth_update = &dce_v11_0_bandwidth_update, .vblank_get_counter = &dce_v11_0_vblank_get_counter, .vblank_wait = &dce_v11_0_vblank_wait, diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index 0a8ad0fc13ea..fde68b959e91 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -3527,7 +3527,6 @@ static void dce_v6_0_encoder_add(struct amdgpu_device *adev, } static const struct amdgpu_display_funcs dce_v6_0_display_funcs = { - .set_vga_render_state = &dce_v6_0_set_vga_render_state, .bandwidth_update = &dce_v6_0_bandwidth_update, .vblank_get_counter = &dce_v6_0_vblank_get_counter, .vblank_wait = &dce_v6_0_vblank_wait, diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c index 7e06c36b6ee9..8e530a01ae83 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c @@ -3576,7 +3576,6 @@ static void dce_v8_0_encoder_add(struct amdgpu_device *adev, } static const struct amdgpu_display_funcs dce_v8_0_display_funcs = { - .set_vga_render_state = &dce_v8_0_set_vga_render_state, .bandwidth_update = &dce_v8_0_bandwidth_update, .vblank_get_counter = &dce_v8_0_vblank_get_counter, .vblank_wait = &dce_v8_0_vblank_wait, diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c index 90bb08309a53..f257702978fe 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c @@ -145,12 +145,6 @@ static void dce_virtual_resume_mc_access(struct amdgpu_device *adev, return; } -static void dce_virtual_set_vga_render_state(struct amdgpu_device *adev, - bool render) -{ - return; -} - /** * dce_virtual_bandwidth_update - program display watermarks * @@ -677,7 +671,6 @@ static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev, } static const struct amdgpu_display_funcs dce_virtual_display_funcs = { - .set_vga_render_state = &dce_virtual_set_vga_render_state, .bandwidth_update = &dce_virtual_bandwidth_update, .vblank_get_counter = &dce_virtual_vblank_get_counter, .vblank_wait = &dce_virtual_vblank_wait, -- cgit v1.2.3 From e4f6b39e8bcd1f4c455acbc1aef2de9a4a32deeb Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 8 Dec 2016 14:53:27 -0500 Subject: drm/amdgpu: remove *_mc_access from display funcs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These are no longer needed now that we use the fb_location programmed by the vbios. Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 - drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 6 -- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 10 --- drivers/gpu/drm/amd/amdgpu/dce_v10_0.c | 130 ----------------------------- drivers/gpu/drm/amd/amdgpu/dce_v11_0.c | 75 ----------------- drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 113 ------------------------- drivers/gpu/drm/amd/amdgpu/dce_v8_0.c | 77 ----------------- drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 91 +++++++++----------- drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c | 18 +--- drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 17 +--- drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 16 +--- 11 files changed, 51 insertions(+), 505 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 407b6c6736ec..20e0ed96efbb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -613,7 +613,6 @@ struct amdgpu_mc { struct amdgpu_irq_src vm_fault; uint32_t vram_type; uint32_t srbm_soft_reset; - struct amdgpu_mode_mc_save save; bool prt_warning; uint64_t stolen_size; /* apertures */ @@ -1910,8 +1909,6 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring) #define amdgpu_display_page_flip_get_scanoutpos(adev, crtc, vbl, pos) (adev)->mode_info.funcs->page_flip_get_scanoutpos((adev), (crtc), (vbl), (pos)) #define amdgpu_display_add_encoder(adev, e, s, c) (adev)->mode_info.funcs->add_encoder((adev), (e), (s), (c)) #define amdgpu_display_add_connector(adev, ci, sd, ct, ib, coi, h, r) (adev)->mode_info.funcs->add_connector((adev), (ci), (sd), (ct), (ib), (coi), (h), (r)) -#define amdgpu_display_stop_mc_access(adev, s) (adev)->mode_info.funcs->stop_mc_access((adev), (s)) -#define amdgpu_display_resume_mc_access(adev, s) (adev)->mode_info.funcs->resume_mc_access((adev), (s)) #define amdgpu_emit_copy_buffer(adev, ib, s, d, b) (adev)->mman.buffer_funcs->emit_copy_buffer((ib), (s), (d), (b)) #define amdgpu_emit_fill_buffer(adev, ib, s, d, b) (adev)->mman.buffer_funcs->emit_fill_buffer((ib), (s), (d), (b)) #define amdgpu_gfx_get_gpu_clock_counter(adev) (adev)->gfx.funcs->get_gpu_clock_counter((adev)) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index f3811f6197e0..ae4387fd2b65 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2851,12 +2851,6 @@ int amdgpu_gpu_reset(struct amdgpu_device *adev) r = amdgpu_suspend(adev); retry: - /* Disable fb access */ - if (adev->mode_info.num_crtc) { - struct amdgpu_mode_mc_save save; - amdgpu_display_stop_mc_access(adev, &save); - amdgpu_wait_for_idle(adev, AMD_IP_BLOCK_TYPE_GMC); - } if (adev->is_atom_fw) amdgpu_atomfirmware_scratch_regs_save(adev); else diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 35bd93cb0c19..b8abd4e18d51 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -257,12 +257,6 @@ struct amdgpu_audio { int num_pins; }; -struct amdgpu_mode_mc_save { - u32 vga_render_control; - u32 vga_hdp_control; - bool crtc_enabled[AMDGPU_MAX_CRTCS]; -}; - struct amdgpu_display_funcs { /* display watermarks */ void (*bandwidth_update)(struct amdgpu_device *adev); @@ -298,10 +292,6 @@ struct amdgpu_display_funcs { uint16_t connector_object_id, struct amdgpu_hpd *hpd, struct amdgpu_router *router); - void (*stop_mc_access)(struct amdgpu_device *adev, - struct amdgpu_mode_mc_save *save); - void (*resume_mc_access)(struct amdgpu_device *adev, - struct amdgpu_mode_mc_save *save); }; struct amdgpu_mode_info { diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index fba084dc43a2..16915a92672b 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c @@ -484,134 +484,6 @@ static bool dce_v10_0_is_display_hung(struct amdgpu_device *adev) return true; } -static void dce_v10_0_stop_mc_access(struct amdgpu_device *adev, - struct amdgpu_mode_mc_save *save) -{ - u32 crtc_enabled, tmp; - int i; - - save->vga_render_control = RREG32(mmVGA_RENDER_CONTROL); - save->vga_hdp_control = RREG32(mmVGA_HDP_CONTROL); - - /* disable VGA render */ - tmp = RREG32(mmVGA_RENDER_CONTROL); - tmp = REG_SET_FIELD(tmp, VGA_RENDER_CONTROL, VGA_VSTATUS_CNTL, 0); - WREG32(mmVGA_RENDER_CONTROL, tmp); - - /* blank the display controllers */ - for (i = 0; i < adev->mode_info.num_crtc; i++) { - crtc_enabled = REG_GET_FIELD(RREG32(mmCRTC_CONTROL + crtc_offsets[i]), - CRTC_CONTROL, CRTC_MASTER_EN); - if (crtc_enabled) { -#if 0 - u32 frame_count; - int j; - - save->crtc_enabled[i] = true; - tmp = RREG32(mmCRTC_BLANK_CONTROL + crtc_offsets[i]); - if (REG_GET_FIELD(tmp, CRTC_BLANK_CONTROL, CRTC_BLANK_DATA_EN) == 0) { - amdgpu_display_vblank_wait(adev, i); - WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 1); - tmp = REG_SET_FIELD(tmp, CRTC_BLANK_CONTROL, CRTC_BLANK_DATA_EN, 1); - WREG32(mmCRTC_BLANK_CONTROL + crtc_offsets[i], tmp); - WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 0); - } - /* wait for the next frame */ - frame_count = amdgpu_display_vblank_get_counter(adev, i); - for (j = 0; j < adev->usec_timeout; j++) { - if (amdgpu_display_vblank_get_counter(adev, i) != frame_count) - break; - udelay(1); - } - tmp = RREG32(mmGRPH_UPDATE + crtc_offsets[i]); - if (REG_GET_FIELD(tmp, GRPH_UPDATE, GRPH_UPDATE_LOCK) == 0) { - tmp = REG_SET_FIELD(tmp, GRPH_UPDATE, GRPH_UPDATE_LOCK, 1); - WREG32(mmGRPH_UPDATE + crtc_offsets[i], tmp); - } - tmp = RREG32(mmMASTER_UPDATE_LOCK + crtc_offsets[i]); - if (REG_GET_FIELD(tmp, MASTER_UPDATE_LOCK, MASTER_UPDATE_LOCK) == 0) { - tmp = REG_SET_FIELD(tmp, MASTER_UPDATE_LOCK, MASTER_UPDATE_LOCK, 1); - WREG32(mmMASTER_UPDATE_LOCK + crtc_offsets[i], tmp); - } -#else - /* XXX this is a hack to avoid strange behavior with EFI on certain systems */ - WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 1); - tmp = RREG32(mmCRTC_CONTROL + crtc_offsets[i]); - tmp = REG_SET_FIELD(tmp, CRTC_CONTROL, CRTC_MASTER_EN, 0); - WREG32(mmCRTC_CONTROL + crtc_offsets[i], tmp); - WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 0); - save->crtc_enabled[i] = false; - /* ***** */ -#endif - } else { - save->crtc_enabled[i] = false; - } - } -} - -static void dce_v10_0_resume_mc_access(struct amdgpu_device *adev, - struct amdgpu_mode_mc_save *save) -{ - u32 tmp, frame_count; - int i, j; - - /* update crtc base addresses */ - for (i = 0; i < adev->mode_info.num_crtc; i++) { - WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i], - upper_32_bits(adev->mc.vram_start)); - WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i], - upper_32_bits(adev->mc.vram_start)); - WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + crtc_offsets[i], - (u32)adev->mc.vram_start); - WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS + crtc_offsets[i], - (u32)adev->mc.vram_start); - - if (save->crtc_enabled[i]) { - tmp = RREG32(mmMASTER_UPDATE_MODE + crtc_offsets[i]); - if (REG_GET_FIELD(tmp, MASTER_UPDATE_MODE, MASTER_UPDATE_MODE) != 0) { - tmp = REG_SET_FIELD(tmp, MASTER_UPDATE_MODE, MASTER_UPDATE_MODE, 0); - WREG32(mmMASTER_UPDATE_MODE + crtc_offsets[i], tmp); - } - tmp = RREG32(mmGRPH_UPDATE + crtc_offsets[i]); - if (REG_GET_FIELD(tmp, GRPH_UPDATE, GRPH_UPDATE_LOCK)) { - tmp = REG_SET_FIELD(tmp, GRPH_UPDATE, GRPH_UPDATE_LOCK, 0); - WREG32(mmGRPH_UPDATE + crtc_offsets[i], tmp); - } - tmp = RREG32(mmMASTER_UPDATE_LOCK + crtc_offsets[i]); - if (REG_GET_FIELD(tmp, MASTER_UPDATE_LOCK, MASTER_UPDATE_LOCK)) { - tmp = REG_SET_FIELD(tmp, MASTER_UPDATE_LOCK, MASTER_UPDATE_LOCK, 0); - WREG32(mmMASTER_UPDATE_LOCK + crtc_offsets[i], tmp); - } - for (j = 0; j < adev->usec_timeout; j++) { - tmp = RREG32(mmGRPH_UPDATE + crtc_offsets[i]); - if (REG_GET_FIELD(tmp, GRPH_UPDATE, GRPH_SURFACE_UPDATE_PENDING) == 0) - break; - udelay(1); - } - tmp = RREG32(mmCRTC_BLANK_CONTROL + crtc_offsets[i]); - tmp = REG_SET_FIELD(tmp, CRTC_BLANK_CONTROL, CRTC_BLANK_DATA_EN, 0); - WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 1); - WREG32(mmCRTC_BLANK_CONTROL + crtc_offsets[i], tmp); - WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 0); - /* wait for the next frame */ - frame_count = amdgpu_display_vblank_get_counter(adev, i); - for (j = 0; j < adev->usec_timeout; j++) { - if (amdgpu_display_vblank_get_counter(adev, i) != frame_count) - break; - udelay(1); - } - } - } - - WREG32(mmVGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(adev->mc.vram_start)); - WREG32(mmVGA_MEMORY_BASE_ADDRESS, lower_32_bits(adev->mc.vram_start)); - - /* Unlock vga access */ - WREG32(mmVGA_HDP_CONTROL, save->vga_hdp_control); - mdelay(1); - WREG32(mmVGA_RENDER_CONTROL, save->vga_render_control); -} - static void dce_v10_0_set_vga_render_state(struct amdgpu_device *adev, bool render) { @@ -3751,8 +3623,6 @@ static const struct amdgpu_display_funcs dce_v10_0_display_funcs = { .page_flip_get_scanoutpos = &dce_v10_0_crtc_get_scanoutpos, .add_encoder = &dce_v10_0_encoder_add, .add_connector = &amdgpu_connector_add, - .stop_mc_access = &dce_v10_0_stop_mc_access, - .resume_mc_access = &dce_v10_0_resume_mc_access, }; static void dce_v10_0_set_display_funcs(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index 4eb3b90903ac..6a43f25c5d96 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c @@ -499,79 +499,6 @@ static bool dce_v11_0_is_display_hung(struct amdgpu_device *adev) return true; } -static void dce_v11_0_stop_mc_access(struct amdgpu_device *adev, - struct amdgpu_mode_mc_save *save) -{ - u32 crtc_enabled, tmp; - int i; - - save->vga_render_control = RREG32(mmVGA_RENDER_CONTROL); - save->vga_hdp_control = RREG32(mmVGA_HDP_CONTROL); - - /* disable VGA render */ - tmp = RREG32(mmVGA_RENDER_CONTROL); - tmp = REG_SET_FIELD(tmp, VGA_RENDER_CONTROL, VGA_VSTATUS_CNTL, 0); - WREG32(mmVGA_RENDER_CONTROL, tmp); - - /* blank the display controllers */ - for (i = 0; i < adev->mode_info.num_crtc; i++) { - crtc_enabled = REG_GET_FIELD(RREG32(mmCRTC_CONTROL + crtc_offsets[i]), - CRTC_CONTROL, CRTC_MASTER_EN); - if (crtc_enabled) { -#if 1 - save->crtc_enabled[i] = true; - tmp = RREG32(mmCRTC_BLANK_CONTROL + crtc_offsets[i]); - if (REG_GET_FIELD(tmp, CRTC_BLANK_CONTROL, CRTC_BLANK_DATA_EN) == 0) { - /*it is correct only for RGB ; black is 0*/ - WREG32(mmCRTC_BLANK_DATA_COLOR + crtc_offsets[i], 0); - tmp = REG_SET_FIELD(tmp, CRTC_BLANK_CONTROL, CRTC_BLANK_DATA_EN, 1); - WREG32(mmCRTC_BLANK_CONTROL + crtc_offsets[i], tmp); - } -#else - /* XXX this is a hack to avoid strange behavior with EFI on certain systems */ - WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 1); - tmp = RREG32(mmCRTC_CONTROL + crtc_offsets[i]); - tmp = REG_SET_FIELD(tmp, CRTC_CONTROL, CRTC_MASTER_EN, 0); - WREG32(mmCRTC_CONTROL + crtc_offsets[i], tmp); - WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 0); - save->crtc_enabled[i] = false; - /* ***** */ -#endif - } else { - save->crtc_enabled[i] = false; - } - } -} - -static void dce_v11_0_resume_mc_access(struct amdgpu_device *adev, - struct amdgpu_mode_mc_save *save) -{ - u32 tmp; - int i; - - /* update crtc base addresses */ - for (i = 0; i < adev->mode_info.num_crtc; i++) { - WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i], - upper_32_bits(adev->mc.vram_start)); - WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + crtc_offsets[i], - (u32)adev->mc.vram_start); - - if (save->crtc_enabled[i]) { - tmp = RREG32(mmCRTC_BLANK_CONTROL + crtc_offsets[i]); - tmp = REG_SET_FIELD(tmp, CRTC_BLANK_CONTROL, CRTC_BLANK_DATA_EN, 0); - WREG32(mmCRTC_BLANK_CONTROL + crtc_offsets[i], tmp); - } - } - - WREG32(mmVGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(adev->mc.vram_start)); - WREG32(mmVGA_MEMORY_BASE_ADDRESS, lower_32_bits(adev->mc.vram_start)); - - /* Unlock vga access */ - WREG32(mmVGA_HDP_CONTROL, save->vga_hdp_control); - mdelay(1); - WREG32(mmVGA_RENDER_CONTROL, save->vga_render_control); -} - static void dce_v11_0_set_vga_render_state(struct amdgpu_device *adev, bool render) { @@ -3820,8 +3747,6 @@ static const struct amdgpu_display_funcs dce_v11_0_display_funcs = { .page_flip_get_scanoutpos = &dce_v11_0_crtc_get_scanoutpos, .add_encoder = &dce_v11_0_encoder_add, .add_connector = &amdgpu_connector_add, - .stop_mc_access = &dce_v11_0_stop_mc_access, - .resume_mc_access = &dce_v11_0_resume_mc_access, }; static void dce_v11_0_set_display_funcs(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index fde68b959e91..48d5dd4974de 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -392,117 +392,6 @@ static u32 dce_v6_0_hpd_get_gpio_reg(struct amdgpu_device *adev) return mmDC_GPIO_HPD_A; } -static u32 evergreen_get_vblank_counter(struct amdgpu_device* adev, int crtc) -{ - if (crtc >= adev->mode_info.num_crtc) - return 0; - else - return RREG32(mmCRTC_STATUS_FRAME_COUNT + crtc_offsets[crtc]); -} - -static void dce_v6_0_stop_mc_access(struct amdgpu_device *adev, - struct amdgpu_mode_mc_save *save) -{ - u32 crtc_enabled, tmp, frame_count; - int i, j; - - save->vga_render_control = RREG32(mmVGA_RENDER_CONTROL); - save->vga_hdp_control = RREG32(mmVGA_HDP_CONTROL); - - /* disable VGA render */ - WREG32(mmVGA_RENDER_CONTROL, 0); - - /* blank the display controllers */ - for (i = 0; i < adev->mode_info.num_crtc; i++) { - crtc_enabled = RREG32(mmCRTC_CONTROL + crtc_offsets[i]) & CRTC_CONTROL__CRTC_MASTER_EN_MASK; - if (crtc_enabled) { - save->crtc_enabled[i] = true; - tmp = RREG32(mmCRTC_BLANK_CONTROL + crtc_offsets[i]); - - if (!(tmp & CRTC_BLANK_CONTROL__CRTC_BLANK_DATA_EN_MASK)) { - dce_v6_0_vblank_wait(adev, i); - WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 1); - tmp |= CRTC_BLANK_CONTROL__CRTC_BLANK_DATA_EN_MASK; - WREG32(mmCRTC_BLANK_CONTROL + crtc_offsets[i], tmp); - WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 0); - } - /* wait for the next frame */ - frame_count = evergreen_get_vblank_counter(adev, i); - for (j = 0; j < adev->usec_timeout; j++) { - if (evergreen_get_vblank_counter(adev, i) != frame_count) - break; - udelay(1); - } - - /* XXX this is a hack to avoid strange behavior with EFI on certain systems */ - WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 1); - tmp = RREG32(mmCRTC_CONTROL + crtc_offsets[i]); - tmp &= ~CRTC_CONTROL__CRTC_MASTER_EN_MASK; - WREG32(mmCRTC_CONTROL + crtc_offsets[i], tmp); - WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 0); - save->crtc_enabled[i] = false; - /* ***** */ - } else { - save->crtc_enabled[i] = false; - } - } -} - -static void dce_v6_0_resume_mc_access(struct amdgpu_device *adev, - struct amdgpu_mode_mc_save *save) -{ - u32 tmp; - int i, j; - - /* update crtc base addresses */ - for (i = 0; i < adev->mode_info.num_crtc; i++) { - WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i], - upper_32_bits(adev->mc.vram_start)); - WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i], - upper_32_bits(adev->mc.vram_start)); - WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + crtc_offsets[i], - (u32)adev->mc.vram_start); - WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS + crtc_offsets[i], - (u32)adev->mc.vram_start); - } - - WREG32(mmVGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(adev->mc.vram_start)); - WREG32(mmVGA_MEMORY_BASE_ADDRESS, (u32)adev->mc.vram_start); - - /* unlock regs and wait for update */ - for (i = 0; i < adev->mode_info.num_crtc; i++) { - if (save->crtc_enabled[i]) { - tmp = RREG32(mmMASTER_UPDATE_MODE + crtc_offsets[i]); - if ((tmp & 0x7) != 0) { - tmp &= ~0x7; - WREG32(mmMASTER_UPDATE_MODE + crtc_offsets[i], tmp); - } - tmp = RREG32(mmGRPH_UPDATE + crtc_offsets[i]); - if (tmp & GRPH_UPDATE__GRPH_UPDATE_LOCK_MASK) { - tmp &= ~GRPH_UPDATE__GRPH_UPDATE_LOCK_MASK; - WREG32(mmGRPH_UPDATE + crtc_offsets[i], tmp); - } - tmp = RREG32(mmMASTER_UPDATE_LOCK + crtc_offsets[i]); - if (tmp & 1) { - tmp &= ~1; - WREG32(mmMASTER_UPDATE_LOCK + crtc_offsets[i], tmp); - } - for (j = 0; j < adev->usec_timeout; j++) { - tmp = RREG32(mmGRPH_UPDATE + crtc_offsets[i]); - if ((tmp & GRPH_UPDATE__GRPH_SURFACE_UPDATE_PENDING_MASK) == 0) - break; - udelay(1); - } - } - } - - /* Unlock vga access */ - WREG32(mmVGA_HDP_CONTROL, save->vga_hdp_control); - mdelay(1); - WREG32(mmVGA_RENDER_CONTROL, save->vga_render_control); - -} - static void dce_v6_0_set_vga_render_state(struct amdgpu_device *adev, bool render) { @@ -3539,8 +3428,6 @@ static const struct amdgpu_display_funcs dce_v6_0_display_funcs = { .page_flip_get_scanoutpos = &dce_v6_0_crtc_get_scanoutpos, .add_encoder = &dce_v6_0_encoder_add, .add_connector = &amdgpu_connector_add, - .stop_mc_access = &dce_v6_0_stop_mc_access, - .resume_mc_access = &dce_v6_0_resume_mc_access, }; static void dce_v6_0_set_display_funcs(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c index 8e530a01ae83..647a48f03574 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c @@ -419,81 +419,6 @@ static bool dce_v8_0_is_display_hung(struct amdgpu_device *adev) return true; } -static void dce_v8_0_stop_mc_access(struct amdgpu_device *adev, - struct amdgpu_mode_mc_save *save) -{ - u32 crtc_enabled, tmp; - int i; - - save->vga_render_control = RREG32(mmVGA_RENDER_CONTROL); - save->vga_hdp_control = RREG32(mmVGA_HDP_CONTROL); - - /* disable VGA render */ - tmp = RREG32(mmVGA_RENDER_CONTROL); - tmp = REG_SET_FIELD(tmp, VGA_RENDER_CONTROL, VGA_VSTATUS_CNTL, 0); - WREG32(mmVGA_RENDER_CONTROL, tmp); - - /* blank the display controllers */ - for (i = 0; i < adev->mode_info.num_crtc; i++) { - crtc_enabled = REG_GET_FIELD(RREG32(mmCRTC_CONTROL + crtc_offsets[i]), - CRTC_CONTROL, CRTC_MASTER_EN); - if (crtc_enabled) { -#if 1 - save->crtc_enabled[i] = true; - tmp = RREG32(mmCRTC_BLANK_CONTROL + crtc_offsets[i]); - if (REG_GET_FIELD(tmp, CRTC_BLANK_CONTROL, CRTC_BLANK_DATA_EN) == 0) { - /*it is correct only for RGB ; black is 0*/ - WREG32(mmCRTC_BLANK_DATA_COLOR + crtc_offsets[i], 0); - tmp = REG_SET_FIELD(tmp, CRTC_BLANK_CONTROL, CRTC_BLANK_DATA_EN, 1); - WREG32(mmCRTC_BLANK_CONTROL + crtc_offsets[i], tmp); - } - mdelay(20); -#else - /* XXX this is a hack to avoid strange behavior with EFI on certain systems */ - WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 1); - tmp = RREG32(mmCRTC_CONTROL + crtc_offsets[i]); - tmp = REG_SET_FIELD(tmp, CRTC_CONTROL, CRTC_MASTER_EN, 0); - WREG32(mmCRTC_CONTROL + crtc_offsets[i], tmp); - WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 0); - save->crtc_enabled[i] = false; - /* ***** */ -#endif - } else { - save->crtc_enabled[i] = false; - } - } -} - -static void dce_v8_0_resume_mc_access(struct amdgpu_device *adev, - struct amdgpu_mode_mc_save *save) -{ - u32 tmp; - int i; - - /* update crtc base addresses */ - for (i = 0; i < adev->mode_info.num_crtc; i++) { - WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i], - upper_32_bits(adev->mc.vram_start)); - WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + crtc_offsets[i], - (u32)adev->mc.vram_start); - - if (save->crtc_enabled[i]) { - tmp = RREG32(mmCRTC_BLANK_CONTROL + crtc_offsets[i]); - tmp = REG_SET_FIELD(tmp, CRTC_BLANK_CONTROL, CRTC_BLANK_DATA_EN, 0); - WREG32(mmCRTC_BLANK_CONTROL + crtc_offsets[i], tmp); - } - mdelay(20); - } - - WREG32(mmVGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(adev->mc.vram_start)); - WREG32(mmVGA_MEMORY_BASE_ADDRESS, lower_32_bits(adev->mc.vram_start)); - - /* Unlock vga access */ - WREG32(mmVGA_HDP_CONTROL, save->vga_hdp_control); - mdelay(1); - WREG32(mmVGA_RENDER_CONTROL, save->vga_render_control); -} - static void dce_v8_0_set_vga_render_state(struct amdgpu_device *adev, bool render) { @@ -3588,8 +3513,6 @@ static const struct amdgpu_display_funcs dce_v8_0_display_funcs = { .page_flip_get_scanoutpos = &dce_v8_0_crtc_get_scanoutpos, .add_encoder = &dce_v8_0_encoder_add, .add_connector = &amdgpu_connector_add, - .stop_mc_access = &dce_v8_0_stop_mc_access, - .resume_mc_access = &dce_v8_0_resume_mc_access, }; static void dce_v8_0_set_display_funcs(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c index f257702978fe..5ac2e17b76ac 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c @@ -95,56 +95,6 @@ static u32 dce_virtual_hpd_get_gpio_reg(struct amdgpu_device *adev) return 0; } -static void dce_virtual_stop_mc_access(struct amdgpu_device *adev, - struct amdgpu_mode_mc_save *save) -{ - switch (adev->asic_type) { -#ifdef CONFIG_DRM_AMDGPU_SI - case CHIP_TAHITI: - case CHIP_PITCAIRN: - case CHIP_VERDE: - case CHIP_OLAND: - dce_v6_0_disable_dce(adev); - break; -#endif -#ifdef CONFIG_DRM_AMDGPU_CIK - case CHIP_BONAIRE: - case CHIP_HAWAII: - case CHIP_KAVERI: - case CHIP_KABINI: - case CHIP_MULLINS: - dce_v8_0_disable_dce(adev); - break; -#endif - case CHIP_FIJI: - case CHIP_TONGA: - dce_v10_0_disable_dce(adev); - break; - case CHIP_CARRIZO: - case CHIP_STONEY: - case CHIP_POLARIS10: - case CHIP_POLARIS11: - case CHIP_POLARIS12: - dce_v11_0_disable_dce(adev); - break; - case CHIP_TOPAZ: -#ifdef CONFIG_DRM_AMDGPU_SI - case CHIP_HAINAN: -#endif - /* no DCE */ - return; - default: - DRM_ERROR("Virtual display unsupported ASIC type: 0x%X\n", adev->asic_type); - } - - return; -} -static void dce_virtual_resume_mc_access(struct amdgpu_device *adev, - struct amdgpu_mode_mc_save *save) -{ - return; -} - /** * dce_virtual_bandwidth_update - program display watermarks * @@ -516,6 +466,45 @@ static int dce_virtual_sw_fini(void *handle) static int dce_virtual_hw_init(void *handle) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + switch (adev->asic_type) { +#ifdef CONFIG_DRM_AMDGPU_SI + case CHIP_TAHITI: + case CHIP_PITCAIRN: + case CHIP_VERDE: + case CHIP_OLAND: + dce_v6_0_disable_dce(adev); + break; +#endif +#ifdef CONFIG_DRM_AMDGPU_CIK + case CHIP_BONAIRE: + case CHIP_HAWAII: + case CHIP_KAVERI: + case CHIP_KABINI: + case CHIP_MULLINS: + dce_v8_0_disable_dce(adev); + break; +#endif + case CHIP_FIJI: + case CHIP_TONGA: + dce_v10_0_disable_dce(adev); + break; + case CHIP_CARRIZO: + case CHIP_STONEY: + case CHIP_POLARIS11: + case CHIP_POLARIS10: + dce_v11_0_disable_dce(adev); + break; + case CHIP_TOPAZ: +#ifdef CONFIG_DRM_AMDGPU_SI + case CHIP_HAINAN: +#endif + /* no DCE */ + break; + default: + DRM_ERROR("Virtual display unsupported ASIC type: 0x%X\n", adev->asic_type); + } return 0; } @@ -683,8 +672,6 @@ static const struct amdgpu_display_funcs dce_virtual_display_funcs = { .page_flip_get_scanoutpos = &dce_virtual_crtc_get_scanoutpos, .add_encoder = NULL, .add_connector = NULL, - .stop_mc_access = &dce_virtual_stop_mc_access, - .resume_mc_access = &dce_virtual_resume_mc_access, }; static void dce_virtual_set_display_funcs(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c index a652fbaa7b8c..c1a124a86775 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c @@ -66,14 +66,10 @@ static const u32 crtc_offsets[6] = SI_CRTC5_REGISTER_OFFSET }; -static void gmc_v6_0_mc_stop(struct amdgpu_device *adev, - struct amdgpu_mode_mc_save *save) +static void gmc_v6_0_mc_stop(struct amdgpu_device *adev) { u32 blackout; - if (adev->mode_info.num_crtc) - amdgpu_display_stop_mc_access(adev, save); - gmc_v6_0_wait_for_idle((void *)adev); blackout = RREG32(mmMC_SHARED_BLACKOUT_CNTL); @@ -90,8 +86,7 @@ static void gmc_v6_0_mc_stop(struct amdgpu_device *adev, } -static void gmc_v6_0_mc_resume(struct amdgpu_device *adev, - struct amdgpu_mode_mc_save *save) +static void gmc_v6_0_mc_resume(struct amdgpu_device *adev) { u32 tmp; @@ -103,10 +98,6 @@ static void gmc_v6_0_mc_resume(struct amdgpu_device *adev, tmp = REG_SET_FIELD(0, BIF_FB_EN, FB_READ_EN, 1); tmp = REG_SET_FIELD(tmp, BIF_FB_EN, FB_WRITE_EN, 1); WREG32(mmBIF_FB_EN, tmp); - - if (adev->mode_info.num_crtc) - amdgpu_display_resume_mc_access(adev, save); - } static int gmc_v6_0_init_microcode(struct amdgpu_device *adev) @@ -975,7 +966,6 @@ static int gmc_v6_0_wait_for_idle(void *handle) static int gmc_v6_0_soft_reset(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct amdgpu_mode_mc_save save; u32 srbm_soft_reset = 0; u32 tmp = RREG32(mmSRBM_STATUS); @@ -991,7 +981,7 @@ static int gmc_v6_0_soft_reset(void *handle) } if (srbm_soft_reset) { - gmc_v6_0_mc_stop(adev, &save); + gmc_v6_0_mc_stop(adev); if (gmc_v6_0_wait_for_idle(adev)) { dev_warn(adev->dev, "Wait for GMC idle timed out !\n"); } @@ -1011,7 +1001,7 @@ static int gmc_v6_0_soft_reset(void *handle) udelay(50); - gmc_v6_0_mc_resume(adev, &save); + gmc_v6_0_mc_resume(adev); udelay(50); } diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c index 31ad68a68c77..575d72583746 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c @@ -76,14 +76,10 @@ static void gmc_v7_0_init_golden_registers(struct amdgpu_device *adev) } } -static void gmc_v7_0_mc_stop(struct amdgpu_device *adev, - struct amdgpu_mode_mc_save *save) +static void gmc_v7_0_mc_stop(struct amdgpu_device *adev) { u32 blackout; - if (adev->mode_info.num_crtc) - amdgpu_display_stop_mc_access(adev, save); - gmc_v7_0_wait_for_idle((void *)adev); blackout = RREG32(mmMC_SHARED_BLACKOUT_CNTL); @@ -99,8 +95,7 @@ static void gmc_v7_0_mc_stop(struct amdgpu_device *adev, udelay(100); } -static void gmc_v7_0_mc_resume(struct amdgpu_device *adev, - struct amdgpu_mode_mc_save *save) +static void gmc_v7_0_mc_resume(struct amdgpu_device *adev) { u32 tmp; @@ -112,9 +107,6 @@ static void gmc_v7_0_mc_resume(struct amdgpu_device *adev, tmp = REG_SET_FIELD(0, BIF_FB_EN, FB_READ_EN, 1); tmp = REG_SET_FIELD(tmp, BIF_FB_EN, FB_WRITE_EN, 1); WREG32(mmBIF_FB_EN, tmp); - - if (adev->mode_info.num_crtc) - amdgpu_display_resume_mc_access(adev, save); } /** @@ -1128,7 +1120,6 @@ static int gmc_v7_0_wait_for_idle(void *handle) static int gmc_v7_0_soft_reset(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct amdgpu_mode_mc_save save; u32 srbm_soft_reset = 0; u32 tmp = RREG32(mmSRBM_STATUS); @@ -1144,7 +1135,7 @@ static int gmc_v7_0_soft_reset(void *handle) } if (srbm_soft_reset) { - gmc_v7_0_mc_stop(adev, &save); + gmc_v7_0_mc_stop(adev); if (gmc_v7_0_wait_for_idle((void *)adev)) { dev_warn(adev->dev, "Wait for GMC idle timed out !\n"); } @@ -1165,7 +1156,7 @@ static int gmc_v7_0_soft_reset(void *handle) /* Wait a little for things to settle down */ udelay(50); - gmc_v7_0_mc_resume(adev, &save); + gmc_v7_0_mc_resume(adev); udelay(50); } diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index 72ab2d04f048..6379177b9fcb 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -161,14 +161,10 @@ static void gmc_v8_0_init_golden_registers(struct amdgpu_device *adev) } } -static void gmc_v8_0_mc_stop(struct amdgpu_device *adev, - struct amdgpu_mode_mc_save *save) +static void gmc_v8_0_mc_stop(struct amdgpu_device *adev) { u32 blackout; - if (adev->mode_info.num_crtc) - amdgpu_display_stop_mc_access(adev, save); - gmc_v8_0_wait_for_idle(adev); blackout = RREG32(mmMC_SHARED_BLACKOUT_CNTL); @@ -184,8 +180,7 @@ static void gmc_v8_0_mc_stop(struct amdgpu_device *adev, udelay(100); } -static void gmc_v8_0_mc_resume(struct amdgpu_device *adev, - struct amdgpu_mode_mc_save *save) +static void gmc_v8_0_mc_resume(struct amdgpu_device *adev) { u32 tmp; @@ -197,9 +192,6 @@ static void gmc_v8_0_mc_resume(struct amdgpu_device *adev, tmp = REG_SET_FIELD(0, BIF_FB_EN, FB_READ_EN, 1); tmp = REG_SET_FIELD(tmp, BIF_FB_EN, FB_WRITE_EN, 1); WREG32(mmBIF_FB_EN, tmp); - - if (adev->mode_info.num_crtc) - amdgpu_display_resume_mc_access(adev, save); } /** @@ -1250,7 +1242,7 @@ static int gmc_v8_0_pre_soft_reset(void *handle) if (!adev->mc.srbm_soft_reset) return 0; - gmc_v8_0_mc_stop(adev, &adev->mc.save); + gmc_v8_0_mc_stop(adev); if (gmc_v8_0_wait_for_idle(adev)) { dev_warn(adev->dev, "Wait for GMC idle timed out !\n"); } @@ -1296,7 +1288,7 @@ static int gmc_v8_0_post_soft_reset(void *handle) if (!adev->mc.srbm_soft_reset) return 0; - gmc_v8_0_mc_resume(adev, &adev->mc.save); + gmc_v8_0_mc_resume(adev); return 0; } -- cgit v1.2.3 From 08d3874636a20b8852f8eea1c6ad1054234c9ae6 Mon Sep 17 00:00:00 2001 From: Mario Kleiner Date: Wed, 21 Jun 2017 03:44:55 +0200 Subject: drm/radeon: Allow vblank_disable_immediate. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With instantaneous high precision vblank timestamping that updates at leading edge of vblank, a cooked hw vblank counter which increments at leading edge of vblank, and reliable page flip execution and completion at leading edge of vblank, we should meet the requirements for fast/immediate vblank irq disable/enable. Testing on Linux-4.12-rc5 + drm-next on a Radeon HD 5770 (DCE 4) with timing measurement equipment indicates this works fine, so allow immediate vblank disable for power saving. For debugging in case of unexpected trouble, booting with kernel cmdline option drm.vblankoffdelay=0 (or echo 0 > /sys/module/drm/parameters/vblankoffdelay) would keep vblank irqs permanently on to approximate old behavior. Reviewed-and-Tested-by: Michel Dänzer Signed-off-by: Mario Kleiner Cc: Alex Deucher Cc: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_irq_kms.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index 7aacb44df201..186076492f64 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c @@ -283,6 +283,10 @@ int radeon_irq_kms_init(struct radeon_device *rdev) int r = 0; spin_lock_init(&rdev->irq.lock); + + /* Disable vblank irqs aggressively for power-saving */ + rdev->ddev->vblank_disable_immediate = true; + r = drm_vblank_init(rdev->ddev, rdev->num_crtc); if (r) { return r; -- cgit v1.2.3 From 8e1b90cc44181405418071a13ead5892c3879239 Mon Sep 17 00:00:00 2001 From: Mario Kleiner Date: Wed, 21 Jun 2017 03:44:56 +0200 Subject: drm/amdgpu: Allow vblank_disable_immediate. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With instantaneous high precision vblank timestamping that updates at leading edge of vblank, a cooked hw vblank counter which increments at leading edge of vblank, and reliable page flip execution and completion at leading edge of vblank, we should meet the requirements for fast/immediate vblank irq disable/enable. Testing on Linux-4.12-rc5 + drm-next on a Radeon R9 380 Tonga Pro (DCE 10) with timing measurement equipment indicates this works fine, so allow immediate vblank disable for power saving. For debugging in case of unexpected trouble, booting with kernel cmdline option drm.vblankoffdelay=0 (or echo 0 > /sys/module/drm/parameters/vblankoffdelay) would keep vblank irqs permanently on to approximate old behavior. Reviewed-by: Michel Dänzer Signed-off-by: Mario Kleiner Cc: Alex Deucher Cc: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c index 62da6c5c6095..a28f8aad2035 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c @@ -220,6 +220,10 @@ int amdgpu_irq_init(struct amdgpu_device *adev) int r = 0; spin_lock_init(&adev->irq.lock); + + /* Disable vblank irqs aggressively for power-saving */ + adev->ddev->vblank_disable_immediate = true; + r = drm_vblank_init(adev->ddev, adev->mode_info.num_crtc); if (r) { return r; -- cgit v1.2.3 From 890419409a3aba2ca7185a824e47d8ded8df11a2 Mon Sep 17 00:00:00 2001 From: Gavin Wan Date: Fri, 23 Jun 2017 13:55:15 -0400 Subject: drm/amdgpu: Support passing amdgpu critical error to host via GPU Mailbox. This feature works for SRIOV enviroment. For non-SRIOV enviroment, the trans_error function does nothing. The error information includes error_code (16bit), error_flags(16bit) and error_data(64bit). Since there are not many errors, we keep the errors in an array and transfer all errors to Host before amdgpu initialization function (amdgpu_device_init) exit. Signed-off-by: Gavin Wan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/Makefile | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 21 ++++++- drivers/gpu/drm/amd/amdgpu/amdgpu_vf_error.c | 85 ++++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_vf_error.h | 62 ++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h | 1 + drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c | 46 ++++++++------- drivers/gpu/drm/amd/amdgpu/mxgpu_ai.h | 4 +- drivers/gpu/drm/amd/amdgpu/mxgpu_vi.c | 1 + drivers/gpu/drm/amd/amdgpu/mxgpu_vi.h | 4 +- 9 files changed, 200 insertions(+), 26 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vf_error.c create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vf_error.h (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index faea6349228f..658bac0cdc5e 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -25,7 +25,7 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \ amdgpu_prime.o amdgpu_vm.o amdgpu_ib.o amdgpu_pll.o \ amdgpu_ucode.o amdgpu_bo_list.o amdgpu_ctx.o amdgpu_sync.o \ amdgpu_gtt_mgr.o amdgpu_vram_mgr.o amdgpu_virt.o amdgpu_atomfirmware.o \ - amdgpu_queue_mgr.o + amdgpu_queue_mgr.o amdgpu_vf_error.o # add asic specific block amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o cik_ih.o kv_smc.o kv_dpm.o \ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index ae4387fd2b65..88e45c6d36ea 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -53,6 +53,7 @@ #include "bif/bif_4_1_d.h" #include #include +#include "amdgpu_vf_error.h" MODULE_FIRMWARE("amdgpu/vega10_gpu_info.bin"); MODULE_FIRMWARE("amdgpu/raven_gpu_info.bin"); @@ -2134,6 +2135,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, r = amdgpu_atombios_init(adev); if (r) { dev_err(adev->dev, "amdgpu_atombios_init failed\n"); + amdgpu_vf_error_put(AMDGIM_ERROR_VF_ATOMBIOS_INIT_FAIL, 0, 0); goto failed; } @@ -2144,6 +2146,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, if (amdgpu_vpost_needed(adev)) { if (!adev->bios) { dev_err(adev->dev, "no vBIOS found\n"); + amdgpu_vf_error_put(AMDGIM_ERROR_VF_NO_VBIOS, 0, 0); r = -EINVAL; goto failed; } @@ -2151,6 +2154,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, r = amdgpu_atom_asic_init(adev->mode_info.atom_context); if (r) { dev_err(adev->dev, "gpu post error!\n"); + amdgpu_vf_error_put(AMDGIM_ERROR_VF_GPU_POST_ERROR, 0, 0); goto failed; } } else { @@ -2162,7 +2166,8 @@ int amdgpu_device_init(struct amdgpu_device *adev, r = amdgpu_atombios_get_clock_info(adev); if (r) { dev_err(adev->dev, "amdgpu_atombios_get_clock_info failed\n"); - return r; + amdgpu_vf_error_put(AMDGIM_ERROR_VF_ATOMBIOS_GET_CLOCK_FAIL, 0, 0); + goto failed; } /* init i2c buses */ amdgpu_atombios_i2c_init(adev); @@ -2172,6 +2177,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, r = amdgpu_fence_driver_init(adev); if (r) { dev_err(adev->dev, "amdgpu_fence_driver_init failed\n"); + amdgpu_vf_error_put(AMDGIM_ERROR_VF_FENCE_INIT_FAIL, 0, 0); goto failed; } @@ -2181,6 +2187,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, r = amdgpu_init(adev); if (r) { dev_err(adev->dev, "amdgpu_init failed\n"); + amdgpu_vf_error_put(AMDGIM_ERROR_VF_AMDGPU_INIT_FAIL, 0, 0); amdgpu_fini(adev); goto failed; } @@ -2200,6 +2207,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, r = amdgpu_ib_pool_init(adev); if (r) { dev_err(adev->dev, "IB initialization failed (%d).\n", r); + amdgpu_vf_error_put(AMDGIM_ERROR_VF_IB_INIT_FAIL, 0, r); goto failed; } @@ -2244,12 +2252,14 @@ int amdgpu_device_init(struct amdgpu_device *adev, r = amdgpu_late_init(adev); if (r) { dev_err(adev->dev, "amdgpu_late_init failed\n"); + amdgpu_vf_error_put(AMDGIM_ERROR_VF_AMDGPU_LATE_INIT_FAIL, 0, r); goto failed; } return 0; failed: + amdgpu_vf_error_trans_all(adev); if (runtime) vga_switcheroo_fini_domain_pm_ops(adev->dev); return r; @@ -2937,6 +2947,7 @@ out: } } else { dev_err(adev->dev, "asic resume failed (%d).\n", r); + amdgpu_vf_error_put(AMDGIM_ERROR_VF_ASIC_RESUME_FAIL, 0, r); for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { if (adev->rings[i] && adev->rings[i]->sched.thread) { kthread_unpark(adev->rings[i]->sched.thread); @@ -2947,12 +2958,16 @@ out: drm_helper_resume_force_mode(adev->ddev); ttm_bo_unlock_delayed_workqueue(&adev->mman.bdev, resched); - if (r) + if (r) { /* bad news, how to tell it to userspace ? */ dev_info(adev->dev, "GPU reset failed\n"); - else + amdgpu_vf_error_put(AMDGIM_ERROR_VF_GPU_RESET_FAIL, 0, r); + } + else { dev_info(adev->dev, "GPU reset successed!\n"); + } + amdgpu_vf_error_trans_all(adev); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vf_error.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vf_error.c new file mode 100644 index 000000000000..45ac91861965 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vf_error.c @@ -0,0 +1,85 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "amdgpu.h" +#include "amdgpu_vf_error.h" +#include "mxgpu_ai.h" + +#define AMDGPU_VF_ERROR_ENTRY_SIZE 16 + +/* struct error_entry - amdgpu VF error information. */ +struct amdgpu_vf_error_buffer { + int read_count; + int write_count; + uint16_t code[AMDGPU_VF_ERROR_ENTRY_SIZE]; + uint16_t flags[AMDGPU_VF_ERROR_ENTRY_SIZE]; + uint64_t data[AMDGPU_VF_ERROR_ENTRY_SIZE]; +}; + +struct amdgpu_vf_error_buffer admgpu_vf_errors; + + +void amdgpu_vf_error_put(uint16_t sub_error_code, uint16_t error_flags, uint64_t error_data) +{ + int index; + uint16_t error_code = AMDGIM_ERROR_CODE(AMDGIM_ERROR_CATEGORY_VF, sub_error_code); + + index = admgpu_vf_errors.write_count % AMDGPU_VF_ERROR_ENTRY_SIZE; + admgpu_vf_errors.code [index] = error_code; + admgpu_vf_errors.flags [index] = error_flags; + admgpu_vf_errors.data [index] = error_data; + admgpu_vf_errors.write_count ++; +} + + +void amdgpu_vf_error_trans_all(struct amdgpu_device *adev) +{ + /* u32 pf2vf_flags = 0; */ + u32 data1, data2, data3; + int index; + + if ((NULL == adev) || (!amdgpu_sriov_vf(adev)) || (!adev->virt.ops) || (!adev->virt.ops->trans_msg)) { + return; + } +/* + TODO: Enable these code when pv2vf_info is merged + AMDGPU_FW_VRAM_PF2VF_READ (adev, feature_flags, &pf2vf_flags); + if (!(pf2vf_flags & AMDGIM_FEATURE_ERROR_LOG_COLLECT)) { + return; + } +*/ + /* The errors are overlay of array, correct read_count as full. */ + if (admgpu_vf_errors.write_count - admgpu_vf_errors.read_count > AMDGPU_VF_ERROR_ENTRY_SIZE) { + admgpu_vf_errors.read_count = admgpu_vf_errors.write_count - AMDGPU_VF_ERROR_ENTRY_SIZE; + } + + while (admgpu_vf_errors.read_count < admgpu_vf_errors.write_count) { + index =admgpu_vf_errors.read_count % AMDGPU_VF_ERROR_ENTRY_SIZE; + data1 = AMDGIM_ERROR_CODE_FLAGS_TO_MAILBOX (admgpu_vf_errors.code[index], admgpu_vf_errors.flags[index]); + data2 = admgpu_vf_errors.data[index] & 0xFFFFFFFF; + data3 = (admgpu_vf_errors.data[index] >> 32) & 0xFFFFFFFF; + + adev->virt.ops->trans_msg(adev, IDH_LOG_VF_ERROR, data1, data2, data3); + admgpu_vf_errors.read_count ++; + } +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vf_error.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vf_error.h new file mode 100644 index 000000000000..2a3278ec76ba --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vf_error.h @@ -0,0 +1,62 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef __VF_ERROR_H__ +#define __VF_ERROR_H__ + +#define AMDGIM_ERROR_CODE_FLAGS_TO_MAILBOX(c,f) (((c & 0xFFFF) << 16) | (f & 0xFFFF)) +#define AMDGIM_ERROR_CODE(t,c) (((t&0xF)<<12)|(c&0xFFF)) + +/* Please keep enum same as AMD GIM driver */ +enum AMDGIM_ERROR_VF { + AMDGIM_ERROR_VF_ATOMBIOS_INIT_FAIL = 0, + AMDGIM_ERROR_VF_NO_VBIOS, + AMDGIM_ERROR_VF_GPU_POST_ERROR, + AMDGIM_ERROR_VF_ATOMBIOS_GET_CLOCK_FAIL, + AMDGIM_ERROR_VF_FENCE_INIT_FAIL, + + AMDGIM_ERROR_VF_AMDGPU_INIT_FAIL, + AMDGIM_ERROR_VF_IB_INIT_FAIL, + AMDGIM_ERROR_VF_AMDGPU_LATE_INIT_FAIL, + AMDGIM_ERROR_VF_ASIC_RESUME_FAIL, + AMDGIM_ERROR_VF_GPU_RESET_FAIL, + + AMDGIM_ERROR_VF_TEST, + AMDGIM_ERROR_VF_MAX +}; + +enum AMDGIM_ERROR_CATEGORY { + AMDGIM_ERROR_CATEGORY_NON_USED = 0, + AMDGIM_ERROR_CATEGORY_GIM, + AMDGIM_ERROR_CATEGORY_PF, + AMDGIM_ERROR_CATEGORY_VF, + AMDGIM_ERROR_CATEGORY_VBIOS, + AMDGIM_ERROR_CATEGORY_MONITOR, + + AMDGIM_ERROR_CATEGORY_MAX +}; + +void amdgpu_vf_error_put(uint16_t sub_error_code, uint16_t error_flags, uint64_t error_data); +void amdgpu_vf_error_trans_all (struct amdgpu_device *adev); + +#endif /* __VF_ERROR_H__ */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h index 9e1062edb76e..e5b1baf387c1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h @@ -43,6 +43,7 @@ struct amdgpu_virt_ops { int (*req_full_gpu)(struct amdgpu_device *adev, bool init); int (*rel_full_gpu)(struct amdgpu_device *adev, bool init); int (*reset_gpu)(struct amdgpu_device *adev); + void (*trans_msg)(struct amdgpu_device *adev, u32 req, u32 data1, u32 data2, u32 data3); }; /* GPU virtualization */ diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c index bde3ca3c21c1..2812d88a8bdd 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c @@ -72,21 +72,6 @@ static void xgpu_ai_mailbox_set_valid(struct amdgpu_device *adev, bool val) reg); } -static void xgpu_ai_mailbox_trans_msg(struct amdgpu_device *adev, - enum idh_request req) -{ - u32 reg; - - reg = RREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0, - mmBIF_BX_PF0_MAILBOX_MSGBUF_TRN_DW0)); - reg = REG_SET_FIELD(reg, BIF_BX_PF0_MAILBOX_MSGBUF_TRN_DW0, - MSGBUF_DATA, req); - WREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF0_MAILBOX_MSGBUF_TRN_DW0), - reg); - - xgpu_ai_mailbox_set_valid(adev, true); -} - static int xgpu_ai_mailbox_rcv_msg(struct amdgpu_device *adev, enum idh_event event) { @@ -154,13 +139,25 @@ static int xgpu_ai_poll_msg(struct amdgpu_device *adev, enum idh_event event) return r; } - -static int xgpu_ai_send_access_requests(struct amdgpu_device *adev, - enum idh_request req) -{ +static void xgpu_ai_mailbox_trans_msg (struct amdgpu_device *adev, + enum idh_request req, u32 data1, u32 data2, u32 data3) { + u32 reg; int r; - xgpu_ai_mailbox_trans_msg(adev, req); + reg = RREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0, + mmBIF_BX_PF0_MAILBOX_MSGBUF_TRN_DW0)); + reg = REG_SET_FIELD(reg, BIF_BX_PF0_MAILBOX_MSGBUF_TRN_DW0, + MSGBUF_DATA, req); + WREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF0_MAILBOX_MSGBUF_TRN_DW0), + reg); + WREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF0_MAILBOX_MSGBUF_TRN_DW1), + data1); + WREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF0_MAILBOX_MSGBUF_TRN_DW2), + data2); + WREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF0_MAILBOX_MSGBUF_TRN_DW3), + data3); + + xgpu_ai_mailbox_set_valid(adev, true); /* start to poll ack */ r = xgpu_ai_poll_ack(adev); @@ -168,6 +165,14 @@ static int xgpu_ai_send_access_requests(struct amdgpu_device *adev, pr_err("Doesn't get ack from pf, continue\n"); xgpu_ai_mailbox_set_valid(adev, false); +} + +static int xgpu_ai_send_access_requests(struct amdgpu_device *adev, + enum idh_request req) +{ + int r; + + xgpu_ai_mailbox_trans_msg(adev, req, 0, 0, 0); /* start to check msg if request is idh_req_gpu_init_access */ if (req == IDH_REQ_GPU_INIT_ACCESS || @@ -342,4 +347,5 @@ const struct amdgpu_virt_ops xgpu_ai_virt_ops = { .req_full_gpu = xgpu_ai_request_full_gpu_access, .rel_full_gpu = xgpu_ai_release_full_gpu_access, .reset_gpu = xgpu_ai_request_reset, + .trans_msg = xgpu_ai_mailbox_trans_msg, }; diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.h b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.h index 9aefc44d2c34..1e91b9a1c591 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.h +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.h @@ -31,7 +31,9 @@ enum idh_request { IDH_REL_GPU_INIT_ACCESS, IDH_REQ_GPU_FINI_ACCESS, IDH_REL_GPU_FINI_ACCESS, - IDH_REQ_GPU_RESET_ACCESS + IDH_REQ_GPU_RESET_ACCESS, + + IDH_LOG_VF_ERROR = 200, }; enum idh_event { diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_vi.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_vi.c index 171a658135b5..c25a831f94ec 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_vi.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_vi.c @@ -613,4 +613,5 @@ const struct amdgpu_virt_ops xgpu_vi_virt_ops = { .req_full_gpu = xgpu_vi_request_full_gpu_access, .rel_full_gpu = xgpu_vi_release_full_gpu_access, .reset_gpu = xgpu_vi_request_reset, + .trans_msg = NULL, /* Does not need to trans VF errors to host. */ }; diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_vi.h b/drivers/gpu/drm/amd/amdgpu/mxgpu_vi.h index 2db741131bc6..c791d73d2d54 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_vi.h +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_vi.h @@ -32,7 +32,9 @@ enum idh_request { IDH_REL_GPU_INIT_ACCESS, IDH_REQ_GPU_FINI_ACCESS, IDH_REL_GPU_FINI_ACCESS, - IDH_REQ_GPU_RESET_ACCESS + IDH_REQ_GPU_RESET_ACCESS, + + IDH_LOG_VF_ERROR = 200, }; /* VI mailbox messages data */ -- cgit v1.2.3 From 011d4bbea969268c013eaf6e39721d3181833711 Mon Sep 17 00:00:00 2001 From: Christian König Date: Mon, 26 Jun 2017 11:37:49 +0200 Subject: drm/amdgpu: cleanup initializing gtt_size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stop spreading the code over all GMC generations. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c | 20 ++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c | 10 +--------- drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 10 +--------- drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 10 +--------- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 10 +--------- 6 files changed, 25 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 20e0ed96efbb..df63823ad4db 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -559,6 +559,7 @@ struct amdgpu_gart { const struct amdgpu_gart_funcs *gart_funcs; }; +void amdgpu_gart_set_defaults(struct amdgpu_device *adev); int amdgpu_gart_table_ram_alloc(struct amdgpu_device *adev); void amdgpu_gart_table_ram_free(struct amdgpu_device *adev); int amdgpu_gart_table_vram_alloc(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c index a57abc1a25fb..982b1cc11dac 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c @@ -55,6 +55,26 @@ /* * Common GART table functions. */ + +/** + * amdgpu_gart_set_defaults - set the default gtt_size + * + * @adev: amdgpu_device pointer + * + * Set the default gtt_size based on parameters and available VRAM. + */ +void amdgpu_gart_set_defaults(struct amdgpu_device *adev) +{ + /* unless the user had overridden it, set the gart + * size equal to the 1024 or vram, whichever is larger. + */ + if (amdgpu_gart_size == -1) + adev->mc.gtt_size = max((AMDGPU_DEFAULT_GTT_SIZE_MB << 20), + adev->mc.mc_vram_size); + else + adev->mc.gtt_size = (uint64_t)amdgpu_gart_size << 20; +} + /** * amdgpu_gart_table_ram_alloc - allocate system ram for gart page table * diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c index c1a124a86775..5f7750c6497e 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c @@ -321,15 +321,7 @@ static int gmc_v6_0_mc_init(struct amdgpu_device *adev) adev->mc.real_vram_size = RREG32(mmCONFIG_MEMSIZE) * 1024ULL * 1024ULL; adev->mc.visible_vram_size = adev->mc.aper_size; - /* unless the user had overridden it, set the gart - * size equal to the 1024 or vram, whichever is larger. - */ - if (amdgpu_gart_size == -1) - adev->mc.gtt_size = max((AMDGPU_DEFAULT_GTT_SIZE_MB << 20), - adev->mc.mc_vram_size); - else - adev->mc.gtt_size = (uint64_t)amdgpu_gart_size << 20; - + amdgpu_gart_set_defaults(adev); gmc_v6_0_vram_gtt_location(adev, &adev->mc); return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c index 575d72583746..388b52febc8b 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c @@ -373,15 +373,7 @@ static int gmc_v7_0_mc_init(struct amdgpu_device *adev) if (adev->mc.visible_vram_size > adev->mc.real_vram_size) adev->mc.visible_vram_size = adev->mc.real_vram_size; - /* unless the user had overridden it, set the gart - * size equal to the 1024 or vram, whichever is larger. - */ - if (amdgpu_gart_size == -1) - adev->mc.gtt_size = max((AMDGPU_DEFAULT_GTT_SIZE_MB << 20), - adev->mc.mc_vram_size); - else - adev->mc.gtt_size = (uint64_t)amdgpu_gart_size << 20; - + amdgpu_gart_set_defaults(adev); gmc_v7_0_vram_gtt_location(adev, &adev->mc); return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index 6379177b9fcb..d148d1c585b3 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -535,15 +535,7 @@ static int gmc_v8_0_mc_init(struct amdgpu_device *adev) if (adev->mc.visible_vram_size > adev->mc.real_vram_size) adev->mc.visible_vram_size = adev->mc.real_vram_size; - /* unless the user had overridden it, set the gart - * size equal to the 1024 or vram, whichever is larger. - */ - if (amdgpu_gart_size == -1) - adev->mc.gtt_size = max((AMDGPU_DEFAULT_GTT_SIZE_MB << 20), - adev->mc.mc_vram_size); - else - adev->mc.gtt_size = (uint64_t)amdgpu_gart_size << 20; - + amdgpu_gart_set_defaults(adev); gmc_v8_0_vram_gtt_location(adev, &adev->mc); return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index c6394ea69f96..dbb43d99e02e 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -494,15 +494,7 @@ static int gmc_v9_0_mc_init(struct amdgpu_device *adev) if (adev->mc.visible_vram_size > adev->mc.real_vram_size) adev->mc.visible_vram_size = adev->mc.real_vram_size; - /* unless the user had overridden it, set the gart - * size equal to the 1024 or vram, whichever is larger. - */ - if (amdgpu_gart_size == -1) - adev->mc.gtt_size = max((AMDGPU_DEFAULT_GTT_SIZE_MB << 20), - adev->mc.mc_vram_size); - else - adev->mc.gtt_size = (uint64_t)amdgpu_gart_size << 20; - + amdgpu_gart_set_defaults(adev); gmc_v9_0_vram_gtt_location(adev, &adev->mc); return 0; -- cgit v1.2.3 From b8e0e6e16e3ac130901111e2c503b3533f9719ee Mon Sep 17 00:00:00 2001 From: Christian König Date: Mon, 26 Jun 2017 15:19:30 +0200 Subject: drm/amdgpu: fix amdgpu_debugfs_gem_bo_info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise we trigger a bunch of WARN_ONs when this is called. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 621f739103a6..96c4493ccf8f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -784,6 +784,7 @@ static int amdgpu_debugfs_gem_bo_info(int id, void *ptr, void *data) unsigned domain; const char *placement; unsigned pin_count; + uint64_t offset; domain = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type); switch (domain) { @@ -798,9 +799,12 @@ static int amdgpu_debugfs_gem_bo_info(int id, void *ptr, void *data) placement = " CPU"; break; } - seq_printf(m, "\t0x%08x: %12ld byte %s @ 0x%010Lx", - id, amdgpu_bo_size(bo), placement, - amdgpu_bo_gpu_offset(bo)); + seq_printf(m, "\t0x%08x: %12ld byte %s", + id, amdgpu_bo_size(bo), placement); + + offset = ACCESS_ONCE(bo->tbo.mem.start); + if (offset != AMDGPU_BO_INVALID_OFFSET) + seq_printf(m, " @ 0x%010Lx", offset); pin_count = ACCESS_ONCE(bo->pin_count); if (pin_count) -- cgit v1.2.3 From 98b09f52db46b11fdc650dd0906ef682c5c0be63 Mon Sep 17 00:00:00 2001 From: ozeng Date: Tue, 27 Jun 2017 14:45:18 -0500 Subject: drm/amdgpu: Changed CU reservation golden settings With previous golden settings, compute task can't use reserved LDS (32K) on CU0 and CU1. On 64K LDS system, if compute work group allocate more than 32K LDS, then it can't be dispatched to CU0 and CU1 because of the reservation. This enables compute task to use reserved LDS on CU0 and CU1. Signed-off-by: Oak Zeng Acked-by: Alex Deucher Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index aa5a50f5eac8..4bb12ee46315 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -193,8 +193,8 @@ static const u32 tonga_golden_common_all[] = mmGB_ADDR_CONFIG, 0xffffffff, 0x22011003, mmSPI_RESOURCE_RESERVE_CU_0, 0xffffffff, 0x00000800, mmSPI_RESOURCE_RESERVE_CU_1, 0xffffffff, 0x00000800, - mmSPI_RESOURCE_RESERVE_EN_CU_0, 0xffffffff, 0x00007FBF, - mmSPI_RESOURCE_RESERVE_EN_CU_1, 0xffffffff, 0x00007FAF + mmSPI_RESOURCE_RESERVE_EN_CU_0, 0xffffffff, 0x00FF7FBF, + mmSPI_RESOURCE_RESERVE_EN_CU_1, 0xffffffff, 0x00FF7FAF }; static const u32 tonga_mgcg_cgcg_init[] = @@ -303,8 +303,8 @@ static const u32 polaris11_golden_common_all[] = mmGB_ADDR_CONFIG, 0xffffffff, 0x22011002, mmSPI_RESOURCE_RESERVE_CU_0, 0xffffffff, 0x00000800, mmSPI_RESOURCE_RESERVE_CU_1, 0xffffffff, 0x00000800, - mmSPI_RESOURCE_RESERVE_EN_CU_0, 0xffffffff, 0x00007FBF, - mmSPI_RESOURCE_RESERVE_EN_CU_1, 0xffffffff, 0x00007FAF, + mmSPI_RESOURCE_RESERVE_EN_CU_0, 0xffffffff, 0x00FF7FBF, + mmSPI_RESOURCE_RESERVE_EN_CU_1, 0xffffffff, 0x00FF7FAF, }; static const u32 golden_settings_polaris10_a11[] = @@ -336,8 +336,8 @@ static const u32 polaris10_golden_common_all[] = mmGB_ADDR_CONFIG, 0xffffffff, 0x22011003, mmSPI_RESOURCE_RESERVE_CU_0, 0xffffffff, 0x00000800, mmSPI_RESOURCE_RESERVE_CU_1, 0xffffffff, 0x00000800, - mmSPI_RESOURCE_RESERVE_EN_CU_0, 0xffffffff, 0x00007FBF, - mmSPI_RESOURCE_RESERVE_EN_CU_1, 0xffffffff, 0x00007FAF, + mmSPI_RESOURCE_RESERVE_EN_CU_0, 0xffffffff, 0x00FF7FBF, + mmSPI_RESOURCE_RESERVE_EN_CU_1, 0xffffffff, 0x00FF7FAF, }; static const u32 fiji_golden_common_all[] = @@ -348,8 +348,8 @@ static const u32 fiji_golden_common_all[] = mmGB_ADDR_CONFIG, 0xffffffff, 0x22011003, mmSPI_RESOURCE_RESERVE_CU_0, 0xffffffff, 0x00000800, mmSPI_RESOURCE_RESERVE_CU_1, 0xffffffff, 0x00000800, - mmSPI_RESOURCE_RESERVE_EN_CU_0, 0xffffffff, 0x00007FBF, - mmSPI_RESOURCE_RESERVE_EN_CU_1, 0xffffffff, 0x00007FAF, + mmSPI_RESOURCE_RESERVE_EN_CU_0, 0xffffffff, 0x00FF7FBF, + mmSPI_RESOURCE_RESERVE_EN_CU_1, 0xffffffff, 0x00FF7FAF, mmGRBM_GFX_INDEX, 0xffffffff, 0xe0000000, mmSPI_CONFIG_CNTL_1, 0x0000000f, 0x00000009, }; @@ -436,8 +436,8 @@ static const u32 iceland_golden_common_all[] = mmGB_ADDR_CONFIG, 0xffffffff, 0x22010001, mmSPI_RESOURCE_RESERVE_CU_0, 0xffffffff, 0x00000800, mmSPI_RESOURCE_RESERVE_CU_1, 0xffffffff, 0x00000800, - mmSPI_RESOURCE_RESERVE_EN_CU_0, 0xffffffff, 0x00007FBF, - mmSPI_RESOURCE_RESERVE_EN_CU_1, 0xffffffff, 0x00007FAF + mmSPI_RESOURCE_RESERVE_EN_CU_0, 0xffffffff, 0x00FF7FBF, + mmSPI_RESOURCE_RESERVE_EN_CU_1, 0xffffffff, 0x00FF7FAF }; static const u32 iceland_mgcg_cgcg_init[] = @@ -532,8 +532,8 @@ static const u32 cz_golden_common_all[] = mmGB_ADDR_CONFIG, 0xffffffff, 0x22010001, mmSPI_RESOURCE_RESERVE_CU_0, 0xffffffff, 0x00000800, mmSPI_RESOURCE_RESERVE_CU_1, 0xffffffff, 0x00000800, - mmSPI_RESOURCE_RESERVE_EN_CU_0, 0xffffffff, 0x00007FBF, - mmSPI_RESOURCE_RESERVE_EN_CU_1, 0xffffffff, 0x00007FAF + mmSPI_RESOURCE_RESERVE_EN_CU_0, 0xffffffff, 0x00FF7FBF, + mmSPI_RESOURCE_RESERVE_EN_CU_1, 0xffffffff, 0x00FF7FAF }; static const u32 cz_mgcg_cgcg_init[] = @@ -637,8 +637,8 @@ static const u32 stoney_golden_common_all[] = mmGB_ADDR_CONFIG, 0xffffffff, 0x12010001, mmSPI_RESOURCE_RESERVE_CU_0, 0xffffffff, 0x00000800, mmSPI_RESOURCE_RESERVE_CU_1, 0xffffffff, 0x00000800, - mmSPI_RESOURCE_RESERVE_EN_CU_0, 0xffffffff, 0x00007FBF, - mmSPI_RESOURCE_RESERVE_EN_CU_1, 0xffffffff, 0x00007FAF, + mmSPI_RESOURCE_RESERVE_EN_CU_0, 0xffffffff, 0x00FF7FBF, + mmSPI_RESOURCE_RESERVE_EN_CU_1, 0xffffffff, 0x00FF7FAF, }; static const u32 stoney_mgcg_cgcg_init[] = -- cgit v1.2.3 From ccfee95c6e6e9614a7c5f1191902de7927b6af2f Mon Sep 17 00:00:00 2001 From: Kent Russell Date: Wed, 28 Jun 2017 15:16:41 -0400 Subject: drm/amdgpu: Update default vram_page_split description MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This was updated to 512 and the description update got missed Signed-off-by: Kent Russell Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index b59f37c83fa6..f8face2a1e77 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -186,7 +186,7 @@ module_param_named(vm_debug, amdgpu_vm_debug, int, 0644); MODULE_PARM_DESC(vm_update_mode, "VM update using CPU (0 = never (default except for large BAR(LB)), 1 = Graphics only, 2 = Compute only (default for LB), 3 = Both"); module_param_named(vm_update_mode, amdgpu_vm_update_mode, int, 0444); -MODULE_PARM_DESC(vram_page_split, "Number of pages after we split VRAM allocations (default 1024, -1 = disable)"); +MODULE_PARM_DESC(vram_page_split, "Number of pages after we split VRAM allocations (default 512, -1 = disable)"); module_param_named(vram_page_split, amdgpu_vram_page_split, int, 0444); MODULE_PARM_DESC(exp_hw_support, "experimental hw support (1 = enable, 0 = disable (default))"); -- cgit v1.2.3 From 0ed279877ddf7ae8e5acd9fe4d464ceba98f37cd Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 29 Jun 2017 12:38:37 -0500 Subject: drm/radeon: add header comment for clarification to vce_v2_0_enable_mgcg() Add function header comment to make it clear that local variable sw_cg is used for debugging and it should not be removed. Addresses-Coverity-ID: 1198635 Cc: Alex Deucher Signed-off-by: Gustavo A. R. Silva Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/vce_v2_0.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/vce_v2_0.c b/drivers/gpu/drm/radeon/vce_v2_0.c index fce214482e72..b0a43b68776d 100644 --- a/drivers/gpu/drm/radeon/vce_v2_0.c +++ b/drivers/gpu/drm/radeon/vce_v2_0.c @@ -104,6 +104,10 @@ static void vce_v2_0_disable_cg(struct radeon_device *rdev) WREG32(VCE_CGTT_CLK_OVERRIDE, 7); } +/* + * Local variable sw_cg is used for debugging purposes, in case we + * ran into problems with dynamic clock gating. Don't remove it. + */ void vce_v2_0_enable_mgcg(struct radeon_device *rdev, bool enable) { bool sw_cg = false; -- cgit v1.2.3 From e8110b1c9bdd3d76610a9783724233a570964d3c Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 28 Jun 2017 13:43:48 +0200 Subject: drm/amdgpu: move ring helpers to amdgpu_ring.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Keep them where they belong. Signed-off-by: Christian König Reviewed-by: Alex Deucher Acked-by: Felix Kuehling --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 44 -------------------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 42 ++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index df63823ad4db..714235f507f6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1792,50 +1792,6 @@ void amdgpu_mm_wdoorbell64(struct amdgpu_device *adev, u32 index, u64 v); #define RBIOS16(i) (RBIOS8(i) | (RBIOS8((i)+1) << 8)) #define RBIOS32(i) ((RBIOS16(i)) | (RBIOS16((i)+2) << 16)) -/* - * RING helpers. - */ -static inline void amdgpu_ring_write(struct amdgpu_ring *ring, uint32_t v) -{ - if (ring->count_dw <= 0) - DRM_ERROR("amdgpu: writing more dwords to the ring than expected!\n"); - ring->ring[ring->wptr++ & ring->buf_mask] = v; - ring->wptr &= ring->ptr_mask; - ring->count_dw--; -} - -static inline void amdgpu_ring_write_multiple(struct amdgpu_ring *ring, void *src, int count_dw) -{ - unsigned occupied, chunk1, chunk2; - void *dst; - - if (unlikely(ring->count_dw < count_dw)) { - DRM_ERROR("amdgpu: writing more dwords to the ring than expected!\n"); - return; - } - - occupied = ring->wptr & ring->buf_mask; - dst = (void *)&ring->ring[occupied]; - chunk1 = ring->buf_mask + 1 - occupied; - chunk1 = (chunk1 >= count_dw) ? count_dw: chunk1; - chunk2 = count_dw - chunk1; - chunk1 <<= 2; - chunk2 <<= 2; - - if (chunk1) - memcpy(dst, src, chunk1); - - if (chunk2) { - src += chunk1; - dst = (void *)ring->ring; - memcpy(dst, src, chunk2); - } - - ring->wptr += count_dw; - ring->wptr &= ring->ptr_mask; - ring->count_dw -= count_dw; -} - static inline struct amdgpu_sdma_instance * amdgpu_get_sdma_instance(struct amdgpu_ring *ring) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h index bc8dec992f73..04cbc3a4d4bf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h @@ -212,4 +212,46 @@ static inline void amdgpu_ring_clear_ring(struct amdgpu_ring *ring) } +static inline void amdgpu_ring_write(struct amdgpu_ring *ring, uint32_t v) +{ + if (ring->count_dw <= 0) + DRM_ERROR("amdgpu: writing more dwords to the ring than expected!\n"); + ring->ring[ring->wptr++ & ring->buf_mask] = v; + ring->wptr &= ring->ptr_mask; + ring->count_dw--; +} + +static inline void amdgpu_ring_write_multiple(struct amdgpu_ring *ring, + void *src, int count_dw) +{ + unsigned occupied, chunk1, chunk2; + void *dst; + + if (unlikely(ring->count_dw < count_dw)) { + DRM_ERROR("amdgpu: writing more dwords to the ring than expected!\n"); + return; + } + + occupied = ring->wptr & ring->buf_mask; + dst = (void *)&ring->ring[occupied]; + chunk1 = ring->buf_mask + 1 - occupied; + chunk1 = (chunk1 >= count_dw) ? count_dw: chunk1; + chunk2 = count_dw - chunk1; + chunk1 <<= 2; + chunk2 <<= 2; + + if (chunk1) + memcpy(dst, src, chunk1); + + if (chunk2) { + src += chunk1; + dst = (void *)ring->ring; + memcpy(dst, src, chunk2); + } + + ring->wptr += count_dw; + ring->wptr &= ring->ptr_mask; + ring->count_dw -= count_dw; +} + #endif -- cgit v1.2.3 From 369421cbfabf0650b73571d7d1c026fc3830e74d Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 28 Jun 2017 13:50:07 +0200 Subject: drm/amdgpu: fix amdgpu_ring_write_multiple MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Overwriting still used ring content has a low probability to cause problems, not writing at all has 100% probability to cause problems. Signed-off-by: Christian König Reviewed-by: Alex Deucher Acked-by: Felix Kuehling --- drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h index 04cbc3a4d4bf..322d25299a00 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h @@ -227,10 +227,8 @@ static inline void amdgpu_ring_write_multiple(struct amdgpu_ring *ring, unsigned occupied, chunk1, chunk2; void *dst; - if (unlikely(ring->count_dw < count_dw)) { + if (unlikely(ring->count_dw < count_dw)) DRM_ERROR("amdgpu: writing more dwords to the ring than expected!\n"); - return; - } occupied = ring->wptr & ring->buf_mask; dst = (void *)&ring->ring[occupied]; -- cgit v1.2.3 From df264f9e08081c8c79523fd9e9f5241ed23ee7e8 Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 28 Jun 2017 15:41:17 +0200 Subject: drm/amdgpu: allow flushing VMID0 before IB execution as well MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows us to queue IBs which needs an up to date system domain as well. Signed-off-by: Christian König Reviewed-by: Alex Deucher Acked-by: Felix Kuehling --- drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c index f774b3f497d2..1b30d2ab9c51 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c @@ -172,7 +172,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, if (ring->funcs->insert_start) ring->funcs->insert_start(ring); - if (vm) { + if (job) { r = amdgpu_vm_flush(ring, job); if (r) { amdgpu_ring_undo(ring); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c index 3d641e10e6b6..4510627ae83e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c @@ -81,6 +81,8 @@ int amdgpu_job_alloc_with_ib(struct amdgpu_device *adev, unsigned size, r = amdgpu_ib_get(adev, NULL, size, &(*job)->ibs[0]); if (r) kfree(*job); + else + (*job)->vm_pd_addr = adev->gart.table_addr; return r; } -- cgit v1.2.3 From fc9c8f5459f2dfa7f83bee3f388faaf570ef96ed Mon Sep 17 00:00:00 2001 From: Christian König Date: Thu, 29 Jun 2017 11:46:15 +0200 Subject: drm/amdgpu: add vm_needs_flush parameter to amdgpu_copy_buffer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows us to flush the system VM here. Signed-off-by: Christian König Reviewed-by: Alex Deucher Acked-by: Felix Kuehling --- drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_test.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 12 ++++++------ drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 9 ++++----- 5 files changed, 15 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c index 1beae5b930d0..2fb299afc12b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c @@ -40,7 +40,7 @@ static int amdgpu_benchmark_do_move(struct amdgpu_device *adev, unsigned size, for (i = 0; i < n; i++) { struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring; r = amdgpu_copy_buffer(ring, saddr, daddr, size, NULL, &fence, - false); + false, false); if (r) goto exit_do_move; r = dma_fence_wait(fence, false); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 8ee69652be8c..c34cf2c1ae4e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -535,7 +535,7 @@ int amdgpu_bo_backup_to_shadow(struct amdgpu_device *adev, r = amdgpu_copy_buffer(ring, bo_addr, shadow_addr, amdgpu_bo_size(bo), resv, fence, - direct); + direct, false); if (!r) amdgpu_bo_fence(bo, *fence, true); @@ -588,7 +588,7 @@ int amdgpu_bo_restore_from_shadow(struct amdgpu_device *adev, r = amdgpu_copy_buffer(ring, shadow_addr, bo_addr, amdgpu_bo_size(bo), resv, fence, - direct); + direct, false); if (!r) amdgpu_bo_fence(bo, *fence, true); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_test.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_test.c index 15510dadde01..d02e611a2dae 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_test.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_test.c @@ -111,7 +111,7 @@ static void amdgpu_do_test_moves(struct amdgpu_device *adev) amdgpu_bo_kunmap(gtt_obj[i]); r = amdgpu_copy_buffer(ring, gtt_addr, vram_addr, - size, NULL, &fence, false); + size, NULL, &fence, false, false); if (r) { DRM_ERROR("Failed GTT->VRAM copy %d\n", i); @@ -156,7 +156,7 @@ static void amdgpu_do_test_moves(struct amdgpu_device *adev) amdgpu_bo_kunmap(vram_obj); r = amdgpu_copy_buffer(ring, vram_addr, gtt_addr, - size, NULL, &fence, false); + size, NULL, &fence, false, false); if (r) { DRM_ERROR("Failed VRAM->GTT copy %d\n", i); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index c9b131b13ef7..8c5f75d29f32 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -318,7 +318,7 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo, r = amdgpu_copy_buffer(ring, old_start, new_start, cur_pages * PAGE_SIZE, - bo->resv, &next, false); + bo->resv, &next, false, false); if (r) goto error; @@ -1256,12 +1256,11 @@ int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma) return ttm_bo_mmap(filp, vma, &adev->mman.bdev); } -int amdgpu_copy_buffer(struct amdgpu_ring *ring, - uint64_t src_offset, - uint64_t dst_offset, - uint32_t byte_count, +int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset, + uint64_t dst_offset, uint32_t byte_count, struct reservation_object *resv, - struct dma_fence **fence, bool direct_submit) + struct dma_fence **fence, bool direct_submit, + bool vm_needs_flush) { struct amdgpu_device *adev = ring->adev; struct amdgpu_job *job; @@ -1283,6 +1282,7 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring, if (r) return r; + job->vm_needs_flush = vm_needs_flush; if (resv) { r = amdgpu_sync_resv(adev, &job->sync, resv, AMDGPU_FENCE_OWNER_UNDEFINED); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index 6bdede8ff12b..cd5bbfa2773f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -61,12 +61,11 @@ int amdgpu_gtt_mgr_alloc(struct ttm_mem_type_manager *man, const struct ttm_place *place, struct ttm_mem_reg *mem); -int amdgpu_copy_buffer(struct amdgpu_ring *ring, - uint64_t src_offset, - uint64_t dst_offset, - uint32_t byte_count, +int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset, + uint64_t dst_offset, uint32_t byte_count, struct reservation_object *resv, - struct dma_fence **fence, bool direct_submit); + struct dma_fence **fence, bool direct_submit, + bool vm_needs_flush); int amdgpu_fill_buffer(struct amdgpu_bo *bo, uint32_t src_data, struct reservation_object *resv, -- cgit v1.2.3 From 92c60d9cf6636fdf740ebc98af0d68426f07b19b Mon Sep 17 00:00:00 2001 From: Christian König Date: Thu, 29 Jun 2017 10:44:39 +0200 Subject: drm/amdgpu: bind BOs to TTM only once MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No need to do this on every round. Signed-off-by: Christian König Reviewed-by: Alex Deucher Acked-by: Felix Kuehling --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 70 ++++++++++++++------------------- 1 file changed, 29 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 8c5f75d29f32..e97dfe888d55 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -252,29 +252,15 @@ static void amdgpu_move_null(struct ttm_buffer_object *bo, new_mem->mm_node = NULL; } -static int amdgpu_mm_node_addr(struct ttm_buffer_object *bo, - struct drm_mm_node *mm_node, - struct ttm_mem_reg *mem, - uint64_t *addr) +static uint64_t amdgpu_mm_node_addr(struct ttm_buffer_object *bo, + struct drm_mm_node *mm_node, + struct ttm_mem_reg *mem) { - int r; - - switch (mem->mem_type) { - case TTM_PL_TT: - r = amdgpu_ttm_bind(bo, mem); - if (r) - return r; - - case TTM_PL_VRAM: - *addr = mm_node->start << PAGE_SHIFT; - *addr += bo->bdev->man[mem->mem_type].gpu_offset; - break; - default: - DRM_ERROR("Unknown placement %d\n", mem->mem_type); - return -EINVAL; - } + uint64_t addr; - return 0; + addr = mm_node->start << PAGE_SHIFT; + addr += bo->bdev->man[mem->mem_type].gpu_offset; + return addr; } static int amdgpu_move_blit(struct ttm_buffer_object *bo, @@ -298,18 +284,25 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo, return -EINVAL; } + if (old_mem->mem_type == TTM_PL_TT) { + r = amdgpu_ttm_bind(bo, old_mem); + if (r) + return r; + } + old_mm = old_mem->mm_node; - r = amdgpu_mm_node_addr(bo, old_mm, old_mem, &old_start); - if (r) - return r; old_size = old_mm->size; + old_start = amdgpu_mm_node_addr(bo, old_mm, old_mem); + if (new_mem->mem_type == TTM_PL_TT) { + r = amdgpu_ttm_bind(bo, new_mem); + if (r) + return r; + } new_mm = new_mem->mm_node; - r = amdgpu_mm_node_addr(bo, new_mm, new_mem, &new_start); - if (r) - return r; new_size = new_mm->size; + new_start = amdgpu_mm_node_addr(bo, new_mm, new_mem); num_pages = new_mem->num_pages; while (num_pages) { @@ -331,10 +324,7 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo, old_size -= cur_pages; if (!old_size) { - r = amdgpu_mm_node_addr(bo, ++old_mm, old_mem, - &old_start); - if (r) - goto error; + old_start = amdgpu_mm_node_addr(bo, ++old_mm, old_mem); old_size = old_mm->size; } else { old_start += cur_pages * PAGE_SIZE; @@ -342,11 +332,7 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo, new_size -= cur_pages; if (!new_size) { - r = amdgpu_mm_node_addr(bo, ++new_mm, new_mem, - &new_start); - if (r) - goto error; - + new_start = amdgpu_mm_node_addr(bo, ++new_mm, new_mem); new_size = new_mm->size; } else { new_start += cur_pages * PAGE_SIZE; @@ -1347,6 +1333,12 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo, return -EINVAL; } + if (bo->tbo.mem.mem_type == TTM_PL_TT) { + r = amdgpu_ttm_bind(&bo->tbo, &bo->tbo.mem); + if (r) + return r; + } + num_pages = bo->tbo.num_pages; mm_node = bo->tbo.mem.mm_node; num_loops = 0; @@ -1382,11 +1374,7 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo, uint32_t byte_count = mm_node->size << PAGE_SHIFT; uint64_t dst_addr; - r = amdgpu_mm_node_addr(&bo->tbo, mm_node, - &bo->tbo.mem, &dst_addr); - if (r) - return r; - + dst_addr = amdgpu_mm_node_addr(&bo->tbo, mm_node, &bo->tbo.mem); while (byte_count) { uint32_t cur_size_in_bytes = min(byte_count, max_bytes); -- cgit v1.2.3 From 98a7f88ce9a9ed26cea939558f33e3d483cfb4f0 Mon Sep 17 00:00:00 2001 From: Christian König Date: Fri, 30 Jun 2017 10:41:07 +0200 Subject: drm/amdgpu: bind BOs with GTT space allocated directly v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This avoids binding them later on. v2: fix typo in function name Signed-off-by: Christian König Reviewed-by: Alex Deucher Acked-by: Felix Kuehling --- drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c | 16 +++++++++- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 49 ++++++++++++++++++----------- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 1 + 3 files changed, 46 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c index f7d22c44034d..1ef625550442 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c @@ -80,6 +80,20 @@ static int amdgpu_gtt_mgr_fini(struct ttm_mem_type_manager *man) return 0; } +/** + * amdgpu_gtt_mgr_is_allocated - Check if mem has address space + * + * @mem: the mem object to check + * + * Check if a mem object has already address space allocated. + */ +bool amdgpu_gtt_mgr_is_allocated(struct ttm_mem_reg *mem) +{ + struct drm_mm_node *node = mem->mm_node; + + return (node->start != AMDGPU_BO_INVALID_OFFSET); +} + /** * amdgpu_gtt_mgr_alloc - allocate new ranges * @@ -101,7 +115,7 @@ int amdgpu_gtt_mgr_alloc(struct ttm_mem_type_manager *man, unsigned long fpfn, lpfn; int r; - if (node->start != AMDGPU_BO_INVALID_OFFSET) + if (amdgpu_gtt_mgr_is_allocated(mem)) return 0; if (place) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index e97dfe888d55..7064d31f0be5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -681,6 +681,31 @@ static void amdgpu_ttm_tt_unpin_userptr(struct ttm_tt *ttm) sg_free_table(ttm->sg); } +static int amdgpu_ttm_do_bind(struct ttm_tt *ttm, struct ttm_mem_reg *mem) +{ + struct amdgpu_ttm_tt *gtt = (void *)ttm; + uint64_t flags; + int r; + + spin_lock(>t->adev->gtt_list_lock); + flags = amdgpu_ttm_tt_pte_flags(gtt->adev, ttm, mem); + gtt->offset = (u64)mem->start << PAGE_SHIFT; + r = amdgpu_gart_bind(gtt->adev, gtt->offset, ttm->num_pages, + ttm->pages, gtt->ttm.dma_address, flags); + + if (r) { + DRM_ERROR("failed to bind %lu pages at 0x%08llX\n", + ttm->num_pages, gtt->offset); + goto error_gart_bind; + } + + list_add_tail(>t->list, >t->adev->gtt_list); +error_gart_bind: + spin_unlock(>t->adev->gtt_list_lock); + return r; + +} + static int amdgpu_ttm_backend_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem) { @@ -704,7 +729,10 @@ static int amdgpu_ttm_backend_bind(struct ttm_tt *ttm, bo_mem->mem_type == AMDGPU_PL_OA) return -EINVAL; - return 0; + if (amdgpu_gtt_mgr_is_allocated(bo_mem)) + r = amdgpu_ttm_do_bind(ttm, bo_mem); + + return r; } bool amdgpu_ttm_is_bound(struct ttm_tt *ttm) @@ -717,8 +745,6 @@ bool amdgpu_ttm_is_bound(struct ttm_tt *ttm) int amdgpu_ttm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *bo_mem) { struct ttm_tt *ttm = bo->ttm; - struct amdgpu_ttm_tt *gtt = (void *)bo->ttm; - uint64_t flags; int r; if (!ttm || amdgpu_ttm_is_bound(ttm)) @@ -731,22 +757,7 @@ int amdgpu_ttm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *bo_mem) return r; } - spin_lock(>t->adev->gtt_list_lock); - flags = amdgpu_ttm_tt_pte_flags(gtt->adev, ttm, bo_mem); - gtt->offset = (u64)bo_mem->start << PAGE_SHIFT; - r = amdgpu_gart_bind(gtt->adev, gtt->offset, ttm->num_pages, - ttm->pages, gtt->ttm.dma_address, flags); - - if (r) { - DRM_ERROR("failed to bind %lu pages at 0x%08llX\n", - ttm->num_pages, gtt->offset); - goto error_gart_bind; - } - - list_add_tail(>t->list, >t->adev->gtt_list); -error_gart_bind: - spin_unlock(>t->adev->gtt_list_lock); - return r; + return amdgpu_ttm_do_bind(ttm, bo_mem); } int amdgpu_ttm_recover_gart(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index cd5bbfa2773f..776a20ae40c4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -56,6 +56,7 @@ struct amdgpu_mman { extern const struct ttm_mem_type_manager_func amdgpu_gtt_mgr_func; extern const struct ttm_mem_type_manager_func amdgpu_vram_mgr_func; +bool amdgpu_gtt_mgr_is_allocated(struct ttm_mem_reg *mem); int amdgpu_gtt_mgr_alloc(struct ttm_mem_type_manager *man, struct ttm_buffer_object *tbo, const struct ttm_place *place, -- cgit v1.2.3 From 7504938f8e733053c8cf17dd7ac1f28053b8126a Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Thu, 8 Jun 2017 09:32:38 +0800 Subject: drm/amdgpu: add check when no firmware need to load Signed-off-by: Huang Rui Reviewed-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c index 4f50eeb65855..17a935df8e1d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c @@ -377,6 +377,11 @@ int amdgpu_ucode_init_bo(struct amdgpu_device *adev) struct amdgpu_firmware_info *ucode = NULL; const struct common_firmware_header *header = NULL; + if (!adev->firmware.fw_size) { + dev_warn(adev->dev, "No ip firmware need to load\n"); + return 0; + } + err = amdgpu_bo_create(adev, adev->firmware.fw_size, PAGE_SIZE, true, amdgpu_sriov_vf(adev) ? AMDGPU_GEM_DOMAIN_VRAM : AMDGPU_GEM_DOMAIN_GTT, AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS, @@ -459,6 +464,9 @@ int amdgpu_ucode_fini_bo(struct amdgpu_device *adev) int i; struct amdgpu_firmware_info *ucode = NULL; + if (!adev->firmware.fw_size) + return 0; + for (i = 0; i < adev->firmware.max_ucodes; i++) { ucode = &adev->firmware.ucode[i]; if (ucode->fw) { -- cgit v1.2.3 From a69c7e0138fcb74d3abd5d3760358ba8aa945bda Mon Sep 17 00:00:00 2001 From: Hawking Zhang Date: Thu, 29 Jun 2017 18:27:38 +0800 Subject: drm/amdgpu: update pctl1 ram index/data for mmhub on raven Signed-off-by: Hawking Zhang Reviewed-by: Alex Deucher Reviewed-by: Junwei Zhang --- drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c | 89 ++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c index 9804318f3488..01918dc5dc55 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c @@ -245,28 +245,28 @@ static void mmhub_v1_0_program_invalidation(struct amdgpu_device *adev) } struct pctl_data { - uint32_t index; - uint32_t data; + uint32_t index; + uint32_t data; }; const struct pctl_data pctl0_data[] = { - {0x0, 0x7a640}, - {0x9, 0x2a64a}, - {0xd, 0x2a680}, - {0x11, 0x6a684}, - {0x19, 0xea68e}, - {0x29, 0xa69e}, - {0x2b, 0x34a6c0}, - {0x61, 0x83a707}, - {0xe6, 0x8a7a4}, - {0xf0, 0x1a7b8}, - {0xf3, 0xfa7cc}, - {0x104, 0x17a7dd}, - {0x11d, 0xa7dc}, - {0x11f, 0x12a7f5}, - {0x133, 0xa808}, - {0x135, 0x12a810}, - {0x149, 0x7a82c} + {0x0, 0x7a640}, + {0x9, 0x2a64a}, + {0xd, 0x2a680}, + {0x11, 0x6a684}, + {0x19, 0xea68e}, + {0x29, 0xa69e}, + {0x2b, 0x34a6c0}, + {0x61, 0x83a707}, + {0xe6, 0x8a7a4}, + {0xf0, 0x1a7b8}, + {0xf3, 0xfa7cc}, + {0x104, 0x17a7dd}, + {0x11d, 0xa7dc}, + {0x11f, 0x12a7f5}, + {0x133, 0xa808}, + {0x135, 0x12a810}, + {0x149, 0x7a82c} }; #define PCTL0_DATA_LEN (sizeof(pctl0_data)/sizeof(pctl0_data[0])) @@ -275,31 +275,38 @@ const struct pctl_data pctl0_data[] = { #define PCTL0_STCTRL_REG_SAVE_RANGE0_LIMIT 0xa833 const struct pctl_data pctl1_data[] = { - {0x0, 0x39a000}, - {0x3b, 0x44a040}, - {0x81, 0x2a08d}, - {0x85, 0x6ba094}, - {0xf2, 0x18a100}, - {0x10c, 0x4a132}, - {0x112, 0xca141}, - {0x120, 0x2fa158}, - {0x151, 0x17a1d0}, - {0x16a, 0x1a1e9}, - {0x16d, 0x13a1ec}, - {0x182, 0x7a201}, - {0x18b, 0x3a20a}, - {0x190, 0x7a580}, - {0x199, 0xa590}, - {0x19b, 0x4a594}, - {0x1a1, 0x1a59c}, - {0x1a4, 0x7a82c}, - {0x1ad, 0xfa7cc}, - {0x1be, 0x17a7dd}, - {0x1d7, 0x12a810} + {0x0, 0x39a000}, + {0x3b, 0x44a040}, + {0x81, 0x2a08d}, + {0x85, 0x6ba094}, + {0xf2, 0x18a100}, + {0x10c, 0x4a132}, + {0x112, 0xca141}, + {0x120, 0x2fa158}, + {0x151, 0x17a1d0}, + {0x16a, 0x1a1e9}, + {0x16d, 0x13a1ec}, + {0x182, 0x7a201}, + {0x18b, 0x3a20a}, + {0x190, 0x7a580}, + {0x199, 0xa590}, + {0x19b, 0x4a594}, + {0x1a1, 0x1a59c}, + {0x1a4, 0x7a82c}, + {0x1ad, 0xfa7cc}, + {0x1be, 0x17a7dd}, + {0x1d7, 0x12a810}, + {0x1eb, 0x4000a7e1}, + {0x1ec, 0x5000a7f5}, + {0x1ed, 0x4000a7e2}, + {0x1ee, 0x5000a7dc}, + {0x1ef, 0x4000a7e3}, + {0x1f0, 0x5000a7f6}, + {0x1f1, 0x5000a7e4} }; #define PCTL1_DATA_LEN (sizeof(pctl1_data)/sizeof(pctl1_data[0])) -#define PCTL1_RENG_EXEC_END_PTR 0x1ea +#define PCTL1_RENG_EXEC_END_PTR 0x1f1 #define PCTL1_STCTRL_REG_SAVE_RANGE0_BASE 0xa000 #define PCTL1_STCTRL_REG_SAVE_RANGE0_LIMIT 0xa20d #define PCTL1_STCTRL_REG_SAVE_RANGE1_BASE 0xa580 -- cgit v1.2.3 From eabd76cef9002697979794826e625b9868e697b5 Mon Sep 17 00:00:00 2001 From: Nicolai Hähnle Date: Tue, 13 Jun 2017 22:12:38 +0200 Subject: drm/amd/sched: print sched job id in amd_sched_job trace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes it easier to correlate amd_sched_job with with other trace points that don't log the job pointer. v2: don't print the sched_job pointer (Andres) Signed-off-by: Nicolai Hähnle Reviewed-by: Andres Rodriguez Reviewed-by: Christian König --- drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h b/drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h index dbd4fd3a810b..8bd38102b58e 100644 --- a/drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h +++ b/drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h @@ -16,16 +16,16 @@ TRACE_EVENT(amd_sched_job, TP_ARGS(sched_job), TP_STRUCT__entry( __field(struct amd_sched_entity *, entity) - __field(struct amd_sched_job *, sched_job) __field(struct dma_fence *, fence) __field(const char *, name) + __field(uint64_t, id) __field(u32, job_count) __field(int, hw_job_count) ), TP_fast_assign( __entry->entity = sched_job->s_entity; - __entry->sched_job = sched_job; + __entry->id = sched_job->id; __entry->fence = &sched_job->s_fence->finished; __entry->name = sched_job->sched->name; __entry->job_count = kfifo_len( @@ -33,8 +33,9 @@ TRACE_EVENT(amd_sched_job, __entry->hw_job_count = atomic_read( &sched_job->sched->hw_rq_count); ), - TP_printk("entity=%p, sched job=%p, fence=%p, ring=%s, job count:%u, hw job count:%d", - __entry->entity, __entry->sched_job, __entry->fence, __entry->name, + TP_printk("entity=%p, id=%llu, fence=%p, ring=%s, job count:%u, hw job count:%d", + __entry->entity, __entry->id, + __entry->fence, __entry->name, __entry->job_count, __entry->hw_job_count) ); -- cgit v1.2.3 From 5327dd8acf05a48b01804af9e4fad90054c6cdb7 Mon Sep 17 00:00:00 2001 From: Christian König Date: Mon, 3 Jul 2017 15:21:42 +0200 Subject: drm/amdgpu: remove stale TODO comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit That is already fixed. Signed-off-by: Christian König Reviewed-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index c34cf2c1ae4e..a85e75327456 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -951,7 +951,6 @@ int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) size = bo->mem.num_pages << PAGE_SHIFT; offset = bo->mem.start << PAGE_SHIFT; - /* TODO: figure out how to map scattered VRAM to the CPU */ if ((offset + size) <= adev->mc.visible_vram_size) return 0; -- cgit v1.2.3 From 663ebbf63180ec6fb67d732ff3a8335c9d266c00 Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 28 Jun 2017 11:06:52 +0200 Subject: drm/amdgpu: trace VM flags as 64bits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise the upper bits are lost. Signed-off-by: Christian König Reviewed-by: Alex Xie Reviewed-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h index 8601904e670a..509f7a63d40c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h @@ -224,7 +224,7 @@ TRACE_EVENT(amdgpu_vm_bo_map, __field(long, start) __field(long, last) __field(u64, offset) - __field(u32, flags) + __field(u64, flags) ), TP_fast_assign( @@ -234,7 +234,7 @@ TRACE_EVENT(amdgpu_vm_bo_map, __entry->offset = mapping->offset; __entry->flags = mapping->flags; ), - TP_printk("bo=%p, start=%lx, last=%lx, offset=%010llx, flags=%08x", + TP_printk("bo=%p, start=%lx, last=%lx, offset=%010llx, flags=%llx", __entry->bo, __entry->start, __entry->last, __entry->offset, __entry->flags) ); @@ -248,7 +248,7 @@ TRACE_EVENT(amdgpu_vm_bo_unmap, __field(long, start) __field(long, last) __field(u64, offset) - __field(u32, flags) + __field(u64, flags) ), TP_fast_assign( @@ -258,7 +258,7 @@ TRACE_EVENT(amdgpu_vm_bo_unmap, __entry->offset = mapping->offset; __entry->flags = mapping->flags; ), - TP_printk("bo=%p, start=%lx, last=%lx, offset=%010llx, flags=%08x", + TP_printk("bo=%p, start=%lx, last=%lx, offset=%010llx, flags=%llx", __entry->bo, __entry->start, __entry->last, __entry->offset, __entry->flags) ); @@ -269,7 +269,7 @@ DECLARE_EVENT_CLASS(amdgpu_vm_mapping, TP_STRUCT__entry( __field(u64, soffset) __field(u64, eoffset) - __field(u32, flags) + __field(u64, flags) ), TP_fast_assign( @@ -277,7 +277,7 @@ DECLARE_EVENT_CLASS(amdgpu_vm_mapping, __entry->eoffset = mapping->last + 1; __entry->flags = mapping->flags; ), - TP_printk("soffs=%010llx, eoffs=%010llx, flags=%08x", + TP_printk("soffs=%010llx, eoffs=%010llx, flags=%llx", __entry->soffset, __entry->eoffset, __entry->flags) ); @@ -293,14 +293,14 @@ DEFINE_EVENT(amdgpu_vm_mapping, amdgpu_vm_bo_mapping, TRACE_EVENT(amdgpu_vm_set_ptes, TP_PROTO(uint64_t pe, uint64_t addr, unsigned count, - uint32_t incr, uint32_t flags), + uint32_t incr, uint64_t flags), TP_ARGS(pe, addr, count, incr, flags), TP_STRUCT__entry( __field(u64, pe) __field(u64, addr) __field(u32, count) __field(u32, incr) - __field(u32, flags) + __field(u64, flags) ), TP_fast_assign( @@ -310,7 +310,7 @@ TRACE_EVENT(amdgpu_vm_set_ptes, __entry->incr = incr; __entry->flags = flags; ), - TP_printk("pe=%010Lx, addr=%010Lx, incr=%u, flags=%08x, count=%u", + TP_printk("pe=%010Lx, addr=%010Lx, incr=%u, flags=%llx, count=%u", __entry->pe, __entry->addr, __entry->incr, __entry->flags, __entry->count) ); -- cgit v1.2.3 From 46886dbfbda2187adbe9028f4d0a190ce96200f1 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Sun, 2 Jul 2017 14:36:47 +0530 Subject: drm: radeon: radeon_ttm: constify ttm_place structures. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ttm_place are not supposed to change at runtime. All functions working with ttm_place provided by work with const ttm_place. So mark the non-const structs as const. File size before: text data bss dec hex filename 9235 344 136 9715 25f3 drivers/gpu/drm/radeon/radeon_ttm.o File size After adding 'const': text data bss dec hex filename 9267 312 136 9715 25f3 drivers/gpu/drm/radeon/radeon_ttm.o Reviewed-by: Christian König Signed-off-by: Arvind Yadav Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_ttm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index faa021396da3..2804b4a15896 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -178,7 +178,7 @@ static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, static void radeon_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *placement) { - static struct ttm_place placements = { + static const struct ttm_place placements = { .fpfn = 0, .lpfn = 0, .flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM -- cgit v1.2.3 From c4fc445a9ded54cfbe4fca6299c0fcb7dcd0b47b Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Sat, 1 Jul 2017 15:17:01 +0530 Subject: drm: radeon: constify drm_prop_enum_list structures. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drm_prop_enum_lists are not supposed to change at runtime. All functions working with drm_prop_enum_list provided by work with const drm_prop_enum_list. So mark the non-const structs as const. File size before: text data bss dec hex filename 18276 384 0 18660 48e4 drivers/gpu/drm/radeon/radeon_display.o File size After adding 'const': text data bss dec hex filename 18660 0 0 18660 48e4 drivers/gpu/drm/radeon/radeon_display.o Reviewed-by: Christian König Signed-off-by: Arvind Yadav Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_display.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 17d3dafc8319..f339c1c10fa1 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -1388,12 +1388,12 @@ static const struct drm_mode_config_funcs radeon_mode_funcs = { .output_poll_changed = radeon_output_poll_changed }; -static struct drm_prop_enum_list radeon_tmds_pll_enum_list[] = +static const struct drm_prop_enum_list radeon_tmds_pll_enum_list[] = { { 0, "driver" }, { 1, "bios" }, }; -static struct drm_prop_enum_list radeon_tv_std_enum_list[] = +static const struct drm_prop_enum_list radeon_tv_std_enum_list[] = { { TV_STD_NTSC, "ntsc" }, { TV_STD_PAL, "pal" }, { TV_STD_PAL_M, "pal-m" }, @@ -1404,25 +1404,25 @@ static struct drm_prop_enum_list radeon_tv_std_enum_list[] = { TV_STD_SECAM, "secam" }, }; -static struct drm_prop_enum_list radeon_underscan_enum_list[] = +static const struct drm_prop_enum_list radeon_underscan_enum_list[] = { { UNDERSCAN_OFF, "off" }, { UNDERSCAN_ON, "on" }, { UNDERSCAN_AUTO, "auto" }, }; -static struct drm_prop_enum_list radeon_audio_enum_list[] = +static const struct drm_prop_enum_list radeon_audio_enum_list[] = { { RADEON_AUDIO_DISABLE, "off" }, { RADEON_AUDIO_ENABLE, "on" }, { RADEON_AUDIO_AUTO, "auto" }, }; /* XXX support different dither options? spatial, temporal, both, etc. */ -static struct drm_prop_enum_list radeon_dither_enum_list[] = +static const struct drm_prop_enum_list radeon_dither_enum_list[] = { { RADEON_FMT_DITHER_DISABLE, "off" }, { RADEON_FMT_DITHER_ENABLE, "on" }, }; -static struct drm_prop_enum_list radeon_output_csc_enum_list[] = +static const struct drm_prop_enum_list radeon_output_csc_enum_list[] = { { RADEON_OUTPUT_CSC_BYPASS, "bypass" }, { RADEON_OUTPUT_CSC_TVRGB, "tvrgb" }, { RADEON_OUTPUT_CSC_YCBCR601, "ycbcr601" }, -- cgit v1.2.3 From 1aaa56029f47e16f9d03e25a313677f16212ad72 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Sun, 2 Jul 2017 14:43:58 +0530 Subject: drm: amd: amdgpu: constify ttm_place structures. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ttm_place are not supposed to change at runtime. All functions working with ttm_place provided by work with const ttm_place. So mark the non-const structs as const. Reviewed-by: Christian König Signed-off-by: Arvind Yadav Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 7064d31f0be5..ace178b393dd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -186,7 +186,7 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, { struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); struct amdgpu_bo *abo; - static struct ttm_place placements = { + static const struct ttm_place placements = { .fpfn = 0, .lpfn = 0, .flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM -- cgit v1.2.3 From 3164cba317c235f950c861928b290dd93b30d821 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 30 Jun 2017 17:00:01 -0400 Subject: drm/amdgpu/atombios: use bios_scratch_reg_offset for atombios MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Align with the atomfirmware code. Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c index 1e8e1123ddf4..8e7a7b9baa1d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c @@ -1686,7 +1686,7 @@ void amdgpu_atombios_scratch_regs_lock(struct amdgpu_device *adev, bool lock) { uint32_t bios_6_scratch; - bios_6_scratch = RREG32(mmBIOS_SCRATCH_6); + bios_6_scratch = RREG32(adev->bios_scratch_reg_offset + 6); if (lock) { bios_6_scratch |= ATOM_S6_CRITICAL_STATE; @@ -1696,15 +1696,17 @@ void amdgpu_atombios_scratch_regs_lock(struct amdgpu_device *adev, bool lock) bios_6_scratch |= ATOM_S6_ACC_MODE; } - WREG32(mmBIOS_SCRATCH_6, bios_6_scratch); + WREG32(adev->bios_scratch_reg_offset + 6, bios_6_scratch); } void amdgpu_atombios_scratch_regs_init(struct amdgpu_device *adev) { uint32_t bios_2_scratch, bios_6_scratch; - bios_2_scratch = RREG32(mmBIOS_SCRATCH_2); - bios_6_scratch = RREG32(mmBIOS_SCRATCH_6); + adev->bios_scratch_reg_offset = mmBIOS_SCRATCH_0; + + bios_2_scratch = RREG32(adev->bios_scratch_reg_offset + 2); + bios_6_scratch = RREG32(adev->bios_scratch_reg_offset + 6); /* let the bios control the backlight */ bios_2_scratch &= ~ATOM_S2_VRI_BRIGHT_ENABLE; @@ -1715,8 +1717,8 @@ void amdgpu_atombios_scratch_regs_init(struct amdgpu_device *adev) /* clear the vbios dpms state */ bios_2_scratch &= ~ATOM_S2_DEVICE_DPMS_STATE; - WREG32(mmBIOS_SCRATCH_2, bios_2_scratch); - WREG32(mmBIOS_SCRATCH_6, bios_6_scratch); + WREG32(adev->bios_scratch_reg_offset + 2, bios_2_scratch); + WREG32(adev->bios_scratch_reg_offset + 6, bios_6_scratch); } void amdgpu_atombios_scratch_regs_save(struct amdgpu_device *adev) @@ -1724,7 +1726,7 @@ void amdgpu_atombios_scratch_regs_save(struct amdgpu_device *adev) int i; for (i = 0; i < AMDGPU_BIOS_NUM_SCRATCH; i++) - adev->bios_scratch[i] = RREG32(mmBIOS_SCRATCH_0 + i); + adev->bios_scratch[i] = RREG32(adev->bios_scratch_reg_offset + i); } void amdgpu_atombios_scratch_regs_restore(struct amdgpu_device *adev) @@ -1738,20 +1740,20 @@ void amdgpu_atombios_scratch_regs_restore(struct amdgpu_device *adev) adev->bios_scratch[7] &= ~ATOM_S7_ASIC_INIT_COMPLETE_MASK; for (i = 0; i < AMDGPU_BIOS_NUM_SCRATCH; i++) - WREG32(mmBIOS_SCRATCH_0 + i, adev->bios_scratch[i]); + WREG32(adev->bios_scratch_reg_offset + i, adev->bios_scratch[i]); } void amdgpu_atombios_scratch_regs_engine_hung(struct amdgpu_device *adev, bool hung) { - u32 tmp = RREG32(mmBIOS_SCRATCH_3); + u32 tmp = RREG32(adev->bios_scratch_reg_offset + 3); if (hung) tmp |= ATOM_S3_ASIC_GUI_ENGINE_HUNG; else tmp &= ~ATOM_S3_ASIC_GUI_ENGINE_HUNG; - WREG32(mmBIOS_SCRATCH_3, tmp); + WREG32(adev->bios_scratch_reg_offset + 3, tmp); } /* Atom needs data in little endian format -- cgit v1.2.3 From d05da0e24bb584baf634489810561fc3d2a83bf3 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 30 Jun 2017 17:08:45 -0400 Subject: drm/amdgpu: unify some atombios/atomfirmware scratch reg functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that we use a pointer to the scratch reg start offset, most of the functions were duplicated. Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c | 35 ------------------------ drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h | 4 --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 20 +++----------- drivers/gpu/drm/amd/amdgpu/soc15.c | 6 ++-- 4 files changed, 7 insertions(+), 58 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c index 4bdda56fccee..9ddfe34d12af 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c @@ -66,41 +66,6 @@ void amdgpu_atomfirmware_scratch_regs_init(struct amdgpu_device *adev) } } -void amdgpu_atomfirmware_scratch_regs_save(struct amdgpu_device *adev) -{ - int i; - - for (i = 0; i < AMDGPU_BIOS_NUM_SCRATCH; i++) - adev->bios_scratch[i] = RREG32(adev->bios_scratch_reg_offset + i); -} - -void amdgpu_atomfirmware_scratch_regs_restore(struct amdgpu_device *adev) -{ - int i; - - /* - * VBIOS will check ASIC_INIT_COMPLETE bit to decide if - * execute ASIC_Init posting via driver - */ - adev->bios_scratch[7] &= ~ATOM_S7_ASIC_INIT_COMPLETE_MASK; - - for (i = 0; i < AMDGPU_BIOS_NUM_SCRATCH; i++) - WREG32(adev->bios_scratch_reg_offset + i, adev->bios_scratch[i]); -} - -void amdgpu_atomfirmware_scratch_regs_engine_hung(struct amdgpu_device *adev, - bool hung) -{ - u32 tmp = RREG32(adev->bios_scratch_reg_offset + 3); - - if (hung) - tmp |= ATOM_S3_ASIC_GUI_ENGINE_HUNG; - else - tmp &= ~ATOM_S3_ASIC_GUI_ENGINE_HUNG; - - WREG32(adev->bios_scratch_reg_offset + 3, tmp); -} - int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device *adev) { struct atom_context *ctx = adev->mode_info.atom_context; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h index a2c3ebe22c71..907e48f6b301 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h @@ -26,10 +26,6 @@ bool amdgpu_atomfirmware_gpu_supports_virtualization(struct amdgpu_device *adev); void amdgpu_atomfirmware_scratch_regs_init(struct amdgpu_device *adev); -void amdgpu_atomfirmware_scratch_regs_save(struct amdgpu_device *adev); -void amdgpu_atomfirmware_scratch_regs_restore(struct amdgpu_device *adev); -void amdgpu_atomfirmware_scratch_regs_engine_hung(struct amdgpu_device *adev, - bool hung); int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device *adev); #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 88e45c6d36ea..7963c54e5d03 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2393,10 +2393,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon) */ amdgpu_bo_evict_vram(adev); - if (adev->is_atom_fw) - amdgpu_atomfirmware_scratch_regs_save(adev); - else - amdgpu_atombios_scratch_regs_save(adev); + amdgpu_atombios_scratch_regs_save(adev); pci_save_state(dev->pdev); if (suspend) { /* Shut down the device */ @@ -2445,10 +2442,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon) if (r) goto unlock; } - if (adev->is_atom_fw) - amdgpu_atomfirmware_scratch_regs_restore(adev); - else - amdgpu_atombios_scratch_regs_restore(adev); + amdgpu_atombios_scratch_regs_restore(adev); /* post card */ if (amdgpu_need_post(adev)) { @@ -2861,15 +2855,9 @@ int amdgpu_gpu_reset(struct amdgpu_device *adev) r = amdgpu_suspend(adev); retry: - if (adev->is_atom_fw) - amdgpu_atomfirmware_scratch_regs_save(adev); - else - amdgpu_atombios_scratch_regs_save(adev); + amdgpu_atombios_scratch_regs_save(adev); r = amdgpu_asic_reset(adev); - if (adev->is_atom_fw) - amdgpu_atomfirmware_scratch_regs_restore(adev); - else - amdgpu_atombios_scratch_regs_restore(adev); + amdgpu_atombios_scratch_regs_restore(adev); /* post card */ amdgpu_atom_asic_init(adev->mode_info.atom_context); diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index a7341d88a320..79f5e3e73e0b 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -25,7 +25,7 @@ #include #include #include "amdgpu.h" -#include "amdgpu_atomfirmware.h" +#include "amdgpu_atombios.h" #include "amdgpu_ih.h" #include "amdgpu_uvd.h" #include "amdgpu_vce.h" @@ -392,11 +392,11 @@ static void soc15_gpu_pci_config_reset(struct amdgpu_device *adev) static int soc15_asic_reset(struct amdgpu_device *adev) { - amdgpu_atomfirmware_scratch_regs_engine_hung(adev, true); + amdgpu_atombios_scratch_regs_engine_hung(adev, true); soc15_gpu_pci_config_reset(adev); - amdgpu_atomfirmware_scratch_regs_engine_hung(adev, false); + amdgpu_atombios_scratch_regs_engine_hung(adev, false); return 0; } -- cgit v1.2.3 From 4426826c02dc367ec3c245ef5c5ca4dcdb45b4c8 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 30 Jun 2017 17:21:42 -0400 Subject: drm/amdgpu/atombios: add function for whether we need asic_init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Check the atom scratch registers to see if asic_init is complete or not. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c | 10 ++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h | 1 + 2 files changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c index 8e7a7b9baa1d..ce443586a0c7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c @@ -1756,6 +1756,16 @@ void amdgpu_atombios_scratch_regs_engine_hung(struct amdgpu_device *adev, WREG32(adev->bios_scratch_reg_offset + 3, tmp); } +bool amdgpu_atombios_scratch_need_asic_init(struct amdgpu_device *adev) +{ + u32 tmp = RREG32(adev->bios_scratch_reg_offset + 7); + + if (tmp & ATOM_S7_ASIC_INIT_COMPLETE_MASK) + return false; + else + return true; +} + /* Atom needs data in little endian format * so swap as appropriate when copying data to * or from atom. Note that atom operates on diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h index 38d0fe32e5cd..b0d5d1d7fdba 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h @@ -200,6 +200,7 @@ void amdgpu_atombios_scratch_regs_save(struct amdgpu_device *adev); void amdgpu_atombios_scratch_regs_restore(struct amdgpu_device *adev); void amdgpu_atombios_scratch_regs_engine_hung(struct amdgpu_device *adev, bool hung); +bool amdgpu_atombios_scratch_need_asic_init(struct amdgpu_device *adev); void amdgpu_atombios_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le); int amdgpu_atombios_get_max_vddc(struct amdgpu_device *adev, u8 voltage_type, -- cgit v1.2.3 From 47ed4e1c93a6c73f313022369c12ddd693890715 Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Tue, 4 Jul 2017 13:11:52 +0800 Subject: drm/amdgpu: add workaround for S3 issues on some vega10 boards Certain MC registers need a delay after writing them to properly update in the init sequence. Signed-off-by: Ken Wang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 15 +++++++++++++++ 2 files changed, 17 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 714235f507f6..bbc7b19d2c1b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1687,6 +1687,8 @@ struct amdgpu_device { bool has_hw_reset; u8 reset_magic[AMDGPU_RESET_MAGIC_NUM]; + /* record last mm index being written through WREG32*/ + unsigned long last_mm_index; }; static inline struct amdgpu_device *amdgpu_ttm_adev(struct ttm_bo_device *bdev) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 7963c54e5d03..8ce522b490c8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -129,6 +129,10 @@ void amdgpu_mm_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v, { trace_amdgpu_mm_wreg(adev->pdev->device, reg, v); + if (adev->asic_type >= CHIP_VEGA10 && reg == 0) { + adev->last_mm_index = v; + } + if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && amdgpu_sriov_runtime(adev)) { BUG_ON(in_interrupt()); return amdgpu_virt_kiq_wreg(adev, reg, v); @@ -144,6 +148,10 @@ void amdgpu_mm_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v, writel(v, ((void __iomem *)adev->rmmio) + (mmMM_DATA * 4)); spin_unlock_irqrestore(&adev->mmio_idx_lock, flags); } + + if (adev->asic_type >= CHIP_VEGA10 && reg == 1 && adev->last_mm_index == 0x5702C) { + udelay(500); + } } u32 amdgpu_io_rreg(struct amdgpu_device *adev, u32 reg) @@ -158,6 +166,9 @@ u32 amdgpu_io_rreg(struct amdgpu_device *adev, u32 reg) void amdgpu_io_wreg(struct amdgpu_device *adev, u32 reg, u32 v) { + if (adev->asic_type >= CHIP_VEGA10 && reg == 0) { + adev->last_mm_index = v; + } if ((reg * 4) < adev->rio_mem_size) iowrite32(v, adev->rio_mem + (reg * 4)); @@ -165,6 +176,10 @@ void amdgpu_io_wreg(struct amdgpu_device *adev, u32 reg, u32 v) iowrite32((reg * 4), adev->rio_mem + (mmMM_INDEX * 4)); iowrite32(v, adev->rio_mem + (mmMM_DATA * 4)); } + + if (adev->asic_type >= CHIP_VEGA10 && reg == 1 && adev->last_mm_index == 0x5702C) { + udelay(500); + } } /** -- cgit v1.2.3 From a80c929442d05bbf7f12d9b828ae59cbebbbe094 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Fri, 23 Jun 2017 15:06:37 +0800 Subject: drm/amdgpu: drop SMU_DRIVER_IF_VERSION check for some vega10 variants Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- .../gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c | 30 +++++++++++++++++----- 1 file changed, 24 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c index 269678443862..408514c965a0 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c @@ -356,6 +356,9 @@ int vega10_set_tools_address(struct pp_smumgr *smumgr) static int vega10_verify_smc_interface(struct pp_smumgr *smumgr) { uint32_t smc_driver_if_version; + struct cgs_system_info sys_info = {0}; + uint32_t dev_id; + uint32_t rev_id; PP_ASSERT_WITH_CODE(!vega10_send_msg_to_smc(smumgr, PPSMC_MSG_GetDriverIfVersion), @@ -363,12 +366,27 @@ static int vega10_verify_smc_interface(struct pp_smumgr *smumgr) return -EINVAL); vega10_read_arg_from_smc(smumgr, &smc_driver_if_version); - if (smc_driver_if_version != SMU9_DRIVER_IF_VERSION) { - pr_err("Your firmware(0x%x) doesn't match \ - SMU9_DRIVER_IF_VERSION(0x%x). \ - Please update your firmware!\n", - smc_driver_if_version, SMU9_DRIVER_IF_VERSION); - return -EINVAL; + sys_info.size = sizeof(struct cgs_system_info); + sys_info.info_id = CGS_SYSTEM_INFO_PCIE_DEV; + cgs_query_system_info(smumgr->device, &sys_info); + dev_id = (uint32_t)sys_info.value; + + sys_info.size = sizeof(struct cgs_system_info); + sys_info.info_id = CGS_SYSTEM_INFO_PCIE_REV; + cgs_query_system_info(smumgr->device, &sys_info); + rev_id = (uint32_t)sys_info.value; + + if (!((dev_id == 0x687f) && + ((rev_id == 0xc0) || + (rev_id == 0xc1) || + (rev_id == 0xc3)))) { + if (smc_driver_if_version != SMU9_DRIVER_IF_VERSION) { + pr_err("Your firmware(0x%x) doesn't match \ + SMU9_DRIVER_IF_VERSION(0x%x). \ + Please update your firmware!\n", + smc_driver_if_version, SMU9_DRIVER_IF_VERSION); + return -EINVAL; + } } return 0; -- cgit v1.2.3 From 747f6c921d0a4ec0cba76d8ef57729a959e0fd30 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Fri, 23 Jun 2017 15:08:15 +0800 Subject: drm/amdgpu: add ACG SMU firmware for other vega10 variants Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c | 8 +++++++- drivers/gpu/drm/amd/amdgpu/soc15.c | 2 -- drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c | 3 ++- 3 files changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c index c0a806280257..e525de2ecb2d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c @@ -719,7 +719,13 @@ static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device, strcpy(fw_name, "amdgpu/polaris12_smc.bin"); break; case CHIP_VEGA10: - strcpy(fw_name, "amdgpu/vega10_smc.bin"); + if ((adev->pdev->device == 0x687f) && + ((adev->pdev->revision == 0xc0) || + (adev->pdev->revision == 0xc1) || + (adev->pdev->revision == 0xc3))) + strcpy(fw_name, "amdgpu/vega10_acg_smc.bin"); + else + strcpy(fw_name, "amdgpu/vega10_smc.bin"); break; default: DRM_ERROR("SMC firmware not supported\n"); diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 79f5e3e73e0b..4003cb517451 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -62,8 +62,6 @@ #include "dce_virtual.h" #include "mxgpu_ai.h" -MODULE_FIRMWARE("amdgpu/vega10_smc.bin"); - #define mmFabricConfigAccessControl 0x0410 #define mmFabricConfigAccessControl_BASE_IDX 0 #define mmFabricConfigAccessControl_DEFAULT 0x00000000 diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c index bcc61ffd13cb..0ac19cf3f987 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c @@ -43,7 +43,8 @@ MODULE_FIRMWARE("amdgpu/polaris11_smc.bin"); MODULE_FIRMWARE("amdgpu/polaris11_smc_sk.bin"); MODULE_FIRMWARE("amdgpu/polaris11_k_smc.bin"); MODULE_FIRMWARE("amdgpu/polaris12_smc.bin"); - +MODULE_FIRMWARE("amdgpu/vega10_smc.bin"); +MODULE_FIRMWARE("amdgpu/vega10_acg_smc.bin"); int smum_early_init(struct pp_instance *handle) { -- cgit v1.2.3 From b7437509525a2de463594c77dc66bf675f8f99fd Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Sat, 24 Jun 2017 16:45:58 +0800 Subject: drm/amd/powerplay: add avfs profiling_info_v4_2 support on Vega10. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/include/atomfirmware.h | 63 ++++++ drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.c | 239 +++++++++++++++------ drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.h | 8 + 3 files changed, 240 insertions(+), 70 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/include/atomfirmware.h b/drivers/gpu/drm/amd/include/atomfirmware.h index 0021a1c63356..837296db9628 100644 --- a/drivers/gpu/drm/amd/include/atomfirmware.h +++ b/drivers/gpu/drm/amd/include/atomfirmware.h @@ -1233,6 +1233,69 @@ struct atom_asic_profiling_info_v4_1 uint32_t phyclk2gfxclk_c; }; +struct atom_asic_profiling_info_v4_2 { + struct atom_common_table_header table_header; + uint32_t maxvddc; + uint32_t minvddc; + uint32_t avfs_meannsigma_acontant0; + uint32_t avfs_meannsigma_acontant1; + uint32_t avfs_meannsigma_acontant2; + uint16_t avfs_meannsigma_dc_tol_sigma; + uint16_t avfs_meannsigma_platform_mean; + uint16_t avfs_meannsigma_platform_sigma; + uint32_t gb_vdroop_table_cksoff_a0; + uint32_t gb_vdroop_table_cksoff_a1; + uint32_t gb_vdroop_table_cksoff_a2; + uint32_t gb_vdroop_table_ckson_a0; + uint32_t gb_vdroop_table_ckson_a1; + uint32_t gb_vdroop_table_ckson_a2; + uint32_t avfsgb_fuse_table_cksoff_m1; + uint32_t avfsgb_fuse_table_cksoff_m2; + uint32_t avfsgb_fuse_table_cksoff_b; + uint32_t avfsgb_fuse_table_ckson_m1; + uint32_t avfsgb_fuse_table_ckson_m2; + uint32_t avfsgb_fuse_table_ckson_b; + uint16_t max_voltage_0_25mv; + uint8_t enable_gb_vdroop_table_cksoff; + uint8_t enable_gb_vdroop_table_ckson; + uint8_t enable_gb_fuse_table_cksoff; + uint8_t enable_gb_fuse_table_ckson; + uint16_t psm_age_comfactor; + uint8_t enable_apply_avfs_cksoff_voltage; + uint8_t reserved; + uint32_t dispclk2gfxclk_a; + uint32_t dispclk2gfxclk_b; + uint32_t dispclk2gfxclk_c; + uint32_t pixclk2gfxclk_a; + uint32_t pixclk2gfxclk_b; + uint32_t pixclk2gfxclk_c; + uint32_t dcefclk2gfxclk_a; + uint32_t dcefclk2gfxclk_b; + uint32_t dcefclk2gfxclk_c; + uint32_t phyclk2gfxclk_a; + uint32_t phyclk2gfxclk_b; + uint32_t phyclk2gfxclk_c; + uint32_t acg_gb_vdroop_table_a0; + uint32_t acg_gb_vdroop_table_a1; + uint32_t acg_gb_vdroop_table_a2; + uint32_t acg_avfsgb_fuse_table_m1; + uint32_t acg_avfsgb_fuse_table_m2; + uint32_t acg_avfsgb_fuse_table_b; + uint8_t enable_acg_gb_vdroop_table; + uint8_t enable_acg_gb_fuse_table; + uint32_t acg_dispclk2gfxclk_a; + uint32_t acg_dispclk2gfxclk_b; + uint32_t acg_dispclk2gfxclk_c; + uint32_t acg_pixclk2gfxclk_a; + uint32_t acg_pixclk2gfxclk_b; + uint32_t acg_pixclk2gfxclk_c; + uint32_t acg_dcefclk2gfxclk_a; + uint32_t acg_dcefclk2gfxclk_b; + uint32_t acg_dcefclk2gfxclk_c; + uint32_t acg_phyclk2gfxclk_a; + uint32_t acg_phyclk2gfxclk_b; + uint32_t acg_phyclk2gfxclk_c; +}; /* *************************************************************************** diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.c b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.c index 720d5006ff62..cd33eb179db2 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.c @@ -276,7 +276,10 @@ int pp_atomfwctrl_get_avfs_information(struct pp_hwmgr *hwmgr, struct pp_atomfwctrl_avfs_parameters *param) { uint16_t idx; + uint8_t format_revision, content_revision; + struct atom_asic_profiling_info_v4_1 *profile; + struct atom_asic_profiling_info_v4_2 *profile_v4_2; idx = GetIndexIntoMasterDataTable(asic_profiling_info); profile = (struct atom_asic_profiling_info_v4_1 *) @@ -286,76 +289,172 @@ int pp_atomfwctrl_get_avfs_information(struct pp_hwmgr *hwmgr, if (!profile) return -1; - param->ulMaxVddc = le32_to_cpu(profile->maxvddc); - param->ulMinVddc = le32_to_cpu(profile->minvddc); - param->ulMeanNsigmaAcontant0 = - le32_to_cpu(profile->avfs_meannsigma_acontant0); - param->ulMeanNsigmaAcontant1 = - le32_to_cpu(profile->avfs_meannsigma_acontant1); - param->ulMeanNsigmaAcontant2 = - le32_to_cpu(profile->avfs_meannsigma_acontant2); - param->usMeanNsigmaDcTolSigma = - le16_to_cpu(profile->avfs_meannsigma_dc_tol_sigma); - param->usMeanNsigmaPlatformMean = - le16_to_cpu(profile->avfs_meannsigma_platform_mean); - param->usMeanNsigmaPlatformSigma = - le16_to_cpu(profile->avfs_meannsigma_platform_sigma); - param->ulGbVdroopTableCksoffA0 = - le32_to_cpu(profile->gb_vdroop_table_cksoff_a0); - param->ulGbVdroopTableCksoffA1 = - le32_to_cpu(profile->gb_vdroop_table_cksoff_a1); - param->ulGbVdroopTableCksoffA2 = - le32_to_cpu(profile->gb_vdroop_table_cksoff_a2); - param->ulGbVdroopTableCksonA0 = - le32_to_cpu(profile->gb_vdroop_table_ckson_a0); - param->ulGbVdroopTableCksonA1 = - le32_to_cpu(profile->gb_vdroop_table_ckson_a1); - param->ulGbVdroopTableCksonA2 = - le32_to_cpu(profile->gb_vdroop_table_ckson_a2); - param->ulGbFuseTableCksoffM1 = - le32_to_cpu(profile->avfsgb_fuse_table_cksoff_m1); - param->ulGbFuseTableCksoffM2 = - le32_to_cpu(profile->avfsgb_fuse_table_cksoff_m2); - param->ulGbFuseTableCksoffB = - le32_to_cpu(profile->avfsgb_fuse_table_cksoff_b); - param->ulGbFuseTableCksonM1 = - le32_to_cpu(profile->avfsgb_fuse_table_ckson_m1); - param->ulGbFuseTableCksonM2 = - le32_to_cpu(profile->avfsgb_fuse_table_ckson_m2); - param->ulGbFuseTableCksonB = - le32_to_cpu(profile->avfsgb_fuse_table_ckson_b); - - param->ucEnableGbVdroopTableCkson = - profile->enable_gb_vdroop_table_ckson; - param->ucEnableGbFuseTableCkson = - profile->enable_gb_fuse_table_ckson; - param->usPsmAgeComfactor = - le16_to_cpu(profile->psm_age_comfactor); - - param->ulDispclk2GfxclkM1 = - le32_to_cpu(profile->dispclk2gfxclk_a); - param->ulDispclk2GfxclkM2 = - le32_to_cpu(profile->dispclk2gfxclk_b); - param->ulDispclk2GfxclkB = - le32_to_cpu(profile->dispclk2gfxclk_c); - param->ulDcefclk2GfxclkM1 = - le32_to_cpu(profile->dcefclk2gfxclk_a); - param->ulDcefclk2GfxclkM2 = - le32_to_cpu(profile->dcefclk2gfxclk_b); - param->ulDcefclk2GfxclkB = - le32_to_cpu(profile->dcefclk2gfxclk_c); - param->ulPixelclk2GfxclkM1 = - le32_to_cpu(profile->pixclk2gfxclk_a); - param->ulPixelclk2GfxclkM2 = - le32_to_cpu(profile->pixclk2gfxclk_b); - param->ulPixelclk2GfxclkB = - le32_to_cpu(profile->pixclk2gfxclk_c); - param->ulPhyclk2GfxclkM1 = - le32_to_cpu(profile->phyclk2gfxclk_a); - param->ulPhyclk2GfxclkM2 = - le32_to_cpu(profile->phyclk2gfxclk_b); - param->ulPhyclk2GfxclkB = - le32_to_cpu(profile->phyclk2gfxclk_c); + format_revision = ((struct atom_common_table_header *)profile)->format_revision; + content_revision = ((struct atom_common_table_header *)profile)->content_revision; + + if (format_revision == 4 && content_revision == 1) { + param->ulMaxVddc = le32_to_cpu(profile->maxvddc); + param->ulMinVddc = le32_to_cpu(profile->minvddc); + param->ulMeanNsigmaAcontant0 = + le32_to_cpu(profile->avfs_meannsigma_acontant0); + param->ulMeanNsigmaAcontant1 = + le32_to_cpu(profile->avfs_meannsigma_acontant1); + param->ulMeanNsigmaAcontant2 = + le32_to_cpu(profile->avfs_meannsigma_acontant2); + param->usMeanNsigmaDcTolSigma = + le16_to_cpu(profile->avfs_meannsigma_dc_tol_sigma); + param->usMeanNsigmaPlatformMean = + le16_to_cpu(profile->avfs_meannsigma_platform_mean); + param->usMeanNsigmaPlatformSigma = + le16_to_cpu(profile->avfs_meannsigma_platform_sigma); + param->ulGbVdroopTableCksoffA0 = + le32_to_cpu(profile->gb_vdroop_table_cksoff_a0); + param->ulGbVdroopTableCksoffA1 = + le32_to_cpu(profile->gb_vdroop_table_cksoff_a1); + param->ulGbVdroopTableCksoffA2 = + le32_to_cpu(profile->gb_vdroop_table_cksoff_a2); + param->ulGbVdroopTableCksonA0 = + le32_to_cpu(profile->gb_vdroop_table_ckson_a0); + param->ulGbVdroopTableCksonA1 = + le32_to_cpu(profile->gb_vdroop_table_ckson_a1); + param->ulGbVdroopTableCksonA2 = + le32_to_cpu(profile->gb_vdroop_table_ckson_a2); + param->ulGbFuseTableCksoffM1 = + le32_to_cpu(profile->avfsgb_fuse_table_cksoff_m1); + param->ulGbFuseTableCksoffM2 = + le32_to_cpu(profile->avfsgb_fuse_table_cksoff_m2); + param->ulGbFuseTableCksoffB = + le32_to_cpu(profile->avfsgb_fuse_table_cksoff_b); + param->ulGbFuseTableCksonM1 = + le32_to_cpu(profile->avfsgb_fuse_table_ckson_m1); + param->ulGbFuseTableCksonM2 = + le32_to_cpu(profile->avfsgb_fuse_table_ckson_m2); + param->ulGbFuseTableCksonB = + le32_to_cpu(profile->avfsgb_fuse_table_ckson_b); + + param->ucEnableGbVdroopTableCkson = + profile->enable_gb_vdroop_table_ckson; + param->ucEnableGbFuseTableCkson = + profile->enable_gb_fuse_table_ckson; + param->usPsmAgeComfactor = + le16_to_cpu(profile->psm_age_comfactor); + + param->ulDispclk2GfxclkM1 = + le32_to_cpu(profile->dispclk2gfxclk_a); + param->ulDispclk2GfxclkM2 = + le32_to_cpu(profile->dispclk2gfxclk_b); + param->ulDispclk2GfxclkB = + le32_to_cpu(profile->dispclk2gfxclk_c); + param->ulDcefclk2GfxclkM1 = + le32_to_cpu(profile->dcefclk2gfxclk_a); + param->ulDcefclk2GfxclkM2 = + le32_to_cpu(profile->dcefclk2gfxclk_b); + param->ulDcefclk2GfxclkB = + le32_to_cpu(profile->dcefclk2gfxclk_c); + param->ulPixelclk2GfxclkM1 = + le32_to_cpu(profile->pixclk2gfxclk_a); + param->ulPixelclk2GfxclkM2 = + le32_to_cpu(profile->pixclk2gfxclk_b); + param->ulPixelclk2GfxclkB = + le32_to_cpu(profile->pixclk2gfxclk_c); + param->ulPhyclk2GfxclkM1 = + le32_to_cpu(profile->phyclk2gfxclk_a); + param->ulPhyclk2GfxclkM2 = + le32_to_cpu(profile->phyclk2gfxclk_b); + param->ulPhyclk2GfxclkB = + le32_to_cpu(profile->phyclk2gfxclk_c); + param->ulAcgGbVdroopTableA0 = 0; + param->ulAcgGbVdroopTableA1 = 0; + param->ulAcgGbVdroopTableA2 = 0; + param->ulAcgGbFuseTableM1 = 0; + param->ulAcgGbFuseTableM2 = 0; + param->ulAcgGbFuseTableB = 0; + param->ucAcgEnableGbVdroopTable = 0; + param->ucAcgEnableGbFuseTable = 0; + } else if (format_revision == 4 && content_revision == 2) { + profile_v4_2 = (struct atom_asic_profiling_info_v4_2 *)profile; + param->ulMaxVddc = le32_to_cpu(profile_v4_2->maxvddc); + param->ulMinVddc = le32_to_cpu(profile_v4_2->minvddc); + param->ulMeanNsigmaAcontant0 = + le32_to_cpu(profile_v4_2->avfs_meannsigma_acontant0); + param->ulMeanNsigmaAcontant1 = + le32_to_cpu(profile_v4_2->avfs_meannsigma_acontant1); + param->ulMeanNsigmaAcontant2 = + le32_to_cpu(profile_v4_2->avfs_meannsigma_acontant2); + param->usMeanNsigmaDcTolSigma = + le16_to_cpu(profile_v4_2->avfs_meannsigma_dc_tol_sigma); + param->usMeanNsigmaPlatformMean = + le16_to_cpu(profile_v4_2->avfs_meannsigma_platform_mean); + param->usMeanNsigmaPlatformSigma = + le16_to_cpu(profile_v4_2->avfs_meannsigma_platform_sigma); + param->ulGbVdroopTableCksoffA0 = + le32_to_cpu(profile_v4_2->gb_vdroop_table_cksoff_a0); + param->ulGbVdroopTableCksoffA1 = + le32_to_cpu(profile_v4_2->gb_vdroop_table_cksoff_a1); + param->ulGbVdroopTableCksoffA2 = + le32_to_cpu(profile_v4_2->gb_vdroop_table_cksoff_a2); + param->ulGbVdroopTableCksonA0 = + le32_to_cpu(profile_v4_2->gb_vdroop_table_ckson_a0); + param->ulGbVdroopTableCksonA1 = + le32_to_cpu(profile_v4_2->gb_vdroop_table_ckson_a1); + param->ulGbVdroopTableCksonA2 = + le32_to_cpu(profile_v4_2->gb_vdroop_table_ckson_a2); + param->ulGbFuseTableCksoffM1 = + le32_to_cpu(profile_v4_2->avfsgb_fuse_table_cksoff_m1); + param->ulGbFuseTableCksoffM2 = + le32_to_cpu(profile_v4_2->avfsgb_fuse_table_cksoff_m2); + param->ulGbFuseTableCksoffB = + le32_to_cpu(profile_v4_2->avfsgb_fuse_table_cksoff_b); + param->ulGbFuseTableCksonM1 = + le32_to_cpu(profile_v4_2->avfsgb_fuse_table_ckson_m1); + param->ulGbFuseTableCksonM2 = + le32_to_cpu(profile_v4_2->avfsgb_fuse_table_ckson_m2); + param->ulGbFuseTableCksonB = + le32_to_cpu(profile_v4_2->avfsgb_fuse_table_ckson_b); + + param->ucEnableGbVdroopTableCkson = + profile_v4_2->enable_gb_vdroop_table_ckson; + param->ucEnableGbFuseTableCkson = + profile_v4_2->enable_gb_fuse_table_ckson; + param->usPsmAgeComfactor = + le16_to_cpu(profile_v4_2->psm_age_comfactor); + + param->ulDispclk2GfxclkM1 = + le32_to_cpu(profile_v4_2->dispclk2gfxclk_a); + param->ulDispclk2GfxclkM2 = + le32_to_cpu(profile_v4_2->dispclk2gfxclk_b); + param->ulDispclk2GfxclkB = + le32_to_cpu(profile_v4_2->dispclk2gfxclk_c); + param->ulDcefclk2GfxclkM1 = + le32_to_cpu(profile_v4_2->dcefclk2gfxclk_a); + param->ulDcefclk2GfxclkM2 = + le32_to_cpu(profile_v4_2->dcefclk2gfxclk_b); + param->ulDcefclk2GfxclkB = + le32_to_cpu(profile_v4_2->dcefclk2gfxclk_c); + param->ulPixelclk2GfxclkM1 = + le32_to_cpu(profile_v4_2->pixclk2gfxclk_a); + param->ulPixelclk2GfxclkM2 = + le32_to_cpu(profile_v4_2->pixclk2gfxclk_b); + param->ulPixelclk2GfxclkB = + le32_to_cpu(profile_v4_2->pixclk2gfxclk_c); + param->ulPhyclk2GfxclkM1 = + le32_to_cpu(profile->phyclk2gfxclk_a); + param->ulPhyclk2GfxclkM2 = + le32_to_cpu(profile_v4_2->phyclk2gfxclk_b); + param->ulPhyclk2GfxclkB = + le32_to_cpu(profile_v4_2->phyclk2gfxclk_c); + param->ulAcgGbVdroopTableA0 = le32_to_cpu(profile_v4_2->acg_gb_vdroop_table_a0); + param->ulAcgGbVdroopTableA1 = le32_to_cpu(profile_v4_2->acg_gb_vdroop_table_a1); + param->ulAcgGbVdroopTableA2 = le32_to_cpu(profile_v4_2->acg_gb_vdroop_table_a2); + param->ulAcgGbFuseTableM1 = le32_to_cpu(profile_v4_2->acg_avfsgb_fuse_table_m1); + param->ulAcgGbFuseTableM2 = le32_to_cpu(profile_v4_2->acg_avfsgb_fuse_table_m2); + param->ulAcgGbFuseTableB = le32_to_cpu(profile_v4_2->acg_avfsgb_fuse_table_b); + param->ucAcgEnableGbVdroopTable = le32_to_cpu(profile_v4_2->enable_acg_gb_vdroop_table); + param->ucAcgEnableGbFuseTable = le32_to_cpu(profile_v4_2->enable_acg_gb_fuse_table); + } else { + pr_info("Invalid VBIOS AVFS ProfilingInfo Revision!\n"); + return -EINVAL; + } return 0; } diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.h b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.h index 81908b5cfd5f..8e6b1f0ddebc 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.h @@ -109,6 +109,14 @@ struct pp_atomfwctrl_avfs_parameters { uint32_t ulPhyclk2GfxclkM1; uint32_t ulPhyclk2GfxclkM2; uint32_t ulPhyclk2GfxclkB; + uint32_t ulAcgGbVdroopTableA0; + uint32_t ulAcgGbVdroopTableA1; + uint32_t ulAcgGbVdroopTableA2; + uint32_t ulAcgGbFuseTableM1; + uint32_t ulAcgGbFuseTableM2; + uint32_t ulAcgGbFuseTableB; + uint32_t ucAcgEnableGbVdroopTable; + uint32_t ucAcgEnableGbFuseTable; }; struct pp_atomfwctrl_gpio_parameters { -- cgit v1.2.3 From 3272cfcf73b9e0932a037ed711347ce9dc97c16e Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Sat, 24 Jun 2017 18:27:07 +0800 Subject: drm/amd/powerplay: export ACG related smu message for vega10 Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/inc/smu9.h | 13 +++++++------ drivers/gpu/drm/amd/powerplay/inc/vega10_ppsmc.h | 4 ++++ 2 files changed, 11 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu9.h b/drivers/gpu/drm/amd/powerplay/inc/smu9.h index 9ef2490c7c2e..550ed675027a 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu9.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu9.h @@ -55,9 +55,9 @@ #define FEATURE_FW_CTF_BIT 23 #define FEATURE_LED_DISPLAY_BIT 24 #define FEATURE_FAN_CONTROL_BIT 25 -#define FEATURE_VOLTAGE_CONTROLLER_BIT 26 -#define FEATURE_SPARE_27_BIT 27 -#define FEATURE_SPARE_28_BIT 28 +#define FEATURE_FAST_PPT_BIT 26 +#define FEATURE_GFX_EDC_BIT 27 +#define FEATURE_ACG_BIT 28 #define FEATURE_SPARE_29_BIT 29 #define FEATURE_SPARE_30_BIT 30 #define FEATURE_SPARE_31_BIT 31 @@ -90,9 +90,10 @@ #define FFEATURE_FW_CTF_MASK (1 << FEATURE_FW_CTF_BIT ) #define FFEATURE_LED_DISPLAY_MASK (1 << FEATURE_LED_DISPLAY_BIT ) #define FFEATURE_FAN_CONTROL_MASK (1 << FEATURE_FAN_CONTROL_BIT ) -#define FFEATURE_VOLTAGE_CONTROLLER_MASK (1 << FEATURE_VOLTAGE_CONTROLLER_BIT ) -#define FFEATURE_SPARE_27_MASK (1 << FEATURE_SPARE_27_BIT ) -#define FFEATURE_SPARE_28_MASK (1 << FEATURE_SPARE_28_BIT ) + +#define FEATURE_FAST_PPT_MASK (1 << FAST_PPT_BIT ) +#define FEATURE_GFX_EDC_MASK (1 << FEATURE_GFX_EDC_BIT ) +#define FEATURE_ACG_MASK (1 << FEATURE_ACG_BIT ) #define FFEATURE_SPARE_29_MASK (1 << FEATURE_SPARE_29_BIT ) #define FFEATURE_SPARE_30_MASK (1 << FEATURE_SPARE_30_BIT ) #define FFEATURE_SPARE_31_MASK (1 << FEATURE_SPARE_31_BIT ) diff --git a/drivers/gpu/drm/amd/powerplay/inc/vega10_ppsmc.h b/drivers/gpu/drm/amd/powerplay/inc/vega10_ppsmc.h index b4af9e85dfa5..cb070ebc7de1 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/vega10_ppsmc.h +++ b/drivers/gpu/drm/amd/powerplay/inc/vega10_ppsmc.h @@ -124,6 +124,10 @@ typedef uint16_t PPSMC_Result; #define PPSMC_MSG_NumOfDisplays 0x56 #define PPSMC_MSG_ReadSerialNumTop32 0x58 #define PPSMC_MSG_ReadSerialNumBottom32 0x59 +#define PPSMC_MSG_RunAcgBtc 0x5C +#define PPSMC_MSG_RunAcgInClosedLoop 0x5D +#define PPSMC_MSG_RunAcgInOpenLoop 0x5E +#define PPSMC_MSG_InitializeAcg 0x5F #define PPSMC_MSG_GetCurrPkgPwr 0x61 #define PPSMC_Message_Count 0x62 -- cgit v1.2.3 From fc3a4fc6317a807002d4f3b6a8af50983feb98cd Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Sat, 24 Jun 2017 18:11:53 +0800 Subject: drm/amd/powerplay: add acg support in pptable for vega10 Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/inc/smu9_driver_if.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu9_driver_if.h b/drivers/gpu/drm/amd/powerplay/inc/smu9_driver_if.h index 532186b6f941..f6d6c61f796a 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu9_driver_if.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu9_driver_if.h @@ -312,7 +312,10 @@ typedef struct { PllSetting_t GfxBoostState; - uint32_t Reserved[14]; + uint8_t AcgEnable[NUM_GFXCLK_DPM_LEVELS]; + GbVdroopTable_t AcgBtcGbVdroopTable; + QuadraticInt_t AcgAvfsGb; + uint32_t Reserved[4]; /* Padding - ignore */ uint32_t MmHubPadding[7]; /* SMU internal use */ -- cgit v1.2.3 From bdb8cd10b99d55d35b869fbf5cd6df9420b9bd85 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Sat, 24 Jun 2017 18:13:26 +0800 Subject: drm/amd/powerplay: enable ACG feature on vega10. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c | 78 +++++++++++++++++++++- drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h | 6 +- 2 files changed, 80 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c index d6f097f44b6c..b14ea319bd95 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c @@ -321,8 +321,7 @@ static void vega10_init_dpm_defaults(struct pp_hwmgr *hwmgr) FEATURE_LED_DISPLAY_BIT; data->smu_features[GNLD_FAN_CONTROL].smu_feature_id = FEATURE_FAN_CONTROL_BIT; - data->smu_features[GNLD_VOLTAGE_CONTROLLER].smu_feature_id = - FEATURE_VOLTAGE_CONTROLLER_BIT; + data->smu_features[GNLD_ACG].smu_feature_id = FEATURE_ACG_BIT; if (!data->registry_data.prefetcher_dpm_key_disabled) data->smu_features[GNLD_DPM_PREFETCHER].supported = true; @@ -386,6 +385,12 @@ static void vega10_init_dpm_defaults(struct pp_hwmgr *hwmgr) if (data->registry_data.vr0hot_enabled) data->smu_features[GNLD_VR0HOT].supported = true; + smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_GetSmuVersion); + vega10_read_arg_from_smc(hwmgr->smumgr, &(data->smu_version)); + /* ACG firmware has major version 5 */ + if ((data->smu_version & 0xff000000) == 0x5000000) + data->smu_features[GNLD_ACG].supported = true; + } #ifdef PPLIB_VEGA10_EVV_SUPPORT @@ -2228,6 +2233,21 @@ static int vega10_populate_avfs_parameters(struct pp_hwmgr *hwmgr) pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m1_shift = 24; pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m2_shift = 12; pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].b_shift = 12; + + pp_table->AcgBtcGbVdroopTable.a0 = avfs_params.ulAcgGbVdroopTableA0; + pp_table->AcgBtcGbVdroopTable.a0_shift = 20; + pp_table->AcgBtcGbVdroopTable.a1 = avfs_params.ulAcgGbVdroopTableA1; + pp_table->AcgBtcGbVdroopTable.a1_shift = 20; + pp_table->AcgBtcGbVdroopTable.a2 = avfs_params.ulAcgGbVdroopTableA2; + pp_table->AcgBtcGbVdroopTable.a2_shift = 20; + + pp_table->AcgAvfsGb.m1 = avfs_params.ulAcgGbFuseTableM1; + pp_table->AcgAvfsGb.m2 = avfs_params.ulAcgGbFuseTableM2; + pp_table->AcgAvfsGb.b = avfs_params.ulAcgGbFuseTableB; + pp_table->AcgAvfsGb.m1_shift = 0; + pp_table->AcgAvfsGb.m2_shift = 0; + pp_table->AcgAvfsGb.b_shift = 0; + } else { data->smu_features[GNLD_AVFS].supported = false; } @@ -2236,6 +2256,55 @@ static int vega10_populate_avfs_parameters(struct pp_hwmgr *hwmgr) return 0; } +static int vega10_acg_enable(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = + (struct vega10_hwmgr *)(hwmgr->backend); + uint32_t agc_btc_response; + + if (data->smu_features[GNLD_ACG].supported) { + if (0 == vega10_enable_smc_features(hwmgr->smumgr, true, + data->smu_features[GNLD_DPM_PREFETCHER].smu_feature_bitmap)) + data->smu_features[GNLD_DPM_PREFETCHER].enabled = true; + + smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_InitializeAcg); + + smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_RunAcgBtc); + vega10_read_arg_from_smc(hwmgr->smumgr, &agc_btc_response);; + + if (1 == agc_btc_response) { + if (1 == data->acg_loop_state) + smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_RunAcgInClosedLoop); + else if (2 == data->acg_loop_state) + smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_RunAcgInOpenLoop); + if (0 == vega10_enable_smc_features(hwmgr->smumgr, true, + data->smu_features[GNLD_ACG].smu_feature_bitmap)) + data->smu_features[GNLD_ACG].enabled = true; + } else { + pr_info("[ACG_Enable] ACG BTC Returned Failed Status!\n"); + data->smu_features[GNLD_ACG].enabled = false; + } + } + + return 0; +} + +static int vega10_acg_disable(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = + (struct vega10_hwmgr *)(hwmgr->backend); + + if (data->smu_features[GNLD_ACG].supported) { + if (data->smu_features[GNLD_ACG].enabled) { + if (0 == vega10_enable_smc_features(hwmgr->smumgr, false, + data->smu_features[GNLD_ACG].smu_feature_bitmap)) + data->smu_features[GNLD_ACG].enabled = false; + } + } + + return 0; +} + static int vega10_populate_gpio_parameters(struct pp_hwmgr *hwmgr) { struct vega10_hwmgr *data = @@ -2506,7 +2575,7 @@ static int vega10_init_smc_table(struct pp_hwmgr *hwmgr) result = vega10_avfs_enable(hwmgr, true); PP_ASSERT_WITH_CODE(!result, "Attempt to enable AVFS feature Failed!", return result); - + vega10_acg_enable(hwmgr); vega10_save_default_power_profile(hwmgr); return 0; @@ -4683,6 +4752,9 @@ static int vega10_disable_dpm_tasks(struct pp_hwmgr *hwmgr) PP_ASSERT_WITH_CODE((tmp_result == 0), "Failed to disable ulv!", result = tmp_result); + tmp_result = vega10_acg_disable(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to disable acg!", result = tmp_result); return result; } diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h index 6e5c5b99593b..415080174b28 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h @@ -64,7 +64,9 @@ enum { GNLD_FW_CTF, GNLD_LED_DISPLAY, GNLD_FAN_CONTROL, - GNLD_VOLTAGE_CONTROLLER, + GNLD_FEATURE_FAST_PPT_BIT, + GNLD_DIDT, + GNLD_ACG, GNLD_FEATURES_MAX }; @@ -381,6 +383,8 @@ struct vega10_hwmgr { struct vega10_smc_state_table smc_state_table; uint32_t config_telemetry; + uint32_t smu_version; + uint32_t acg_loop_state; }; #define VEGA10_DPM2_NEAR_TDP_DEC 10 -- cgit v1.2.3 From 8fdf074f1840eae838bbccbec37d0a1504ee432b Mon Sep 17 00:00:00 2001 From: Monk Liu Date: Tue, 6 Jun 2017 17:25:13 +0800 Subject: drm/amdgpu:fix world switch hang MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit for SR-IOV, we must keep the pipeline-sync in the protection of COND_EXEC, otherwise the command consumed by CPG is not consistent when world switch triggerd, e.g.: world switch hit and the IB frame is skipped so the fence won't signal, thus CP will jump to the next DMAframe's pipeline-sync command, and it will make CP hang foever. after pipelin-sync moved into COND_EXEC the consistency can be guaranteed Signed-off-by: Monk Liu Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 5 +++-- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 7 +++++-- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c index 1b30d2ab9c51..659997bfff30 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c @@ -130,6 +130,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, unsigned i; int r = 0; + bool need_pipe_sync = false; if (num_ibs == 0) return -EINVAL; @@ -165,7 +166,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, if (ring->funcs->emit_pipeline_sync && job && ((tmp = amdgpu_sync_get_fence(&job->sched_sync)) || amdgpu_vm_need_pipeline_sync(ring, job))) { - amdgpu_ring_emit_pipeline_sync(ring); + need_pipe_sync = true; dma_fence_put(tmp); } @@ -173,7 +174,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, ring->funcs->insert_start(ring); if (job) { - r = amdgpu_vm_flush(ring, job); + r = amdgpu_vm_flush(ring, job, need_pipe_sync); if (r) { amdgpu_ring_undo(ring); return r; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index cda9e5d8b831..30c4322ddce7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -743,7 +743,7 @@ static bool amdgpu_vm_is_large_bar(struct amdgpu_device *adev) * * Emit a VM flush when it is necessary. */ -int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job) +int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, bool need_pipe_sync) { struct amdgpu_device *adev = ring->adev; unsigned vmhub = ring->funcs->vmhub; @@ -765,12 +765,15 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job) vm_flush_needed = true; } - if (!vm_flush_needed && !gds_switch_needed) + if (!vm_flush_needed && !gds_switch_needed && !need_pipe_sync) return 0; if (ring->funcs->init_cond_exec) patch_offset = amdgpu_ring_init_cond_exec(ring); + if (need_pipe_sync) + amdgpu_ring_emit_pipeline_sync(ring); + if (ring->funcs->emit_vm_flush && vm_flush_needed) { struct dma_fence *fence; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h index 936f158bc5ec..3441ec58c823 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h @@ -222,7 +222,7 @@ int amdgpu_vm_alloc_pts(struct amdgpu_device *adev, int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, struct amdgpu_sync *sync, struct dma_fence *fence, struct amdgpu_job *job); -int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job); +int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, bool need_pipe_sync); void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vmhub, unsigned vmid); void amdgpu_vm_reset_all_ids(struct amdgpu_device *adev); -- cgit v1.2.3 From c708535e9ced6213b7c327eff88970e95515ec8a Mon Sep 17 00:00:00 2001 From: Shaoyun Liu Date: Wed, 5 Jul 2017 10:53:55 -0400 Subject: drm/amdgpu: Add WREG32_SOC15_NO_KIQ macro define Signed-off-by: Shaoyun Liu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/soc15_common.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/soc15_common.h b/drivers/gpu/drm/amd/amdgpu/soc15_common.h index e2d330eed952..7a8e4e28abb2 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15_common.h +++ b/drivers/gpu/drm/amd/amdgpu/soc15_common.h @@ -77,6 +77,13 @@ struct nbio_pcie_index_data { (3 == reg##_BASE_IDX ? ip##_BASE__INST##inst##_SEG3 + reg : \ (ip##_BASE__INST##inst##_SEG4 + reg))))), value) +#define WREG32_SOC15_NO_KIQ(ip, inst, reg, value) \ + WREG32_NO_KIQ( (0 == reg##_BASE_IDX ? ip##_BASE__INST##inst##_SEG0 + reg : \ + (1 == reg##_BASE_IDX ? ip##_BASE__INST##inst##_SEG1 + reg : \ + (2 == reg##_BASE_IDX ? ip##_BASE__INST##inst##_SEG2 + reg : \ + (3 == reg##_BASE_IDX ? ip##_BASE__INST##inst##_SEG3 + reg : \ + (ip##_BASE__INST##inst##_SEG4 + reg))))), value) + #define WREG32_SOC15_OFFSET(ip, inst, reg, offset, value) \ WREG32( (0 == reg##_BASE_IDX ? ip##_BASE__INST##inst##_SEG0 + reg : \ (1 == reg##_BASE_IDX ? ip##_BASE__INST##inst##_SEG1 + reg : \ -- cgit v1.2.3 From 57ea8c7b4d831caac27631329507baf2fbe094ae Mon Sep 17 00:00:00 2001 From: Shaoyun Liu Date: Wed, 5 Jul 2017 10:56:14 -0400 Subject: drm/amdgpu: NO KIQ usage on nbio hdp flush routine nbio hdp flush routine are called within atomic context. Avoid use KIQ when write to the HDP_MEM_COHERENCY_FLUSH_CNTL register since this register has its own VF copy Signed-off-by: Shaoyun Liu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/nbio_v6_1.c | 2 +- drivers/gpu/drm/amd/amdgpu/nbio_v7_0.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v6_1.c b/drivers/gpu/drm/amd/amdgpu/nbio_v6_1.c index 1e272f785def..61c00281a61b 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v6_1.c +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v6_1.c @@ -67,7 +67,7 @@ void nbio_v6_1_mc_access_enable(struct amdgpu_device *adev, bool enable) void nbio_v6_1_hdp_flush(struct amdgpu_device *adev) { - WREG32_SOC15(NBIO, 0, mmBIF_BX_PF0_HDP_MEM_COHERENCY_FLUSH_CNTL, 0); + WREG32_SOC15_NO_KIQ(NBIO, 0, mmBIF_BX_PF0_HDP_MEM_COHERENCY_FLUSH_CNTL, 0); } u32 nbio_v6_1_get_memsize(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_0.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_0.c index aa04632523fa..11b70d601922 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_0.c @@ -65,7 +65,7 @@ void nbio_v7_0_mc_access_enable(struct amdgpu_device *adev, bool enable) void nbio_v7_0_hdp_flush(struct amdgpu_device *adev) { - WREG32_SOC15(NBIO, 0, mmHDP_MEM_COHERENCY_FLUSH_CNTL, 0); + WREG32_SOC15_NO_KIQ(NBIO, 0, mmHDP_MEM_COHERENCY_FLUSH_CNTL, 0); } u32 nbio_v7_0_get_memsize(struct amdgpu_device *adev) -- cgit v1.2.3 From edc4d3db0660624996ef4d1bbc7e8b39572fbe2e Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Fri, 2 Jun 2017 10:42:28 +0800 Subject: drm/amdgpu: remove superfluous check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Huang Rui Reviewed-by: Christian König Reviewed-by: Junwei Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 15 +++++---------- drivers/gpu/drm/amd/amdgpu/psp_v3_1.c | 8 ++++---- 2 files changed, 9 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 4083be61b328..dc2cc28c9588 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -435,16 +435,11 @@ static int psp_hw_fini(void *handle) psp_ring_destroy(psp, PSP_RING_TYPE__KM); - if (psp->tmr_buf) - amdgpu_bo_free_kernel(&psp->tmr_bo, &psp->tmr_mc_addr, &psp->tmr_buf); - - if (psp->fw_pri_buf) - amdgpu_bo_free_kernel(&psp->fw_pri_bo, - &psp->fw_pri_mc_addr, &psp->fw_pri_buf); - - if (psp->fence_buf_bo) - amdgpu_bo_free_kernel(&psp->fence_buf_bo, - &psp->fence_buf_mc_addr, &psp->fence_buf); + amdgpu_bo_free_kernel(&psp->tmr_bo, &psp->tmr_mc_addr, &psp->tmr_buf); + amdgpu_bo_free_kernel(&psp->fw_pri_bo, + &psp->fw_pri_mc_addr, &psp->fw_pri_buf); + amdgpu_bo_free_kernel(&psp->fence_buf_bo, + &psp->fence_buf_mc_addr, &psp->fence_buf); kfree(psp->cmd); psp->cmd = NULL; diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c index c98d77d0c8f8..48f69fe6b9e2 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c @@ -341,10 +341,10 @@ int psp_v3_1_ring_destroy(struct psp_context *psp, enum psp_ring_type ring_type) ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64), 0x80000000, 0x80000000, false); - if (ring->ring_mem) - amdgpu_bo_free_kernel(&adev->firmware.rbuf, - &ring->ring_mem_mc_addr, - (void **)&ring->ring_mem); + amdgpu_bo_free_kernel(&adev->firmware.rbuf, + &ring->ring_mem_mc_addr, + (void **)&ring->ring_mem); + return ret; } -- cgit v1.2.3 From 311146c91a2fdb4de92a0769cc1e5359a49b4c04 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Sun, 11 Jun 2017 18:28:00 +0800 Subject: drm/amdgpu: fix missed asd bo free when hw_fini MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Huang Rui Reviewed-by: Christian König Reviewed-by: Junwei Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index dc2cc28c9588..e54c8fe90288 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -440,6 +440,8 @@ static int psp_hw_fini(void *handle) &psp->fw_pri_mc_addr, &psp->fw_pri_buf); amdgpu_bo_free_kernel(&psp->fence_buf_bo, &psp->fence_buf_mc_addr, &psp->fence_buf); + amdgpu_bo_free_kernel(&psp->asd_shared_bo, &psp->asd_shared_mc_addr, + &psp->asd_shared_buf); kfree(psp->cmd); psp->cmd = NULL; -- cgit v1.2.3 From a1952da73f8951eeb6e99e2b4fd1b8680ed9d801 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Sun, 11 Jun 2017 18:57:08 +0800 Subject: drm/amdgpu: make psp cmd buffer as a reserve memory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Huang Rui Acked-by: Christian König Reviewed-by: Junwei Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 38 ++++++++++++++++----------------- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h | 5 +++++ 2 files changed, 23 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index e54c8fe90288..5346f291f881 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -118,33 +118,18 @@ psp_cmd_submit_buf(struct psp_context *psp, int index) { int ret; - struct amdgpu_bo *cmd_buf_bo; - uint64_t cmd_buf_mc_addr; - struct psp_gfx_cmd_resp *cmd_buf_mem; - struct amdgpu_device *adev = psp->adev; - - ret = amdgpu_bo_create_kernel(adev, PSP_CMD_BUFFER_SIZE, PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &cmd_buf_bo, &cmd_buf_mc_addr, - (void **)&cmd_buf_mem); - if (ret) - return ret; - memset(cmd_buf_mem, 0, PSP_CMD_BUFFER_SIZE); + memset(psp->cmd_buf_mem, 0, PSP_CMD_BUFFER_SIZE); - memcpy(cmd_buf_mem, cmd, sizeof(struct psp_gfx_cmd_resp)); + memcpy(psp->cmd_buf_mem, cmd, sizeof(struct psp_gfx_cmd_resp)); - ret = psp_cmd_submit(psp, ucode, cmd_buf_mc_addr, + ret = psp_cmd_submit(psp, ucode, psp->cmd_buf_mc_addr, fence_mc_addr, index); while (*((unsigned int *)psp->fence_buf) != index) { msleep(1); } - amdgpu_bo_free_kernel(&cmd_buf_bo, - &cmd_buf_mc_addr, - (void **)&cmd_buf_mem); - return ret; } @@ -351,6 +336,13 @@ static int psp_load_fw(struct amdgpu_device *adev) &psp->fence_buf_bo, &psp->fence_buf_mc_addr, &psp->fence_buf); + if (ret) + goto failed_mem2; + + ret = amdgpu_bo_create_kernel(adev, PSP_CMD_BUFFER_SIZE, PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &psp->cmd_buf_bo, &psp->cmd_buf_mc_addr, + (void **)&psp->cmd_buf_mem); if (ret) goto failed_mem1; @@ -358,7 +350,7 @@ static int psp_load_fw(struct amdgpu_device *adev) ret = psp_ring_init(psp, PSP_RING_TYPE__KM); if (ret) - goto failed_mem1; + goto failed_mem; ret = psp_tmr_init(psp); if (ret) @@ -379,9 +371,13 @@ static int psp_load_fw(struct amdgpu_device *adev) return 0; failed_mem: + amdgpu_bo_free_kernel(&psp->cmd_buf_bo, + &psp->cmd_buf_mc_addr, + (void **)&psp->cmd_buf_mem); +failed_mem1: amdgpu_bo_free_kernel(&psp->fence_buf_bo, &psp->fence_buf_mc_addr, &psp->fence_buf); -failed_mem1: +failed_mem2: amdgpu_bo_free_kernel(&psp->fw_pri_bo, &psp->fw_pri_mc_addr, &psp->fw_pri_buf); failed: @@ -442,6 +438,8 @@ static int psp_hw_fini(void *handle) &psp->fence_buf_mc_addr, &psp->fence_buf); amdgpu_bo_free_kernel(&psp->asd_shared_bo, &psp->asd_shared_mc_addr, &psp->asd_shared_buf); + amdgpu_bo_free_kernel(&psp->cmd_buf_bo, &psp->cmd_buf_mc_addr, + (void **)&psp->cmd_buf_mem); kfree(psp->cmd); psp->cmd = NULL; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h index 1a1c8b469f93..538fa9dbfb21 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h @@ -108,6 +108,11 @@ struct psp_context struct amdgpu_bo *fence_buf_bo; uint64_t fence_buf_mc_addr; void *fence_buf; + + /* cmd buffer */ + struct amdgpu_bo *cmd_buf_bo; + uint64_t cmd_buf_mc_addr; + struct psp_gfx_cmd_resp *cmd_buf_mem; }; struct amdgpu_psp_funcs { -- cgit v1.2.3 From 342169c42214bd7682f550eccae119e85f09006c Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Tue, 4 Jul 2017 16:14:06 +0800 Subject: drm/amdgpu: set firmware loading type as direct by default for raven In previous case, driver can't enable psp via the kernel parameter for raven. We should open this path and set it as direct by default till psp firmware loading is workable. Signed-off-by: Huang Rui Reviewed-by: Junwei Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c index 17a935df8e1d..fcfb9d4f7477 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c @@ -275,14 +275,10 @@ amdgpu_ucode_get_load_type(struct amdgpu_device *adev, int load_type) else return AMDGPU_FW_LOAD_PSP; case CHIP_RAVEN: -#if 0 - if (!load_type) + if (load_type != 2) return AMDGPU_FW_LOAD_DIRECT; else return AMDGPU_FW_LOAD_PSP; -#else - return AMDGPU_FW_LOAD_DIRECT; -#endif default: DRM_ERROR("Unknow firmware load type\n"); } -- cgit v1.2.3 From 8882635119f3d0bd9071ea00d873014f56f37cd0 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 6 Jul 2017 09:36:27 +0800 Subject: drm/amd/powerplay: fixed wrong data type declaration for ppfeaturemask Signed-off-by: Evan Quan Reviewed-by: Rex Zhu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index f8face2a1e77..d90dc426ee5b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -199,7 +199,7 @@ MODULE_PARM_DESC(sched_hw_submission, "the max number of HW submissions (default module_param_named(sched_hw_submission, amdgpu_sched_hw_submission, int, 0444); MODULE_PARM_DESC(ppfeaturemask, "all power features enabled (default))"); -module_param_named(ppfeaturemask, amdgpu_pp_feature_mask, int, 0444); +module_param_named(ppfeaturemask, amdgpu_pp_feature_mask, uint, 0444); MODULE_PARM_DESC(no_evict, "Support pinning request from user space (1 = enable, 0 = disable (default))"); module_param_named(no_evict, amdgpu_no_evict, int, 0444); -- cgit v1.2.3 From bcadae84232d42260f802152609060cc766e1166 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Thu, 15 Jun 2017 13:58:41 +0800 Subject: drm/amd/powerplay: fix avfs state update error on polaris. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c index 9616cedc139c..7e0347088941 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c @@ -200,15 +200,16 @@ polaris10_avfs_event_mgr(struct pp_smumgr *smumgr, bool SMU_VFT_INTACT) PP_ASSERT_WITH_CODE(0 == polaris10_perform_btc(smumgr), "[AVFS][Polaris10_AVFSEventMgr] Failure at SmuPolaris10_PerformBTC. AVFS Disabled", return -1); - + smu_data->avfs.avfs_btc_status = AVFS_BTC_ENABLEAVFS; break; case AVFS_BTC_DISABLED: + case AVFS_BTC_ENABLEAVFS: case AVFS_BTC_NOTSUPPORTED: break; default: - pr_info("[AVFS] Something is broken. See log!"); + pr_err("AVFS failed status is %x!\n", smu_data->avfs.avfs_btc_status); break; } -- cgit v1.2.3 From b37afd41a1f5a7d9dbc4cc6ede62e590a31e2192 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Thu, 15 Jun 2017 14:02:51 +0800 Subject: drm/amd/powerplay: refine avfs enable code on fiji. 1. simplify avfs state switch. 2. delete save/restore VFT table functions as not support by fiji. 3. implement thermal_avfs_enable funciton. Signed-off-by: Rex Zhu Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c | 19 ++++ drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.h | 1 + drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c | 115 ++------------------- 3 files changed, 28 insertions(+), 107 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c index 6a320b27aefd..ca24e155ef2d 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c @@ -2129,6 +2129,25 @@ int fiji_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) return 0; } + +int fiji_thermal_avfs_enable(struct pp_hwmgr *hwmgr) +{ + int ret; + struct pp_smumgr *smumgr = (struct pp_smumgr *)(hwmgr->smumgr); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(smumgr->backend); + + if (smu_data->avfs.AvfsBtcStatus != AVFS_BTC_ENABLEAVFS) + return 0; + + ret = smum_send_msg_to_smc(smumgr, PPSMC_MSG_EnableAvfs); + + if (!ret) + /* If this param is not changed, this function could fire unnecessarily */ + smu_data->avfs.AvfsBtcStatus = AVFS_BTC_COMPLETED_PREVIOUSLY; + + return ret; +} + static int fiji_program_mem_timing_parameters(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.h b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.h index 0e9e1f2d7238..d9c72d992e30 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.h +++ b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.h @@ -48,5 +48,6 @@ int fiji_initialize_mc_reg_table(struct pp_hwmgr *hwmgr); bool fiji_is_dpm_running(struct pp_hwmgr *hwmgr); int fiji_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr, struct amd_pp_profile *request); +int fiji_thermal_avfs_enable(struct pp_hwmgr *hwmgr); #endif diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c index a1cb78552cf6..719e8853b0dc 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c @@ -194,22 +194,10 @@ static int fiji_start_avfs_btc(struct pp_smumgr *smumgr) int result = 0; struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend); - priv->avfs.AvfsBtcStatus = AVFS_BTC_STARTED; if (priv->avfs.AvfsBtcParam) { if (!smum_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_PerformBtc, priv->avfs.AvfsBtcParam)) { - if (!smum_send_msg_to_smc(smumgr, PPSMC_MSG_EnableAvfs)) { - priv->avfs.AvfsBtcStatus = AVFS_BTC_COMPLETED_UNSAVED; - result = 0; - } else { - pr_err("[AVFS][fiji_start_avfs_btc] Attempt" - " to Enable AVFS Failed!"); - smum_send_msg_to_smc(smumgr, PPSMC_MSG_DisableAvfs); - result = -1; - } - } else { - pr_err("[AVFS][fiji_start_avfs_btc] " - "PerformBTC SMU msg failed"); + pr_err("PerformBTC SMU msg failed \n"); result = -1; } } @@ -224,42 +212,6 @@ static int fiji_start_avfs_btc(struct pp_smumgr *smumgr) return result; } -static int fiji_setup_pm_fuse_for_avfs(struct pp_smumgr *smumgr) -{ - int result = 0; - uint32_t table_start; - uint32_t charz_freq_addr, inversion_voltage_addr, charz_freq; - uint16_t inversion_voltage; - - charz_freq = 0x30750000; /* In 10KHz units 0x00007530 Actual value */ - inversion_voltage = 0x1A04; /* mV Q14.2 0x41A Actual value */ - - PP_ASSERT_WITH_CODE(0 == smu7_read_smc_sram_dword(smumgr, - SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU73_Firmware_Header, - PmFuseTable), &table_start, 0x40000), - "[AVFS][Fiji_SetupGfxLvlStruct] SMU could not communicate " - "starting address of PmFuse structure", - return -1;); - - charz_freq_addr = table_start + - offsetof(struct SMU73_Discrete_PmFuses, PsmCharzFreq); - inversion_voltage_addr = table_start + - offsetof(struct SMU73_Discrete_PmFuses, InversionVoltage); - - result = smu7_copy_bytes_to_smc(smumgr, charz_freq_addr, - (uint8_t *)(&charz_freq), sizeof(charz_freq), 0x40000); - PP_ASSERT_WITH_CODE(0 == result, - "[AVFS][fiji_setup_pm_fuse_for_avfs] charz_freq could not " - "be populated.", return -1;); - - result = smu7_copy_bytes_to_smc(smumgr, inversion_voltage_addr, - (uint8_t *)(&inversion_voltage), sizeof(inversion_voltage), 0x40000); - PP_ASSERT_WITH_CODE(0 == result, "[AVFS][fiji_setup_pm_fuse_for_avfs] " - "charz_freq could not be populated.", return -1;); - - return result; -} - static int fiji_setup_graphics_level_structure(struct pp_smumgr *smumgr) { int32_t vr_config; @@ -298,67 +250,18 @@ static int fiji_setup_graphics_level_structure(struct pp_smumgr *smumgr) return 0; } -/* Work in Progress */ -static int fiji_restore_vft_table(struct pp_smumgr *smumgr) -{ - struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend); - - if (AVFS_BTC_COMPLETED_SAVED == priv->avfs.AvfsBtcStatus) { - priv->avfs.AvfsBtcStatus = AVFS_BTC_COMPLETED_RESTORED; - return 0; - } else - return -EINVAL; -} - -/* Work in Progress */ -static int fiji_save_vft_table(struct pp_smumgr *smumgr) -{ - struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend); - - if (AVFS_BTC_COMPLETED_SAVED == priv->avfs.AvfsBtcStatus) { - priv->avfs.AvfsBtcStatus = AVFS_BTC_COMPLETED_RESTORED; - return 0; - } else - return -EINVAL; -} - static int fiji_avfs_event_mgr(struct pp_smumgr *smumgr, bool smu_started) { struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend); switch (priv->avfs.AvfsBtcStatus) { - case AVFS_BTC_COMPLETED_SAVED: /*S3 State - Pre SMU Start */ - priv->avfs.AvfsBtcStatus = AVFS_BTC_RESTOREVFT_FAILED; - PP_ASSERT_WITH_CODE(0 == fiji_restore_vft_table(smumgr), - "[AVFS][fiji_avfs_event_mgr] Could not Copy Graphics " - "Level table over to SMU", - return -1;); - priv->avfs.AvfsBtcStatus = AVFS_BTC_COMPLETED_RESTORED; - break; - case AVFS_BTC_COMPLETED_RESTORED: /*S3 State - Post SMU Start*/ - priv->avfs.AvfsBtcStatus = AVFS_BTC_SMUMSG_ERROR; - PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(smumgr, - 0x666), - "[AVFS][fiji_avfs_event_mgr] SMU did not respond " - "correctly to VftTableIsValid Msg", - return -1;); - priv->avfs.AvfsBtcStatus = AVFS_BTC_SMUMSG_ERROR; - PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(smumgr, - PPSMC_MSG_EnableAvfs), - "[AVFS][fiji_avfs_event_mgr] SMU did not respond " - "correctly to EnableAvfs Message Msg", - return -1;); - priv->avfs.AvfsBtcStatus = AVFS_BTC_COMPLETED_SAVED; + case AVFS_BTC_COMPLETED_PREVIOUSLY: break; + case AVFS_BTC_BOOT: /*Cold Boot State - Post SMU Start*/ if (!smu_started) break; priv->avfs.AvfsBtcStatus = AVFS_BTC_FAILED; - PP_ASSERT_WITH_CODE(0 == fiji_setup_pm_fuse_for_avfs(smumgr), - "[AVFS][fiji_avfs_event_mgr] Failure at " - "fiji_setup_pm_fuse_for_avfs", - return -1;); - priv->avfs.AvfsBtcStatus = AVFS_BTC_DPMTABLESETUP_FAILED; PP_ASSERT_WITH_CODE(0 == fiji_setup_graphics_level_structure(smumgr), "[AVFS][fiji_avfs_event_mgr] Could not Copy Graphics Level" " table over to SMU", @@ -373,18 +276,15 @@ static int fiji_avfs_event_mgr(struct pp_smumgr *smumgr, bool smu_started) "[AVFS][fiji_avfs_event_mgr] Failure at " "fiji_start_avfs_btc. AVFS Disabled", return -1;); - priv->avfs.AvfsBtcStatus = AVFS_BTC_SAVEVFT_FAILED; - PP_ASSERT_WITH_CODE(0 == fiji_save_vft_table(smumgr), - "[AVFS][fiji_avfs_event_mgr] Could not save VFT Table", - return -1;); - priv->avfs.AvfsBtcStatus = AVFS_BTC_COMPLETED_SAVED; + + priv->avfs.AvfsBtcStatus = AVFS_BTC_ENABLEAVFS; break; case AVFS_BTC_DISABLED: /* Do nothing */ - break; case AVFS_BTC_NOTSUPPORTED: /* Do nothing */ + case AVFS_BTC_ENABLEAVFS: break; default: - pr_err("[AVFS] Something is broken. See log!"); + pr_err("AVFS failed status is %x !\n", priv->avfs.AvfsBtcStatus); break; } return 0; @@ -514,6 +414,7 @@ const struct pp_smumgr_func fiji_smu_funcs = { .init_smc_table = fiji_init_smc_table, .update_sclk_threshold = fiji_update_sclk_threshold, .thermal_setup_fan_table = fiji_thermal_setup_fan_table, + .thermal_avfs_enable = fiji_thermal_avfs_enable, .populate_all_graphic_levels = fiji_populate_all_graphic_levels, .populate_all_memory_levels = fiji_populate_all_memory_levels, .get_mac_definition = fiji_get_mac_definition, -- cgit v1.2.3 From ce09d8ecb1b5db528b43e4799a267ea446f93799 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Wed, 5 Jul 2017 18:12:46 +0800 Subject: drm/amd/powerplay: move VI common AVFS code to smu7_smumgr.c Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/inc/smumgr.h | 3 + drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c | 6 +- drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c | 75 ++++++++++------------ drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.h | 11 ---- .../gpu/drm/amd/powerplay/smumgr/polaris10_smc.c | 4 +- .../drm/amd/powerplay/smumgr/polaris10_smumgr.c | 29 ++++----- .../drm/amd/powerplay/smumgr/polaris10_smumgr.h | 12 +--- drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c | 6 +- drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h | 8 ++- drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c | 8 +++ 10 files changed, 75 insertions(+), 87 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/powerplay/inc/smumgr.h b/drivers/gpu/drm/amd/powerplay/inc/smumgr.h index 976e942ec694..5d61cc9d4554 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smumgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smumgr.h @@ -131,6 +131,7 @@ struct pp_smumgr_func { bool (*is_dpm_running)(struct pp_hwmgr *hwmgr); int (*populate_requested_graphic_levels)(struct pp_hwmgr *hwmgr, struct amd_pp_profile *request); + bool (*is_hw_avfs_present)(struct pp_smumgr *smumgr); }; struct pp_smumgr { @@ -202,6 +203,8 @@ extern bool smum_is_dpm_running(struct pp_hwmgr *hwmgr); extern int smum_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr, struct amd_pp_profile *request); +extern bool smum_is_hw_avfs_present(struct pp_smumgr *smumgr); + #define SMUM_FIELD_SHIFT(reg, field) reg##__##field##__SHIFT #define SMUM_FIELD_MASK(reg, field) reg##__##field##_MASK diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c index ca24e155ef2d..8712f093d6d9 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c @@ -2134,16 +2134,16 @@ int fiji_thermal_avfs_enable(struct pp_hwmgr *hwmgr) { int ret; struct pp_smumgr *smumgr = (struct pp_smumgr *)(hwmgr->smumgr); - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(smumgr->backend); + struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(smumgr->backend); - if (smu_data->avfs.AvfsBtcStatus != AVFS_BTC_ENABLEAVFS) + if (smu_data->avfs.avfs_btc_status != AVFS_BTC_ENABLEAVFS) return 0; ret = smum_send_msg_to_smc(smumgr, PPSMC_MSG_EnableAvfs); if (!ret) /* If this param is not changed, this function could fire unnecessarily */ - smu_data->avfs.AvfsBtcStatus = AVFS_BTC_COMPLETED_PREVIOUSLY; + smu_data->avfs.avfs_btc_status = AVFS_BTC_COMPLETED_PREVIOUSLY; return ret; } diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c index 719e8853b0dc..6ae948fc524f 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c @@ -161,44 +161,47 @@ static int fiji_start_smu_in_non_protection_mode(struct pp_smumgr *smumgr) static int fiji_setup_pwr_virus(struct pp_smumgr *smumgr) { - int i, result = -1; + int i; + int result = -EINVAL; uint32_t reg, data; - const PWR_Command_Table *virus = PwrVirusTable; - struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend); - priv->avfs.AvfsBtcStatus = AVFS_LOAD_VIRUS; - for (i = 0; (i < PWR_VIRUS_TABLE_SIZE); i++) { - switch (virus->command) { + const PWR_Command_Table *pvirus = PwrVirusTable; + struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(smumgr->backend); + + for (i = 0; i < PWR_VIRUS_TABLE_SIZE; i++) { + switch (pvirus->command) { case PwrCmdWrite: - reg = virus->reg; - data = virus->data; + reg = pvirus->reg; + data = pvirus->data; cgs_write_register(smumgr->device, reg, data); break; + case PwrCmdEnd: - priv->avfs.AvfsBtcStatus = AVFS_BTC_VIRUS_LOADED; result = 0; break; + default: - pr_err("Table Exit with Invalid Command!"); - priv->avfs.AvfsBtcStatus = AVFS_BTC_VIRUS_FAIL; - result = -1; + pr_info("Table Exit with Invalid Command!"); + smu_data->avfs.avfs_btc_status = AVFS_BTC_VIRUS_FAIL; + result = -EINVAL; break; } - virus++; + pvirus++; } + return result; } static int fiji_start_avfs_btc(struct pp_smumgr *smumgr) { int result = 0; - struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend); + struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(smumgr->backend); - if (priv->avfs.AvfsBtcParam) { - if (!smum_send_msg_to_smc_with_parameter(smumgr, - PPSMC_MSG_PerformBtc, priv->avfs.AvfsBtcParam)) { - pr_err("PerformBTC SMU msg failed \n"); - result = -1; + if (0 != smu_data->avfs.avfs_btc_param) { + if (0 != smu7_send_msg_to_smc_with_parameter(smumgr, + PPSMC_MSG_PerformBtc, smu_data->avfs.avfs_btc_param)) { + pr_info("[AVFS][Fiji_PerformBtc] PerformBTC SMU msg failed"); + result = -EINVAL; } } /* Soft-Reset to reset the engine before loading uCode */ @@ -252,39 +255,39 @@ static int fiji_setup_graphics_level_structure(struct pp_smumgr *smumgr) static int fiji_avfs_event_mgr(struct pp_smumgr *smumgr, bool smu_started) { - struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend); + struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(smumgr->backend); - switch (priv->avfs.AvfsBtcStatus) { + switch (smu_data->avfs.avfs_btc_status) { case AVFS_BTC_COMPLETED_PREVIOUSLY: break; case AVFS_BTC_BOOT: /*Cold Boot State - Post SMU Start*/ if (!smu_started) break; - priv->avfs.AvfsBtcStatus = AVFS_BTC_FAILED; + smu_data->avfs.avfs_btc_status = AVFS_BTC_FAILED; PP_ASSERT_WITH_CODE(0 == fiji_setup_graphics_level_structure(smumgr), "[AVFS][fiji_avfs_event_mgr] Could not Copy Graphics Level" " table over to SMU", - return -1;); - priv->avfs.AvfsBtcStatus = AVFS_BTC_VIRUS_FAIL; + return -EINVAL;); + smu_data->avfs.avfs_btc_status = AVFS_BTC_VIRUS_FAIL; PP_ASSERT_WITH_CODE(0 == fiji_setup_pwr_virus(smumgr), "[AVFS][fiji_avfs_event_mgr] Could not setup " "Pwr Virus for AVFS ", - return -1;); - priv->avfs.AvfsBtcStatus = AVFS_BTC_FAILED; + return -EINVAL;); + smu_data->avfs.avfs_btc_status = AVFS_BTC_FAILED; PP_ASSERT_WITH_CODE(0 == fiji_start_avfs_btc(smumgr), "[AVFS][fiji_avfs_event_mgr] Failure at " "fiji_start_avfs_btc. AVFS Disabled", - return -1;); + return -EINVAL;); - priv->avfs.AvfsBtcStatus = AVFS_BTC_ENABLEAVFS; + smu_data->avfs.avfs_btc_status = AVFS_BTC_ENABLEAVFS; break; case AVFS_BTC_DISABLED: /* Do nothing */ case AVFS_BTC_NOTSUPPORTED: /* Do nothing */ case AVFS_BTC_ENABLEAVFS: break; default: - pr_err("AVFS failed status is %x !\n", priv->avfs.AvfsBtcStatus); + pr_err("AVFS failed status is %x !\n", smu_data->avfs.avfs_btc_status); break; } return 0; @@ -377,19 +380,6 @@ static int fiji_smu_init(struct pp_smumgr *smumgr) if (smu7_init(smumgr)) return -EINVAL; - fiji_priv->avfs.AvfsBtcStatus = AVFS_BTC_BOOT; - if (fiji_is_hw_avfs_present(smumgr)) - /* AVFS Parameter - * 0 - BTC DC disabled, BTC AC disabled - * 1 - BTC DC enabled, BTC AC disabled - * 2 - BTC DC disabled, BTC AC enabled - * 3 - BTC DC enabled, BTC AC enabled - * Default is 0 - BTC DC disabled, BTC AC disabled - */ - fiji_priv->avfs.AvfsBtcParam = 0; - else - fiji_priv->avfs.AvfsBtcStatus = AVFS_BTC_NOTSUPPORTED; - for (i = 0; i < SMU73_MAX_LEVELS_GRAPHICS; i++) fiji_priv->activity_target[i] = 30; @@ -421,4 +411,5 @@ const struct pp_smumgr_func fiji_smu_funcs = { .initialize_mc_reg_table = fiji_initialize_mc_reg_table, .is_dpm_running = fiji_is_dpm_running, .populate_requested_graphic_levels = fiji_populate_requested_graphic_levels, + .is_hw_avfs_present = fiji_is_hw_avfs_present, }; diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.h index adcbdfb209be..175bf9f8ef9c 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.h +++ b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.h @@ -28,17 +28,8 @@ #include "smu7_smumgr.h" - -struct fiji_smu_avfs { - enum AVFS_BTC_STATUS AvfsBtcStatus; - uint32_t AvfsBtcParam; -}; - - struct fiji_smumgr { struct smu7_smumgr smu7_data; - - struct fiji_smu_avfs avfs; struct SMU73_Discrete_DpmTable smc_state_table; struct SMU73_Discrete_Ulv ulv_setting; struct SMU73_Discrete_PmFuses power_tune_table; @@ -47,7 +38,5 @@ struct fiji_smumgr { }; - - #endif diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.c b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.c index f68e759e8be2..99a00bd39256 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.c @@ -1498,7 +1498,7 @@ static int polaris10_populate_avfs_parameters(struct pp_hwmgr *hwmgr) table_info->vdd_dep_on_sclk; - if (smu_data->avfs.avfs_btc_status == AVFS_BTC_NOTSUPPORTED) + if (((struct smu7_smumgr *)smu_data)->avfs.avfs_btc_status == AVFS_BTC_NOTSUPPORTED) return result; result = atomctrl_get_avfs_information(hwmgr, &avfs_params); @@ -1889,7 +1889,7 @@ int polaris10_thermal_avfs_enable(struct pp_hwmgr *hwmgr) { int ret; struct pp_smumgr *smumgr = (struct pp_smumgr *)(hwmgr->smumgr); - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend); + struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(smumgr->backend); struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); if (smu_data->avfs.avfs_btc_status == AVFS_BTC_NOTSUPPORTED) diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c index 7e0347088941..75f43dadc56b 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c @@ -60,16 +60,14 @@ static const SMU74_Discrete_GraphicsLevel avfs_graphics_level_polaris10[8] = { static const SMU74_Discrete_MemoryLevel avfs_memory_level_polaris10 = { 0x100ea446, 0, 0x30750000, 0x01, 0x01, 0x01, 0x00, 0x00, 0x64, 0x00, 0x00, 0x1f00, 0x00, 0x00}; - static int polaris10_setup_pwr_virus(struct pp_smumgr *smumgr) { int i; - int result = -1; + int result = -EINVAL; uint32_t reg, data; const PWR_Command_Table *pvirus = pwr_virus_table; - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend); - + struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(smumgr->backend); for (i = 0; i < PWR_VIRUS_TABLE_SIZE; i++) { switch (pvirus->command) { @@ -86,7 +84,7 @@ static int polaris10_setup_pwr_virus(struct pp_smumgr *smumgr) default: pr_info("Table Exit with Invalid Command!"); smu_data->avfs.avfs_btc_status = AVFS_BTC_VIRUS_FAIL; - result = -1; + result = -EINVAL; break; } pvirus++; @@ -98,7 +96,7 @@ static int polaris10_setup_pwr_virus(struct pp_smumgr *smumgr) static int polaris10_perform_btc(struct pp_smumgr *smumgr) { int result = 0; - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend); + struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(smumgr->backend); if (0 != smu_data->avfs.avfs_btc_param) { if (0 != smu7_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_PerformBtc, smu_data->avfs.avfs_btc_param)) { @@ -172,10 +170,11 @@ static int polaris10_setup_graphics_level_structure(struct pp_smumgr *smumgr) return 0; } + static int polaris10_avfs_event_mgr(struct pp_smumgr *smumgr, bool SMU_VFT_INTACT) { - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend); + struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(smumgr->backend); switch (smu_data->avfs.avfs_btc_status) { case AVFS_BTC_COMPLETED_PREVIOUSLY: @@ -185,21 +184,21 @@ polaris10_avfs_event_mgr(struct pp_smumgr *smumgr, bool SMU_VFT_INTACT) smu_data->avfs.avfs_btc_status = AVFS_BTC_DPMTABLESETUP_FAILED; PP_ASSERT_WITH_CODE(0 == polaris10_setup_graphics_level_structure(smumgr), - "[AVFS][Polaris10_AVFSEventMgr] Could not Copy Graphics Level table over to SMU", - return -1); + "[AVFS][Polaris10_AVFSEventMgr] Could not Copy Graphics Level table over to SMU", + return -EINVAL); if (smu_data->avfs.avfs_btc_param > 1) { pr_info("[AVFS][Polaris10_AVFSEventMgr] AC BTC has not been successfully verified on Fiji. There may be in this setting."); smu_data->avfs.avfs_btc_status = AVFS_BTC_VIRUS_FAIL; - PP_ASSERT_WITH_CODE(-1 == polaris10_setup_pwr_virus(smumgr), + PP_ASSERT_WITH_CODE(0 == polaris10_setup_pwr_virus(smumgr), "[AVFS][Polaris10_AVFSEventMgr] Could not setup Pwr Virus for AVFS ", - return -1); + return -EINVAL); } smu_data->avfs.avfs_btc_status = AVFS_BTC_FAILED; PP_ASSERT_WITH_CODE(0 == polaris10_perform_btc(smumgr), "[AVFS][Polaris10_AVFSEventMgr] Failure at SmuPolaris10_PerformBTC. AVFS Disabled", - return -1); + return -EINVAL); smu_data->avfs.avfs_btc_status = AVFS_BTC_ENABLEAVFS; break; @@ -377,11 +376,6 @@ static int polaris10_smu_init(struct pp_smumgr *smumgr) if (smu7_init(smumgr)) return -EINVAL; - if (polaris10_is_hw_avfs_present(smumgr)) - smu_data->avfs.avfs_btc_status = AVFS_BTC_BOOT; - else - smu_data->avfs.avfs_btc_status = AVFS_BTC_NOTSUPPORTED; - for (i = 0; i < SMU74_MAX_LEVELS_GRAPHICS; i++) smu_data->activity_target[i] = PPPOLARIS10_TARGETACTIVITY_DFLT; @@ -411,4 +405,5 @@ const struct pp_smumgr_func polaris10_smu_funcs = { .get_mac_definition = polaris10_get_mac_definition, .is_dpm_running = polaris10_is_dpm_running, .populate_requested_graphic_levels = polaris10_populate_requested_graphic_levels, + .is_hw_avfs_present = polaris10_is_hw_avfs_present, }; diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.h index 49ebf1d5a53c..5e19c24b0561 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.h +++ b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.h @@ -32,11 +32,6 @@ #define SMC_RAM_END 0x40000 -struct polaris10_avfs { - enum AVFS_BTC_STATUS avfs_btc_status; - uint32_t avfs_btc_param; -}; - struct polaris10_pt_defaults { uint8_t SviLoadLineEn; uint8_t SviLoadLineVddC; @@ -51,8 +46,6 @@ struct polaris10_pt_defaults { uint16_t BAPMTI_RC[SMU74_DTE_ITERATIONS * SMU74_DTE_SOURCES * SMU74_DTE_SINKS]; }; - - struct polaris10_range_table { uint32_t trans_lower_frequency; /* in 10khz */ uint32_t trans_upper_frequency; @@ -61,14 +54,13 @@ struct polaris10_range_table { struct polaris10_smumgr { struct smu7_smumgr smu7_data; uint8_t protected_mode; - struct polaris10_avfs avfs; SMU74_Discrete_DpmTable smc_state_table; struct SMU74_Discrete_Ulv ulv_setting; struct SMU74_Discrete_PmFuses power_tune_table; struct polaris10_range_table range_table[NUM_SCLK_RANGE]; const struct polaris10_pt_defaults *power_tune_defaults; - uint32_t activity_target[SMU74_MAX_LEVELS_GRAPHICS]; - uint32_t bif_sclk_table[SMU74_MAX_LEVELS_LINK]; + uint32_t activity_target[SMU74_MAX_LEVELS_GRAPHICS]; + uint32_t bif_sclk_table[SMU74_MAX_LEVELS_LINK]; }; diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c index 35ac27681415..76347ff6d655 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c @@ -540,7 +540,6 @@ int smu7_upload_smu_firmware_image(struct pp_smumgr *smumgr) return result; } - int smu7_init(struct pp_smumgr *smumgr) { struct smu7_smumgr *smu_data; @@ -596,6 +595,11 @@ int smu7_init(struct pp_smumgr *smumgr) (cgs_handle_t)smu_data->smu_buffer.handle); return -EINVAL); + if (smum_is_hw_avfs_present(smumgr)) + smu_data->avfs.avfs_btc_status = AVFS_BTC_BOOT; + else + smu_data->avfs.avfs_btc_status = AVFS_BTC_NOTSUPPORTED; + return 0; } diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h index 919be435b49c..ee5e32d2921e 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h +++ b/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h @@ -37,6 +37,11 @@ struct smu7_buffer_entry { unsigned long handle; }; +struct smu7_avfs { + enum AVFS_BTC_STATUS avfs_btc_status; + uint32_t avfs_btc_param; +}; + struct smu7_smumgr { uint8_t *header; uint8_t *mec_image; @@ -50,7 +55,8 @@ struct smu7_smumgr { uint32_t arb_table_start; uint32_t ulv_setting_starts; uint8_t security_hard_key; - uint32_t acpi_optimization; + uint32_t acpi_optimization; + struct smu7_avfs avfs; }; diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c index 0ac19cf3f987..3bdf6478de7f 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c @@ -404,3 +404,11 @@ int smum_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr, return 0; } + +bool smum_is_hw_avfs_present(struct pp_smumgr *smumgr) +{ + if (smumgr->smumgr_funcs->is_hw_avfs_present) + return smumgr->smumgr_funcs->is_hw_avfs_present(smumgr); + + return false; +} -- cgit v1.2.3 From 74c31c6e61f3f903799986a07ab5b7c7437d456a Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Mon, 3 Jul 2017 17:50:45 +0800 Subject: drm/amd/powerplay: add avfs check for old asics on Vi. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c index 1f01020ce3a9..f01cda93f178 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c @@ -4630,6 +4630,15 @@ static int smu7_set_power_profile_state(struct pp_hwmgr *hwmgr, static int smu7_avfs_control(struct pp_hwmgr *hwmgr, bool enable) { + struct pp_smumgr *smumgr = (struct pp_smumgr *)(hwmgr->smumgr); + struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(smumgr->backend); + + if (smu_data == NULL) + return -EINVAL; + + if (smu_data->avfs.avfs_btc_status == AVFS_BTC_NOTSUPPORTED) + return 0; + if (enable) { if (!PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, FEATURE_STATUS, AVS_ON)) -- cgit v1.2.3 From a5d20c405a37db7e59089422e795ad58feb37638 Mon Sep 17 00:00:00 2001 From: Alex Xie Date: Wed, 5 Jul 2017 18:02:04 -0400 Subject: drm/amdgpu: Free resources of bo_list when idr_alloc fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Alex Xie Reviewed-by: Chunming Zhou Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c index f621ee115c98..a71b875d0503 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c @@ -83,7 +83,7 @@ static int amdgpu_bo_list_create(struct amdgpu_device *adev, r = idr_alloc(&fpriv->bo_list_handles, list, 1, 0, GFP_KERNEL); mutex_unlock(&fpriv->bo_list_lock); if (r < 0) { - kfree(list); + amdgpu_bo_list_free(list); return r; } *id = r; -- cgit v1.2.3 From 6c8855541492b3d812d55c9fe5a2ed17ddf022b8 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 5 Jul 2017 15:17:00 -0400 Subject: drm/amdgpu/atom: fix atom_fw check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Not all vbios images seem to set the version appropriately. Switch the check based on asic type instead. Reviewed-by: Hawking Zhang Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c index 365e735f6647..ea3a2501c7cd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c @@ -86,19 +86,6 @@ static bool check_atom_bios(uint8_t *bios, size_t size) return false; } -static bool is_atom_fw(uint8_t *bios) -{ - uint16_t bios_header_start = bios[0x48] | (bios[0x49] << 8); - uint8_t frev = bios[bios_header_start + 2]; - uint8_t crev = bios[bios_header_start + 3]; - - if ((frev < 3) || - ((frev == 3) && (crev < 3))) - return false; - - return true; -} - /* If you boot an IGP board with a discrete card as the primary, * the IGP rom is not accessible via the rom bar as the IGP rom is * part of the system bios. On boot, the system bios puts a @@ -455,6 +442,6 @@ bool amdgpu_get_bios(struct amdgpu_device *adev) return false; success: - adev->is_atom_fw = is_atom_fw(adev->bios); + adev->is_atom_fw = (adev->asic_type >= CHIP_VEGA10) ? true : false; return true; } -- cgit v1.2.3 From 21f6bcb6d449d24b63dd1d5d030d34d88baa6a0f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 5 Jul 2017 15:26:48 -0400 Subject: drm/amdgpu/atomfirmware: implement vram_width for APUs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement support using the new atomfirmware system info table. Reviewed-by: Hawking Zhang Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c | 33 ++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h | 1 + 2 files changed, 34 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c index 9ddfe34d12af..a7d65f033883 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c @@ -95,3 +95,36 @@ int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device *adev) ctx->scratch_size_bytes = usage_bytes; return 0; } + +union igp_info { + struct atom_integrated_system_info_v1_11 v11; +}; + +/* + * Return vram width from integrated system info table, if available, + * or 0 if not. + */ +int amdgpu_atomfirmware_get_vram_width(struct amdgpu_device *adev) +{ + struct amdgpu_mode_info *mode_info = &adev->mode_info; + int index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, + integratedsysteminfo); + u16 data_offset, size; + union igp_info *igp_info; + u8 frev, crev; + + /* get any igp specific overrides */ + if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, &size, + &frev, &crev, &data_offset)) { + igp_info = (union igp_info *) + (mode_info->atom_context->bios + data_offset); + switch (crev) { + case 11: + return igp_info->v11.umachannelnumber * 64; + default: + return 0; + } + } + + return 0; +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h index 907e48f6b301..cedafbb9183e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h @@ -27,5 +27,6 @@ bool amdgpu_atomfirmware_gpu_supports_virtualization(struct amdgpu_device *adev); void amdgpu_atomfirmware_scratch_regs_init(struct amdgpu_device *adev); int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device *adev); +int amdgpu_atomfirmware_get_vram_width(struct amdgpu_device *adev); #endif -- cgit v1.2.3 From 8d6a5230e1a00c2f69e6c7e8a8fcef6d81a06dde Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 5 Jul 2017 15:37:35 -0400 Subject: drm/amdgpu/gmc9: get vram width from atom for Raven MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Get it from the system info table. Reviewed-by: Hawking Zhang Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 76 ++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index dbb43d99e02e..8ec148727149 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -23,6 +23,7 @@ #include #include "amdgpu.h" #include "gmc_v9_0.h" +#include "amdgpu_atomfirmware.h" #include "vega10/soc15ip.h" #include "vega10/HDP/hdp_4_0_offset.h" @@ -442,43 +443,46 @@ static int gmc_v9_0_mc_init(struct amdgpu_device *adev) u32 tmp; int chansize, numchan; - /* hbm memory channel size */ - chansize = 128; - - tmp = RREG32_SOC15(DF, 0, mmDF_CS_AON0_DramBaseAddress0); - tmp &= DF_CS_AON0_DramBaseAddress0__IntLvNumChan_MASK; - tmp >>= DF_CS_AON0_DramBaseAddress0__IntLvNumChan__SHIFT; - switch (tmp) { - case 0: - default: - numchan = 1; - break; - case 1: - numchan = 2; - break; - case 2: - numchan = 0; - break; - case 3: - numchan = 4; - break; - case 4: - numchan = 0; - break; - case 5: - numchan = 8; - break; - case 6: - numchan = 0; - break; - case 7: - numchan = 16; - break; - case 8: - numchan = 2; - break; + adev->mc.vram_width = amdgpu_atomfirmware_get_vram_width(adev); + if (!adev->mc.vram_width) { + /* hbm memory channel size */ + chansize = 128; + + tmp = RREG32_SOC15(DF, 0, mmDF_CS_AON0_DramBaseAddress0); + tmp &= DF_CS_AON0_DramBaseAddress0__IntLvNumChan_MASK; + tmp >>= DF_CS_AON0_DramBaseAddress0__IntLvNumChan__SHIFT; + switch (tmp) { + case 0: + default: + numchan = 1; + break; + case 1: + numchan = 2; + break; + case 2: + numchan = 0; + break; + case 3: + numchan = 4; + break; + case 4: + numchan = 0; + break; + case 5: + numchan = 8; + break; + case 6: + numchan = 0; + break; + case 7: + numchan = 16; + break; + case 8: + numchan = 2; + break; + } + adev->mc.vram_width = numchan * chansize; } - adev->mc.vram_width = numchan * chansize; /* Could aper size report 0 ? */ adev->mc.aper_base = pci_resource_start(adev->pdev, 0); -- cgit v1.2.3 From 606ce3c098b19cd5458930a133ef1577c64b1072 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 6 Jul 2017 10:15:46 -0400 Subject: drm/amdgpu: make arrays pctl0_data and pctl1_data static The arrays pctl0_data and pctl1_data do not need to be in global scope, so them both static. Cleans up sparse warnings: symbol 'pctl0_data' was not declared. Should it be static? symbol 'pctl1_data' was not declared. Should it be static? Signed-off-by: Colin Ian King Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c index 01918dc5dc55..9f2cf78907a3 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c @@ -249,7 +249,7 @@ struct pctl_data { uint32_t data; }; -const struct pctl_data pctl0_data[] = { +static const struct pctl_data pctl0_data[] = { {0x0, 0x7a640}, {0x9, 0x2a64a}, {0xd, 0x2a680}, @@ -274,7 +274,7 @@ const struct pctl_data pctl0_data[] = { #define PCTL0_STCTRL_REG_SAVE_RANGE0_BASE 0xa640 #define PCTL0_STCTRL_REG_SAVE_RANGE0_LIMIT 0xa833 -const struct pctl_data pctl1_data[] = { +static const struct pctl_data pctl1_data[] = { {0x0, 0x39a000}, {0x3b, 0x44a040}, {0x81, 0x2a08d}, -- cgit v1.2.3 From cc25188afdb886044785be4c29f3993c3a3b2b92 Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 28 Jun 2017 12:18:54 +0200 Subject: drm/amdgpu: reserve the first 2x512 pages of GART MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We want to use them as remap address space. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c | 5 ++++- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c index 1ef625550442..f46a97d91675 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c @@ -43,12 +43,15 @@ static int amdgpu_gtt_mgr_init(struct ttm_mem_type_manager *man, unsigned long p_size) { struct amdgpu_gtt_mgr *mgr; + uint64_t start, size; mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); if (!mgr) return -ENOMEM; - drm_mm_init(&mgr->mm, 0, p_size); + start = AMDGPU_GTT_MAX_TRANSFER_SIZE * AMDGPU_GTT_NUM_TRANSFER_WINDOWS; + size = p_size - start; + drm_mm_init(&mgr->mm, start, size); spin_lock_init(&mgr->lock); mgr->available = p_size; man->priv = mgr; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index 776a20ae40c4..c8059f067185 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -34,6 +34,9 @@ #define AMDGPU_PL_FLAG_GWS (TTM_PL_FLAG_PRIV << 1) #define AMDGPU_PL_FLAG_OA (TTM_PL_FLAG_PRIV << 2) +#define AMDGPU_GTT_MAX_TRANSFER_SIZE 512 +#define AMDGPU_GTT_NUM_TRANSFER_WINDOWS 2 + struct amdgpu_mman { struct ttm_bo_global_ref bo_global_ref; struct drm_global_reference mem_global_ref; -- cgit v1.2.3 From 0c2c421e2657da6eece66bd22eaaedf21dcebef7 Mon Sep 17 00:00:00 2001 From: Christian König Date: Thu, 29 Jun 2017 17:24:26 +0200 Subject: drm/amdgpu: add amdgpu_gart_map function v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows us to write the mapped PTEs into an IB instead of the table directly. v2: fix build with debugfs enabled, remove unused assignment Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c | 62 ++++++++++++++++++++++++-------- 2 files changed, 51 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index bbc7b19d2c1b..56cac98892f1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -570,6 +570,9 @@ int amdgpu_gart_init(struct amdgpu_device *adev); void amdgpu_gart_fini(struct amdgpu_device *adev); int amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset, int pages); +int amdgpu_gart_map(struct amdgpu_device *adev, uint64_t offset, + int pages, dma_addr_t *dma_addr, uint64_t flags, + void *dst); int amdgpu_gart_bind(struct amdgpu_device *adev, uint64_t offset, int pages, struct page **pagelist, dma_addr_t *dma_addr, uint64_t flags); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c index 982b1cc11dac..b4048a91c814 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c @@ -282,6 +282,41 @@ int amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset, return 0; } +/** + * amdgpu_gart_map - map dma_addresses into GART entries + * + * @adev: amdgpu_device pointer + * @offset: offset into the GPU's gart aperture + * @pages: number of pages to bind + * @dma_addr: DMA addresses of pages + * + * Map the dma_addresses into GART entries (all asics). + * Returns 0 for success, -EINVAL for failure. + */ +int amdgpu_gart_map(struct amdgpu_device *adev, uint64_t offset, + int pages, dma_addr_t *dma_addr, uint64_t flags, + void *dst) +{ + uint64_t page_base; + unsigned i, j, t; + + if (!adev->gart.ready) { + WARN(1, "trying to bind memory to uninitialized GART !\n"); + return -EINVAL; + } + + t = offset / AMDGPU_GPU_PAGE_SIZE; + + for (i = 0; i < pages; i++) { + page_base = dma_addr[i]; + for (j = 0; j < (PAGE_SIZE / AMDGPU_GPU_PAGE_SIZE); j++, t++) { + amdgpu_gart_set_pte_pde(adev, dst, t, page_base, flags); + page_base += AMDGPU_GPU_PAGE_SIZE; + } + } + return 0; +} + /** * amdgpu_gart_bind - bind pages into the gart page table * @@ -299,31 +334,30 @@ int amdgpu_gart_bind(struct amdgpu_device *adev, uint64_t offset, int pages, struct page **pagelist, dma_addr_t *dma_addr, uint64_t flags) { - unsigned t; - unsigned p; - uint64_t page_base; - int i, j; +#ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS + unsigned i,t,p; +#endif + int r; if (!adev->gart.ready) { WARN(1, "trying to bind memory to uninitialized GART !\n"); return -EINVAL; } +#ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS t = offset / AMDGPU_GPU_PAGE_SIZE; p = t / (PAGE_SIZE / AMDGPU_GPU_PAGE_SIZE); - - for (i = 0; i < pages; i++, p++) { -#ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS + for (i = 0; i < pages; i++, p++) adev->gart.pages[p] = pagelist[i]; #endif - if (adev->gart.ptr) { - page_base = dma_addr[i]; - for (j = 0; j < (PAGE_SIZE / AMDGPU_GPU_PAGE_SIZE); j++, t++) { - amdgpu_gart_set_pte_pde(adev, adev->gart.ptr, t, page_base, flags); - page_base += AMDGPU_GPU_PAGE_SIZE; - } - } + + if (adev->gart.ptr) { + r = amdgpu_gart_map(adev, offset, pages, dma_addr, flags, + adev->gart.ptr); + if (r) + return r; } + mb(); amdgpu_gart_flush_gpu_tlb(adev, 0); return 0; -- cgit v1.2.3 From abca90f1c8103528ca4b194fdc69e933bd23db4c Mon Sep 17 00:00:00 2001 From: Christian König Date: Fri, 30 Jun 2017 11:05:54 +0200 Subject: drm/amdgpu: use the GTT windows for BO moves v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This way we don't need to map the full BO at a time any more. v2: use fixed windows for src/dst Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 125 +++++++++++++++++++++++++++----- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 2 + 2 files changed, 108 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index ace178b393dd..4a34b61d44ef 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -47,10 +47,15 @@ #define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) +static int amdgpu_map_buffer(struct ttm_buffer_object *bo, + struct ttm_mem_reg *mem, unsigned num_pages, + uint64_t offset, unsigned window, + struct amdgpu_ring *ring, + uint64_t *addr); + static int amdgpu_ttm_debugfs_init(struct amdgpu_device *adev); static void amdgpu_ttm_debugfs_fini(struct amdgpu_device *adev); - /* * Global memory. */ @@ -97,6 +102,8 @@ static int amdgpu_ttm_global_init(struct amdgpu_device *adev) goto error_bo; } + mutex_init(&adev->mman.gtt_window_lock); + ring = adev->mman.buffer_funcs_ring; rq = &ring->sched.sched_rq[AMD_SCHED_PRIORITY_KERNEL]; r = amd_sched_entity_init(&ring->sched, &adev->mman.entity, @@ -123,6 +130,7 @@ static void amdgpu_ttm_global_fini(struct amdgpu_device *adev) if (adev->mman.mem_global_referenced) { amd_sched_entity_fini(adev->mman.entity.sched, &adev->mman.entity); + mutex_destroy(&adev->mman.gtt_window_lock); drm_global_item_unref(&adev->mman.bo_global_ref.ref); drm_global_item_unref(&adev->mman.mem_global_ref); adev->mman.mem_global_referenced = false; @@ -256,10 +264,13 @@ static uint64_t amdgpu_mm_node_addr(struct ttm_buffer_object *bo, struct drm_mm_node *mm_node, struct ttm_mem_reg *mem) { - uint64_t addr; + uint64_t addr = 0; - addr = mm_node->start << PAGE_SHIFT; - addr += bo->bdev->man[mem->mem_type].gpu_offset; + if (mem->mem_type != TTM_PL_TT || + amdgpu_gtt_mgr_is_allocated(mem)) { + addr = mm_node->start << PAGE_SHIFT; + addr += bo->bdev->man[mem->mem_type].gpu_offset; + } return addr; } @@ -284,34 +295,41 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo, return -EINVAL; } - if (old_mem->mem_type == TTM_PL_TT) { - r = amdgpu_ttm_bind(bo, old_mem); - if (r) - return r; - } - old_mm = old_mem->mm_node; old_size = old_mm->size; old_start = amdgpu_mm_node_addr(bo, old_mm, old_mem); - if (new_mem->mem_type == TTM_PL_TT) { - r = amdgpu_ttm_bind(bo, new_mem); - if (r) - return r; - } - new_mm = new_mem->mm_node; new_size = new_mm->size; new_start = amdgpu_mm_node_addr(bo, new_mm, new_mem); num_pages = new_mem->num_pages; + mutex_lock(&adev->mman.gtt_window_lock); while (num_pages) { - unsigned long cur_pages = min(old_size, new_size); + unsigned long cur_pages = min(min(old_size, new_size), + (u64)AMDGPU_GTT_MAX_TRANSFER_SIZE); + uint64_t from = old_start, to = new_start; struct dma_fence *next; - r = amdgpu_copy_buffer(ring, old_start, new_start, + if (old_mem->mem_type == TTM_PL_TT && + !amdgpu_gtt_mgr_is_allocated(old_mem)) { + r = amdgpu_map_buffer(bo, old_mem, cur_pages, + old_start, 0, ring, &from); + if (r) + goto error; + } + + if (new_mem->mem_type == TTM_PL_TT && + !amdgpu_gtt_mgr_is_allocated(new_mem)) { + r = amdgpu_map_buffer(bo, new_mem, cur_pages, + new_start, 1, ring, &to); + if (r) + goto error; + } + + r = amdgpu_copy_buffer(ring, from, to, cur_pages * PAGE_SIZE, - bo->resv, &next, false, false); + bo->resv, &next, false, true); if (r) goto error; @@ -338,12 +356,15 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo, new_start += cur_pages * PAGE_SIZE; } } + mutex_unlock(&adev->mman.gtt_window_lock); r = ttm_bo_pipeline_move(bo, fence, evict, new_mem); dma_fence_put(fence); return r; error: + mutex_unlock(&adev->mman.gtt_window_lock); + if (fence) dma_fence_wait(fence, false); dma_fence_put(fence); @@ -1253,6 +1274,72 @@ int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma) return ttm_bo_mmap(filp, vma, &adev->mman.bdev); } +static int amdgpu_map_buffer(struct ttm_buffer_object *bo, + struct ttm_mem_reg *mem, unsigned num_pages, + uint64_t offset, unsigned window, + struct amdgpu_ring *ring, + uint64_t *addr) +{ + struct amdgpu_ttm_tt *gtt = (void *)bo->ttm; + struct amdgpu_device *adev = ring->adev; + struct ttm_tt *ttm = bo->ttm; + struct amdgpu_job *job; + unsigned num_dw, num_bytes; + dma_addr_t *dma_address; + struct dma_fence *fence; + uint64_t src_addr, dst_addr; + uint64_t flags; + int r; + + BUG_ON(adev->mman.buffer_funcs->copy_max_bytes < + AMDGPU_GTT_MAX_TRANSFER_SIZE * 8); + + *addr = adev->mc.gtt_start; + *addr += (u64)window * AMDGPU_GTT_MAX_TRANSFER_SIZE * + AMDGPU_GPU_PAGE_SIZE; + + num_dw = adev->mman.buffer_funcs->copy_num_dw; + while (num_dw & 0x7) + num_dw++; + + num_bytes = num_pages * 8; + + r = amdgpu_job_alloc_with_ib(adev, num_dw * 4 + num_bytes, &job); + if (r) + return r; + + src_addr = num_dw * 4; + src_addr += job->ibs[0].gpu_addr; + + dst_addr = adev->gart.table_addr; + dst_addr += window * AMDGPU_GTT_MAX_TRANSFER_SIZE * 8; + amdgpu_emit_copy_buffer(adev, &job->ibs[0], src_addr, + dst_addr, num_bytes); + + amdgpu_ring_pad_ib(ring, &job->ibs[0]); + WARN_ON(job->ibs[0].length_dw > num_dw); + + dma_address = >t->ttm.dma_address[offset >> PAGE_SHIFT]; + flags = amdgpu_ttm_tt_pte_flags(adev, ttm, mem); + r = amdgpu_gart_map(adev, 0, num_pages, dma_address, flags, + &job->ibs[0].ptr[num_dw]); + if (r) + goto error_free; + + r = amdgpu_job_submit(job, ring, &adev->mman.entity, + AMDGPU_FENCE_OWNER_UNDEFINED, &fence); + if (r) + goto error_free; + + dma_fence_put(fence); + + return r; + +error_free: + amdgpu_job_free(job); + return r; +} + int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset, uint64_t dst_offset, uint32_t byte_count, struct reservation_object *resv, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index c8059f067185..4f5c1da5922e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -52,6 +52,8 @@ struct amdgpu_mman { /* buffer handling */ const struct amdgpu_buffer_funcs *buffer_funcs; struct amdgpu_ring *buffer_funcs_ring; + + struct mutex gtt_window_lock; /* Scheduler entity for buffer moves */ struct amd_sched_entity entity; }; -- cgit v1.2.3 From 5e7e83963fcf7688c2a171bedd9e76e2aa4eb85a Mon Sep 17 00:00:00 2001 From: Christian König Date: Fri, 30 Jun 2017 12:19:42 +0200 Subject: drm/amdgpu: stop mapping BOs to GTT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No need to map BOs to GTT on eviction and intermediate transfers any more. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 4a34b61d44ef..fb9c6988f5f2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -199,7 +199,6 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, .lpfn = 0, .flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM }; - unsigned i; if (!amdgpu_ttm_bo_is_amdgpu_bo(bo)) { placement->placement = &placements; @@ -217,20 +216,6 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_CPU); } else { amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_GTT); - for (i = 0; i < abo->placement.num_placement; ++i) { - if (!(abo->placements[i].flags & - TTM_PL_FLAG_TT)) - continue; - - if (abo->placements[i].lpfn) - continue; - - /* set an upper limit to force directly - * allocating address space for the BO. - */ - abo->placements[i].lpfn = - adev->mc.gtt_size >> PAGE_SHIFT; - } } break; case TTM_PL_TT: @@ -391,7 +376,7 @@ static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo, placement.num_busy_placement = 1; placement.busy_placement = &placements; placements.fpfn = 0; - placements.lpfn = adev->mc.gtt_size >> PAGE_SHIFT; + placements.lpfn = 0; placements.flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_TT; r = ttm_bo_mem_space(bo, &placement, &tmp_mem, interruptible, no_wait_gpu); @@ -438,7 +423,7 @@ static int amdgpu_move_ram_vram(struct ttm_buffer_object *bo, placement.num_busy_placement = 1; placement.busy_placement = &placements; placements.fpfn = 0; - placements.lpfn = adev->mc.gtt_size >> PAGE_SHIFT; + placements.lpfn = 0; placements.flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_TT; r = ttm_bo_mem_space(bo, &placement, &tmp_mem, interruptible, no_wait_gpu); -- cgit v1.2.3 From 935eefb312566364ef395eb29574e093686dbec8 Mon Sep 17 00:00:00 2001 From: Christian König Date: Fri, 30 Jun 2017 12:20:45 +0200 Subject: drm/amdgpu: remove maximum BO size limitation v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can finally remove this now. v2: remove now unused max_size variable as well. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 96c4493ccf8f..917ac5e074a0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -49,7 +49,6 @@ int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size, struct drm_gem_object **obj) { struct amdgpu_bo *robj; - unsigned long max_size; int r; *obj = NULL; @@ -58,17 +57,6 @@ int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size, alignment = PAGE_SIZE; } - if (!(initial_domain & (AMDGPU_GEM_DOMAIN_GDS | AMDGPU_GEM_DOMAIN_GWS | AMDGPU_GEM_DOMAIN_OA))) { - /* Maximum bo size is the unpinned gtt size since we use the gtt to - * handle vram to system pool migrations. - */ - max_size = adev->mc.gtt_size - adev->gart_pin_size; - if (size > max_size) { - DRM_DEBUG("Allocation size %ldMb bigger than %ldMb limit\n", - size >> 20, max_size >> 20); - return -ENOMEM; - } - } retry: r = amdgpu_bo_create(adev, size, alignment, kernel, initial_domain, flags, NULL, NULL, &robj); -- cgit v1.2.3 From 09628c3f68c6ec63c8eba324eb7fd70d46bf3eb2 Mon Sep 17 00:00:00 2001 From: Christian König Date: Fri, 30 Jun 2017 14:37:02 +0200 Subject: drm/amdgpu: use TTM values instead of MC values for the info queries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the TTM values instead of the hardware config here. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index b0b23101d1c8..63017de99f36 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -485,7 +485,8 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file vram_gtt.vram_size -= adev->vram_pin_size; vram_gtt.vram_cpu_accessible_size = adev->mc.visible_vram_size; vram_gtt.vram_cpu_accessible_size -= (adev->vram_pin_size - adev->invisible_pin_size); - vram_gtt.gtt_size = adev->mc.gtt_size; + vram_gtt.gtt_size = adev->mman.bdev.man[TTM_PL_TT].size; + vram_gtt.gtt_size *= PAGE_SIZE; vram_gtt.gtt_size -= adev->gart_pin_size; return copy_to_user(out, &vram_gtt, min((size_t)size, sizeof(vram_gtt))) ? -EFAULT : 0; @@ -510,9 +511,10 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file mem.cpu_accessible_vram.max_allocation = mem.cpu_accessible_vram.usable_heap_size * 3 / 4; - mem.gtt.total_heap_size = adev->mc.gtt_size; - mem.gtt.usable_heap_size = - adev->mc.gtt_size - adev->gart_pin_size; + mem.gtt.total_heap_size = adev->mman.bdev.man[TTM_PL_TT].size; + mem.gtt.total_heap_size *= PAGE_SIZE; + mem.gtt.usable_heap_size = mem.gtt.total_heap_size + - adev->gart_pin_size; mem.gtt.heap_usage = atomic64_read(&adev->gtt_usage); mem.gtt.max_allocation = mem.gtt.usable_heap_size * 3 / 4; -- cgit v1.2.3 From 560460f282543d484158c7760464495392f8fa4a Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Mon, 3 Jul 2017 22:37:44 +0800 Subject: drm/amd/powerplay: added index gc cac read/write apis for vega10 Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/soc15.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 4003cb517451..ca9fa3fe788d 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -196,6 +196,28 @@ static void soc15_didt_wreg(struct amdgpu_device *adev, u32 reg, u32 v) spin_unlock_irqrestore(&adev->didt_idx_lock, flags); } +static u32 soc15_gc_cac_rreg(struct amdgpu_device *adev, u32 reg) +{ + unsigned long flags; + u32 r; + + spin_lock_irqsave(&adev->gc_cac_idx_lock, flags); + WREG32_SOC15(GC, 0, mmGC_CAC_IND_INDEX, (reg)); + r = RREG32_SOC15(GC, 0, mmGC_CAC_IND_DATA); + spin_unlock_irqrestore(&adev->gc_cac_idx_lock, flags); + return r; +} + +static void soc15_gc_cac_wreg(struct amdgpu_device *adev, u32 reg, u32 v) +{ + unsigned long flags; + + spin_lock_irqsave(&adev->gc_cac_idx_lock, flags); + WREG32_SOC15(GC, 0, mmGC_CAC_IND_INDEX, (reg)); + WREG32_SOC15(GC, 0, mmGC_CAC_IND_DATA, (v)); + spin_unlock_irqrestore(&adev->gc_cac_idx_lock, flags); +} + static u32 soc15_get_config_memsize(struct amdgpu_device *adev) { if (adev->flags & AMD_IS_APU) @@ -555,6 +577,8 @@ static int soc15_common_early_init(void *handle) adev->uvd_ctx_wreg = &soc15_uvd_ctx_wreg; adev->didt_rreg = &soc15_didt_rreg; adev->didt_wreg = &soc15_didt_wreg; + adev->gc_cac_rreg = &soc15_gc_cac_rreg; + adev->gc_cac_wreg = &soc15_gc_cac_wreg; adev->asic_funcs = &soc15_asic_funcs; -- cgit v1.2.3 From 16abb5d206499d8cb84103c758d45afbfecf76c0 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Tue, 4 Jul 2017 09:21:50 +0800 Subject: drm/amd/powerplay: added new se_cac_idx r/w APIs v2 - v2: added missing spinlock init Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 6 ++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 1 + 2 files changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 56cac98892f1..1bb1912f863c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1560,6 +1560,10 @@ struct amdgpu_device { spinlock_t gc_cac_idx_lock; amdgpu_rreg_t gc_cac_rreg; amdgpu_wreg_t gc_cac_wreg; + /* protects concurrent se_cac register access */ + spinlock_t se_cac_idx_lock; + amdgpu_rreg_t se_cac_rreg; + amdgpu_wreg_t se_cac_wreg; /* protects concurrent ENDPOINT (audio) register access */ spinlock_t audio_endpt_idx_lock; amdgpu_block_rreg_t audio_endpt_rreg; @@ -1747,6 +1751,8 @@ void amdgpu_mm_wdoorbell64(struct amdgpu_device *adev, u32 index, u64 v); #define WREG32_DIDT(reg, v) adev->didt_wreg(adev, (reg), (v)) #define RREG32_GC_CAC(reg) adev->gc_cac_rreg(adev, (reg)) #define WREG32_GC_CAC(reg, v) adev->gc_cac_wreg(adev, (reg), (v)) +#define RREG32_SE_CAC(reg) adev->se_cac_rreg(adev, (reg)) +#define WREG32_SE_CAC(reg, v) adev->se_cac_wreg(adev, (reg), (v)) #define RREG32_AUDIO_ENDPT(block, reg) adev->audio_endpt_rreg(adev, (block), (reg)) #define WREG32_AUDIO_ENDPT(block, reg, v) adev->audio_endpt_wreg(adev, (block), (reg), (v)) #define WREG32_P(reg, val, mask) \ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 8ce522b490c8..541695768f0a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2075,6 +2075,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, spin_lock_init(&adev->uvd_ctx_idx_lock); spin_lock_init(&adev->didt_idx_lock); spin_lock_init(&adev->gc_cac_idx_lock); + spin_lock_init(&adev->se_cac_idx_lock); spin_lock_init(&adev->audio_endpt_idx_lock); spin_lock_init(&adev->mm_stats.lock); -- cgit v1.2.3 From 2f11fb02873890aca30deb9ca4b65b841c487bd9 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Tue, 4 Jul 2017 09:23:01 +0800 Subject: drm/amd/powerplay: added soc15 support for new se_cac_idx APIs Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/soc15.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index ca9fa3fe788d..0d9a3dd302a7 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -218,6 +218,28 @@ static void soc15_gc_cac_wreg(struct amdgpu_device *adev, u32 reg, u32 v) spin_unlock_irqrestore(&adev->gc_cac_idx_lock, flags); } +static u32 soc15_se_cac_rreg(struct amdgpu_device *adev, u32 reg) +{ + unsigned long flags; + u32 r; + + spin_lock_irqsave(&adev->se_cac_idx_lock, flags); + WREG32_SOC15(GC, 0, mmSE_CAC_IND_INDEX, (reg)); + r = RREG32_SOC15(GC, 0, mmSE_CAC_IND_DATA); + spin_unlock_irqrestore(&adev->se_cac_idx_lock, flags); + return r; +} + +static void soc15_se_cac_wreg(struct amdgpu_device *adev, u32 reg, u32 v) +{ + unsigned long flags; + + spin_lock_irqsave(&adev->se_cac_idx_lock, flags); + WREG32_SOC15(GC, 0, mmSE_CAC_IND_INDEX, (reg)); + WREG32_SOC15(GC, 0, mmSE_CAC_IND_DATA, (v)); + spin_unlock_irqrestore(&adev->se_cac_idx_lock, flags); +} + static u32 soc15_get_config_memsize(struct amdgpu_device *adev) { if (adev->flags & AMD_IS_APU) @@ -579,6 +601,8 @@ static int soc15_common_early_init(void *handle) adev->didt_wreg = &soc15_didt_wreg; adev->gc_cac_rreg = &soc15_gc_cac_rreg; adev->gc_cac_wreg = &soc15_gc_cac_wreg; + adev->se_cac_rreg = &soc15_se_cac_rreg; + adev->se_cac_wreg = &soc15_se_cac_wreg; adev->asic_funcs = &soc15_asic_funcs; -- cgit v1.2.3 From c62a59d0c8117f709f1e7a9fc8ccc1aae1db3f2c Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Tue, 4 Jul 2017 09:24:34 +0800 Subject: drm/amd/powerplay: added support for new se_cac_idx APIs to cgs Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c | 4 ++++ drivers/gpu/drm/amd/include/cgs_common.h | 1 + 2 files changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c index e525de2ecb2d..9b589402b58d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c @@ -240,6 +240,8 @@ static uint32_t amdgpu_cgs_read_ind_register(struct cgs_device *cgs_device, return RREG32_DIDT(index); case CGS_IND_REG_GC_CAC: return RREG32_GC_CAC(index); + case CGS_IND_REG_SE_CAC: + return RREG32_SE_CAC(index); case CGS_IND_REG__AUDIO_ENDPT: DRM_ERROR("audio endpt register access not implemented.\n"); return 0; @@ -266,6 +268,8 @@ static void amdgpu_cgs_write_ind_register(struct cgs_device *cgs_device, return WREG32_DIDT(index, value); case CGS_IND_REG_GC_CAC: return WREG32_GC_CAC(index, value); + case CGS_IND_REG_SE_CAC: + return WREG32_SE_CAC(index, value); case CGS_IND_REG__AUDIO_ENDPT: DRM_ERROR("audio endpt register access not implemented.\n"); return; diff --git a/drivers/gpu/drm/amd/include/cgs_common.h b/drivers/gpu/drm/amd/include/cgs_common.h index 0a94f749e3c0..b46d12df8df0 100644 --- a/drivers/gpu/drm/amd/include/cgs_common.h +++ b/drivers/gpu/drm/amd/include/cgs_common.h @@ -50,6 +50,7 @@ enum cgs_ind_reg { CGS_IND_REG__UVD_CTX, CGS_IND_REG__DIDT, CGS_IND_REG_GC_CAC, + CGS_IND_REG_SE_CAC, CGS_IND_REG__AUDIO_ENDPT }; -- cgit v1.2.3 From 209ee27e9ba35c53e18284c7bb5ac2ba6a2fcd22 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Tue, 4 Jul 2017 15:37:09 +0800 Subject: drm/amd/powerplay: added grbm_idx_mutex lock/unlock to cgs v2 - v2: rename param 'en' as 'lock' Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c | 12 ++++++++++++ drivers/gpu/drm/amd/include/cgs_common.h | 5 +++++ 2 files changed, 17 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c index 9b589402b58d..a99e0bca6812 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c @@ -614,6 +614,17 @@ static int amdgpu_cgs_enter_safe_mode(struct cgs_device *cgs_device, return 0; } +static void amdgpu_cgs_lock_grbm_idx(struct cgs_device *cgs_device, + bool lock) +{ + CGS_FUNC_ADEV; + + if (lock) + mutex_lock(&adev->grbm_idx_mutex); + else + mutex_unlock(&adev->grbm_idx_mutex); +} + static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device, enum cgs_ucode_id type, struct cgs_firmware_info *info) @@ -1127,6 +1138,7 @@ static const struct cgs_ops amdgpu_cgs_ops = { .query_system_info = amdgpu_cgs_query_system_info, .is_virtualization_enabled = amdgpu_cgs_is_virtualization_enabled, .enter_safe_mode = amdgpu_cgs_enter_safe_mode, + .lock_grbm_idx = amdgpu_cgs_lock_grbm_idx, }; static const struct cgs_os_ops amdgpu_cgs_os_ops = { diff --git a/drivers/gpu/drm/amd/include/cgs_common.h b/drivers/gpu/drm/amd/include/cgs_common.h index b46d12df8df0..0214f63f52fc 100644 --- a/drivers/gpu/drm/amd/include/cgs_common.h +++ b/drivers/gpu/drm/amd/include/cgs_common.h @@ -407,6 +407,8 @@ typedef int (*cgs_is_virtualization_enabled_t)(void *cgs_device); typedef int (*cgs_enter_safe_mode)(struct cgs_device *cgs_device, bool en); +typedef void (*cgs_lock_grbm_idx)(struct cgs_device *cgs_device, bool lock); + struct cgs_ops { /* memory management calls (similar to KFD interface) */ cgs_alloc_gpu_mem_t alloc_gpu_mem; @@ -442,6 +444,7 @@ struct cgs_ops { cgs_query_system_info query_system_info; cgs_is_virtualization_enabled_t is_virtualization_enabled; cgs_enter_safe_mode enter_safe_mode; + cgs_lock_grbm_idx lock_grbm_idx; }; struct cgs_os_ops; /* To be define in OS-specific CGS header */ @@ -518,4 +521,6 @@ struct cgs_device #define cgs_enter_safe_mode(cgs_device, en) \ CGS_CALL(enter_safe_mode, cgs_device, en) +#define cgs_lock_grbm_idx(cgs_device, lock) \ + CGS_CALL(lock_grbm_idx, cgs_device, lock) #endif /* _CGS_COMMON_H */ -- cgit v1.2.3 From 9b7b8154cdb8225cbef2f470285fd97ddbd34a44 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Wed, 5 Jul 2017 15:33:00 +0800 Subject: drm/amd/powerplay: added didt support for vega10 Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c | 56 + drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h | 5 + .../gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c | 1291 ++++++++++++++++++++ .../gpu/drm/amd/powerplay/hwmgr/vega10_powertune.h | 16 + .../gpu/drm/amd/powerplay/inc/hardwaremanager.h | 5 + drivers/gpu/drm/amd/powerplay/inc/pp_debug.h | 6 + drivers/gpu/drm/amd/powerplay/inc/pp_soc15.h | 2 + 7 files changed, 1381 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c index b14ea319bd95..8d567620576a 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c @@ -146,6 +146,19 @@ static void vega10_set_default_registry_data(struct pp_hwmgr *hwmgr) data->registry_data.vr1hot_enabled = 1; data->registry_data.regulator_hot_gpio_support = 1; + data->registry_data.didt_support = 1; + if (data->registry_data.didt_support) { + data->registry_data.didt_mode = 6; + data->registry_data.sq_ramping_support = 1; + data->registry_data.db_ramping_support = 0; + data->registry_data.td_ramping_support = 0; + data->registry_data.tcp_ramping_support = 0; + data->registry_data.dbr_ramping_support = 0; + data->registry_data.edc_didt_support = 1; + data->registry_data.gc_didt_support = 0; + data->registry_data.psm_didt_support = 0; + } + data->display_voltage_mode = PPVEGA10_VEGA10DISPLAYVOLTAGEMODE_DFLT; data->dcef_clk_quad_eqn_a = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; data->dcef_clk_quad_eqn_b = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; @@ -222,6 +235,8 @@ static int vega10_set_features_platform_caps(struct pp_hwmgr *hwmgr) /* assume disabled */ phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PowerContainment); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DiDtSupport); phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SQRamping); phm_cap_unset(hwmgr->platform_descriptor.platformCaps, @@ -230,6 +245,34 @@ static int vega10_set_features_platform_caps(struct pp_hwmgr *hwmgr) PHM_PlatformCaps_TDRamping); phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TCPRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DBRRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DiDtEDCEnable); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_GCEDC); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PSM); + + if (data->registry_data.didt_support) { + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DiDtSupport); + if (data->registry_data.sq_ramping_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SQRamping); + if (data->registry_data.db_ramping_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DBRamping); + if (data->registry_data.td_ramping_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TDRamping); + if (data->registry_data.tcp_ramping_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TCPRamping); + if (data->registry_data.dbr_ramping_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DBRRamping); + if (data->registry_data.edc_didt_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DiDtEDCEnable); + if (data->registry_data.gc_didt_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_GCEDC); + if (data->registry_data.psm_didt_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PSM); + } if (data->registry_data.power_containment_support) phm_cap_set(hwmgr->platform_descriptor.platformCaps, @@ -322,6 +365,7 @@ static void vega10_init_dpm_defaults(struct pp_hwmgr *hwmgr) data->smu_features[GNLD_FAN_CONTROL].smu_feature_id = FEATURE_FAN_CONTROL_BIT; data->smu_features[GNLD_ACG].smu_feature_id = FEATURE_ACG_BIT; + data->smu_features[GNLD_DIDT].smu_feature_id = FEATURE_GFX_EDC_BIT; if (!data->registry_data.prefetcher_dpm_key_disabled) data->smu_features[GNLD_DPM_PREFETCHER].supported = true; @@ -391,6 +435,9 @@ static void vega10_init_dpm_defaults(struct pp_hwmgr *hwmgr) if ((data->smu_version & 0xff000000) == 0x5000000) data->smu_features[GNLD_ACG].supported = true; + if (data->registry_data.didt_support) + data->smu_features[GNLD_DIDT].supported = true; + } #ifdef PPLIB_VEGA10_EVV_SUPPORT @@ -2907,6 +2954,11 @@ static int vega10_enable_dpm_tasks(struct pp_hwmgr *hwmgr) PP_ASSERT_WITH_CODE(!tmp_result, "Failed to start DPM!", result = tmp_result); + /* enable didt, do not abort if failed didt */ + tmp_result = vega10_enable_didt_config(hwmgr); + PP_ASSERT(!tmp_result, + "Failed to enable didt config!"); + tmp_result = vega10_enable_power_containment(hwmgr); PP_ASSERT_WITH_CODE(!tmp_result, "Failed to enable power containment!", @@ -4736,6 +4788,10 @@ static int vega10_disable_dpm_tasks(struct pp_hwmgr *hwmgr) PP_ASSERT_WITH_CODE((tmp_result == 0), "Failed to disable power containment!", result = tmp_result); + tmp_result = vega10_disable_didt_config(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to disable didt config!", result = tmp_result); + tmp_result = vega10_avfs_enable(hwmgr, false); PP_ASSERT_WITH_CODE((tmp_result == 0), "Failed to disable AVFS!", result = tmp_result); diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h index 415080174b28..5c97a8b6c46a 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h @@ -232,7 +232,9 @@ struct vega10_registry_data { uint8_t cac_support; uint8_t clock_stretcher_support; uint8_t db_ramping_support; + uint8_t didt_mode; uint8_t didt_support; + uint8_t edc_didt_support; uint8_t dynamic_state_patching_support; uint8_t enable_pkg_pwr_tracking_feature; uint8_t enable_tdc_limit_feature; @@ -265,6 +267,9 @@ struct vega10_registry_data { uint8_t tcp_ramping_support; uint8_t tdc_support; uint8_t td_ramping_support; + uint8_t dbr_ramping_support; + uint8_t gc_didt_support; + uint8_t psm_didt_support; uint8_t thermal_out_gpio_support; uint8_t thermal_support; uint8_t fw_ctf_enabled; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c index 3f72268e99bb..fbafc849ea71 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c @@ -26,7 +26,1298 @@ #include "vega10_powertune.h" #include "vega10_smumgr.h" #include "vega10_ppsmc.h" +#include "vega10_inc.h" #include "pp_debug.h" +#include "pp_soc15.h" + +static const struct vega10_didt_config_reg SEDiDtTuningCtrlConfig_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* DIDT_SQ */ + { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x3853 }, + { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x3153 }, + + /* DIDT_TD */ + { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x0dde }, + { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x0dde }, + + /* DIDT_TCP */ + { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x3dde }, + { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x3dde }, + + /* DIDT_DB */ + { ixDIDT_DB_TUNING_CTRL, DIDT_DB_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_DB_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x3dde }, + { ixDIDT_DB_TUNING_CTRL, DIDT_DB_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_DB_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x3dde }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg SEDiDtCtrl3Config_vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /*DIDT_SQ_CTRL3 */ + { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__GC_DIDT_ENABLE_MASK, DIDT_SQ_CTRL3__GC_DIDT_ENABLE__SHIFT, 0x0000 }, + { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__GC_DIDT_CLK_EN_OVERRIDE_MASK, DIDT_SQ_CTRL3__GC_DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__THROTTLE_POLICY_MASK, DIDT_SQ_CTRL3__THROTTLE_POLICY__SHIFT, 0x0003 }, + { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__DIDT_TRIGGER_THROTTLE_LOWBIT_MASK, DIDT_SQ_CTRL3__DIDT_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0000 }, + { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__DIDT_POWER_LEVEL_LOWBIT_MASK, DIDT_SQ_CTRL3__DIDT_POWER_LEVEL_LOWBIT__SHIFT, 0x0000 }, + { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__DIDT_STALL_PATTERN_BIT_NUMS_MASK, DIDT_SQ_CTRL3__DIDT_STALL_PATTERN_BIT_NUMS__SHIFT, 0x0003 }, + { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__GC_DIDT_LEVEL_COMB_EN_MASK, DIDT_SQ_CTRL3__GC_DIDT_LEVEL_COMB_EN__SHIFT, 0x0000 }, + { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__SE_DIDT_LEVEL_COMB_EN_MASK, DIDT_SQ_CTRL3__SE_DIDT_LEVEL_COMB_EN__SHIFT, 0x0000 }, + { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__QUALIFY_STALL_EN_MASK, DIDT_SQ_CTRL3__QUALIFY_STALL_EN__SHIFT, 0x0000 }, + { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__DIDT_STALL_SEL_MASK, DIDT_SQ_CTRL3__DIDT_STALL_SEL__SHIFT, 0x0000 }, + { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__DIDT_FORCE_STALL_MASK, DIDT_SQ_CTRL3__DIDT_FORCE_STALL__SHIFT, 0x0000 }, + { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__DIDT_STALL_DELAY_EN_MASK, DIDT_SQ_CTRL3__DIDT_STALL_DELAY_EN__SHIFT, 0x0000 }, + + /*DIDT_TCP_CTRL3 */ + { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__GC_DIDT_ENABLE_MASK, DIDT_TCP_CTRL3__GC_DIDT_ENABLE__SHIFT, 0x0000 }, + { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__GC_DIDT_CLK_EN_OVERRIDE_MASK, DIDT_TCP_CTRL3__GC_DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__THROTTLE_POLICY_MASK, DIDT_TCP_CTRL3__THROTTLE_POLICY__SHIFT, 0x0003 }, + { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__DIDT_TRIGGER_THROTTLE_LOWBIT_MASK, DIDT_TCP_CTRL3__DIDT_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0000 }, + { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__DIDT_POWER_LEVEL_LOWBIT_MASK, DIDT_TCP_CTRL3__DIDT_POWER_LEVEL_LOWBIT__SHIFT, 0x0000 }, + { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__DIDT_STALL_PATTERN_BIT_NUMS_MASK, DIDT_TCP_CTRL3__DIDT_STALL_PATTERN_BIT_NUMS__SHIFT, 0x0003 }, + { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__GC_DIDT_LEVEL_COMB_EN_MASK, DIDT_TCP_CTRL3__GC_DIDT_LEVEL_COMB_EN__SHIFT, 0x0000 }, + { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__SE_DIDT_LEVEL_COMB_EN_MASK, DIDT_TCP_CTRL3__SE_DIDT_LEVEL_COMB_EN__SHIFT, 0x0000 }, + { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__QUALIFY_STALL_EN_MASK, DIDT_TCP_CTRL3__QUALIFY_STALL_EN__SHIFT, 0x0000 }, + { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__DIDT_STALL_SEL_MASK, DIDT_TCP_CTRL3__DIDT_STALL_SEL__SHIFT, 0x0000 }, + { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__DIDT_FORCE_STALL_MASK, DIDT_TCP_CTRL3__DIDT_FORCE_STALL__SHIFT, 0x0000 }, + { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__DIDT_STALL_DELAY_EN_MASK, DIDT_TCP_CTRL3__DIDT_STALL_DELAY_EN__SHIFT, 0x0000 }, + + /*DIDT_TD_CTRL3 */ + { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__GC_DIDT_ENABLE_MASK, DIDT_TD_CTRL3__GC_DIDT_ENABLE__SHIFT, 0x0000 }, + { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__GC_DIDT_CLK_EN_OVERRIDE_MASK, DIDT_TD_CTRL3__GC_DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__THROTTLE_POLICY_MASK, DIDT_TD_CTRL3__THROTTLE_POLICY__SHIFT, 0x0003 }, + { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__DIDT_TRIGGER_THROTTLE_LOWBIT_MASK, DIDT_TD_CTRL3__DIDT_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0000 }, + { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__DIDT_POWER_LEVEL_LOWBIT_MASK, DIDT_TD_CTRL3__DIDT_POWER_LEVEL_LOWBIT__SHIFT, 0x0000 }, + { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__DIDT_STALL_PATTERN_BIT_NUMS_MASK, DIDT_TD_CTRL3__DIDT_STALL_PATTERN_BIT_NUMS__SHIFT, 0x0003 }, + { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__GC_DIDT_LEVEL_COMB_EN_MASK, DIDT_TD_CTRL3__GC_DIDT_LEVEL_COMB_EN__SHIFT, 0x0000 }, + { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__SE_DIDT_LEVEL_COMB_EN_MASK, DIDT_TD_CTRL3__SE_DIDT_LEVEL_COMB_EN__SHIFT, 0x0000 }, + { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__QUALIFY_STALL_EN_MASK, DIDT_TD_CTRL3__QUALIFY_STALL_EN__SHIFT, 0x0000 }, + { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__DIDT_STALL_SEL_MASK, DIDT_TD_CTRL3__DIDT_STALL_SEL__SHIFT, 0x0000 }, + { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__DIDT_FORCE_STALL_MASK, DIDT_TD_CTRL3__DIDT_FORCE_STALL__SHIFT, 0x0000 }, + { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__DIDT_STALL_DELAY_EN_MASK, DIDT_TD_CTRL3__DIDT_STALL_DELAY_EN__SHIFT, 0x0000 }, + + /*DIDT_DB_CTRL3 */ + { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__GC_DIDT_ENABLE_MASK, DIDT_DB_CTRL3__GC_DIDT_ENABLE__SHIFT, 0x0000 }, + { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__GC_DIDT_CLK_EN_OVERRIDE_MASK, DIDT_DB_CTRL3__GC_DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__THROTTLE_POLICY_MASK, DIDT_DB_CTRL3__THROTTLE_POLICY__SHIFT, 0x0003 }, + { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__DIDT_TRIGGER_THROTTLE_LOWBIT_MASK, DIDT_DB_CTRL3__DIDT_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0000 }, + { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__DIDT_POWER_LEVEL_LOWBIT_MASK, DIDT_DB_CTRL3__DIDT_POWER_LEVEL_LOWBIT__SHIFT, 0x0000 }, + { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__DIDT_STALL_PATTERN_BIT_NUMS_MASK, DIDT_DB_CTRL3__DIDT_STALL_PATTERN_BIT_NUMS__SHIFT, 0x0003 }, + { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__GC_DIDT_LEVEL_COMB_EN_MASK, DIDT_DB_CTRL3__GC_DIDT_LEVEL_COMB_EN__SHIFT, 0x0000 }, + { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__SE_DIDT_LEVEL_COMB_EN_MASK, DIDT_DB_CTRL3__SE_DIDT_LEVEL_COMB_EN__SHIFT, 0x0000 }, + { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__QUALIFY_STALL_EN_MASK, DIDT_DB_CTRL3__QUALIFY_STALL_EN__SHIFT, 0x0000 }, + { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__DIDT_STALL_SEL_MASK, DIDT_DB_CTRL3__DIDT_STALL_SEL__SHIFT, 0x0000 }, + { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__DIDT_FORCE_STALL_MASK, DIDT_DB_CTRL3__DIDT_FORCE_STALL__SHIFT, 0x0000 }, + { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__DIDT_STALL_DELAY_EN_MASK, DIDT_DB_CTRL3__DIDT_STALL_DELAY_EN__SHIFT, 0x0000 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg SEDiDtCtrl2Config_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* DIDT_SQ */ + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__MAX_POWER_DELTA_MASK, DIDT_SQ_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3853 }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_SQ_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x00c0 }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_SQ_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000 }, + + /* DIDT_TD */ + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__MAX_POWER_DELTA_MASK, DIDT_TD_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3fff }, + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_TD_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x00c0 }, + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_TD_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0001 }, + + /* DIDT_TCP */ + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__MAX_POWER_DELTA_MASK, DIDT_TCP_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3dde }, + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_TCP_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x00c0 }, + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_TCP_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0001 }, + + /* DIDT_DB */ + { ixDIDT_DB_CTRL2, DIDT_DB_CTRL2__MAX_POWER_DELTA_MASK, DIDT_DB_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3dde }, + { ixDIDT_DB_CTRL2, DIDT_DB_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_DB_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x00c0 }, + { ixDIDT_DB_CTRL2, DIDT_DB_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_DB_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0001 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg SEDiDtCtrl1Config_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* DIDT_SQ */ + { ixDIDT_SQ_CTRL1, DIDT_SQ_CTRL1__MIN_POWER_MASK, DIDT_SQ_CTRL1__MIN_POWER__SHIFT, 0x0000 }, + { ixDIDT_SQ_CTRL1, DIDT_SQ_CTRL1__MAX_POWER_MASK, DIDT_SQ_CTRL1__MAX_POWER__SHIFT, 0xffff }, + /* DIDT_TD */ + { ixDIDT_TD_CTRL1, DIDT_TD_CTRL1__MIN_POWER_MASK, DIDT_TD_CTRL1__MIN_POWER__SHIFT, 0x0000 }, + { ixDIDT_TD_CTRL1, DIDT_TD_CTRL1__MAX_POWER_MASK, DIDT_TD_CTRL1__MAX_POWER__SHIFT, 0xffff }, + /* DIDT_TCP */ + { ixDIDT_TCP_CTRL1, DIDT_TCP_CTRL1__MIN_POWER_MASK, DIDT_TCP_CTRL1__MIN_POWER__SHIFT, 0x0000 }, + { ixDIDT_TCP_CTRL1, DIDT_TCP_CTRL1__MAX_POWER_MASK, DIDT_TCP_CTRL1__MAX_POWER__SHIFT, 0xffff }, + /* DIDT_DB */ + { ixDIDT_DB_CTRL1, DIDT_DB_CTRL1__MIN_POWER_MASK, DIDT_DB_CTRL1__MIN_POWER__SHIFT, 0x0000 }, + { ixDIDT_DB_CTRL1, DIDT_DB_CTRL1__MAX_POWER_MASK, DIDT_DB_CTRL1__MAX_POWER__SHIFT, 0xffff }, + + { 0xFFFFFFFF } /* End of list */ +}; + + +static const struct vega10_didt_config_reg SEDiDtWeightConfig_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* DIDT_SQ */ + { ixDIDT_SQ_WEIGHT0_3, 0xFFFFFFFF, 0, 0x2B363B1A }, + { ixDIDT_SQ_WEIGHT4_7, 0xFFFFFFFF, 0, 0x270B2432 }, + { ixDIDT_SQ_WEIGHT8_11, 0xFFFFFFFF, 0, 0x00000018 }, + + /* DIDT_TD */ + { ixDIDT_TD_WEIGHT0_3, 0xFFFFFFFF, 0, 0x2B1D220F }, + { ixDIDT_TD_WEIGHT4_7, 0xFFFFFFFF, 0, 0x00007558 }, + { ixDIDT_TD_WEIGHT8_11, 0xFFFFFFFF, 0, 0x00000000 }, + + /* DIDT_TCP */ + { ixDIDT_TCP_WEIGHT0_3, 0xFFFFFFFF, 0, 0x5ACE160D }, + { ixDIDT_TCP_WEIGHT4_7, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_TCP_WEIGHT8_11, 0xFFFFFFFF, 0, 0x00000000 }, + + /* DIDT_DB */ + { ixDIDT_DB_WEIGHT0_3, 0xFFFFFFFF, 0, 0x0E152A0F }, + { ixDIDT_DB_WEIGHT4_7, 0xFFFFFFFF, 0, 0x09061813 }, + { ixDIDT_DB_WEIGHT8_11, 0xFFFFFFFF, 0, 0x00000013 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg SEDiDtCtrl0Config_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* DIDT_SQ */ + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CTRL_EN_MASK, DIDT_SQ_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0000 }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__PHASE_OFFSET_MASK, DIDT_SQ_CTRL0__PHASE_OFFSET__SHIFT, 0x0000 }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CTRL_RST_MASK, DIDT_SQ_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000 }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_SQ_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_STALL_CTRL_EN_MASK, DIDT_SQ_CTRL0__DIDT_STALL_CTRL_EN__SHIFT, 0x0001 }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_TUNING_CTRL_EN_MASK, DIDT_SQ_CTRL0__DIDT_TUNING_CTRL_EN__SHIFT, 0x0001 }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_STALL_AUTO_RELEASE_EN_MASK, DIDT_SQ_CTRL0__DIDT_STALL_AUTO_RELEASE_EN__SHIFT, 0x0001 }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_SQ_CTRL0__DIDT_HI_POWER_THRESHOLD__SHIFT, 0xffff }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_AUTO_MPD_EN_MASK, DIDT_SQ_CTRL0__DIDT_AUTO_MPD_EN__SHIFT, 0x0000 }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_STALL_EVENT_EN_MASK, DIDT_SQ_CTRL0__DIDT_STALL_EVENT_EN__SHIFT, 0x0000 }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_STALL_EVENT_COUNTER_CLEAR_MASK, DIDT_SQ_CTRL0__DIDT_STALL_EVENT_COUNTER_CLEAR__SHIFT, 0x0000 }, + /* DIDT_TD */ + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CTRL_EN_MASK, DIDT_TD_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0000 }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__PHASE_OFFSET_MASK, DIDT_TD_CTRL0__PHASE_OFFSET__SHIFT, 0x0000 }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CTRL_RST_MASK, DIDT_TD_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000 }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_TD_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_STALL_CTRL_EN_MASK, DIDT_TD_CTRL0__DIDT_STALL_CTRL_EN__SHIFT, 0x0001 }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_TUNING_CTRL_EN_MASK, DIDT_TD_CTRL0__DIDT_TUNING_CTRL_EN__SHIFT, 0x0001 }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_STALL_AUTO_RELEASE_EN_MASK, DIDT_TD_CTRL0__DIDT_STALL_AUTO_RELEASE_EN__SHIFT, 0x0001 }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_TD_CTRL0__DIDT_HI_POWER_THRESHOLD__SHIFT, 0xffff }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_AUTO_MPD_EN_MASK, DIDT_TD_CTRL0__DIDT_AUTO_MPD_EN__SHIFT, 0x0000 }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_STALL_EVENT_EN_MASK, DIDT_TD_CTRL0__DIDT_STALL_EVENT_EN__SHIFT, 0x0000 }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_STALL_EVENT_COUNTER_CLEAR_MASK, DIDT_TD_CTRL0__DIDT_STALL_EVENT_COUNTER_CLEAR__SHIFT, 0x0000 }, + /* DIDT_TCP */ + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CTRL_EN_MASK, DIDT_TCP_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0000 }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__PHASE_OFFSET_MASK, DIDT_TCP_CTRL0__PHASE_OFFSET__SHIFT, 0x0000 }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CTRL_RST_MASK, DIDT_TCP_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000 }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_TCP_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_STALL_CTRL_EN_MASK, DIDT_TCP_CTRL0__DIDT_STALL_CTRL_EN__SHIFT, 0x0001 }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_TUNING_CTRL_EN_MASK, DIDT_TCP_CTRL0__DIDT_TUNING_CTRL_EN__SHIFT, 0x0001 }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_STALL_AUTO_RELEASE_EN_MASK, DIDT_TCP_CTRL0__DIDT_STALL_AUTO_RELEASE_EN__SHIFT, 0x0001 }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_TCP_CTRL0__DIDT_HI_POWER_THRESHOLD__SHIFT, 0xffff }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_AUTO_MPD_EN_MASK, DIDT_TCP_CTRL0__DIDT_AUTO_MPD_EN__SHIFT, 0x0000 }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_STALL_EVENT_EN_MASK, DIDT_TCP_CTRL0__DIDT_STALL_EVENT_EN__SHIFT, 0x0000 }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_STALL_EVENT_COUNTER_CLEAR_MASK, DIDT_TCP_CTRL0__DIDT_STALL_EVENT_COUNTER_CLEAR__SHIFT, 0x0000 }, + /* DIDT_DB */ + { ixDIDT_DB_CTRL0, DIDT_DB_CTRL0__DIDT_CTRL_EN_MASK, DIDT_DB_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0000 }, + { ixDIDT_DB_CTRL0, DIDT_DB_CTRL0__PHASE_OFFSET_MASK, DIDT_DB_CTRL0__PHASE_OFFSET__SHIFT, 0x0000 }, + { ixDIDT_DB_CTRL0, DIDT_DB_CTRL0__DIDT_CTRL_RST_MASK, DIDT_DB_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000 }, + { ixDIDT_DB_CTRL0, DIDT_DB_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_DB_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { ixDIDT_DB_CTRL0, DIDT_DB_CTRL0__DIDT_STALL_CTRL_EN_MASK, DIDT_DB_CTRL0__DIDT_STALL_CTRL_EN__SHIFT, 0x0001 }, + { ixDIDT_DB_CTRL0, DIDT_DB_CTRL0__DIDT_TUNING_CTRL_EN_MASK, DIDT_DB_CTRL0__DIDT_TUNING_CTRL_EN__SHIFT, 0x0001 }, + { ixDIDT_DB_CTRL0, DIDT_DB_CTRL0__DIDT_STALL_AUTO_RELEASE_EN_MASK, DIDT_DB_CTRL0__DIDT_STALL_AUTO_RELEASE_EN__SHIFT, 0x0001 }, + { ixDIDT_DB_CTRL0, DIDT_DB_CTRL0__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_DB_CTRL0__DIDT_HI_POWER_THRESHOLD__SHIFT, 0xffff }, + { ixDIDT_DB_CTRL0, DIDT_DB_CTRL0__DIDT_AUTO_MPD_EN_MASK, DIDT_DB_CTRL0__DIDT_AUTO_MPD_EN__SHIFT, 0x0000 }, + { ixDIDT_DB_CTRL0, DIDT_DB_CTRL0__DIDT_STALL_EVENT_EN_MASK, DIDT_DB_CTRL0__DIDT_STALL_EVENT_EN__SHIFT, 0x0000 }, + { ixDIDT_DB_CTRL0, DIDT_DB_CTRL0__DIDT_STALL_EVENT_COUNTER_CLEAR_MASK, DIDT_DB_CTRL0__DIDT_STALL_EVENT_COUNTER_CLEAR__SHIFT, 0x0000 }, + + { 0xFFFFFFFF } /* End of list */ +}; + + +static const struct vega10_didt_config_reg SEDiDtStallCtrlConfig_vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* DIDT_SQ */ + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0004 }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0004 }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_SQ_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x000a }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_SQ_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x000a }, + + /* DIDT_TD */ + { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001 }, + { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001 }, + { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_TD_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x000a }, + { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_TD_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x000a }, + + /* DIDT_TCP */ + { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001 }, + { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001 }, + { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_TCP_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x000a }, + { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_TCP_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x000a }, + + /* DIDT_DB */ + { ixDIDT_DB_STALL_CTRL, DIDT_DB_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_DB_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0004 }, + { ixDIDT_DB_STALL_CTRL, DIDT_DB_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_DB_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0004 }, + { ixDIDT_DB_STALL_CTRL, DIDT_DB_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_DB_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x000a }, + { ixDIDT_DB_STALL_CTRL, DIDT_DB_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_DB_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x000a }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg SEDiDtStallPatternConfig_vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* DIDT_SQ_STALL_PATTERN_1_2 */ + { ixDIDT_SQ_STALL_PATTERN_1_2, DIDT_SQ_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_1_MASK, DIDT_SQ_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_1__SHIFT, 0x0001 }, + { ixDIDT_SQ_STALL_PATTERN_1_2, DIDT_SQ_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_2_MASK, DIDT_SQ_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_2__SHIFT, 0x0001 }, + + /* DIDT_SQ_STALL_PATTERN_3_4 */ + { ixDIDT_SQ_STALL_PATTERN_3_4, DIDT_SQ_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_3_MASK, DIDT_SQ_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_3__SHIFT, 0x0001 }, + { ixDIDT_SQ_STALL_PATTERN_3_4, DIDT_SQ_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_4_MASK, DIDT_SQ_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_4__SHIFT, 0x0001 }, + + /* DIDT_SQ_STALL_PATTERN_5_6 */ + { ixDIDT_SQ_STALL_PATTERN_5_6, DIDT_SQ_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_5_MASK, DIDT_SQ_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_5__SHIFT, 0x0000 }, + { ixDIDT_SQ_STALL_PATTERN_5_6, DIDT_SQ_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_6_MASK, DIDT_SQ_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_6__SHIFT, 0x0000 }, + + /* DIDT_SQ_STALL_PATTERN_7 */ + { ixDIDT_SQ_STALL_PATTERN_7, DIDT_SQ_STALL_PATTERN_7__DIDT_STALL_PATTERN_7_MASK, DIDT_SQ_STALL_PATTERN_7__DIDT_STALL_PATTERN_7__SHIFT, 0x0000 }, + + /* DIDT_TCP_STALL_PATTERN_1_2 */ + { ixDIDT_TCP_STALL_PATTERN_1_2, DIDT_TCP_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_1_MASK, DIDT_TCP_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_1__SHIFT, 0x0001 }, + { ixDIDT_TCP_STALL_PATTERN_1_2, DIDT_TCP_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_2_MASK, DIDT_TCP_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_2__SHIFT, 0x0001 }, + + /* DIDT_TCP_STALL_PATTERN_3_4 */ + { ixDIDT_TCP_STALL_PATTERN_3_4, DIDT_TCP_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_3_MASK, DIDT_TCP_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_3__SHIFT, 0x0001 }, + { ixDIDT_TCP_STALL_PATTERN_3_4, DIDT_TCP_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_4_MASK, DIDT_TCP_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_4__SHIFT, 0x0001 }, + + /* DIDT_TCP_STALL_PATTERN_5_6 */ + { ixDIDT_TCP_STALL_PATTERN_5_6, DIDT_TCP_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_5_MASK, DIDT_TCP_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_5__SHIFT, 0x0000 }, + { ixDIDT_TCP_STALL_PATTERN_5_6, DIDT_TCP_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_6_MASK, DIDT_TCP_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_6__SHIFT, 0x0000 }, + + /* DIDT_TCP_STALL_PATTERN_7 */ + { ixDIDT_TCP_STALL_PATTERN_7, DIDT_TCP_STALL_PATTERN_7__DIDT_STALL_PATTERN_7_MASK, DIDT_TCP_STALL_PATTERN_7__DIDT_STALL_PATTERN_7__SHIFT, 0x0000 }, + + /* DIDT_TD_STALL_PATTERN_1_2 */ + { ixDIDT_TD_STALL_PATTERN_1_2, DIDT_TD_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_1_MASK, DIDT_TD_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_1__SHIFT, 0x0001 }, + { ixDIDT_TD_STALL_PATTERN_1_2, DIDT_TD_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_2_MASK, DIDT_TD_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_2__SHIFT, 0x0001 }, + + /* DIDT_TD_STALL_PATTERN_3_4 */ + { ixDIDT_TD_STALL_PATTERN_3_4, DIDT_TD_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_3_MASK, DIDT_TD_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_3__SHIFT, 0x0001 }, + { ixDIDT_TD_STALL_PATTERN_3_4, DIDT_TD_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_4_MASK, DIDT_TD_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_4__SHIFT, 0x0001 }, + + /* DIDT_TD_STALL_PATTERN_5_6 */ + { ixDIDT_TD_STALL_PATTERN_5_6, DIDT_TD_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_5_MASK, DIDT_TD_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_5__SHIFT, 0x0000 }, + { ixDIDT_TD_STALL_PATTERN_5_6, DIDT_TD_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_6_MASK, DIDT_TD_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_6__SHIFT, 0x0000 }, + + /* DIDT_TD_STALL_PATTERN_7 */ + { ixDIDT_TD_STALL_PATTERN_7, DIDT_TD_STALL_PATTERN_7__DIDT_STALL_PATTERN_7_MASK, DIDT_TD_STALL_PATTERN_7__DIDT_STALL_PATTERN_7__SHIFT, 0x0000 }, + + /* DIDT_DB_STALL_PATTERN_1_2 */ + { ixDIDT_DB_STALL_PATTERN_1_2, DIDT_DB_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_1_MASK, DIDT_DB_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_1__SHIFT, 0x0001 }, + { ixDIDT_DB_STALL_PATTERN_1_2, DIDT_DB_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_2_MASK, DIDT_DB_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_2__SHIFT, 0x0001 }, + + /* DIDT_DB_STALL_PATTERN_3_4 */ + { ixDIDT_DB_STALL_PATTERN_3_4, DIDT_DB_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_3_MASK, DIDT_DB_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_3__SHIFT, 0x0001 }, + { ixDIDT_DB_STALL_PATTERN_3_4, DIDT_DB_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_4_MASK, DIDT_DB_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_4__SHIFT, 0x0001 }, + + /* DIDT_DB_STALL_PATTERN_5_6 */ + { ixDIDT_DB_STALL_PATTERN_5_6, DIDT_DB_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_5_MASK, DIDT_DB_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_5__SHIFT, 0x0000 }, + { ixDIDT_DB_STALL_PATTERN_5_6, DIDT_DB_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_6_MASK, DIDT_DB_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_6__SHIFT, 0x0000 }, + + /* DIDT_DB_STALL_PATTERN_7 */ + { ixDIDT_DB_STALL_PATTERN_7, DIDT_DB_STALL_PATTERN_7__DIDT_STALL_PATTERN_7_MASK, DIDT_DB_STALL_PATTERN_7__DIDT_STALL_PATTERN_7__SHIFT, 0x0000 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg SELCacConfig_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* SQ */ + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x00060021 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x00860021 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x01060021 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x01860021 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x02060021 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x02860021 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x03060021 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x03860021 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x04060021 }, + /* TD */ + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x000E0020 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x008E0020 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x010E0020 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x018E0020 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x020E0020 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x028E0020 }, + /* TCP */ + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x001c0020 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x009c0020 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x011c0020 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x019c0020 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x021c0020 }, + /* DB */ + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x00200008 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x00820008 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x01020008 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x01820008 }, + + { 0xFFFFFFFF } /* End of list */ +}; + + +static const struct vega10_didt_config_reg SEEDCStallPatternConfig_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* SQ */ + { ixDIDT_SQ_EDC_STALL_PATTERN_1_2, 0xFFFFFFFF, 0, 0x00030001 }, + { ixDIDT_SQ_EDC_STALL_PATTERN_3_4, 0xFFFFFFFF, 0, 0x000F0007 }, + { ixDIDT_SQ_EDC_STALL_PATTERN_5_6, 0xFFFFFFFF, 0, 0x003F001F }, + { ixDIDT_SQ_EDC_STALL_PATTERN_7, 0xFFFFFFFF, 0, 0x0000007F }, + /* TD */ + { ixDIDT_TD_EDC_STALL_PATTERN_1_2, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_TD_EDC_STALL_PATTERN_3_4, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_TD_EDC_STALL_PATTERN_5_6, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_TD_EDC_STALL_PATTERN_7, 0xFFFFFFFF, 0, 0x00000000 }, + /* TCP */ + { ixDIDT_TCP_EDC_STALL_PATTERN_1_2, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_TCP_EDC_STALL_PATTERN_3_4, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_TCP_EDC_STALL_PATTERN_5_6, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_TCP_EDC_STALL_PATTERN_7, 0xFFFFFFFF, 0, 0x00000000 }, + /* DB */ + { ixDIDT_DB_EDC_STALL_PATTERN_1_2, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_DB_EDC_STALL_PATTERN_3_4, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_DB_EDC_STALL_PATTERN_5_6, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_DB_EDC_STALL_PATTERN_7, 0xFFFFFFFF, 0, 0x00000000 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg SEEDCForceStallPatternConfig_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* SQ */ + { ixDIDT_SQ_EDC_STALL_PATTERN_1_2, 0xFFFFFFFF, 0, 0x00000015 }, + { ixDIDT_SQ_EDC_STALL_PATTERN_3_4, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_SQ_EDC_STALL_PATTERN_5_6, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_SQ_EDC_STALL_PATTERN_7, 0xFFFFFFFF, 0, 0x00000000 }, + /* TD */ + { ixDIDT_TD_EDC_STALL_PATTERN_1_2, 0xFFFFFFFF, 0, 0x00000015 }, + { ixDIDT_TD_EDC_STALL_PATTERN_3_4, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_TD_EDC_STALL_PATTERN_5_6, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_TD_EDC_STALL_PATTERN_7, 0xFFFFFFFF, 0, 0x00000000 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg SEEDCStallDelayConfig_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* SQ */ + { ixDIDT_SQ_EDC_STALL_DELAY_1, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_SQ_EDC_STALL_DELAY_2, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_SQ_EDC_STALL_DELAY_3, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_SQ_EDC_STALL_DELAY_4, 0xFFFFFFFF, 0, 0x00000000 }, + /* TD */ + { ixDIDT_TD_EDC_STALL_DELAY_1, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_TD_EDC_STALL_DELAY_2, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_TD_EDC_STALL_DELAY_3, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_TD_EDC_STALL_DELAY_4, 0xFFFFFFFF, 0, 0x00000000 }, + /* TCP */ + { ixDIDT_TCP_EDC_STALL_DELAY_1, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_TCP_EDC_STALL_DELAY_2, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_TCP_EDC_STALL_DELAY_3, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_TCP_EDC_STALL_DELAY_4, 0xFFFFFFFF, 0, 0x00000000 }, + /* DB */ + { ixDIDT_DB_EDC_STALL_DELAY_1, 0xFFFFFFFF, 0, 0x00000000 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg SEEDCThresholdConfig_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + { ixDIDT_SQ_EDC_THRESHOLD, 0xFFFFFFFF, 0, 0x0000010E }, + { ixDIDT_TD_EDC_THRESHOLD, 0xFFFFFFFF, 0, 0xFFFFFFFF }, + { ixDIDT_TCP_EDC_THRESHOLD, 0xFFFFFFFF, 0, 0xFFFFFFFF }, + { ixDIDT_DB_EDC_THRESHOLD, 0xFFFFFFFF, 0, 0xFFFFFFFF }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg SEEDCCtrlResetConfig_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* SQ */ + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_EN_MASK, DIDT_SQ_EDC_CTRL__EDC_EN__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_SW_RST_MASK, DIDT_SQ_EDC_CTRL__EDC_SW_RST__SHIFT, 0x0001 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_CLK_EN_OVERRIDE_MASK, DIDT_SQ_EDC_CTRL__EDC_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_FORCE_STALL_MASK, DIDT_SQ_EDC_CTRL__EDC_FORCE_STALL__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT_MASK, DIDT_SQ_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS_MASK, DIDT_SQ_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA_MASK, DIDT_SQ_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_EN_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_EN__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_STALL_POLICY_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_STALL_POLICY__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_LEVEL_COMB_EN_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_LEVEL_COMB_EN__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__SE_EDC_LEVEL_COMB_EN_MASK, DIDT_SQ_EDC_CTRL__SE_EDC_LEVEL_COMB_EN__SHIFT, 0x0000 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg SEEDCCtrlConfig_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* SQ */ + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_EN_MASK, DIDT_SQ_EDC_CTRL__EDC_EN__SHIFT, 0x0001 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_SW_RST_MASK, DIDT_SQ_EDC_CTRL__EDC_SW_RST__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_CLK_EN_OVERRIDE_MASK, DIDT_SQ_EDC_CTRL__EDC_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_FORCE_STALL_MASK, DIDT_SQ_EDC_CTRL__EDC_FORCE_STALL__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT_MASK, DIDT_SQ_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0004 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS_MASK, DIDT_SQ_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS__SHIFT, 0x0006 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA_MASK, DIDT_SQ_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_EN_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_EN__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_STALL_POLICY_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_STALL_POLICY__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_LEVEL_COMB_EN_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_LEVEL_COMB_EN__SHIFT, 0x0001 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__SE_EDC_LEVEL_COMB_EN_MASK, DIDT_SQ_EDC_CTRL__SE_EDC_LEVEL_COMB_EN__SHIFT, 0x0000 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg SEEDCCtrlForceStallConfig_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* SQ */ + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_EN_MASK, DIDT_SQ_EDC_CTRL__EDC_EN__SHIFT, 0x0001 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_SW_RST_MASK, DIDT_SQ_EDC_CTRL__EDC_SW_RST__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_CLK_EN_OVERRIDE_MASK, DIDT_SQ_EDC_CTRL__EDC_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_FORCE_STALL_MASK, DIDT_SQ_EDC_CTRL__EDC_FORCE_STALL__SHIFT, 0x0001 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT_MASK, DIDT_SQ_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0001 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS_MASK, DIDT_SQ_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS__SHIFT, 0x000C }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA_MASK, DIDT_SQ_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_EN_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_EN__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_STALL_POLICY_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_STALL_POLICY__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_LEVEL_COMB_EN_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_LEVEL_COMB_EN__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__SE_EDC_LEVEL_COMB_EN_MASK, DIDT_SQ_EDC_CTRL__SE_EDC_LEVEL_COMB_EN__SHIFT, 0x0001 }, + + /* TD */ + { ixDIDT_TD_EDC_CTRL, DIDT_TD_EDC_CTRL__EDC_EN_MASK, DIDT_TD_EDC_CTRL__EDC_EN__SHIFT, 0x0001 }, + { ixDIDT_TD_EDC_CTRL, DIDT_TD_EDC_CTRL__EDC_SW_RST_MASK, DIDT_TD_EDC_CTRL__EDC_SW_RST__SHIFT, 0x0000 }, + { ixDIDT_TD_EDC_CTRL, DIDT_TD_EDC_CTRL__EDC_CLK_EN_OVERRIDE_MASK, DIDT_TD_EDC_CTRL__EDC_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { ixDIDT_TD_EDC_CTRL, DIDT_TD_EDC_CTRL__EDC_FORCE_STALL_MASK, DIDT_TD_EDC_CTRL__EDC_FORCE_STALL__SHIFT, 0x0001 }, + { ixDIDT_TD_EDC_CTRL, DIDT_TD_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT_MASK, DIDT_TD_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0001 }, + { ixDIDT_TD_EDC_CTRL, DIDT_TD_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS_MASK, DIDT_TD_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS__SHIFT, 0x000E }, + { ixDIDT_TD_EDC_CTRL, DIDT_TD_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA_MASK, DIDT_TD_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA__SHIFT, 0x0000 }, + { ixDIDT_TD_EDC_CTRL, DIDT_TD_EDC_CTRL__GC_EDC_EN_MASK, DIDT_TD_EDC_CTRL__GC_EDC_EN__SHIFT, 0x0000 }, + { ixDIDT_TD_EDC_CTRL, DIDT_TD_EDC_CTRL__GC_EDC_STALL_POLICY_MASK, DIDT_TD_EDC_CTRL__GC_EDC_STALL_POLICY__SHIFT, 0x0000 }, + { ixDIDT_TD_EDC_CTRL, DIDT_TD_EDC_CTRL__GC_EDC_LEVEL_COMB_EN_MASK, DIDT_TD_EDC_CTRL__GC_EDC_LEVEL_COMB_EN__SHIFT, 0x0000 }, + { ixDIDT_TD_EDC_CTRL, DIDT_TD_EDC_CTRL__SE_EDC_LEVEL_COMB_EN_MASK, DIDT_TD_EDC_CTRL__SE_EDC_LEVEL_COMB_EN__SHIFT, 0x0001 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg GCDiDtDroopCtrlConfig_vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + { mmGC_DIDT_DROOP_CTRL, GC_DIDT_DROOP_CTRL__DIDT_DROOP_LEVEL_EN_MASK, GC_DIDT_DROOP_CTRL__DIDT_DROOP_LEVEL_EN__SHIFT, 0x0000 }, + { mmGC_DIDT_DROOP_CTRL, GC_DIDT_DROOP_CTRL__DIDT_DROOP_THRESHOLD_MASK, GC_DIDT_DROOP_CTRL__DIDT_DROOP_THRESHOLD__SHIFT, 0x0000 }, + { mmGC_DIDT_DROOP_CTRL, GC_DIDT_DROOP_CTRL__DIDT_DROOP_LEVEL_INDEX_MASK, GC_DIDT_DROOP_CTRL__DIDT_DROOP_LEVEL_INDEX__SHIFT, 0x0000 }, + { mmGC_DIDT_DROOP_CTRL, GC_DIDT_DROOP_CTRL__DIDT_LEVEL_SEL_MASK, GC_DIDT_DROOP_CTRL__DIDT_LEVEL_SEL__SHIFT, 0x0000 }, + { mmGC_DIDT_DROOP_CTRL, GC_DIDT_DROOP_CTRL__DIDT_DROOP_LEVEL_OVERFLOW_MASK, GC_DIDT_DROOP_CTRL__DIDT_DROOP_LEVEL_OVERFLOW__SHIFT, 0x0000 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg GCDiDtCtrl0Config_vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + { mmGC_DIDT_CTRL0, GC_DIDT_CTRL0__DIDT_CTRL_EN_MASK, GC_DIDT_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0000 }, + { mmGC_DIDT_CTRL0, GC_DIDT_CTRL0__PHASE_OFFSET_MASK, GC_DIDT_CTRL0__PHASE_OFFSET__SHIFT, 0x0000 }, + { mmGC_DIDT_CTRL0, GC_DIDT_CTRL0__DIDT_SW_RST_MASK, GC_DIDT_CTRL0__DIDT_SW_RST__SHIFT, 0x0000 }, + { mmGC_DIDT_CTRL0, GC_DIDT_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, GC_DIDT_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { mmGC_DIDT_CTRL0, GC_DIDT_CTRL0__DIDT_TRIGGER_THROTTLE_LOWBIT_MASK, GC_DIDT_CTRL0__DIDT_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0000 }, + { 0xFFFFFFFF } /* End of list */ +}; + + +static const struct vega10_didt_config_reg PSMSEEDCStallPatternConfig_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* SQ EDC STALL PATTERNs */ + { ixDIDT_SQ_EDC_STALL_PATTERN_1_2, DIDT_SQ_EDC_STALL_PATTERN_1_2__EDC_STALL_PATTERN_1_MASK, DIDT_SQ_EDC_STALL_PATTERN_1_2__EDC_STALL_PATTERN_1__SHIFT, 0x0101 }, + { ixDIDT_SQ_EDC_STALL_PATTERN_1_2, DIDT_SQ_EDC_STALL_PATTERN_1_2__EDC_STALL_PATTERN_2_MASK, DIDT_SQ_EDC_STALL_PATTERN_1_2__EDC_STALL_PATTERN_2__SHIFT, 0x0101 }, + { ixDIDT_SQ_EDC_STALL_PATTERN_3_4, DIDT_SQ_EDC_STALL_PATTERN_3_4__EDC_STALL_PATTERN_3_MASK, DIDT_SQ_EDC_STALL_PATTERN_3_4__EDC_STALL_PATTERN_3__SHIFT, 0x1111 }, + { ixDIDT_SQ_EDC_STALL_PATTERN_3_4, DIDT_SQ_EDC_STALL_PATTERN_3_4__EDC_STALL_PATTERN_4_MASK, DIDT_SQ_EDC_STALL_PATTERN_3_4__EDC_STALL_PATTERN_4__SHIFT, 0x1111 }, + + { ixDIDT_SQ_EDC_STALL_PATTERN_5_6, DIDT_SQ_EDC_STALL_PATTERN_5_6__EDC_STALL_PATTERN_5_MASK, DIDT_SQ_EDC_STALL_PATTERN_5_6__EDC_STALL_PATTERN_5__SHIFT, 0x1515 }, + { ixDIDT_SQ_EDC_STALL_PATTERN_5_6, DIDT_SQ_EDC_STALL_PATTERN_5_6__EDC_STALL_PATTERN_6_MASK, DIDT_SQ_EDC_STALL_PATTERN_5_6__EDC_STALL_PATTERN_6__SHIFT, 0x1515 }, + + { ixDIDT_SQ_EDC_STALL_PATTERN_7, DIDT_SQ_EDC_STALL_PATTERN_7__EDC_STALL_PATTERN_7_MASK, DIDT_SQ_EDC_STALL_PATTERN_7__EDC_STALL_PATTERN_7__SHIFT, 0x5555 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg PSMSEEDCStallDelayConfig_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* SQ EDC STALL DELAYs */ + { ixDIDT_SQ_EDC_STALL_DELAY_1, DIDT_SQ_EDC_STALL_DELAY_1__EDC_STALL_DELAY_SQ0_MASK, DIDT_SQ_EDC_STALL_DELAY_1__EDC_STALL_DELAY_SQ0__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_STALL_DELAY_1, DIDT_SQ_EDC_STALL_DELAY_1__EDC_STALL_DELAY_SQ1_MASK, DIDT_SQ_EDC_STALL_DELAY_1__EDC_STALL_DELAY_SQ1__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_STALL_DELAY_1, DIDT_SQ_EDC_STALL_DELAY_1__EDC_STALL_DELAY_SQ2_MASK, DIDT_SQ_EDC_STALL_DELAY_1__EDC_STALL_DELAY_SQ2__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_STALL_DELAY_1, DIDT_SQ_EDC_STALL_DELAY_1__EDC_STALL_DELAY_SQ3_MASK, DIDT_SQ_EDC_STALL_DELAY_1__EDC_STALL_DELAY_SQ3__SHIFT, 0x0000 }, + + { ixDIDT_SQ_EDC_STALL_DELAY_2, DIDT_SQ_EDC_STALL_DELAY_2__EDC_STALL_DELAY_SQ4_MASK, DIDT_SQ_EDC_STALL_DELAY_2__EDC_STALL_DELAY_SQ4__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_STALL_DELAY_2, DIDT_SQ_EDC_STALL_DELAY_2__EDC_STALL_DELAY_SQ5_MASK, DIDT_SQ_EDC_STALL_DELAY_2__EDC_STALL_DELAY_SQ5__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_STALL_DELAY_2, DIDT_SQ_EDC_STALL_DELAY_2__EDC_STALL_DELAY_SQ6_MASK, DIDT_SQ_EDC_STALL_DELAY_2__EDC_STALL_DELAY_SQ6__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_STALL_DELAY_2, DIDT_SQ_EDC_STALL_DELAY_2__EDC_STALL_DELAY_SQ7_MASK, DIDT_SQ_EDC_STALL_DELAY_2__EDC_STALL_DELAY_SQ7__SHIFT, 0x0000 }, + + { ixDIDT_SQ_EDC_STALL_DELAY_3, DIDT_SQ_EDC_STALL_DELAY_3__EDC_STALL_DELAY_SQ8_MASK, DIDT_SQ_EDC_STALL_DELAY_3__EDC_STALL_DELAY_SQ8__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_STALL_DELAY_3, DIDT_SQ_EDC_STALL_DELAY_3__EDC_STALL_DELAY_SQ9_MASK, DIDT_SQ_EDC_STALL_DELAY_3__EDC_STALL_DELAY_SQ9__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_STALL_DELAY_3, DIDT_SQ_EDC_STALL_DELAY_3__EDC_STALL_DELAY_SQ10_MASK, DIDT_SQ_EDC_STALL_DELAY_3__EDC_STALL_DELAY_SQ10__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_STALL_DELAY_3, DIDT_SQ_EDC_STALL_DELAY_3__EDC_STALL_DELAY_SQ11_MASK, DIDT_SQ_EDC_STALL_DELAY_3__EDC_STALL_DELAY_SQ11__SHIFT, 0x0000 }, + + { ixDIDT_SQ_EDC_STALL_DELAY_4, DIDT_SQ_EDC_STALL_DELAY_4__EDC_STALL_DELAY_SQ12_MASK, DIDT_SQ_EDC_STALL_DELAY_4__EDC_STALL_DELAY_SQ12__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_STALL_DELAY_4, DIDT_SQ_EDC_STALL_DELAY_4__EDC_STALL_DELAY_SQ12_MASK, DIDT_SQ_EDC_STALL_DELAY_4__EDC_STALL_DELAY_SQ13__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_STALL_DELAY_4, DIDT_SQ_EDC_STALL_DELAY_4__EDC_STALL_DELAY_SQ14_MASK, DIDT_SQ_EDC_STALL_DELAY_4__EDC_STALL_DELAY_SQ14__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_STALL_DELAY_4, DIDT_SQ_EDC_STALL_DELAY_4__EDC_STALL_DELAY_SQ15_MASK, DIDT_SQ_EDC_STALL_DELAY_4__EDC_STALL_DELAY_SQ15__SHIFT, 0x0000 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg PSMSEEDCThresholdConfig_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* SQ EDC THRESHOLD */ + { ixDIDT_SQ_EDC_THRESHOLD, DIDT_SQ_EDC_THRESHOLD__EDC_THRESHOLD_MASK, DIDT_SQ_EDC_THRESHOLD__EDC_THRESHOLD__SHIFT, 0x0000 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg PSMSEEDCCtrlResetConfig_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* SQ EDC CTRL */ + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_EN_MASK, DIDT_SQ_EDC_CTRL__EDC_EN__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_SW_RST_MASK, DIDT_SQ_EDC_CTRL__EDC_SW_RST__SHIFT, 0x0001 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_CLK_EN_OVERRIDE_MASK, DIDT_SQ_EDC_CTRL__EDC_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_FORCE_STALL_MASK, DIDT_SQ_EDC_CTRL__EDC_FORCE_STALL__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT_MASK, DIDT_SQ_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS_MASK, DIDT_SQ_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA_MASK, DIDT_SQ_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_EN_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_EN__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_STALL_POLICY_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_STALL_POLICY__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_LEVEL_COMB_EN_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_LEVEL_COMB_EN__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__SE_EDC_LEVEL_COMB_EN_MASK, DIDT_SQ_EDC_CTRL__SE_EDC_LEVEL_COMB_EN__SHIFT, 0x0000 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg PSMSEEDCCtrlConfig_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* SQ EDC CTRL */ + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_EN_MASK, DIDT_SQ_EDC_CTRL__EDC_EN__SHIFT, 0x0001 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_SW_RST_MASK, DIDT_SQ_EDC_CTRL__EDC_SW_RST__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_CLK_EN_OVERRIDE_MASK, DIDT_SQ_EDC_CTRL__EDC_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_FORCE_STALL_MASK, DIDT_SQ_EDC_CTRL__EDC_FORCE_STALL__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT_MASK, DIDT_SQ_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS_MASK, DIDT_SQ_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS__SHIFT, 0x000E }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA_MASK, DIDT_SQ_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_EN_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_EN__SHIFT, 0x0001 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_STALL_POLICY_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_STALL_POLICY__SHIFT, 0x0003 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_LEVEL_COMB_EN_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_LEVEL_COMB_EN__SHIFT, 0x0001 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__SE_EDC_LEVEL_COMB_EN_MASK, DIDT_SQ_EDC_CTRL__SE_EDC_LEVEL_COMB_EN__SHIFT, 0x0000 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg PSMGCEDCThresholdConfig_vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + { mmGC_EDC_THRESHOLD, GC_EDC_THRESHOLD__EDC_THRESHOLD_MASK, GC_EDC_THRESHOLD__EDC_THRESHOLD__SHIFT, 0x0000000 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg PSMGCEDCDroopCtrlConfig_vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + { mmGC_EDC_DROOP_CTRL, GC_EDC_DROOP_CTRL__EDC_DROOP_LEVEL_EN_MASK, GC_EDC_DROOP_CTRL__EDC_DROOP_LEVEL_EN__SHIFT, 0x0001 }, + { mmGC_EDC_DROOP_CTRL, GC_EDC_DROOP_CTRL__EDC_DROOP_THRESHOLD_MASK, GC_EDC_DROOP_CTRL__EDC_DROOP_THRESHOLD__SHIFT, 0x0384 }, + { mmGC_EDC_DROOP_CTRL, GC_EDC_DROOP_CTRL__EDC_DROOP_LEVEL_INDEX_MASK, GC_EDC_DROOP_CTRL__EDC_DROOP_LEVEL_INDEX__SHIFT, 0x0001 }, + { mmGC_EDC_DROOP_CTRL, GC_EDC_DROOP_CTRL__AVG_PSM_SEL_MASK, GC_EDC_DROOP_CTRL__AVG_PSM_SEL__SHIFT, 0x0001 }, + { mmGC_EDC_DROOP_CTRL, GC_EDC_DROOP_CTRL__EDC_LEVEL_SEL_MASK, GC_EDC_DROOP_CTRL__EDC_LEVEL_SEL__SHIFT, 0x0001 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg PSMGCEDCCtrlResetConfig_vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_EN_MASK, GC_EDC_CTRL__EDC_EN__SHIFT, 0x0000 }, + { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_SW_RST_MASK, GC_EDC_CTRL__EDC_SW_RST__SHIFT, 0x0001 }, + { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_CLK_EN_OVERRIDE_MASK, GC_EDC_CTRL__EDC_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_FORCE_STALL_MASK, GC_EDC_CTRL__EDC_FORCE_STALL__SHIFT, 0x0000 }, + { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT_MASK, GC_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0000 }, + { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA_MASK, GC_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA__SHIFT, 0x0000 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg PSMGCEDCCtrlConfig_vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_EN_MASK, GC_EDC_CTRL__EDC_EN__SHIFT, 0x0001 }, + { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_SW_RST_MASK, GC_EDC_CTRL__EDC_SW_RST__SHIFT, 0x0000 }, + { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_CLK_EN_OVERRIDE_MASK, GC_EDC_CTRL__EDC_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_FORCE_STALL_MASK, GC_EDC_CTRL__EDC_FORCE_STALL__SHIFT, 0x0000 }, + { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT_MASK, GC_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0000 }, + { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA_MASK, GC_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA__SHIFT, 0x0000 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg AvfsPSMResetConfig_vega10[]= +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + { 0x16A02, 0xFFFFFFFF, 0x0, 0x0000005F }, + { 0x16A05, 0xFFFFFFFF, 0x0, 0x00000001 }, + { 0x16A06, 0x00000001, 0x0, 0x02000000 }, + { 0x16A01, 0xFFFFFFFF, 0x0, 0x00003027 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg AvfsPSMInitConfig_vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + { 0x16A05, 0xFFFFFFFF, 0x18, 0x00000001 }, + { 0x16A05, 0xFFFFFFFF, 0x8, 0x00000003 }, + { 0x16A05, 0xFFFFFFFF, 0xa, 0x00000006 }, + { 0x16A05, 0xFFFFFFFF, 0x7, 0x00000000 }, + { 0x16A06, 0xFFFFFFFF, 0x18, 0x00000001 }, + { 0x16A06, 0xFFFFFFFF, 0x19, 0x00000001 }, + { 0x16A01, 0xFFFFFFFF, 0x0, 0x00003027 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static int vega10_program_didt_config_registers(struct pp_hwmgr *hwmgr, const struct vega10_didt_config_reg *config_regs, enum vega10_didt_config_reg_type reg_type) +{ + uint32_t data; + + PP_ASSERT_WITH_CODE((config_regs != NULL), "[vega10_program_didt_config_registers] Invalid config register table!", return -EINVAL); + + while (config_regs->offset != 0xFFFFFFFF) { + switch (reg_type) { + case VEGA10_CONFIGREG_DIDT: + data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, config_regs->offset); + data &= ~config_regs->mask; + data |= ((config_regs->value << config_regs->shift) & config_regs->mask); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, config_regs->offset, data); + break; + case VEGA10_CONFIGREG_GCCAC: + data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG_GC_CAC, config_regs->offset); + data &= ~config_regs->mask; + data |= ((config_regs->value << config_regs->shift) & config_regs->mask); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG_GC_CAC, config_regs->offset, data); + break; + case VEGA10_CONFIGREG_SECAC: + data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG_SE_CAC, config_regs->offset); + data &= ~config_regs->mask; + data |= ((config_regs->value << config_regs->shift) & config_regs->mask); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG_SE_CAC, config_regs->offset, data); + break; + default: + return -EINVAL; + } + + config_regs++; + } + + return 0; +} + +static int vega10_program_gc_didt_config_registers(struct pp_hwmgr *hwmgr, const struct vega10_didt_config_reg *config_regs) +{ + uint32_t data; + + while (config_regs->offset != 0xFFFFFFFF) { + data = cgs_read_register(hwmgr->device, config_regs->offset); + data &= ~config_regs->mask; + data |= ((config_regs->value << config_regs->shift) & config_regs->mask); + cgs_write_register(hwmgr->device, config_regs->offset, data); + config_regs++; + } + + return 0; +} + +static void vega10_didt_set_mask(struct pp_hwmgr *hwmgr, const bool enable) +{ + uint32_t data; + int result; + uint32_t en = (enable ? 1 : 0); + uint32_t didt_block_info = SQ_IR_MASK | TCP_IR_MASK | TD_PCC_MASK; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SQRamping)) { + data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_SQ_CTRL0); + data &= ~DIDT_SQ_CTRL0__DIDT_CTRL_EN_MASK; + data |= ((en << DIDT_SQ_CTRL0__DIDT_CTRL_EN__SHIFT) & DIDT_SQ_CTRL0__DIDT_CTRL_EN_MASK); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_SQ_CTRL0, data); + didt_block_info &= ~SQ_Enable_MASK; + didt_block_info |= en << SQ_Enable_SHIFT; + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DBRamping)) { + data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_DB_CTRL0); + data &= ~DIDT_DB_CTRL0__DIDT_CTRL_EN_MASK; + data |= ((en << DIDT_DB_CTRL0__DIDT_CTRL_EN__SHIFT) & DIDT_DB_CTRL0__DIDT_CTRL_EN_MASK); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_DB_CTRL0, data); + didt_block_info &= ~DB_Enable_MASK; + didt_block_info |= en << DB_Enable_SHIFT; + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TDRamping)) { + data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_TD_CTRL0); + data &= ~DIDT_TD_CTRL0__DIDT_CTRL_EN_MASK; + data |= ((en << DIDT_TD_CTRL0__DIDT_CTRL_EN__SHIFT) & DIDT_TD_CTRL0__DIDT_CTRL_EN_MASK); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_TD_CTRL0, data); + didt_block_info &= ~TD_Enable_MASK; + didt_block_info |= en << TD_Enable_SHIFT; + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TCPRamping)) { + data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_TCP_CTRL0); + data &= ~DIDT_TCP_CTRL0__DIDT_CTRL_EN_MASK; + data |= ((en << DIDT_TCP_CTRL0__DIDT_CTRL_EN__SHIFT) & DIDT_TCP_CTRL0__DIDT_CTRL_EN_MASK); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_TCP_CTRL0, data); + didt_block_info &= ~TCP_Enable_MASK; + didt_block_info |= en << TCP_Enable_SHIFT; + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DBRRamping)) { + data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_DBR_CTRL0); + data &= ~DIDT_DBR_CTRL0__DIDT_CTRL_EN_MASK; + data |= ((en << DIDT_DBR_CTRL0__DIDT_CTRL_EN__SHIFT) & DIDT_DBR_CTRL0__DIDT_CTRL_EN_MASK); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_DBR_CTRL0, data); + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DiDtEDCEnable)) { + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SQRamping)) { + data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_SQ_EDC_CTRL); + data &= ~DIDT_SQ_EDC_CTRL__EDC_EN_MASK; + data |= ((en << DIDT_SQ_EDC_CTRL__EDC_EN__SHIFT) & DIDT_SQ_EDC_CTRL__EDC_EN_MASK); + data &= ~DIDT_SQ_EDC_CTRL__EDC_SW_RST_MASK; + data |= ((~en << DIDT_SQ_EDC_CTRL__EDC_SW_RST__SHIFT) & DIDT_SQ_EDC_CTRL__EDC_SW_RST_MASK); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_SQ_EDC_CTRL, data); + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DBRamping)) { + data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_DB_EDC_CTRL); + data &= ~DIDT_DB_EDC_CTRL__EDC_EN_MASK; + data |= ((en << DIDT_DB_EDC_CTRL__EDC_EN__SHIFT) & DIDT_DB_EDC_CTRL__EDC_EN_MASK); + data &= ~DIDT_DB_EDC_CTRL__EDC_SW_RST_MASK; + data |= ((~en << DIDT_DB_EDC_CTRL__EDC_SW_RST__SHIFT) & DIDT_DB_EDC_CTRL__EDC_SW_RST_MASK); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_DB_EDC_CTRL, data); + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TDRamping)) { + data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_TD_EDC_CTRL); + data &= ~DIDT_TD_EDC_CTRL__EDC_EN_MASK; + data |= ((en << DIDT_TD_EDC_CTRL__EDC_EN__SHIFT) & DIDT_TD_EDC_CTRL__EDC_EN_MASK); + data &= ~DIDT_TD_EDC_CTRL__EDC_SW_RST_MASK; + data |= ((~en << DIDT_TD_EDC_CTRL__EDC_SW_RST__SHIFT) & DIDT_TD_EDC_CTRL__EDC_SW_RST_MASK); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_TD_EDC_CTRL, data); + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TCPRamping)) { + data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_TCP_EDC_CTRL); + data &= ~DIDT_TCP_EDC_CTRL__EDC_EN_MASK; + data |= ((en << DIDT_TCP_EDC_CTRL__EDC_EN__SHIFT) & DIDT_TCP_EDC_CTRL__EDC_EN_MASK); + data &= ~DIDT_TCP_EDC_CTRL__EDC_SW_RST_MASK; + data |= ((~en << DIDT_TCP_EDC_CTRL__EDC_SW_RST__SHIFT) & DIDT_TCP_EDC_CTRL__EDC_SW_RST_MASK); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_TCP_EDC_CTRL, data); + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DBRRamping)) { + data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_DBR_EDC_CTRL); + data &= ~DIDT_DBR_EDC_CTRL__EDC_EN_MASK; + data |= ((en << DIDT_DBR_EDC_CTRL__EDC_EN__SHIFT) & DIDT_DBR_EDC_CTRL__EDC_EN_MASK); + data &= ~DIDT_DBR_EDC_CTRL__EDC_SW_RST_MASK; + data |= ((~en << DIDT_DBR_EDC_CTRL__EDC_SW_RST__SHIFT) & DIDT_DBR_EDC_CTRL__EDC_SW_RST_MASK); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_DBR_EDC_CTRL, data); + } + } + + if (enable) { + /* For Vega10, SMC does not support any mask yet. */ + result = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_ConfigureGfxDidt, didt_block_info); + PP_ASSERT((0 == result), "[EnableDiDtConfig] SMC Configure Gfx Didt Failed!"); + } +} + +static int vega10_enable_cac_driving_se_didt_config(struct pp_hwmgr *hwmgr) +{ + int result; + uint32_t num_se = 0, count, data; + struct cgs_system_info sys_info = {0}; + uint32_t reg; + + sys_info.size = sizeof(struct cgs_system_info); + sys_info.info_id = CGS_SYSTEM_INFO_GFX_SE_INFO; + if (cgs_query_system_info(hwmgr->device, &sys_info) == 0) + num_se = sys_info.value; + + cgs_enter_safe_mode(hwmgr->device, true); + + cgs_lock_grbm_idx(hwmgr->device, true); + reg = soc15_get_register_offset(GC_HWID, 0, mmGRBM_GFX_INDEX_BASE_IDX, mmGRBM_GFX_INDEX); + for (count = 0; count < num_se; count++) { + data = GRBM_GFX_INDEX__INSTANCE_BROADCAST_WRITES_MASK | GRBM_GFX_INDEX__SH_BROADCAST_WRITES_MASK | ( count << GRBM_GFX_INDEX__SE_INDEX__SHIFT); + cgs_write_register(hwmgr->device, reg, data); + + result = vega10_program_didt_config_registers(hwmgr, SEDiDtStallCtrlConfig_vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, SEDiDtStallPatternConfig_vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, SEDiDtWeightConfig_Vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, SEDiDtCtrl1Config_Vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, SEDiDtCtrl2Config_Vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, SEDiDtCtrl3Config_vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, SEDiDtTuningCtrlConfig_Vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, SELCacConfig_Vega10, VEGA10_CONFIGREG_SECAC); + result |= vega10_program_didt_config_registers(hwmgr, SEDiDtCtrl0Config_Vega10, VEGA10_CONFIGREG_DIDT); + + if (0 != result) + break; + } + cgs_write_register(hwmgr->device, reg, 0xE0000000); + cgs_lock_grbm_idx(hwmgr->device, false); + + vega10_didt_set_mask(hwmgr, true); + + cgs_enter_safe_mode(hwmgr->device, false); + + return 0; +} + +static int vega10_disable_cac_driving_se_didt_config(struct pp_hwmgr *hwmgr) +{ + cgs_enter_safe_mode(hwmgr->device, true); + + vega10_didt_set_mask(hwmgr, false); + + cgs_enter_safe_mode(hwmgr->device, false); + + return 0; +} + +static int vega10_enable_psm_gc_didt_config(struct pp_hwmgr *hwmgr) +{ + int result; + uint32_t num_se = 0, count, data; + struct cgs_system_info sys_info = {0}; + uint32_t reg; + + sys_info.size = sizeof(struct cgs_system_info); + sys_info.info_id = CGS_SYSTEM_INFO_GFX_SE_INFO; + if (cgs_query_system_info(hwmgr->device, &sys_info) == 0) + num_se = sys_info.value; + + cgs_enter_safe_mode(hwmgr->device, true); + + cgs_lock_grbm_idx(hwmgr->device, true); + reg = soc15_get_register_offset(GC_HWID, 0, mmGRBM_GFX_INDEX_BASE_IDX, mmGRBM_GFX_INDEX); + for (count = 0; count < num_se; count++) { + data = GRBM_GFX_INDEX__INSTANCE_BROADCAST_WRITES_MASK | GRBM_GFX_INDEX__SH_BROADCAST_WRITES_MASK | ( count << GRBM_GFX_INDEX__SE_INDEX__SHIFT); + cgs_write_register(hwmgr->device, reg, data); + + result = vega10_program_didt_config_registers(hwmgr, SEDiDtStallCtrlConfig_vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, SEDiDtStallPatternConfig_vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, SEDiDtCtrl3Config_vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, SEDiDtCtrl0Config_Vega10, VEGA10_CONFIGREG_DIDT); + if (0 != result) + break; + } + cgs_write_register(hwmgr->device, reg, 0xE0000000); + cgs_lock_grbm_idx(hwmgr->device, false); + + vega10_didt_set_mask(hwmgr, true); + + cgs_enter_safe_mode(hwmgr->device, false); + + vega10_program_gc_didt_config_registers(hwmgr, GCDiDtDroopCtrlConfig_vega10); + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_GCEDC)) + vega10_program_gc_didt_config_registers(hwmgr, GCDiDtCtrl0Config_vega10); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PSM)) + vega10_program_gc_didt_config_registers(hwmgr, AvfsPSMInitConfig_vega10); + + return 0; +} + +static int vega10_disable_psm_gc_didt_config(struct pp_hwmgr *hwmgr) +{ + uint32_t data; + + cgs_enter_safe_mode(hwmgr->device, true); + + vega10_didt_set_mask(hwmgr, false); + + cgs_enter_safe_mode(hwmgr->device, false); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_GCEDC)) { + data = 0x00000000; + cgs_write_register(hwmgr->device, mmGC_DIDT_CTRL0, data); + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PSM)) + vega10_program_gc_didt_config_registers(hwmgr, AvfsPSMResetConfig_vega10); + + return 0; +} + +static int vega10_enable_se_edc_config(struct pp_hwmgr *hwmgr) +{ + int result; + uint32_t num_se = 0, count, data; + struct cgs_system_info sys_info = {0}; + uint32_t reg; + + sys_info.size = sizeof(struct cgs_system_info); + sys_info.info_id = CGS_SYSTEM_INFO_GFX_SE_INFO; + if (cgs_query_system_info(hwmgr->device, &sys_info) == 0) + num_se = sys_info.value; + + cgs_enter_safe_mode(hwmgr->device, true); + + cgs_lock_grbm_idx(hwmgr->device, true); + reg = soc15_get_register_offset(GC_HWID, 0, mmGRBM_GFX_INDEX_BASE_IDX, mmGRBM_GFX_INDEX); + for (count = 0; count < num_se; count++) { + data = GRBM_GFX_INDEX__INSTANCE_BROADCAST_WRITES_MASK | GRBM_GFX_INDEX__SH_BROADCAST_WRITES_MASK | ( count << GRBM_GFX_INDEX__SE_INDEX__SHIFT); + cgs_write_register(hwmgr->device, reg, data); + result = vega10_program_didt_config_registers(hwmgr, SEDiDtWeightConfig_Vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, SEEDCStallPatternConfig_Vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, SEEDCStallDelayConfig_Vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, SEEDCThresholdConfig_Vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, SEEDCCtrlResetConfig_Vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, SEEDCCtrlConfig_Vega10, VEGA10_CONFIGREG_DIDT); + + if (0 != result) + break; + } + cgs_write_register(hwmgr->device, reg, 0xE0000000); + cgs_lock_grbm_idx(hwmgr->device, false); + + vega10_didt_set_mask(hwmgr, true); + + cgs_enter_safe_mode(hwmgr->device, false); + + return 0; +} + +static int vega10_disable_se_edc_config(struct pp_hwmgr *hwmgr) +{ + cgs_enter_safe_mode(hwmgr->device, true); + + vega10_didt_set_mask(hwmgr, false); + + cgs_enter_safe_mode(hwmgr->device, false); + + return 0; +} + +static int vega10_enable_psm_gc_edc_config(struct pp_hwmgr *hwmgr) +{ + int result; + uint32_t num_se = 0; + uint32_t count, data; + struct cgs_system_info sys_info = {0}; + uint32_t reg; + + sys_info.size = sizeof(struct cgs_system_info); + sys_info.info_id = CGS_SYSTEM_INFO_GFX_SE_INFO; + if (cgs_query_system_info(hwmgr->device, &sys_info) == 0) + num_se = sys_info.value; + + cgs_enter_safe_mode(hwmgr->device, true); + + vega10_program_gc_didt_config_registers(hwmgr, AvfsPSMResetConfig_vega10); + + cgs_lock_grbm_idx(hwmgr->device, true); + reg = soc15_get_register_offset(GC_HWID, 0, mmGRBM_GFX_INDEX_BASE_IDX, mmGRBM_GFX_INDEX); + for (count = 0; count < num_se; count++) { + data = GRBM_GFX_INDEX__INSTANCE_BROADCAST_WRITES_MASK | GRBM_GFX_INDEX__SH_BROADCAST_WRITES_MASK | ( count << GRBM_GFX_INDEX__SE_INDEX__SHIFT); + cgs_write_register(hwmgr->device, reg, data); + result |= vega10_program_didt_config_registers(hwmgr, PSMSEEDCStallPatternConfig_Vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, PSMSEEDCStallDelayConfig_Vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, PSMSEEDCCtrlResetConfig_Vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, PSMSEEDCCtrlConfig_Vega10, VEGA10_CONFIGREG_DIDT); + + if (0 != result) + break; + } + cgs_write_register(hwmgr->device, reg, 0xE0000000); + cgs_lock_grbm_idx(hwmgr->device, false); + + vega10_didt_set_mask(hwmgr, true); + + cgs_enter_safe_mode(hwmgr->device, false); + + vega10_program_gc_didt_config_registers(hwmgr, PSMGCEDCDroopCtrlConfig_vega10); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_GCEDC)) { + vega10_program_gc_didt_config_registers(hwmgr, PSMGCEDCCtrlResetConfig_vega10); + vega10_program_gc_didt_config_registers(hwmgr, PSMGCEDCCtrlConfig_vega10); + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PSM)) + vega10_program_gc_didt_config_registers(hwmgr, AvfsPSMInitConfig_vega10); + + return 0; +} + +static int vega10_disable_psm_gc_edc_config(struct pp_hwmgr *hwmgr) +{ + uint32_t data; + + cgs_enter_safe_mode(hwmgr->device, true); + + vega10_didt_set_mask(hwmgr, false); + + cgs_enter_safe_mode(hwmgr->device, false); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_GCEDC)) { + data = 0x00000000; + cgs_write_register(hwmgr->device, mmGC_EDC_CTRL, data); + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PSM)) + vega10_program_gc_didt_config_registers(hwmgr, AvfsPSMResetConfig_vega10); + + return 0; +} + +static int vega10_enable_se_edc_force_stall_config(struct pp_hwmgr *hwmgr) +{ + uint32_t reg; + int result; + + cgs_enter_safe_mode(hwmgr->device, true); + + cgs_lock_grbm_idx(hwmgr->device, true); + reg = soc15_get_register_offset(GC_HWID, 0, mmGRBM_GFX_INDEX_BASE_IDX, mmGRBM_GFX_INDEX); + cgs_write_register(hwmgr->device, reg, 0xE0000000); + cgs_lock_grbm_idx(hwmgr->device, false); + + result = vega10_program_didt_config_registers(hwmgr, SEEDCForceStallPatternConfig_Vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, SEEDCCtrlForceStallConfig_Vega10, VEGA10_CONFIGREG_DIDT); + if (0 != result) + return result; + + vega10_didt_set_mask(hwmgr, true); + + cgs_enter_safe_mode(hwmgr->device, false); + + return 0; +} + +static int vega10_disable_se_edc_force_stall_config(struct pp_hwmgr *hwmgr) +{ + int result; + + result = vega10_disable_se_edc_config(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), "[DisableDiDtConfig] Pre DIDT disable clock gating failed!", return result); + + return 0; +} + +int vega10_enable_didt_config(struct pp_hwmgr *hwmgr) +{ + int result = 0; + struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend); + + if (data->smu_features[GNLD_DIDT].supported) { + if (data->smu_features[GNLD_DIDT].enabled) + PP_DBG_LOG("[EnableDiDtConfig] Feature DiDt Already enabled!\n"); + + switch (data->registry_data.didt_mode) { + case 0: + result = vega10_enable_cac_driving_se_didt_config(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), "[EnableDiDt] Attempt to enable DiDt Mode 0 Failed!", return result); + break; + case 2: + result = vega10_enable_psm_gc_didt_config(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), "[EnableDiDt] Attempt to enable DiDt Mode 2 Failed!", return result); + break; + case 3: + result = vega10_enable_se_edc_config(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), "[EnableDiDt] Attempt to enable DiDt Mode 3 Failed!", return result); + break; + case 1: + case 4: + case 5: + result = vega10_enable_psm_gc_edc_config(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), "[EnableDiDt] Attempt to enable DiDt Mode 5 Failed!", return result); + break; + case 6: + result = vega10_enable_se_edc_force_stall_config(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), "[EnableDiDt] Attempt to enable DiDt Mode 6 Failed!", return result); + break; + default: + result = -EINVAL; + break; + } + + if (0 == result) { + PP_ASSERT_WITH_CODE((!vega10_enable_smc_features(hwmgr->smumgr, true, data->smu_features[GNLD_DIDT].smu_feature_bitmap)), + "[EnableDiDtConfig] Attempt to Enable DiDt feature Failed!", return result); + data->smu_features[GNLD_DIDT].enabled = true; + } + } + + return result; +} + +int vega10_disable_didt_config(struct pp_hwmgr *hwmgr) +{ + int result = 0; + struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend); + + if (data->smu_features[GNLD_DIDT].supported) { + if (!data->smu_features[GNLD_DIDT].enabled) + PP_DBG_LOG("[DisableDiDtConfig] Feature DiDt Already Disabled!\n"); + + switch (data->registry_data.didt_mode) { + case 0: + result = vega10_disable_cac_driving_se_didt_config(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), "[DisableDiDt] Attempt to disable DiDt Mode 0 Failed!", return result); + break; + case 2: + result = vega10_disable_psm_gc_didt_config(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), "[DisableDiDt] Attempt to disable DiDt Mode 2 Failed!", return result); + break; + case 3: + result = vega10_disable_se_edc_config(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), "[DisableDiDt] Attempt to disable DiDt Mode 3 Failed!", return result); + break; + case 1: + case 4: + case 5: + result = vega10_disable_psm_gc_edc_config(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), "[DisableDiDt] Attempt to disable DiDt Mode 5 Failed!", return result); + break; + case 6: + result = vega10_disable_se_edc_force_stall_config(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), "[DisableDiDt] Attempt to disable DiDt Mode 6 Failed!", return result); + break; + default: + result = -EINVAL; + break; + } + + if (0 == result) { + PP_ASSERT_WITH_CODE((0 != vega10_enable_smc_features(hwmgr->smumgr, false, data->smu_features[GNLD_DIDT].smu_feature_bitmap)), + "[DisableDiDtConfig] Attempt to Disable DiDt feature Failed!", return result); + data->smu_features[GNLD_DIDT].enabled = false; + } + } + + return result; +} void vega10_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) { diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.h index 9ecaa27c0bb5..b95771ab89cd 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.h @@ -31,6 +31,12 @@ enum vega10_pt_config_reg_type { VEGA10_CONFIGREG_MAX }; +enum vega10_didt_config_reg_type { + VEGA10_CONFIGREG_DIDT = 0, + VEGA10_CONFIGREG_GCCAC, + VEGA10_CONFIGREG_SECAC +}; + /* PowerContainment Features */ #define POWERCONTAINMENT_FEATURE_DTE 0x00000001 #define POWERCONTAINMENT_FEATURE_TDCLimit 0x00000002 @@ -44,6 +50,13 @@ struct vega10_pt_config_reg { enum vega10_pt_config_reg_type type; }; +struct vega10_didt_config_reg { + uint32_t offset; + uint32_t mask; + uint32_t shift; + uint32_t value; +}; + struct vega10_pt_defaults { uint8_t SviLoadLineEn; uint8_t SviLoadLineVddC; @@ -62,5 +75,8 @@ int vega10_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n); int vega10_power_control_set_level(struct pp_hwmgr *hwmgr); int vega10_disable_power_containment(struct pp_hwmgr *hwmgr); +int vega10_enable_didt_config(struct pp_hwmgr *hwmgr); +int vega10_disable_didt_config(struct pp_hwmgr *hwmgr); + #endif /* _VEGA10_POWERTUNE_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h b/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h index a1ebe1014492..a4c8b09b6f14 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h @@ -164,9 +164,14 @@ enum phm_platform_caps { PHM_PlatformCaps_EnablePlatformPowerManagement, /* indicates that Platform Power Management feature is supported */ PHM_PlatformCaps_SurpriseRemoval, /* indicates that surprise removal feature is requested */ PHM_PlatformCaps_NewCACVoltage, /* indicates new CAC voltage table support */ + PHM_PlatformCaps_DiDtSupport, /* for dI/dT feature */ PHM_PlatformCaps_DBRamping, /* for dI/dT feature */ PHM_PlatformCaps_TDRamping, /* for dI/dT feature */ PHM_PlatformCaps_TCPRamping, /* for dI/dT feature */ + PHM_PlatformCaps_DBRRamping, /* for dI/dT feature */ + PHM_PlatformCaps_DiDtEDCEnable, /* for dI/dT feature */ + PHM_PlatformCaps_GCEDC, /* for dI/dT feature */ + PHM_PlatformCaps_PSM, /* for dI/dT feature */ PHM_PlatformCaps_EnableSMU7ThermalManagement, /* SMC will manage thermal events */ PHM_PlatformCaps_FPS, /* FPS support */ PHM_PlatformCaps_ACP, /* ACP support */ diff --git a/drivers/gpu/drm/amd/powerplay/inc/pp_debug.h b/drivers/gpu/drm/amd/powerplay/inc/pp_debug.h index f3f9ebb631a5..822cd8b5bf90 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/pp_debug.h +++ b/drivers/gpu/drm/amd/powerplay/inc/pp_debug.h @@ -42,6 +42,12 @@ } \ } while (0) +#define PP_ASSERT(cond, msg) \ + do { \ + if (!(cond)) { \ + pr_warn("%s\n", msg); \ + } \ + } while (0) #define PP_DBG_LOG(fmt, ...) \ do { \ diff --git a/drivers/gpu/drm/amd/powerplay/inc/pp_soc15.h b/drivers/gpu/drm/amd/powerplay/inc/pp_soc15.h index 227d999b6bd1..a511611ec7e0 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/pp_soc15.h +++ b/drivers/gpu/drm/amd/powerplay/inc/pp_soc15.h @@ -41,6 +41,8 @@ inline static uint32_t soc15_get_register_offset( reg = MP1_BASE.instance[inst].segment[segment] + offset; else if (hw_id == DF_HWID) reg = DF_BASE.instance[inst].segment[segment] + offset; + else if (hw_id == GC_HWID) + reg = GC_BASE.instance[inst].segment[segment] + offset; return reg; } -- cgit v1.2.3 From 12097c6d67ba851d7eea7ab82b7ba70019347bfd Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 6 Jul 2017 13:38:09 -0400 Subject: drm/amdgpu: add nbio 6.1 register init function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Used for nbio registers that need to be initialized. Currently only used for a golden setting that got missed on some boards. Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/nbio_v6_1.c | 13 +++++++++++++ drivers/gpu/drm/amd/amdgpu/nbio_v6_1.h | 1 + 2 files changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v6_1.c b/drivers/gpu/drm/amd/amdgpu/nbio_v6_1.c index 61c00281a61b..045988b18bc3 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v6_1.c +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v6_1.c @@ -32,6 +32,7 @@ #define smnCPM_CONTROL 0x11180460 #define smnPCIE_CNTL2 0x11180070 +#define smnPCIE_CONFIG_CNTL 0x11180044 u32 nbio_v6_1_get_rev_id(struct amdgpu_device *adev) { @@ -256,3 +257,15 @@ void nbio_v6_1_detect_hw_virt(struct amdgpu_device *adev) adev->virt.caps |= AMDGPU_PASSTHROUGH_MODE; } } + +void nbio_v6_1_init_registers(struct amdgpu_device *adev) +{ + uint32_t def, data; + + def = data = RREG32_PCIE(smnPCIE_CONFIG_CNTL); + data = REG_SET_FIELD(data, PCIE_CONFIG_CNTL, CI_SWUS_MAX_READ_REQUEST_SIZE_MODE, 1); + data = REG_SET_FIELD(data, PCIE_CONFIG_CNTL, CI_SWUS_MAX_READ_REQUEST_SIZE_PRIV, 1); + + if (def != data) + WREG32_PCIE(smnPCIE_CONFIG_CNTL, data); +} diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v6_1.h b/drivers/gpu/drm/amd/amdgpu/nbio_v6_1.h index f6f8bc045518..686e4b4d296a 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v6_1.h +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v6_1.h @@ -50,5 +50,6 @@ void nbio_v6_1_update_medium_grain_clock_gating(struct amdgpu_device *adev, bool void nbio_v6_1_update_medium_grain_light_sleep(struct amdgpu_device *adev, bool enable); void nbio_v6_1_get_clockgating_state(struct amdgpu_device *adev, u32 *flags); void nbio_v6_1_detect_hw_virt(struct amdgpu_device *adev); +void nbio_v6_1_init_registers(struct amdgpu_device *adev); #endif -- cgit v1.2.3 From 833fa075b87c36be437a941393d750c36022d902 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 6 Jul 2017 13:43:55 -0400 Subject: drm/amdgpu/soc15: init nbio registers for vega10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Call nbio init registers on hw_init to set up any nbio registers that need initialization at hw init time. Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/soc15.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 0d9a3dd302a7..8dc023296773 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -727,6 +727,9 @@ static int soc15_common_hw_init(void *handle) soc15_pcie_gen3_enable(adev); /* enable aspm */ soc15_program_aspm(adev); + /* setup nbio registers */ + if (!(adev->flags & AMD_IS_APU)) + nbio_v6_1_init_registers(adev); /* enable the doorbell aperture */ soc15_enable_doorbell_aperture(adev, true); -- cgit v1.2.3 From 70d17a25da21e1d497db3580ae27682952ddfd98 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 30 Jun 2017 17:26:47 -0400 Subject: drm/amdgpu: check scratch registers to see if we need post (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rather than checking the CONGIG_MEMSIZE register as that may not be reliable on some APUs. v2: The scratch register is only used on CIK+ Reviewed-by: Junwei Zhang Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 541695768f0a..d92ac5c1af54 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -736,7 +736,12 @@ bool amdgpu_need_post(struct amdgpu_device *adev) adev->has_hw_reset = false; return true; } - /* then check MEM_SIZE, in case the crtcs are off */ + + /* bios scratch used on CIK+ */ + if (adev->asic_type >= CHIP_BONAIRE) + return amdgpu_atombios_scratch_need_asic_init(adev); + + /* check MEM_SIZE for older asics */ reg = amdgpu_asic_get_config_memsize(adev); if ((reg != 0) && (reg != 0xffffffff)) -- cgit v1.2.3 From 3490bdb537fbf94a7a57f6c353a39e6306a9cfbd Mon Sep 17 00:00:00 2001 From: Christian König Date: Thu, 6 Jul 2017 22:02:41 +0200 Subject: drm/amdgpu: move GART struct and function into amdgpu_gart.h v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No functional change, just cleanup. v2: rebased, keep gart name. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 48 +------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_gart.h | 77 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 1 + 3 files changed, 79 insertions(+), 47 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_gart.h (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 1bb1912f863c..9c1146228421 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -68,6 +68,7 @@ #include "gpu_scheduler.h" #include "amdgpu_virt.h" +#include "amdgpu_gart.h" /* * Modules parameters. @@ -531,53 +532,6 @@ int amdgpu_mode_dumb_mmap(struct drm_file *filp, int amdgpu_fence_slab_init(void); void amdgpu_fence_slab_fini(void); -/* - * GART structures, functions & helpers - */ -struct amdgpu_mc; - -#define AMDGPU_GPU_PAGE_SIZE 4096 -#define AMDGPU_GPU_PAGE_MASK (AMDGPU_GPU_PAGE_SIZE - 1) -#define AMDGPU_GPU_PAGE_SHIFT 12 -#define AMDGPU_GPU_PAGE_ALIGN(a) (((a) + AMDGPU_GPU_PAGE_MASK) & ~AMDGPU_GPU_PAGE_MASK) - -struct amdgpu_gart { - dma_addr_t table_addr; - struct amdgpu_bo *robj; - void *ptr; - unsigned num_gpu_pages; - unsigned num_cpu_pages; - unsigned table_size; -#ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS - struct page **pages; -#endif - bool ready; - - /* Asic default pte flags */ - uint64_t gart_pte_flags; - - const struct amdgpu_gart_funcs *gart_funcs; -}; - -void amdgpu_gart_set_defaults(struct amdgpu_device *adev); -int amdgpu_gart_table_ram_alloc(struct amdgpu_device *adev); -void amdgpu_gart_table_ram_free(struct amdgpu_device *adev); -int amdgpu_gart_table_vram_alloc(struct amdgpu_device *adev); -void amdgpu_gart_table_vram_free(struct amdgpu_device *adev); -int amdgpu_gart_table_vram_pin(struct amdgpu_device *adev); -void amdgpu_gart_table_vram_unpin(struct amdgpu_device *adev); -int amdgpu_gart_init(struct amdgpu_device *adev); -void amdgpu_gart_fini(struct amdgpu_device *adev); -int amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset, - int pages); -int amdgpu_gart_map(struct amdgpu_device *adev, uint64_t offset, - int pages, dma_addr_t *dma_addr, uint64_t flags, - void *dst); -int amdgpu_gart_bind(struct amdgpu_device *adev, uint64_t offset, - int pages, struct page **pagelist, - dma_addr_t *dma_addr, uint64_t flags); -int amdgpu_ttm_recover_gart(struct amdgpu_device *adev); - /* * VMHUB structures, functions & helpers */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.h new file mode 100644 index 000000000000..d4cce6936200 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.h @@ -0,0 +1,77 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef __AMDGPU_GART_H__ +#define __AMDGPU_GART_H__ + +#include + +/* + * GART structures, functions & helpers + */ +struct amdgpu_device; +struct amdgpu_bo; +struct amdgpu_gart_funcs; + +#define AMDGPU_GPU_PAGE_SIZE 4096 +#define AMDGPU_GPU_PAGE_MASK (AMDGPU_GPU_PAGE_SIZE - 1) +#define AMDGPU_GPU_PAGE_SHIFT 12 +#define AMDGPU_GPU_PAGE_ALIGN(a) (((a) + AMDGPU_GPU_PAGE_MASK) & ~AMDGPU_GPU_PAGE_MASK) + +struct amdgpu_gart { + dma_addr_t table_addr; + struct amdgpu_bo *robj; + void *ptr; + unsigned num_gpu_pages; + unsigned num_cpu_pages; + unsigned table_size; +#ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS + struct page **pages; +#endif + bool ready; + + /* Asic default pte flags */ + uint64_t gart_pte_flags; + + const struct amdgpu_gart_funcs *gart_funcs; +}; + +void amdgpu_gart_set_defaults(struct amdgpu_device *adev); +int amdgpu_gart_table_ram_alloc(struct amdgpu_device *adev); +void amdgpu_gart_table_ram_free(struct amdgpu_device *adev); +int amdgpu_gart_table_vram_alloc(struct amdgpu_device *adev); +void amdgpu_gart_table_vram_free(struct amdgpu_device *adev); +int amdgpu_gart_table_vram_pin(struct amdgpu_device *adev); +void amdgpu_gart_table_vram_unpin(struct amdgpu_device *adev); +int amdgpu_gart_init(struct amdgpu_device *adev); +void amdgpu_gart_fini(struct amdgpu_device *adev); +int amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset, + int pages); +int amdgpu_gart_map(struct amdgpu_device *adev, uint64_t offset, + int pages, dma_addr_t *dma_addr, uint64_t flags, + void *dst); +int amdgpu_gart_bind(struct amdgpu_device *adev, uint64_t offset, + int pages, struct page **pagelist, + dma_addr_t *dma_addr, uint64_t flags); + +#endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index 4f5c1da5922e..f137c2458ee8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -80,5 +80,6 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo, int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma); bool amdgpu_ttm_is_bound(struct ttm_tt *ttm); int amdgpu_ttm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *bo_mem); +int amdgpu_ttm_recover_gart(struct amdgpu_device *adev); #endif -- cgit v1.2.3 From ed21c047e9753ed5c7abe437ec25222b7d538a89 Mon Sep 17 00:00:00 2001 From: Christian König Date: Thu, 6 Jul 2017 22:26:05 +0200 Subject: drm/amdgpu: remove gtt_base_align handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Not used any more. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 - drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c | 1 - drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 1 - drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 1 - drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 1 - 6 files changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 9c1146228421..590798f0c245 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -564,7 +564,6 @@ struct amdgpu_mc { unsigned vram_width; u64 real_vram_size; int vram_mtrr; - u64 gtt_base_align; u64 mc_mask; const struct firmware *fw; /* MC firmware */ uint32_t fw_version; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index d92ac5c1af54..c635abdac96f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -696,8 +696,8 @@ void amdgpu_gtt_location(struct amdgpu_device *adev, struct amdgpu_mc *mc) { u64 size_af, size_bf; - size_af = ((adev->mc.mc_mask - mc->vram_end) + mc->gtt_base_align) & ~mc->gtt_base_align; - size_bf = mc->vram_start & ~mc->gtt_base_align; + size_af = adev->mc.mc_mask - mc->vram_end; + size_bf = mc->vram_start; if (size_bf > size_af) { if (mc->gtt_size > size_bf) { dev_warn(adev->dev, "limiting GTT\n"); @@ -709,7 +709,7 @@ void amdgpu_gtt_location(struct amdgpu_device *adev, struct amdgpu_mc *mc) dev_warn(adev->dev, "limiting GTT\n"); mc->gtt_size = size_af; } - mc->gtt_start = (mc->vram_end + 1 + mc->gtt_base_align) & ~mc->gtt_base_align; + mc->gtt_start = mc->vram_end + 1; } mc->gtt_end = mc->gtt_start + mc->gtt_size - 1; dev_info(adev->dev, "GTT: %lluM 0x%016llX - 0x%016llX\n", diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c index 5f7750c6497e..810d5734ce1e 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c @@ -228,7 +228,6 @@ static void gmc_v6_0_vram_gtt_location(struct amdgpu_device *adev, mc->mc_vram_size = 0xFFC0000000ULL; } amdgpu_vram_location(adev, &adev->mc, base); - adev->mc.gtt_base_align = 0; amdgpu_gtt_location(adev, mc); } diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c index 388b52febc8b..066f00ad4152 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c @@ -244,7 +244,6 @@ static void gmc_v7_0_vram_gtt_location(struct amdgpu_device *adev, mc->mc_vram_size = 0xFFC0000000ULL; } amdgpu_vram_location(adev, &adev->mc, base); - adev->mc.gtt_base_align = 0; amdgpu_gtt_location(adev, mc); } diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index d148d1c585b3..f30c39c72bca 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -406,7 +406,6 @@ static void gmc_v8_0_vram_gtt_location(struct amdgpu_device *adev, mc->mc_vram_size = 0xFFC0000000ULL; } amdgpu_vram_location(adev, &adev->mc, base); - adev->mc.gtt_base_align = 0; amdgpu_gtt_location(adev, mc); } diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 8ec148727149..dd2756ec11b8 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -420,7 +420,6 @@ static void gmc_v9_0_vram_gtt_location(struct amdgpu_device *adev, if (!amdgpu_sriov_vf(adev)) base = mmhub_v1_0_get_fb_location(adev); amdgpu_vram_location(adev, &adev->mc, base); - adev->mc.gtt_base_align = 0; amdgpu_gtt_location(adev, mc); /* base offset of vram pages */ if (adev->flags & AMD_IS_APU) -- cgit v1.2.3 From 6f02a69648f14024213ab65cd4a4a701e40e46ff Mon Sep 17 00:00:00 2001 From: Christian König Date: Fri, 7 Jul 2017 11:56:59 +0200 Subject: drm/amdgpu: consistent name all GART related parts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename symbols from gtt_ to gart_ as appropriate. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 8 ++--- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 22 +++++++------- drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c | 12 ++++---- drivers/gpu/drm/amd/amdgpu/amdgpu_test.c | 48 +++++++++++++++--------------- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 10 +++---- drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c | 8 ++--- drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c | 8 ++--- drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 8 ++--- drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 8 ++--- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 4 +-- drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c | 8 ++--- 11 files changed, 72 insertions(+), 72 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 590798f0c245..b19557b8c683 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -556,9 +556,9 @@ struct amdgpu_mc { * about vram size near mc fb location */ u64 mc_vram_size; u64 visible_vram_size; - u64 gtt_size; - u64 gtt_start; - u64 gtt_end; + u64 gart_size; + u64 gart_start; + u64 gart_end; u64 vram_start; u64 vram_end; unsigned vram_width; @@ -1860,7 +1860,7 @@ bool amdgpu_ttm_tt_is_readonly(struct ttm_tt *ttm); uint64_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm, struct ttm_mem_reg *mem); void amdgpu_vram_location(struct amdgpu_device *adev, struct amdgpu_mc *mc, u64 base); -void amdgpu_gtt_location(struct amdgpu_device *adev, struct amdgpu_mc *mc); +void amdgpu_gart_location(struct amdgpu_device *adev, struct amdgpu_mc *mc); void amdgpu_ttm_set_active_vram_size(struct amdgpu_device *adev, u64 size); int amdgpu_ttm_init(struct amdgpu_device *adev); void amdgpu_ttm_fini(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index c635abdac96f..84ff824ea260 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -681,7 +681,7 @@ void amdgpu_vram_location(struct amdgpu_device *adev, struct amdgpu_mc *mc, u64 } /** - * amdgpu_gtt_location - try to find GTT location + * amdgpu_gart_location - try to find GTT location * @adev: amdgpu device structure holding all necessary informations * @mc: memory controller structure holding memory informations * @@ -692,28 +692,28 @@ void amdgpu_vram_location(struct amdgpu_device *adev, struct amdgpu_mc *mc, u64 * * FIXME: when reducing GTT size align new size on power of 2. */ -void amdgpu_gtt_location(struct amdgpu_device *adev, struct amdgpu_mc *mc) +void amdgpu_gart_location(struct amdgpu_device *adev, struct amdgpu_mc *mc) { u64 size_af, size_bf; size_af = adev->mc.mc_mask - mc->vram_end; size_bf = mc->vram_start; if (size_bf > size_af) { - if (mc->gtt_size > size_bf) { + if (mc->gart_size > size_bf) { dev_warn(adev->dev, "limiting GTT\n"); - mc->gtt_size = size_bf; + mc->gart_size = size_bf; } - mc->gtt_start = 0; + mc->gart_start = 0; } else { - if (mc->gtt_size > size_af) { + if (mc->gart_size > size_af) { dev_warn(adev->dev, "limiting GTT\n"); - mc->gtt_size = size_af; + mc->gart_size = size_af; } - mc->gtt_start = mc->vram_end + 1; + mc->gart_start = mc->vram_end + 1; } - mc->gtt_end = mc->gtt_start + mc->gtt_size - 1; + mc->gart_end = mc->gart_start + mc->gart_size - 1; dev_info(adev->dev, "GTT: %lluM 0x%016llX - 0x%016llX\n", - mc->gtt_size >> 20, mc->gtt_start, mc->gtt_end); + mc->gart_size >> 20, mc->gart_start, mc->gart_end); } /* @@ -2031,7 +2031,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, adev->flags = flags; adev->asic_type = flags & AMD_ASIC_MASK; adev->usec_timeout = AMDGPU_MAX_USEC_TIMEOUT; - adev->mc.gtt_size = 512 * 1024 * 1024; + adev->mc.gart_size = 512 * 1024 * 1024; adev->accel_working = false; adev->num_rings = 0; adev->mman.buffer_funcs = NULL; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c index b4048a91c814..d578ca6f2dfd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c @@ -57,11 +57,11 @@ */ /** - * amdgpu_gart_set_defaults - set the default gtt_size + * amdgpu_gart_set_defaults - set the default gart_size * * @adev: amdgpu_device pointer * - * Set the default gtt_size based on parameters and available VRAM. + * Set the default gart_size based on parameters and available VRAM. */ void amdgpu_gart_set_defaults(struct amdgpu_device *adev) { @@ -69,10 +69,10 @@ void amdgpu_gart_set_defaults(struct amdgpu_device *adev) * size equal to the 1024 or vram, whichever is larger. */ if (amdgpu_gart_size == -1) - adev->mc.gtt_size = max((AMDGPU_DEFAULT_GTT_SIZE_MB << 20), + adev->mc.gart_size = max((AMDGPU_DEFAULT_GTT_SIZE_MB << 20), adev->mc.mc_vram_size); else - adev->mc.gtt_size = (uint64_t)amdgpu_gart_size << 20; + adev->mc.gart_size = (uint64_t)amdgpu_gart_size << 20; } /** @@ -387,8 +387,8 @@ int amdgpu_gart_init(struct amdgpu_device *adev) if (r) return r; /* Compute table size */ - adev->gart.num_cpu_pages = adev->mc.gtt_size / PAGE_SIZE; - adev->gart.num_gpu_pages = adev->mc.gtt_size / AMDGPU_GPU_PAGE_SIZE; + adev->gart.num_cpu_pages = adev->mc.gart_size / PAGE_SIZE; + adev->gart.num_gpu_pages = adev->mc.gart_size / AMDGPU_GPU_PAGE_SIZE; DRM_INFO("GART: num cpu pages %u, num gpu pages %u\n", adev->gart.num_cpu_pages, adev->gart.num_gpu_pages); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_test.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_test.c index d02e611a2dae..3c4d7574d704 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_test.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_test.c @@ -33,7 +33,7 @@ static void amdgpu_do_test_moves(struct amdgpu_device *adev) struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring; struct amdgpu_bo *vram_obj = NULL; struct amdgpu_bo **gtt_obj = NULL; - uint64_t gtt_addr, vram_addr; + uint64_t gart_addr, vram_addr; unsigned n, size; int i, r; @@ -42,7 +42,7 @@ static void amdgpu_do_test_moves(struct amdgpu_device *adev) /* Number of tests = * (Total GTT - IB pool - writeback page - ring buffers) / test size */ - n = adev->mc.gtt_size - AMDGPU_IB_POOL_SIZE*64*1024; + n = adev->mc.gart_size - AMDGPU_IB_POOL_SIZE*64*1024; for (i = 0; i < AMDGPU_MAX_RINGS; ++i) if (adev->rings[i]) n -= adev->rings[i]->ring_size; @@ -76,7 +76,7 @@ static void amdgpu_do_test_moves(struct amdgpu_device *adev) } for (i = 0; i < n; i++) { void *gtt_map, *vram_map; - void **gtt_start, **gtt_end; + void **gart_start, **gart_end; void **vram_start, **vram_end; struct dma_fence *fence = NULL; @@ -91,7 +91,7 @@ static void amdgpu_do_test_moves(struct amdgpu_device *adev) r = amdgpu_bo_reserve(gtt_obj[i], false); if (unlikely(r != 0)) goto out_lclean_unref; - r = amdgpu_bo_pin(gtt_obj[i], AMDGPU_GEM_DOMAIN_GTT, >t_addr); + r = amdgpu_bo_pin(gtt_obj[i], AMDGPU_GEM_DOMAIN_GTT, &gart_addr); if (r) { DRM_ERROR("Failed to pin GTT object %d\n", i); goto out_lclean_unres; @@ -103,14 +103,14 @@ static void amdgpu_do_test_moves(struct amdgpu_device *adev) goto out_lclean_unpin; } - for (gtt_start = gtt_map, gtt_end = gtt_map + size; - gtt_start < gtt_end; - gtt_start++) - *gtt_start = gtt_start; + for (gart_start = gtt_map, gart_end = gtt_map + size; + gart_start < gart_end; + gart_start++) + *gart_start = gart_start; amdgpu_bo_kunmap(gtt_obj[i]); - r = amdgpu_copy_buffer(ring, gtt_addr, vram_addr, + r = amdgpu_copy_buffer(ring, gart_addr, vram_addr, size, NULL, &fence, false, false); if (r) { @@ -132,21 +132,21 @@ static void amdgpu_do_test_moves(struct amdgpu_device *adev) goto out_lclean_unpin; } - for (gtt_start = gtt_map, gtt_end = gtt_map + size, + for (gart_start = gtt_map, gart_end = gtt_map + size, vram_start = vram_map, vram_end = vram_map + size; vram_start < vram_end; - gtt_start++, vram_start++) { - if (*vram_start != gtt_start) { + gart_start++, vram_start++) { + if (*vram_start != gart_start) { DRM_ERROR("Incorrect GTT->VRAM copy %d: Got 0x%p, " "expected 0x%p (GTT/VRAM offset " "0x%16llx/0x%16llx)\n", - i, *vram_start, gtt_start, + i, *vram_start, gart_start, (unsigned long long) - (gtt_addr - adev->mc.gtt_start + - (void*)gtt_start - gtt_map), + (gart_addr - adev->mc.gart_start + + (void*)gart_start - gtt_map), (unsigned long long) (vram_addr - adev->mc.vram_start + - (void*)gtt_start - gtt_map)); + (void*)gart_start - gtt_map)); amdgpu_bo_kunmap(vram_obj); goto out_lclean_unpin; } @@ -155,7 +155,7 @@ static void amdgpu_do_test_moves(struct amdgpu_device *adev) amdgpu_bo_kunmap(vram_obj); - r = amdgpu_copy_buffer(ring, vram_addr, gtt_addr, + r = amdgpu_copy_buffer(ring, vram_addr, gart_addr, size, NULL, &fence, false, false); if (r) { @@ -177,20 +177,20 @@ static void amdgpu_do_test_moves(struct amdgpu_device *adev) goto out_lclean_unpin; } - for (gtt_start = gtt_map, gtt_end = gtt_map + size, + for (gart_start = gtt_map, gart_end = gtt_map + size, vram_start = vram_map, vram_end = vram_map + size; - gtt_start < gtt_end; - gtt_start++, vram_start++) { - if (*gtt_start != vram_start) { + gart_start < gart_end; + gart_start++, vram_start++) { + if (*gart_start != vram_start) { DRM_ERROR("Incorrect VRAM->GTT copy %d: Got 0x%p, " "expected 0x%p (VRAM/GTT offset " "0x%16llx/0x%16llx)\n", - i, *gtt_start, vram_start, + i, *gart_start, vram_start, (unsigned long long) (vram_addr - adev->mc.vram_start + (void*)vram_start - vram_map), (unsigned long long) - (gtt_addr - adev->mc.gtt_start + + (gart_addr - adev->mc.gart_start + (void*)vram_start - vram_map)); amdgpu_bo_kunmap(gtt_obj[i]); goto out_lclean_unpin; @@ -200,7 +200,7 @@ static void amdgpu_do_test_moves(struct amdgpu_device *adev) amdgpu_bo_kunmap(gtt_obj[i]); DRM_INFO("Tested GTT->VRAM and VRAM->GTT copy for GTT offset 0x%llx\n", - gtt_addr - adev->mc.gtt_start); + gart_addr - adev->mc.gart_start); continue; out_lclean_unpin: diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index fb9c6988f5f2..4e711d9af67c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -158,7 +158,7 @@ static int amdgpu_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, break; case TTM_PL_TT: man->func = &amdgpu_gtt_mgr_func; - man->gpu_offset = adev->mc.gtt_start; + man->gpu_offset = adev->mc.gart_start; man->available_caching = TTM_PL_MASK_CACHING; man->default_caching = TTM_PL_FLAG_CACHED; man->flags = TTM_MEMTYPE_FLAG_MAPPABLE | TTM_MEMTYPE_FLAG_CMA; @@ -1144,13 +1144,13 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) DRM_INFO("amdgpu: %uM of VRAM memory ready\n", (unsigned) (adev->mc.real_vram_size / (1024 * 1024))); r = ttm_bo_init_mm(&adev->mman.bdev, TTM_PL_TT, - adev->mc.gtt_size >> PAGE_SHIFT); + adev->mc.gart_size >> PAGE_SHIFT); if (r) { DRM_ERROR("Failed initializing GTT heap.\n"); return r; } DRM_INFO("amdgpu: %uM of GTT memory ready.\n", - (unsigned)(adev->mc.gtt_size / (1024 * 1024))); + (unsigned)(adev->mc.gart_size / (1024 * 1024))); adev->gds.mem.total_size = adev->gds.mem.total_size << AMDGPU_GDS_SHIFT; adev->gds.mem.gfx_partition_size = adev->gds.mem.gfx_partition_size << AMDGPU_GDS_SHIFT; @@ -1279,7 +1279,7 @@ static int amdgpu_map_buffer(struct ttm_buffer_object *bo, BUG_ON(adev->mman.buffer_funcs->copy_max_bytes < AMDGPU_GTT_MAX_TRANSFER_SIZE * 8); - *addr = adev->mc.gtt_start; + *addr = adev->mc.gart_start; *addr += (u64)window * AMDGPU_GTT_MAX_TRANSFER_SIZE * AMDGPU_GPU_PAGE_SIZE; @@ -1645,7 +1645,7 @@ static int amdgpu_ttm_debugfs_init(struct amdgpu_device *adev) adev, &amdgpu_ttm_gtt_fops); if (IS_ERR(ent)) return PTR_ERR(ent); - i_size_write(ent->d_inode, adev->mc.gtt_size); + i_size_write(ent->d_inode, adev->mc.gart_size); adev->mman.gtt = ent; #endif diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c index a42f483767e7..3ff786cfc947 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c @@ -58,14 +58,14 @@ static void gfxhub_v1_0_init_gart_aperture_regs(struct amdgpu_device *adev) gfxhub_v1_0_init_gart_pt_regs(adev); WREG32_SOC15(GC, 0, mmVM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32, - (u32)(adev->mc.gtt_start >> 12)); + (u32)(adev->mc.gart_start >> 12)); WREG32_SOC15(GC, 0, mmVM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32, - (u32)(adev->mc.gtt_start >> 44)); + (u32)(adev->mc.gart_start >> 44)); WREG32_SOC15(GC, 0, mmVM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32, - (u32)(adev->mc.gtt_end >> 12)); + (u32)(adev->mc.gart_end >> 12)); WREG32_SOC15(GC, 0, mmVM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32, - (u32)(adev->mc.gtt_end >> 44)); + (u32)(adev->mc.gart_end >> 44)); } static void gfxhub_v1_0_init_system_aperture_regs(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c index 810d5734ce1e..886df0902067 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c @@ -228,7 +228,7 @@ static void gmc_v6_0_vram_gtt_location(struct amdgpu_device *adev, mc->mc_vram_size = 0xFFC0000000ULL; } amdgpu_vram_location(adev, &adev->mc, base); - amdgpu_gtt_location(adev, mc); + amdgpu_gart_location(adev, mc); } static void gmc_v6_0_mc_program(struct amdgpu_device *adev) @@ -481,8 +481,8 @@ static int gmc_v6_0_gart_enable(struct amdgpu_device *adev) (4UL << VM_L2_CNTL3__BANK_SELECT__SHIFT) | (4UL << VM_L2_CNTL3__L2_CACHE_BIGK_FRAGMENT_SIZE__SHIFT)); /* setup context0 */ - WREG32(mmVM_CONTEXT0_PAGE_TABLE_START_ADDR, adev->mc.gtt_start >> 12); - WREG32(mmVM_CONTEXT0_PAGE_TABLE_END_ADDR, adev->mc.gtt_end >> 12); + WREG32(mmVM_CONTEXT0_PAGE_TABLE_START_ADDR, adev->mc.gart_start >> 12); + WREG32(mmVM_CONTEXT0_PAGE_TABLE_END_ADDR, adev->mc.gart_end >> 12); WREG32(mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR, adev->gart.table_addr >> 12); WREG32(mmVM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR, (u32)(adev->dummy_page.addr >> 12)); @@ -529,7 +529,7 @@ static int gmc_v6_0_gart_enable(struct amdgpu_device *adev) gmc_v6_0_gart_flush_gpu_tlb(adev, 0); dev_info(adev->dev, "PCIE GART of %uM enabled (table at 0x%016llX).\n", - (unsigned)(adev->mc.gtt_size >> 20), + (unsigned)(adev->mc.gart_size >> 20), (unsigned long long)adev->gart.table_addr); adev->gart.ready = true; return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c index 066f00ad4152..21a45b403b21 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c @@ -244,7 +244,7 @@ static void gmc_v7_0_vram_gtt_location(struct amdgpu_device *adev, mc->mc_vram_size = 0xFFC0000000ULL; } amdgpu_vram_location(adev, &adev->mc, base); - amdgpu_gtt_location(adev, mc); + amdgpu_gart_location(adev, mc); } /** @@ -584,8 +584,8 @@ static int gmc_v7_0_gart_enable(struct amdgpu_device *adev) tmp = REG_SET_FIELD(tmp, VM_L2_CNTL3, L2_CACHE_BIGK_FRAGMENT_SIZE, 4); WREG32(mmVM_L2_CNTL3, tmp); /* setup context0 */ - WREG32(mmVM_CONTEXT0_PAGE_TABLE_START_ADDR, adev->mc.gtt_start >> 12); - WREG32(mmVM_CONTEXT0_PAGE_TABLE_END_ADDR, adev->mc.gtt_end >> 12); + WREG32(mmVM_CONTEXT0_PAGE_TABLE_START_ADDR, adev->mc.gart_start >> 12); + WREG32(mmVM_CONTEXT0_PAGE_TABLE_END_ADDR, adev->mc.gart_end >> 12); WREG32(mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR, adev->gart.table_addr >> 12); WREG32(mmVM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR, (u32)(adev->dummy_page.addr >> 12)); @@ -639,7 +639,7 @@ static int gmc_v7_0_gart_enable(struct amdgpu_device *adev) gmc_v7_0_gart_flush_gpu_tlb(adev, 0); DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", - (unsigned)(adev->mc.gtt_size >> 20), + (unsigned)(adev->mc.gart_size >> 20), (unsigned long long)adev->gart.table_addr); adev->gart.ready = true; return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index f30c39c72bca..2b39606f1d3c 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -406,7 +406,7 @@ static void gmc_v8_0_vram_gtt_location(struct amdgpu_device *adev, mc->mc_vram_size = 0xFFC0000000ULL; } amdgpu_vram_location(adev, &adev->mc, base); - amdgpu_gtt_location(adev, mc); + amdgpu_gart_location(adev, mc); } /** @@ -786,8 +786,8 @@ static int gmc_v8_0_gart_enable(struct amdgpu_device *adev) tmp = REG_SET_FIELD(tmp, VM_L2_CNTL4, VMC_TAP_CONTEXT1_PTE_REQUEST_SNOOP, 0); WREG32(mmVM_L2_CNTL4, tmp); /* setup context0 */ - WREG32(mmVM_CONTEXT0_PAGE_TABLE_START_ADDR, adev->mc.gtt_start >> 12); - WREG32(mmVM_CONTEXT0_PAGE_TABLE_END_ADDR, adev->mc.gtt_end >> 12); + WREG32(mmVM_CONTEXT0_PAGE_TABLE_START_ADDR, adev->mc.gart_start >> 12); + WREG32(mmVM_CONTEXT0_PAGE_TABLE_END_ADDR, adev->mc.gart_end >> 12); WREG32(mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR, adev->gart.table_addr >> 12); WREG32(mmVM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR, (u32)(adev->dummy_page.addr >> 12)); @@ -842,7 +842,7 @@ static int gmc_v8_0_gart_enable(struct amdgpu_device *adev) gmc_v8_0_gart_flush_gpu_tlb(adev, 0); DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", - (unsigned)(adev->mc.gtt_size >> 20), + (unsigned)(adev->mc.gart_size >> 20), (unsigned long long)adev->gart.table_addr); adev->gart.ready = true; return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index dd2756ec11b8..677181fdfa00 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -420,7 +420,7 @@ static void gmc_v9_0_vram_gtt_location(struct amdgpu_device *adev, if (!amdgpu_sriov_vf(adev)) base = mmhub_v1_0_get_fb_location(adev); amdgpu_vram_location(adev, &adev->mc, base); - amdgpu_gtt_location(adev, mc); + amdgpu_gart_location(adev, mc); /* base offset of vram pages */ if (adev->flags & AMD_IS_APU) adev->vm_manager.vram_base_offset = gfxhub_v1_0_get_mc_fb_offset(adev); @@ -736,7 +736,7 @@ static int gmc_v9_0_gart_enable(struct amdgpu_device *adev) gmc_v9_0_gart_flush_gpu_tlb(adev, 0); DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", - (unsigned)(adev->mc.gtt_size >> 20), + (unsigned)(adev->mc.gart_size >> 20), (unsigned long long)adev->gart.table_addr); adev->gart.ready = true; return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c index 9f2cf78907a3..0780e830b76b 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c @@ -69,14 +69,14 @@ static void mmhub_v1_0_init_gart_aperture_regs(struct amdgpu_device *adev) mmhub_v1_0_init_gart_pt_regs(adev); WREG32_SOC15(MMHUB, 0, mmVM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32, - (u32)(adev->mc.gtt_start >> 12)); + (u32)(adev->mc.gart_start >> 12)); WREG32_SOC15(MMHUB, 0, mmVM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32, - (u32)(adev->mc.gtt_start >> 44)); + (u32)(adev->mc.gart_start >> 44)); WREG32_SOC15(MMHUB, 0, mmVM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32, - (u32)(adev->mc.gtt_end >> 12)); + (u32)(adev->mc.gart_end >> 12)); WREG32_SOC15(MMHUB, 0, mmVM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32, - (u32)(adev->mc.gtt_end >> 44)); + (u32)(adev->mc.gart_end >> 44)); } static void mmhub_v1_0_init_system_aperture_regs(struct amdgpu_device *adev) -- cgit v1.2.3 From bb84284e10ec3447b4bb74cfa493d5c384a0b798 Mon Sep 17 00:00:00 2001 From: Christian König Date: Fri, 7 Jul 2017 13:16:37 +0200 Subject: drm/amdgpu: limit the GTT manager address space MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We should only cover the GART size with the GTT manager. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c index f46a97d91675..5e6b90c6794f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c @@ -42,6 +42,7 @@ struct amdgpu_gtt_mgr { static int amdgpu_gtt_mgr_init(struct ttm_mem_type_manager *man, unsigned long p_size) { + struct amdgpu_device *adev = amdgpu_ttm_adev(man->bdev); struct amdgpu_gtt_mgr *mgr; uint64_t start, size; @@ -50,7 +51,7 @@ static int amdgpu_gtt_mgr_init(struct ttm_mem_type_manager *man, return -ENOMEM; start = AMDGPU_GTT_MAX_TRANSFER_SIZE * AMDGPU_GTT_NUM_TRANSFER_WINDOWS; - size = p_size - start; + size = (adev->mc.gart_size >> PAGE_SHIFT) - start; drm_mm_init(&mgr->mm, start, size); spin_lock_init(&mgr->lock); mgr->available = p_size; @@ -112,6 +113,7 @@ int amdgpu_gtt_mgr_alloc(struct ttm_mem_type_manager *man, const struct ttm_place *place, struct ttm_mem_reg *mem) { + struct amdgpu_device *adev = amdgpu_ttm_adev(man->bdev); struct amdgpu_gtt_mgr *mgr = man->priv; struct drm_mm_node *node = mem->mm_node; enum drm_mm_insert_mode mode; @@ -129,7 +131,7 @@ int amdgpu_gtt_mgr_alloc(struct ttm_mem_type_manager *man, if (place && place->lpfn) lpfn = place->lpfn; else - lpfn = man->size; + lpfn = adev->gart.num_cpu_pages; mode = DRM_MM_INSERT_BEST; if (place && place->flags & TTM_PL_FLAG_TOPDOWN) -- cgit v1.2.3 From 36d3837266c53a92a909f22f6bbf0846c0e6464f Mon Sep 17 00:00:00 2001 From: Christian König Date: Fri, 7 Jul 2017 13:17:45 +0200 Subject: drm/amdgpu: add new gttsize module parameter v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows setting the gtt size independent of the gart size. v2: fix copy and paste typo Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 7 +++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 ++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 12 +++++++++--- 4 files changed, 21 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index b19557b8c683..c7436ea425b4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -76,6 +76,7 @@ extern int amdgpu_modeset; extern int amdgpu_vram_limit; extern int amdgpu_gart_size; +extern int amdgpu_gtt_size; extern int amdgpu_moverate; extern int amdgpu_benchmarking; extern int amdgpu_testing; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 84ff824ea260..49dd8e0ddd17 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1141,6 +1141,13 @@ static void amdgpu_check_arguments(struct amdgpu_device *adev) } } + if (amdgpu_gtt_size != -1 && amdgpu_gtt_size < 32) { + /* gtt size must be greater or equal to 32M */ + dev_warn(adev->dev, "gtt size (%d) too small\n", + amdgpu_gtt_size); + amdgpu_gtt_size = -1; + } + amdgpu_check_vm_size(adev); amdgpu_check_block_size(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index d90dc426ee5b..b83e87fef6a8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -75,6 +75,7 @@ int amdgpu_vram_limit = 0; int amdgpu_gart_size = -1; /* auto */ +int amdgpu_gtt_size = -1; /* auto */ int amdgpu_moverate = -1; /* auto */ int amdgpu_benchmarking = 0; int amdgpu_testing = 0; @@ -123,6 +124,9 @@ module_param_named(vramlimit, amdgpu_vram_limit, int, 0600); MODULE_PARM_DESC(gartsize, "Size of PCIE/IGP gart to setup in megabytes (32, 64, etc., -1 = auto)"); module_param_named(gartsize, amdgpu_gart_size, int, 0600); +MODULE_PARM_DESC(gttsize, "Size of the GTT domain in megabytes (-1 = auto)"); +module_param_named(gttsize, amdgpu_gtt_size, int, 0600); + MODULE_PARM_DESC(moverate, "Maximum buffer migration rate in MB/s. (32, 64, etc., -1=auto, 0=1=disabled)"); module_param_named(moverate, amdgpu_moverate, int, 0600); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 4e711d9af67c..b5420b20c2f5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1097,6 +1097,7 @@ static struct ttm_bo_driver amdgpu_bo_driver = { int amdgpu_ttm_init(struct amdgpu_device *adev) { + uint64_t gtt_size; int r; r = amdgpu_ttm_global_init(adev); @@ -1143,14 +1144,19 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) } DRM_INFO("amdgpu: %uM of VRAM memory ready\n", (unsigned) (adev->mc.real_vram_size / (1024 * 1024))); - r = ttm_bo_init_mm(&adev->mman.bdev, TTM_PL_TT, - adev->mc.gart_size >> PAGE_SHIFT); + + if (amdgpu_gtt_size == -1) + gtt_size = max((AMDGPU_DEFAULT_GTT_SIZE_MB << 20), + adev->mc.mc_vram_size); + else + gtt_size = (uint64_t)amdgpu_gtt_size << 20; + r = ttm_bo_init_mm(&adev->mman.bdev, TTM_PL_TT, gtt_size >> PAGE_SHIFT); if (r) { DRM_ERROR("Failed initializing GTT heap.\n"); return r; } DRM_INFO("amdgpu: %uM of GTT memory ready.\n", - (unsigned)(adev->mc.gart_size / (1024 * 1024))); + (unsigned)(gtt_size / (1024 * 1024))); adev->gds.mem.total_size = adev->gds.mem.total_size << AMDGPU_GDS_SHIFT; adev->gds.mem.gfx_partition_size = adev->gds.mem.gfx_partition_size << AMDGPU_GDS_SHIFT; -- cgit v1.2.3 From f9321cc4408bd90bb0adcd929c04322aaf6afdcc Mon Sep 17 00:00:00 2001 From: Christian König Date: Fri, 7 Jul 2017 13:44:05 +0200 Subject: drm/amdgpu: change gartsize default to 256MB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Limit the default GART size and save a lot of VRAM. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 12 +++++------- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c | 9 +-------- 4 files changed, 10 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index c7436ea425b4..019a4b73e5f5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -75,7 +75,7 @@ */ extern int amdgpu_modeset; extern int amdgpu_vram_limit; -extern int amdgpu_gart_size; +extern unsigned amdgpu_gart_size; extern int amdgpu_gtt_size; extern int amdgpu_moverate; extern int amdgpu_benchmarking; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 49dd8e0ddd17..0e629931210c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1132,13 +1132,11 @@ static void amdgpu_check_arguments(struct amdgpu_device *adev) amdgpu_sched_jobs = roundup_pow_of_two(amdgpu_sched_jobs); } - if (amdgpu_gart_size != -1) { - /* gtt size must be greater or equal to 32M */ - if (amdgpu_gart_size < 32) { - dev_warn(adev->dev, "gart size (%d) too small\n", - amdgpu_gart_size); - amdgpu_gart_size = -1; - } + if (amdgpu_gart_size < 32) { + /* gart size must be greater or equal to 32M */ + dev_warn(adev->dev, "gart size (%d) too small\n", + amdgpu_gart_size); + amdgpu_gart_size = 32; } if (amdgpu_gtt_size != -1 && amdgpu_gtt_size < 32) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index b83e87fef6a8..ed760f477542 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -74,7 +74,7 @@ #define KMS_DRIVER_PATCHLEVEL 0 int amdgpu_vram_limit = 0; -int amdgpu_gart_size = -1; /* auto */ +unsigned amdgpu_gart_size = 256; int amdgpu_gtt_size = -1; /* auto */ int amdgpu_moverate = -1; /* auto */ int amdgpu_benchmarking = 0; @@ -121,8 +121,8 @@ int amdgpu_lbpw = -1; MODULE_PARM_DESC(vramlimit, "Restrict VRAM for testing, in megabytes"); module_param_named(vramlimit, amdgpu_vram_limit, int, 0600); -MODULE_PARM_DESC(gartsize, "Size of PCIE/IGP gart to setup in megabytes (32, 64, etc., -1 = auto)"); -module_param_named(gartsize, amdgpu_gart_size, int, 0600); +MODULE_PARM_DESC(gartsize, "Size of PCIE/IGP gart to setup in megabytes (32, 64, etc.)"); +module_param_named(gartsize, amdgpu_gart_size, uint, 0600); MODULE_PARM_DESC(gttsize, "Size of the GTT domain in megabytes (-1 = auto)"); module_param_named(gttsize, amdgpu_gtt_size, int, 0600); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c index d578ca6f2dfd..5cc4987cd887 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c @@ -65,14 +65,7 @@ */ void amdgpu_gart_set_defaults(struct amdgpu_device *adev) { - /* unless the user had overridden it, set the gart - * size equal to the 1024 or vram, whichever is larger. - */ - if (amdgpu_gart_size == -1) - adev->mc.gart_size = max((AMDGPU_DEFAULT_GTT_SIZE_MB << 20), - adev->mc.mc_vram_size); - else - adev->mc.gart_size = (uint64_t)amdgpu_gart_size << 20; + adev->mc.gart_size = (uint64_t)amdgpu_gart_size << 20; } /** -- cgit v1.2.3 From 218b5dcde4d30e071eec4201a36af665ccfa7e1c Mon Sep 17 00:00:00 2001 From: John Brooks Date: Tue, 27 Jun 2017 22:33:17 -0400 Subject: drm/amdgpu: Add vis_vramlimit module parameter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow specifying a limit on visible VRAM via a module parameter. This is helpful for testing performance under visible VRAM pressure. v2: Add cast to 64-bit (Christian König) Signed-off-by: John Brooks Reviewed-by: Michel Dänzer Reviewed-by: Christian König Signed-off-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 ++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 8 ++++++++ 3 files changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 019a4b73e5f5..0d6b0617cdf0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -75,6 +75,7 @@ */ extern int amdgpu_modeset; extern int amdgpu_vram_limit; +extern int amdgpu_vis_vram_limit; extern unsigned amdgpu_gart_size; extern int amdgpu_gtt_size; extern int amdgpu_moverate; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index ed760f477542..3c83fe6c5db8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -74,6 +74,7 @@ #define KMS_DRIVER_PATCHLEVEL 0 int amdgpu_vram_limit = 0; +int amdgpu_vis_vram_limit = 0; unsigned amdgpu_gart_size = 256; int amdgpu_gtt_size = -1; /* auto */ int amdgpu_moverate = -1; /* auto */ @@ -121,6 +122,9 @@ int amdgpu_lbpw = -1; MODULE_PARM_DESC(vramlimit, "Restrict VRAM for testing, in megabytes"); module_param_named(vramlimit, amdgpu_vram_limit, int, 0600); +MODULE_PARM_DESC(vis_vramlimit, "Restrict visible VRAM for testing, in megabytes"); +module_param_named(vis_vramlimit, amdgpu_vis_vram_limit, int, 0444); + MODULE_PARM_DESC(gartsize, "Size of PCIE/IGP gart to setup in megabytes (32, 64, etc.)"); module_param_named(gartsize, amdgpu_gart_size, uint, 0600); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index b5420b20c2f5..e238084b7142 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1099,6 +1099,7 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) { uint64_t gtt_size; int r; + u64 vis_vram_limit; r = amdgpu_ttm_global_init(adev); if (r) { @@ -1122,6 +1123,13 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) DRM_ERROR("Failed initializing VRAM heap.\n"); return r; } + + /* Reduce size of CPU-visible VRAM if requested */ + vis_vram_limit = (u64)amdgpu_vis_vram_limit * 1024 * 1024; + if (amdgpu_vis_vram_limit > 0 && + vis_vram_limit <= adev->mc.visible_vram_size) + adev->mc.visible_vram_size = vis_vram_limit; + /* Change the size here instead of the init above so only lpfn is affected */ amdgpu_ttm_set_active_vram_size(adev, adev->mc.visible_vram_size); -- cgit v1.2.3 From 00f06b246a3056bbaa901a90a5a93c9f81ab8e36 Mon Sep 17 00:00:00 2001 From: John Brooks Date: Tue, 27 Jun 2017 22:33:18 -0400 Subject: drm/amdgpu: Throttle visible VRAM moves separately MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The BO move throttling code is designed to allow VRAM to fill quickly if it is relatively empty. However, this does not take into account situations where the visible VRAM is smaller than total VRAM, and total VRAM may not be close to full but the visible VRAM segment is under pressure. In such situations, visible VRAM would experience unrestricted swapping and performance would drop. Add a separate counter specifically for moves involving visible VRAM, and check it before moving BOs there. v2: Only perform calculations for separate counter if visible VRAM is smaller than total VRAM. (Michel Dänzer) v3: [Michel Dänzer] * Use BO's location rather than the AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED flag to determine whether to account a move for visible VRAM in most cases. * Use a single if (adev->mc.visible_vram_size < adev->mc.real_vram_size) { block in amdgpu_cs_get_threshold_for_moves. Fixes: 95844d20ae02 (drm/amdgpu: throttle buffer migrations at CS using a fixed MBps limit (v2)) Signed-off-by: John Brooks Reviewed-by: Christian König Signed-off-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 92 ++++++++++++++++++++++++------ drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 12 +++- 3 files changed, 87 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 0d6b0617cdf0..c290b262d7da 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1117,7 +1117,9 @@ struct amdgpu_cs_parser { struct list_head validated; struct dma_fence *fence; uint64_t bytes_moved_threshold; + uint64_t bytes_moved_vis_threshold; uint64_t bytes_moved; + uint64_t bytes_moved_vis; struct amdgpu_bo_list_entry *evictable; /* user fence */ @@ -1555,6 +1557,7 @@ struct amdgpu_device { spinlock_t lock; s64 last_update_us; s64 accum_us; /* accumulated microseconds */ + s64 accum_us_vis; /* for visible VRAM */ u32 log2_max_MBps; } mm_stats; @@ -1846,7 +1849,8 @@ void amdgpu_pci_config_reset(struct amdgpu_device *adev); bool amdgpu_need_post(struct amdgpu_device *adev); void amdgpu_update_display_priority(struct amdgpu_device *adev); -void amdgpu_cs_report_moved_bytes(struct amdgpu_device *adev, u64 num_bytes); +void amdgpu_cs_report_moved_bytes(struct amdgpu_device *adev, u64 num_bytes, + u64 num_vis_bytes); void amdgpu_ttm_placement_from_domain(struct amdgpu_bo *abo, u32 domain); bool amdgpu_ttm_bo_is_amdgpu_bo(struct ttm_buffer_object *bo); int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 5599c01b265d..33789510e663 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -223,10 +223,11 @@ static s64 bytes_to_us(struct amdgpu_device *adev, u64 bytes) * ticks. The accumulated microseconds (us) are converted to bytes and * returned. */ -static u64 amdgpu_cs_get_threshold_for_moves(struct amdgpu_device *adev) +static void amdgpu_cs_get_threshold_for_moves(struct amdgpu_device *adev, + u64 *max_bytes, + u64 *max_vis_bytes) { s64 time_us, increment_us; - u64 max_bytes; u64 free_vram, total_vram, used_vram; /* Allow a maximum of 200 accumulated ms. This is basically per-IB @@ -238,8 +239,11 @@ static u64 amdgpu_cs_get_threshold_for_moves(struct amdgpu_device *adev) */ const s64 us_upper_bound = 200000; - if (!adev->mm_stats.log2_max_MBps) - return 0; + if (!adev->mm_stats.log2_max_MBps) { + *max_bytes = 0; + *max_vis_bytes = 0; + return; + } total_vram = adev->mc.real_vram_size - adev->vram_pin_size; used_vram = atomic64_read(&adev->vram_usage); @@ -280,23 +284,45 @@ static u64 amdgpu_cs_get_threshold_for_moves(struct amdgpu_device *adev) adev->mm_stats.accum_us = max(min_us, adev->mm_stats.accum_us); } - /* This returns 0 if the driver is in debt to disallow (optional) + /* This is set to 0 if the driver is in debt to disallow (optional) * buffer moves. */ - max_bytes = us_to_bytes(adev, adev->mm_stats.accum_us); + *max_bytes = us_to_bytes(adev, adev->mm_stats.accum_us); + + /* Do the same for visible VRAM if half of it is free */ + if (adev->mc.visible_vram_size < adev->mc.real_vram_size) { + u64 total_vis_vram = adev->mc.visible_vram_size; + u64 used_vis_vram = atomic64_read(&adev->vram_vis_usage); + + if (used_vis_vram < total_vis_vram) { + u64 free_vis_vram = total_vis_vram - used_vis_vram; + adev->mm_stats.accum_us_vis = min(adev->mm_stats.accum_us_vis + + increment_us, us_upper_bound); + + if (free_vis_vram >= total_vis_vram / 2) + adev->mm_stats.accum_us_vis = + max(bytes_to_us(adev, free_vis_vram / 2), + adev->mm_stats.accum_us_vis); + } + + *max_vis_bytes = us_to_bytes(adev, adev->mm_stats.accum_us_vis); + } else { + *max_vis_bytes = 0; + } spin_unlock(&adev->mm_stats.lock); - return max_bytes; } /* Report how many bytes have really been moved for the last command * submission. This can result in a debt that can stop buffer migrations * temporarily. */ -void amdgpu_cs_report_moved_bytes(struct amdgpu_device *adev, u64 num_bytes) +void amdgpu_cs_report_moved_bytes(struct amdgpu_device *adev, u64 num_bytes, + u64 num_vis_bytes) { spin_lock(&adev->mm_stats.lock); adev->mm_stats.accum_us -= bytes_to_us(adev, num_bytes); + adev->mm_stats.accum_us_vis -= bytes_to_us(adev, num_vis_bytes); spin_unlock(&adev->mm_stats.lock); } @@ -304,7 +330,7 @@ static int amdgpu_cs_bo_validate(struct amdgpu_cs_parser *p, struct amdgpu_bo *bo) { struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); - u64 initial_bytes_moved; + u64 initial_bytes_moved, bytes_moved; uint32_t domain; int r; @@ -314,17 +340,35 @@ static int amdgpu_cs_bo_validate(struct amdgpu_cs_parser *p, /* Don't move this buffer if we have depleted our allowance * to move it. Don't move anything if the threshold is zero. */ - if (p->bytes_moved < p->bytes_moved_threshold) - domain = bo->prefered_domains; - else + if (p->bytes_moved < p->bytes_moved_threshold) { + if (adev->mc.visible_vram_size < adev->mc.real_vram_size && + (bo->flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED)) { + /* And don't move a CPU_ACCESS_REQUIRED BO to limited + * visible VRAM if we've depleted our allowance to do + * that. + */ + if (p->bytes_moved_vis < p->bytes_moved_vis_threshold) + domain = bo->prefered_domains; + else + domain = bo->allowed_domains; + } else { + domain = bo->prefered_domains; + } + } else { domain = bo->allowed_domains; + } retry: amdgpu_ttm_placement_from_domain(bo, domain); initial_bytes_moved = atomic64_read(&adev->num_bytes_moved); r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false); - p->bytes_moved += atomic64_read(&adev->num_bytes_moved) - - initial_bytes_moved; + bytes_moved = atomic64_read(&adev->num_bytes_moved) - + initial_bytes_moved; + p->bytes_moved += bytes_moved; + if (adev->mc.visible_vram_size < adev->mc.real_vram_size && + bo->tbo.mem.mem_type == TTM_PL_VRAM && + bo->tbo.mem.start < adev->mc.visible_vram_size >> PAGE_SHIFT) + p->bytes_moved_vis += bytes_moved; if (unlikely(r == -ENOMEM) && domain != bo->allowed_domains) { domain = bo->allowed_domains; @@ -350,7 +394,8 @@ static bool amdgpu_cs_try_evict(struct amdgpu_cs_parser *p, struct amdgpu_bo_list_entry *candidate = p->evictable; struct amdgpu_bo *bo = candidate->robj; struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); - u64 initial_bytes_moved; + u64 initial_bytes_moved, bytes_moved; + bool update_bytes_moved_vis; uint32_t other; /* If we reached our current BO we can forget it */ @@ -370,10 +415,17 @@ static bool amdgpu_cs_try_evict(struct amdgpu_cs_parser *p, /* Good we can try to move this BO somewhere else */ amdgpu_ttm_placement_from_domain(bo, other); + update_bytes_moved_vis = + adev->mc.visible_vram_size < adev->mc.real_vram_size && + bo->tbo.mem.mem_type == TTM_PL_VRAM && + bo->tbo.mem.start < adev->mc.visible_vram_size >> PAGE_SHIFT; initial_bytes_moved = atomic64_read(&adev->num_bytes_moved); r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false); - p->bytes_moved += atomic64_read(&adev->num_bytes_moved) - + bytes_moved = atomic64_read(&adev->num_bytes_moved) - initial_bytes_moved; + p->bytes_moved += bytes_moved; + if (update_bytes_moved_vis) + p->bytes_moved_vis += bytes_moved; if (unlikely(r)) break; @@ -554,8 +606,10 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, list_splice(&need_pages, &p->validated); } - p->bytes_moved_threshold = amdgpu_cs_get_threshold_for_moves(p->adev); + amdgpu_cs_get_threshold_for_moves(p->adev, &p->bytes_moved_threshold, + &p->bytes_moved_vis_threshold); p->bytes_moved = 0; + p->bytes_moved_vis = 0; p->evictable = list_last_entry(&p->validated, struct amdgpu_bo_list_entry, tv.head); @@ -579,8 +633,8 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, goto error_validate; } - amdgpu_cs_report_moved_bytes(p->adev, p->bytes_moved); - + amdgpu_cs_report_moved_bytes(p->adev, p->bytes_moved, + p->bytes_moved_vis); fpriv->vm.last_eviction_counter = atomic64_read(&p->adev->num_evictions); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index a85e75327456..e429829ae93d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -322,7 +322,7 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev, struct amdgpu_bo *bo; enum ttm_bo_type type; unsigned long page_align; - u64 initial_bytes_moved; + u64 initial_bytes_moved, bytes_moved; size_t acc_size; int r; @@ -398,8 +398,14 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev, r = ttm_bo_init_reserved(&adev->mman.bdev, &bo->tbo, size, type, &bo->placement, page_align, !kernel, NULL, acc_size, sg, resv, &amdgpu_ttm_bo_destroy); - amdgpu_cs_report_moved_bytes(adev, - atomic64_read(&adev->num_bytes_moved) - initial_bytes_moved); + bytes_moved = atomic64_read(&adev->num_bytes_moved) - + initial_bytes_moved; + if (adev->mc.visible_vram_size < adev->mc.real_vram_size && + bo->tbo.mem.mem_type == TTM_PL_VRAM && + bo->tbo.mem.start < adev->mc.visible_vram_size >> PAGE_SHIFT) + amdgpu_cs_report_moved_bytes(adev, bytes_moved, bytes_moved); + else + amdgpu_cs_report_moved_bytes(adev, bytes_moved, 0); if (unlikely(r != 0)) return r; -- cgit v1.2.3 From 96cf8271df546d0f4cfc9ddddbc42dce633e0190 Mon Sep 17 00:00:00 2001 From: John Brooks Date: Fri, 30 Jun 2017 11:31:08 -0400 Subject: drm/amdgpu: Set/clear CPU_ACCESS flag on page fault and move to VRAM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a BO is moved to VRAM, clear AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED. This allows it to potentially later move to invisible VRAM if the CPU does not access it again. Setting the CPU_ACCESS flag in amdgpu_bo_fault_reserve_notify() also means that we can remove the loop to restrict lpfn to the end of visible VRAM, because amdgpu_ttm_placement_init() will do it for us. v3 [Michel Dänzer] * Use AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED instead of a new flag (Christian König) * Clear flag in amdgpu_bo_move instead of amdgpu_move_ram_vram (Christian) * Explicitly mention amdgpu_bo_fault_reserve_notify in amdgpu_bo_move * Also clear flag in amdgpu_bo_create_restricted Suggested-by: Michel Dänzer Signed-off-by: John Brooks Reviewed-by: Christian König Signed-off-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 20 ++++++++++---------- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 9 +++++++++ 2 files changed, 19 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index e429829ae93d..93601fbea695 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -432,6 +432,10 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev, trace_amdgpu_bo_create(bo); + /* Treat CPU_ACCESS_REQUIRED only as a hint if given by UMD */ + if (type == ttm_bo_type_device) + bo->flags &= ~AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED; + return 0; fail_unreserve: @@ -945,13 +949,17 @@ int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) { struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); struct amdgpu_bo *abo; - unsigned long offset, size, lpfn; - int i, r; + unsigned long offset, size; + int r; if (!amdgpu_ttm_bo_is_amdgpu_bo(bo)) return 0; abo = container_of(bo, struct amdgpu_bo, tbo); + + /* Remember that this BO was accessed by the CPU */ + abo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED; + if (bo->mem.mem_type != TTM_PL_VRAM) return 0; @@ -967,14 +975,6 @@ int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) /* hurrah the memory is not visible ! */ atomic64_inc(&adev->num_vram_cpu_page_faults); amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_VRAM); - lpfn = adev->mc.visible_vram_size >> PAGE_SHIFT; - for (i = 0; i < abo->placement.num_placement; i++) { - /* Force into visible VRAM */ - if ((abo->placements[i].flags & TTM_PL_FLAG_VRAM) && - (!abo->placements[i].lpfn || - abo->placements[i].lpfn > lpfn)) - abo->placements[i].lpfn = lpfn; - } r = ttm_bo_validate(bo, &abo->placement, false, false); if (unlikely(r == -ENOMEM)) { amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_GTT); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index e238084b7142..9bbaffbd5f6a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -499,6 +499,15 @@ memcpy: } } + if (bo->type == ttm_bo_type_device && + new_mem->mem_type == TTM_PL_VRAM && + old_mem->mem_type != TTM_PL_VRAM) { + /* amdgpu_bo_fault_reserve_notify will re-set this if the CPU + * accesses the BO after it's moved. + */ + abo->flags &= ~AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED; + } + /* update statistics */ atomic64_add((u64)bo->num_pages << PAGE_SHIFT, &adev->num_bytes_moved); return 0; -- cgit v1.2.3 From 41d9a6a728ea34d697dc74bc5fea1b6f6c5fce80 Mon Sep 17 00:00:00 2001 From: John Brooks Date: Tue, 27 Jun 2017 22:33:21 -0400 Subject: drm/amdgpu: Don't force BOs into visible VRAM for page faults MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no need for page faults to force BOs into visible VRAM if it's full, and the time it takes to do so is great enough to cause noticeable stuttering. Add GTT as a possible placement so that if visible VRAM is full, page faults move BOs to GTT instead of evicting other BOs from VRAM. Suggested-by: Michel Dänzer Signed-off-by: John Brooks Reviewed-by: Michel Dänzer Reviewed-by: Christian König Signed-off-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 93601fbea695..6e24339ecc46 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -974,18 +974,21 @@ int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) /* hurrah the memory is not visible ! */ atomic64_inc(&adev->num_vram_cpu_page_faults); - amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_VRAM); + amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_VRAM | + AMDGPU_GEM_DOMAIN_GTT); + + /* Avoid costly evictions; only set GTT as a busy placement */ + abo->placement.num_busy_placement = 1; + abo->placement.busy_placement = &abo->placements[1]; + r = ttm_bo_validate(bo, &abo->placement, false, false); - if (unlikely(r == -ENOMEM)) { - amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_GTT); - return ttm_bo_validate(bo, &abo->placement, false, false); - } else if (unlikely(r != 0)) { + if (unlikely(r != 0)) return r; - } offset = bo->mem.start << PAGE_SHIFT; /* this should never happen */ - if ((offset + size) > adev->mc.visible_vram_size) + if (bo->mem.mem_type == TTM_PL_VRAM && + (offset + size) > adev->mc.visible_vram_size) return -EINVAL; return 0; -- cgit v1.2.3 From cb2dd1a6b641b015b30e4272198e6035d7777adb Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Tue, 4 Jul 2017 17:16:42 +0900 Subject: drm/amdgpu: Try evicting from CPU visible to invisible VRAM first MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This gives BOs which haven't been accessed by the CPU since they were moved to visible VRAM another chance to stay in VRAM when another BO needs to go to visible VRAM. This should allow BOs to stay in VRAM longer in some cases. v2: * Only do this for BOs which don't have the AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED flag set. Reviewed-by: Christian König Signed-off-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 9bbaffbd5f6a..da8b0e15a30c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -214,7 +214,35 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, adev->mman.buffer_funcs_ring && adev->mman.buffer_funcs_ring->ready == false) { amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_CPU); + } else if (adev->mc.visible_vram_size < adev->mc.real_vram_size && + !(abo->flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED)) { + unsigned fpfn = adev->mc.visible_vram_size >> PAGE_SHIFT; + struct drm_mm_node *node = bo->mem.mm_node; + unsigned long pages_left; + + for (pages_left = bo->mem.num_pages; + pages_left; + pages_left -= node->size, node++) { + if (node->start < fpfn) + break; + } + + if (!pages_left) + goto gtt; + + /* Try evicting to the CPU inaccessible part of VRAM + * first, but only set GTT as busy placement, so this + * BO will be evicted to GTT rather than causing other + * BOs to be evicted from VRAM + */ + amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_VRAM | + AMDGPU_GEM_DOMAIN_GTT); + abo->placements[0].fpfn = fpfn; + abo->placements[0].lpfn = 0; + abo->placement.busy_placement = &abo->placements[1]; + abo->placement.num_busy_placement = 1; } else { +gtt: amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_GTT); } break; -- cgit v1.2.3 From 4048f0f0d63ed372a8d2333f6eec4dd0ca183c6c Mon Sep 17 00:00:00 2001 From: shaoyunl Date: Fri, 4 Dec 2015 15:01:22 -0500 Subject: drm/amdgpu: Enable SDMA_CNTL.ATC_L1_ENABLE for SDMA on CZ For GFX context, the ATC bit in SDMA*_GFX_VIRTUAL_ADDRESS can be cleared to perform in VM mode. For RLC context, to support ATC mode , ATC bit in SDMA*_RLC*_VIRTUAL_ADDRESS should be set. SDMA_CNTL.ATC_L1_ENABLE bit is global setting that enables the L1-L2 translation for ATC address. Signed-off-by: shaoyun liu Reviewed-by: Felix Kuehling Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c index 1d766ae98dc8..67a29fb3d3b3 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c @@ -556,12 +556,18 @@ static void sdma_v3_0_ctx_switch_enable(struct amdgpu_device *adev, bool enable) for (i = 0; i < adev->sdma.num_instances; i++) { f32_cntl = RREG32(mmSDMA0_CNTL + sdma_offsets[i]); - if (enable) + if (enable) { f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_CNTL, AUTO_CTXSW_ENABLE, 1); - else + f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_CNTL, + ATC_L1_ENABLE, 1); + } else { f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_CNTL, AUTO_CTXSW_ENABLE, 0); + f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_CNTL, + ATC_L1_ENABLE, 1); + } + WREG32(mmSDMA0_CNTL + sdma_offsets[i], f32_cntl); } } -- cgit v1.2.3 From 763dbbfa5f678ceec59b81bc13bc9dc445920e9b Mon Sep 17 00:00:00 2001 From: Felix Kuehling Date: Wed, 15 Jun 2016 16:33:15 -0400 Subject: drm/amdgpu: Enable SDMA context switching for CIK Enable SDMA context switching on CIK (copied from sdma_v3_0.c). Signed-off-by: Felix Kuehling Reviewed-by: Chunming Zhou Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/cik_sdma.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c index c216e16826c9..4a9cea03f54f 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c +++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c @@ -341,6 +341,33 @@ static void cik_sdma_rlc_stop(struct amdgpu_device *adev) /* XXX todo */ } +/** + * cik_ctx_switch_enable - stop the async dma engines context switch + * + * @adev: amdgpu_device pointer + * @enable: enable/disable the DMA MEs context switch. + * + * Halt or unhalt the async dma engines context switch (VI). + */ +static void cik_ctx_switch_enable(struct amdgpu_device *adev, bool enable) +{ + u32 f32_cntl; + int i; + + for (i = 0; i < adev->sdma.num_instances; i++) { + f32_cntl = RREG32(mmSDMA0_CNTL + sdma_offsets[i]); + if (enable) { + f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_CNTL, + AUTO_CTXSW_ENABLE, 1); + } else { + f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_CNTL, + AUTO_CTXSW_ENABLE, 0); + } + + WREG32(mmSDMA0_CNTL + sdma_offsets[i], f32_cntl); + } +} + /** * cik_sdma_enable - stop the async dma engines * @@ -537,6 +564,8 @@ static int cik_sdma_start(struct amdgpu_device *adev) /* halt the engine before programing */ cik_sdma_enable(adev, false); + /* enable sdma ring preemption */ + cik_ctx_switch_enable(adev, true); /* start the gfx rings and rlc compute queues */ r = cik_sdma_gfx_resume(adev); @@ -984,6 +1013,7 @@ static int cik_sdma_hw_fini(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + cik_ctx_switch_enable(adev, false); cik_sdma_enable(adev, false); return 0; -- cgit v1.2.3 From a667386cb997a136e169de3cf70f007223bb74ee Mon Sep 17 00:00:00 2001 From: Felix Kuehling Date: Fri, 15 Jul 2016 18:37:05 -0400 Subject: drm/amdgpu: Make SDMA phase quantum configurable Set a configurable SDMA phase quantum when enabling SDMA context switching. The default value significantly reduces SDMA latency in page table updates when user-mode SDMA queues have concurrent activity, compared to the initial HW setting. Signed-off-by: Felix Kuehling Reviewed-by: Andres Rodriguez Reviewed-by: Shaoyun Liu Acked-by: Chunming Zhou Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 ++++ drivers/gpu/drm/amd/amdgpu/cik_sdma.c | 32 ++++++++++++++++++++++++++++++- drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c | 32 ++++++++++++++++++++++++++++++- drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 34 ++++++++++++++++++++++++++++++++- 5 files changed, 100 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index c290b262d7da..ebd077fdce1b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -107,6 +107,7 @@ extern unsigned amdgpu_pcie_gen_cap; extern unsigned amdgpu_pcie_lane_cap; extern unsigned amdgpu_cg_mask; extern unsigned amdgpu_pg_mask; +extern unsigned amdgpu_sdma_phase_quantum; extern char *amdgpu_disable_cu; extern char *amdgpu_virtual_display; extern unsigned amdgpu_pp_feature_mask; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 3c83fe6c5db8..b3d7beb6806c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -108,6 +108,7 @@ unsigned amdgpu_pcie_gen_cap = 0; unsigned amdgpu_pcie_lane_cap = 0; unsigned amdgpu_cg_mask = 0xffffffff; unsigned amdgpu_pg_mask = 0xffffffff; +unsigned amdgpu_sdma_phase_quantum = 32; char *amdgpu_disable_cu = NULL; char *amdgpu_virtual_display = NULL; unsigned amdgpu_pp_feature_mask = 0xffffffff; @@ -227,6 +228,9 @@ module_param_named(cg_mask, amdgpu_cg_mask, uint, 0444); MODULE_PARM_DESC(pg_mask, "Powergating flags mask (0 = disable power gating)"); module_param_named(pg_mask, amdgpu_pg_mask, uint, 0444); +MODULE_PARM_DESC(sdma_phase_quantum, "SDMA context switch phase quantum (x 1K GPU clock cycles, 0 = no change (default 32))"); +module_param_named(sdma_phase_quantum, amdgpu_sdma_phase_quantum, uint, 0444); + MODULE_PARM_DESC(disable_cu, "Disable CUs (se.sh.cu,...)"); module_param_named(disable_cu, amdgpu_disable_cu, charp, 0444); diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c index 4a9cea03f54f..f508f4d01e4a 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c +++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c @@ -351,14 +351,44 @@ static void cik_sdma_rlc_stop(struct amdgpu_device *adev) */ static void cik_ctx_switch_enable(struct amdgpu_device *adev, bool enable) { - u32 f32_cntl; + u32 f32_cntl, phase_quantum = 0; int i; + if (amdgpu_sdma_phase_quantum) { + unsigned value = amdgpu_sdma_phase_quantum; + unsigned unit = 0; + + while (value > (SDMA0_PHASE0_QUANTUM__VALUE_MASK >> + SDMA0_PHASE0_QUANTUM__VALUE__SHIFT)) { + value = (value + 1) >> 1; + unit++; + } + if (unit > (SDMA0_PHASE0_QUANTUM__UNIT_MASK >> + SDMA0_PHASE0_QUANTUM__UNIT__SHIFT)) { + value = (SDMA0_PHASE0_QUANTUM__VALUE_MASK >> + SDMA0_PHASE0_QUANTUM__VALUE__SHIFT); + unit = (SDMA0_PHASE0_QUANTUM__UNIT_MASK >> + SDMA0_PHASE0_QUANTUM__UNIT__SHIFT); + WARN_ONCE(1, + "clamping sdma_phase_quantum to %uK clock cycles\n", + value << unit); + } + phase_quantum = + value << SDMA0_PHASE0_QUANTUM__VALUE__SHIFT | + unit << SDMA0_PHASE0_QUANTUM__UNIT__SHIFT; + } + for (i = 0; i < adev->sdma.num_instances; i++) { f32_cntl = RREG32(mmSDMA0_CNTL + sdma_offsets[i]); if (enable) { f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_CNTL, AUTO_CTXSW_ENABLE, 1); + if (amdgpu_sdma_phase_quantum) { + WREG32(mmSDMA0_PHASE0_QUANTUM + sdma_offsets[i], + phase_quantum); + WREG32(mmSDMA0_PHASE1_QUANTUM + sdma_offsets[i], + phase_quantum); + } } else { f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_CNTL, AUTO_CTXSW_ENABLE, 0); diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c index 67a29fb3d3b3..b1de44f22824 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c @@ -551,9 +551,33 @@ static void sdma_v3_0_rlc_stop(struct amdgpu_device *adev) */ static void sdma_v3_0_ctx_switch_enable(struct amdgpu_device *adev, bool enable) { - u32 f32_cntl; + u32 f32_cntl, phase_quantum = 0; int i; + if (amdgpu_sdma_phase_quantum) { + unsigned value = amdgpu_sdma_phase_quantum; + unsigned unit = 0; + + while (value > (SDMA0_PHASE0_QUANTUM__VALUE_MASK >> + SDMA0_PHASE0_QUANTUM__VALUE__SHIFT)) { + value = (value + 1) >> 1; + unit++; + } + if (unit > (SDMA0_PHASE0_QUANTUM__UNIT_MASK >> + SDMA0_PHASE0_QUANTUM__UNIT__SHIFT)) { + value = (SDMA0_PHASE0_QUANTUM__VALUE_MASK >> + SDMA0_PHASE0_QUANTUM__VALUE__SHIFT); + unit = (SDMA0_PHASE0_QUANTUM__UNIT_MASK >> + SDMA0_PHASE0_QUANTUM__UNIT__SHIFT); + WARN_ONCE(1, + "clamping sdma_phase_quantum to %uK clock cycles\n", + value << unit); + } + phase_quantum = + value << SDMA0_PHASE0_QUANTUM__VALUE__SHIFT | + unit << SDMA0_PHASE0_QUANTUM__UNIT__SHIFT; + } + for (i = 0; i < adev->sdma.num_instances; i++) { f32_cntl = RREG32(mmSDMA0_CNTL + sdma_offsets[i]); if (enable) { @@ -561,6 +585,12 @@ static void sdma_v3_0_ctx_switch_enable(struct amdgpu_device *adev, bool enable) AUTO_CTXSW_ENABLE, 1); f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_CNTL, ATC_L1_ENABLE, 1); + if (amdgpu_sdma_phase_quantum) { + WREG32(mmSDMA0_PHASE0_QUANTUM + sdma_offsets[i], + phase_quantum); + WREG32(mmSDMA0_PHASE1_QUANTUM + sdma_offsets[i], + phase_quantum); + } } else { f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_CNTL, AUTO_CTXSW_ENABLE, 0); diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index 4a65697ccc94..591f3e7fb508 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c @@ -493,13 +493,45 @@ static void sdma_v4_0_rlc_stop(struct amdgpu_device *adev) */ static void sdma_v4_0_ctx_switch_enable(struct amdgpu_device *adev, bool enable) { - u32 f32_cntl; + u32 f32_cntl, phase_quantum = 0; int i; + if (amdgpu_sdma_phase_quantum) { + unsigned value = amdgpu_sdma_phase_quantum; + unsigned unit = 0; + + while (value > (SDMA0_PHASE0_QUANTUM__VALUE_MASK >> + SDMA0_PHASE0_QUANTUM__VALUE__SHIFT)) { + value = (value + 1) >> 1; + unit++; + } + if (unit > (SDMA0_PHASE0_QUANTUM__UNIT_MASK >> + SDMA0_PHASE0_QUANTUM__UNIT__SHIFT)) { + value = (SDMA0_PHASE0_QUANTUM__VALUE_MASK >> + SDMA0_PHASE0_QUANTUM__VALUE__SHIFT); + unit = (SDMA0_PHASE0_QUANTUM__UNIT_MASK >> + SDMA0_PHASE0_QUANTUM__UNIT__SHIFT); + WARN_ONCE(1, + "clamping sdma_phase_quantum to %uK clock cycles\n", + value << unit); + } + phase_quantum = + value << SDMA0_PHASE0_QUANTUM__VALUE__SHIFT | + unit << SDMA0_PHASE0_QUANTUM__UNIT__SHIFT; + } + for (i = 0; i < adev->sdma.num_instances; i++) { f32_cntl = RREG32(sdma_v4_0_get_reg_offset(i, mmSDMA0_CNTL)); f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_CNTL, AUTO_CTXSW_ENABLE, enable ? 1 : 0); + if (enable && amdgpu_sdma_phase_quantum) { + WREG32(sdma_v4_0_get_reg_offset(i, mmSDMA0_PHASE0_QUANTUM), + phase_quantum); + WREG32(sdma_v4_0_get_reg_offset(i, mmSDMA0_PHASE1_QUANTUM), + phase_quantum); + WREG32(sdma_v4_0_get_reg_offset(i, mmSDMA0_PHASE2_QUANTUM), + phase_quantum); + } WREG32(sdma_v4_0_get_reg_offset(i, mmSDMA0_CNTL), f32_cntl); } -- cgit v1.2.3 From ba997709a6135355a1f311336c7c4a6c0e37dfe9 Mon Sep 17 00:00:00 2001 From: Yong Zhao Date: Mon, 9 Nov 2015 17:21:45 -0500 Subject: drm/amdgpu: Correctly establish the suspend/resume hook for amdkfd Signed-off-by: Yong Zhao Reviewed-by: Felix Kuehling Reviewed-by: Oded Gabbay Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 7 +++++++ drivers/gpu/drm/amd/amdgpu/cik.c | 9 +-------- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 0e629931210c..078886c6b758 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -55,6 +55,8 @@ #include #include "amdgpu_vf_error.h" +#include "amdgpu_amdkfd.h" + MODULE_FIRMWARE("amdgpu/vega10_gpu_info.bin"); MODULE_FIRMWARE("amdgpu/raven_gpu_info.bin"); @@ -2378,6 +2380,8 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon) } drm_modeset_unlock_all(dev); + amdgpu_amdkfd_suspend(adev); + /* unpin the front buffers and cursors */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); @@ -2511,6 +2515,9 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon) } } } + r = amdgpu_amdkfd_resume(adev); + if (r) + return r; /* blat the mode back in */ if (fbcon) { diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c index 37a499ab30eb..567c4a5cf90c 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik.c +++ b/drivers/gpu/drm/amd/amdgpu/cik.c @@ -1824,21 +1824,14 @@ static int cik_common_suspend(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - amdgpu_amdkfd_suspend(adev); - return cik_common_hw_fini(adev); } static int cik_common_resume(void *handle) { - int r; struct amdgpu_device *adev = (struct amdgpu_device *)handle; - r = cik_common_hw_init(adev); - if (r) - return r; - - return amdgpu_amdkfd_resume(adev); + return cik_common_hw_init(adev); } static bool cik_common_is_idle(void *handle) -- cgit v1.2.3 From 9f57f7b47d4c9559ae85666eeaf9ffd150096574 Mon Sep 17 00:00:00 2001 From: Jay Cornwall Date: Wed, 26 Apr 2017 14:51:57 -0500 Subject: drm/amdgpu: Send no-retry XNACK for all fault types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A subset of VM fault types currently send retry XNACK to the client. This causes a storm of interrupts from the VM to the host. Until the storm is throttled by other means send no-retry XNACK for all fault types instead. No change in behavior to the client which will stall indefinitely with the current configuration in any case. Improves system stability under GC or MMHUB faults. Signed-off-by: Jay Cornwall Reviewed-by: Felix Kuehling Reviewed-by: John Bridgman Acked-by: Alex Deucher Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c | 3 +++ drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c | 3 +++ 2 files changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c index 3ff786cfc947..008ad3dc4afd 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c @@ -206,6 +206,9 @@ static void gfxhub_v1_0_setup_vmid_config(struct amdgpu_device *adev) tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, PAGE_TABLE_BLOCK_SIZE, adev->vm_manager.block_size - 9); + /* Send no-retry XNACK on fault to suppress VM fault storm. */ + tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, + RETRY_PERMISSION_OR_INVALID_PAGE_FAULT, 0); WREG32_SOC15_OFFSET(GC, 0, mmVM_CONTEXT1_CNTL, i, tmp); WREG32_SOC15_OFFSET(GC, 0, mmVM_CONTEXT1_PAGE_TABLE_START_ADDR_LO32, i*2, 0); WREG32_SOC15_OFFSET(GC, 0, mmVM_CONTEXT1_PAGE_TABLE_START_ADDR_HI32, i*2, 0); diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c index 0780e830b76b..96f1628541bb 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c @@ -222,6 +222,9 @@ static void mmhub_v1_0_setup_vmid_config(struct amdgpu_device *adev) tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, PAGE_TABLE_BLOCK_SIZE, adev->vm_manager.block_size - 9); + /* Send no-retry XNACK on fault to suppress VM fault storm. */ + tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, + RETRY_PERMISSION_OR_INVALID_PAGE_FAULT, 0); WREG32_SOC15_OFFSET(MMHUB, 0, mmVM_CONTEXT1_CNTL, i, tmp); WREG32_SOC15_OFFSET(MMHUB, 0, mmVM_CONTEXT1_PAGE_TABLE_START_ADDR_LO32, i*2, 0); WREG32_SOC15_OFFSET(MMHUB, 0, mmVM_CONTEXT1_PAGE_TABLE_START_ADDR_HI32, i*2, 0); -- cgit v1.2.3 From 79077ee1edceb95d8c0215a9af5e8373232672df Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 10 Jul 2017 10:39:09 -0400 Subject: drm/amdgpu: add get_clock_info for atomfirmware MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The information has moved to different tables, notably smu_info for core refclk and umc_info for mem refclk. Acked-by: Chunming Zhou Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c | 93 ++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h | 1 + 2 files changed, 94 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c index a7d65f033883..f9ffe8ef0cd6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c @@ -128,3 +128,96 @@ int amdgpu_atomfirmware_get_vram_width(struct amdgpu_device *adev) return 0; } + +union firmware_info { + struct atom_firmware_info_v3_1 v31; +}; + +union smu_info { + struct atom_smu_info_v3_1 v31; +}; + +union umc_info { + struct atom_umc_info_v3_1 v31; +}; + +int amdgpu_atomfirmware_get_clock_info(struct amdgpu_device *adev) +{ + struct amdgpu_mode_info *mode_info = &adev->mode_info; + struct amdgpu_pll *spll = &adev->clock.spll; + struct amdgpu_pll *mpll = &adev->clock.mpll; + uint8_t frev, crev; + uint16_t data_offset; + int ret = -EINVAL, index; + + index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, + firmwareinfo); + if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) { + union firmware_info *firmware_info = + (union firmware_info *)(mode_info->atom_context->bios + + data_offset); + + adev->clock.default_sclk = + le32_to_cpu(firmware_info->v31.bootup_sclk_in10khz); + adev->clock.default_mclk = + le32_to_cpu(firmware_info->v31.bootup_mclk_in10khz); + + adev->pm.current_sclk = adev->clock.default_sclk; + adev->pm.current_mclk = adev->clock.default_mclk; + + /* not technically a clock, but... */ + adev->mode_info.firmware_flags = + le32_to_cpu(firmware_info->v31.firmware_capability); + + ret = 0; + } + + index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, + smu_info); + if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) { + union smu_info *smu_info = + (union smu_info *)(mode_info->atom_context->bios + + data_offset); + + /* system clock */ + spll->reference_freq = le32_to_cpu(smu_info->v31.core_refclk_10khz); + + spll->reference_div = 0; + spll->min_post_div = 1; + spll->max_post_div = 1; + spll->min_ref_div = 2; + spll->max_ref_div = 0xff; + spll->min_feedback_div = 4; + spll->max_feedback_div = 0xff; + spll->best_vco = 0; + + ret = 0; + } + + index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, + umc_info); + if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) { + union umc_info *umc_info = + (union umc_info *)(mode_info->atom_context->bios + + data_offset); + + /* memory clock */ + mpll->reference_freq = le32_to_cpu(umc_info->v31.mem_refclk_10khz); + + mpll->reference_div = 0; + mpll->min_post_div = 1; + mpll->max_post_div = 1; + mpll->min_ref_div = 2; + mpll->max_ref_div = 0xff; + mpll->min_feedback_div = 4; + mpll->max_feedback_div = 0xff; + mpll->best_vco = 0; + + ret = 0; + } + + return ret; +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h index cedafbb9183e..288b97e54347 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h @@ -28,5 +28,6 @@ bool amdgpu_atomfirmware_gpu_supports_virtualization(struct amdgpu_device *adev) void amdgpu_atomfirmware_scratch_regs_init(struct amdgpu_device *adev); int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device *adev); int amdgpu_atomfirmware_get_vram_width(struct amdgpu_device *adev); +int amdgpu_atomfirmware_get_clock_info(struct amdgpu_device *adev); #endif -- cgit v1.2.3 From 88b64e9536746eadc366ac1e23c8c67f14b249f5 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 10 Jul 2017 10:43:10 -0400 Subject: drm/amdgpu: call atomfirmware get_clock_info for atomfirmware systems MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rather than the legacy atombios version. Acked-by: Chunming Zhou Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 078886c6b758..a9eeaad49d18 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2189,7 +2189,15 @@ int amdgpu_device_init(struct amdgpu_device *adev, DRM_INFO("GPU post is not needed\n"); } - if (!adev->is_atom_fw) { + if (adev->is_atom_fw) { + /* Initialize clocks */ + r = amdgpu_atomfirmware_get_clock_info(adev); + if (r) { + dev_err(adev->dev, "amdgpu_atomfirmware_get_clock_info failed\n"); + amdgpu_vf_error_put(AMDGIM_ERROR_VF_ATOMBIOS_GET_CLOCK_FAIL, 0, 0); + goto failed; + } + } else { /* Initialize clocks */ r = amdgpu_atombios_get_clock_info(adev); if (r) { -- cgit v1.2.3 From 1a6ec7ed03e89b859325790221ca77d09fd4a3d0 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 11 Jul 2017 18:59:24 -0400 Subject: drm/amdgpu/soc15: drop dead function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Maybe a leftover from bringup? Reviewed-by: Chunming Zhou Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/soc15.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 8dc023296773..f2c3a49f73a0 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -566,13 +566,6 @@ static uint32_t soc15_get_rev_id(struct amdgpu_device *adev) return nbio_v6_1_get_rev_id(adev); } - -int gmc_v9_0_mc_wait_for_idle(struct amdgpu_device *adev) -{ - /* to be implemented in MC IP*/ - return 0; -} - static const struct amdgpu_asic_funcs soc15_asic_funcs = { .read_disabled_bios = &soc15_read_disabled_bios, -- cgit v1.2.3 From 6d949d247379ec92e1a0642fc7a227284488360e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 12 Jul 2017 09:18:07 -0400 Subject: drm/amdgpu: implement si_read_bios_from_rom MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows us to read the vbios image directly from ROM. This is already implemented for other asics, but was not yet available for SI. Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/si.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c index f45fb0f022b3..812a24dd1204 100644 --- a/drivers/gpu/drm/amd/amdgpu/si.c +++ b/drivers/gpu/drm/amd/amdgpu/si.c @@ -1150,6 +1150,33 @@ static bool si_read_disabled_bios(struct amdgpu_device *adev) return r; } +#define mmROM_INDEX 0x2A +#define mmROM_DATA 0x2B + +static bool si_read_bios_from_rom(struct amdgpu_device *adev, + u8 *bios, u32 length_bytes) +{ + u32 *dw_ptr; + u32 i, length_dw; + + if (bios == NULL) + return false; + if (length_bytes == 0) + return false; + /* APU vbios image is part of sbios image */ + if (adev->flags & AMD_IS_APU) + return false; + + dw_ptr = (u32 *)bios; + length_dw = ALIGN(length_bytes, 4) / 4; + /* set rom index to 0 */ + WREG32(mmROM_INDEX, 0); + for (i = 0; i < length_dw; i++) + dw_ptr[i] = RREG32(mmROM_DATA); + + return true; +} + //xxx: not implemented static int si_asic_reset(struct amdgpu_device *adev) { @@ -1206,6 +1233,7 @@ static void si_detect_hw_virtualization(struct amdgpu_device *adev) static const struct amdgpu_asic_funcs si_asic_funcs = { .read_disabled_bios = &si_read_disabled_bios, + .read_bios_from_rom = &si_read_bios_from_rom, .read_register = &si_read_register, .reset = &si_asic_reset, .set_vga_state = &si_vga_set_state, -- cgit v1.2.3 From 1d11ee89862ae7c1932e8b742fbb8340598f8874 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 11 Jul 2017 22:53:29 +0300 Subject: drm/amdgpu: Off by one sanity checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is just future proofing code, not something that can be triggered in real life. We're testing to make sure we don't shift wrap when we do "1ull << i" so "i" has to be in the 0-63 range. If it's 64 then we have gone too far. Acked-by: Christian König Signed-off-by: Dan Carpenter Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 4bb12ee46315..3fbc7b22446c 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -4564,7 +4564,7 @@ static int gfx_v8_0_kiq_kcq_enable(struct amdgpu_device *adev) /* This situation may be hit in the future if a new HW * generation exposes more than 64 queues. If so, the * definition of queue_mask needs updating */ - if (WARN_ON(i > (sizeof(queue_mask)*8))) { + if (WARN_ON(i >= (sizeof(queue_mask)*8))) { DRM_ERROR("Invalid KCQ enabled: %d\n", i); break; } diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 3a0b69b09ed6..e63925dffd2a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -2425,7 +2425,7 @@ static int gfx_v9_0_kiq_kcq_enable(struct amdgpu_device *adev) /* This situation may be hit in the future if a new HW * generation exposes more than 64 queues. If so, the * definition of queue_mask needs updating */ - if (WARN_ON(i > (sizeof(queue_mask)*8))) { + if (WARN_ON(i >= (sizeof(queue_mask)*8))) { DRM_ERROR("Invalid KCQ enabled: %d\n", i); break; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index 955aa304ff48..0def783889cd 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -671,7 +671,7 @@ static int set_sched_resources(struct device_queue_manager *dqm) /* This situation may be hit in the future if a new HW * generation exposes more than 64 queues. If so, the * definition of res.queue_mask needs updating */ - if (WARN_ON(i > (sizeof(res.queue_mask)*8))) { + if (WARN_ON(i >= (sizeof(res.queue_mask)*8))) { pr_err("Invalid queue enabled by amdgpu: %d\n", i); break; } -- cgit v1.2.3 From 5cb818b861be114148e8dbeb4259698148019dd1 Mon Sep 17 00:00:00 2001 From: Jim Qu Date: Wed, 12 Jul 2017 15:52:26 +0800 Subject: drm/amd/amdgpu: fix si_enable_smc_cac() failed issue Signed-off-by: Jim Qu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/si_dpm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c index a7ad8390981c..d63873f3f574 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c @@ -2055,6 +2055,7 @@ static void si_initialize_powertune_defaults(struct amdgpu_device *adev) case 0x682C: si_pi->cac_weights = cac_weights_cape_verde_pro; si_pi->dte_data = dte_data_sun_xt; + update_dte_from_pl2 = true; break; case 0x6825: case 0x6827: -- cgit v1.2.3 From fd971375411542f9d81111bb081e58727eb09138 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 11 Jul 2017 11:11:41 -0400 Subject: drm/amdgpu/gfx: keep all compute queues on the same pipe Spreading them causes performance regressions using compute queues on Polaris 11. Cc: Jim Qu Acked-by: Jim Qu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c index e26108aad3fe..4f6c68fc1dd9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c @@ -125,7 +125,8 @@ void amdgpu_gfx_compute_queue_acquire(struct amdgpu_device *adev) if (mec >= adev->gfx.mec.num_mec) break; - if (adev->gfx.mec.num_mec > 1) { + /* FIXME: spreading the queues across pipes causes perf regressions */ + if (0) { /* policy: amdgpu owns the first two queues of the first MEC */ if (mec == 0 && queue < 2) set_bit(i, adev->gfx.mec.queue_bitmap); -- cgit v1.2.3 From 6f1ceabbd7091b81139e342fc2b08105bc4fa035 Mon Sep 17 00:00:00 2001 From: Christian König Date: Tue, 11 Jul 2017 16:59:21 +0200 Subject: drm/amdgpu: fix VM flush for CPU based updates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't have any update fence in that case, so the need for flushing isn't detected automatically. Signed-off-by: Christian König Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 30c4322ddce7..84260f7737d3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -422,7 +422,7 @@ static int amdgpu_vm_grab_reserved_vmid_locked(struct amdgpu_vm *vm, struct dma_fence *updates = sync->last_vm_update; int r = 0; struct dma_fence *flushed, *tmp; - bool needs_flush = false; + bool needs_flush = vm->use_cpu_for_update; flushed = id->flushed_updates; if ((amdgpu_vm_had_gpu_reset(adev, id)) || @@ -543,11 +543,11 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, } kfree(fences); - job->vm_needs_flush = false; + job->vm_needs_flush = vm->use_cpu_for_update; /* Check if we can use a VMID already assigned to this VM */ list_for_each_entry_reverse(id, &id_mgr->ids_lru, list) { struct dma_fence *flushed; - bool needs_flush = false; + bool needs_flush = vm->use_cpu_for_update; /* Check all the prerequisites to using this VMID */ if (amdgpu_vm_had_gpu_reset(adev, id)) -- cgit v1.2.3 From a33cab7aacb2aa5bfe82ea6beaf51870af84a10e Mon Sep 17 00:00:00 2001 From: Christian König Date: Tue, 11 Jul 2017 17:13:00 +0200 Subject: drm/amdgpu: fix amdgpu_vm_bo_wait MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to wait with the correct owner on unmap operations or otherwise can run into VM faults. Also always wait for the page directory since this is where the reservation object comes from. So rename the function to amdgpu_vm_wait_pd instead as well. Signed-off-by: Christian König Acked-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 84260f7737d3..db9f12e85fb4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -996,13 +996,14 @@ static void amdgpu_vm_cpu_set_ptes(struct amdgpu_pte_update_params *params, amdgpu_gart_flush_gpu_tlb(params->adev, 0); } -static int amdgpu_vm_bo_wait(struct amdgpu_device *adev, struct amdgpu_bo *bo) +static int amdgpu_vm_wait_pd(struct amdgpu_device *adev, struct amdgpu_vm *vm, + void *owner) { struct amdgpu_sync sync; int r; amdgpu_sync_create(&sync); - amdgpu_sync_resv(adev, &sync, bo->tbo.resv, AMDGPU_FENCE_OWNER_VM); + amdgpu_sync_resv(adev, &sync, vm->root.bo->tbo.resv, owner); r = amdgpu_sync_wait(&sync, true); amdgpu_sync_free(&sync); @@ -1048,7 +1049,7 @@ static int amdgpu_vm_update_level(struct amdgpu_device *adev, r = amdgpu_bo_kmap(parent->bo, (void **)&pd_addr); if (r) return r; - r = amdgpu_vm_bo_wait(adev, parent->bo); + r = amdgpu_vm_wait_pd(adev, vm, AMDGPU_FENCE_OWNER_VM); if (unlikely(r)) { amdgpu_bo_kunmap(parent->bo); return r; @@ -1445,6 +1446,10 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, params.vm = vm; params.src = src; + /* sync to everything on unmapping */ + if (!(flags & AMDGPU_PTE_VALID)) + owner = AMDGPU_FENCE_OWNER_UNDEFINED; + if (vm->use_cpu_for_update) { /* params.src is used as flag to indicate system Memory */ if (pages_addr) @@ -1453,7 +1458,7 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, /* Wait for PT BOs to be free. PTs share the same resv. object * as the root PD BO */ - r = amdgpu_vm_bo_wait(adev, vm->root.bo); + r = amdgpu_vm_wait_pd(adev, vm, owner); if (unlikely(r)) return r; @@ -1465,10 +1470,6 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, ring = container_of(vm->entity.sched, struct amdgpu_ring, sched); - /* sync to everything on unmapping */ - if (!(flags & AMDGPU_PTE_VALID)) - owner = AMDGPU_FENCE_OWNER_UNDEFINED; - nptes = last - start + 1; /* -- cgit v1.2.3 From 6927798572a930a4a56f66eb36916d861ff56ad6 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 13 Jul 2017 15:37:11 -0400 Subject: drm/amdgpu: remove VM shadow WARN_ONs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Printing a warning into the logs that we will certainly run into a BUG() is completely nonsense, the BUG() is more than noisy enough. Signed-off-by: Christian König Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index db9f12e85fb4..74cbe10a0115 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -1044,8 +1044,7 @@ static int amdgpu_vm_update_level(struct amdgpu_device *adev, params.adev = adev; shadow = parent->bo->shadow; - WARN_ON(vm->use_cpu_for_update && shadow); - if (vm->use_cpu_for_update && !shadow) { + if (vm->use_cpu_for_update) { r = amdgpu_bo_kmap(parent->bo, (void **)&pd_addr); if (r) return r; @@ -1310,9 +1309,6 @@ static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params, r = amdgpu_bo_kmap(pt, (void *)&pe_start); if (r) return r; - - WARN_ONCE(pt->shadow, - "CPU VM update doesn't support shadow pages"); } else { if (pt->shadow) { pe_start = amdgpu_bo_gpu_offset(pt->shadow); -- cgit v1.2.3 From 03918b36f6602df298b5ce7925ef77f7ecf0756a Mon Sep 17 00:00:00 2001 From: Christian König Date: Tue, 11 Jul 2017 17:15:37 +0200 Subject: drm/amdgpu: trace setting VM page tables with the CPU as well MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Handy for debugging. Signed-off-by: Christian König Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 74cbe10a0115..5638c16887d8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -982,6 +982,8 @@ static void amdgpu_vm_cpu_set_ptes(struct amdgpu_pte_update_params *params, unsigned int i; uint64_t value; + trace_amdgpu_vm_set_ptes(pe, addr, count, incr, flags); + for (i = 0; i < count; i++) { value = params->pages_addr ? amdgpu_vm_map_gart(params->pages_addr, addr) : -- cgit v1.2.3 From 68c62306b378451ddb1a14c08022d18df3848b4d Mon Sep 17 00:00:00 2001 From: Christian König Date: Tue, 11 Jul 2017 17:23:29 +0200 Subject: drm/amdgpu: flush the HDP only once for CPU based VM updates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No need to do this after every single update. Signed-off-by: Christian König Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 5638c16887d8..24879cf3da9b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -992,10 +992,6 @@ static void amdgpu_vm_cpu_set_ptes(struct amdgpu_pte_update_params *params, i, value, flags); addr += incr; } - - /* Flush HDP */ - mb(); - amdgpu_gart_flush_gpu_tlb(params->adev, 0); } static int amdgpu_vm_wait_pd(struct amdgpu_device *adev, struct amdgpu_vm *vm, @@ -1238,6 +1234,12 @@ int amdgpu_vm_update_directories(struct amdgpu_device *adev, if (r) amdgpu_vm_invalidate_level(&vm->root); + if (vm->use_cpu_for_update) { + /* Flush HDP */ + mb(); + amdgpu_gart_flush_gpu_tlb(adev, 0); + } + return r; } @@ -1745,6 +1747,12 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, list_add(&bo_va->vm_status, &vm->cleared); spin_unlock(&vm->status_lock); + if (vm->use_cpu_for_update) { + /* Flush HDP */ + mb(); + amdgpu_gart_flush_gpu_tlb(adev, 0); + } + return 0; } -- cgit v1.2.3 From 6375bbb4d259416ad867ab887333ee88d1b90323 Mon Sep 17 00:00:00 2001 From: Christian König Date: Tue, 11 Jul 2017 17:25:49 +0200 Subject: drm/amdgpu: make sure BOs are always kunmapped MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a BO is moved or destroyed it shouldn't be kmapped any more. Signed-off-by: Christian König Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 6e24339ecc46..a019556a8e71 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -93,6 +93,7 @@ static void amdgpu_ttm_bo_destroy(struct ttm_buffer_object *tbo) bo = container_of(tbo, struct amdgpu_bo, tbo); + amdgpu_bo_kunmap(bo); amdgpu_update_memory_usage(adev, &bo->tbo.mem, NULL); drm_gem_object_release(&bo->gem_base); @@ -931,6 +932,8 @@ void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, abo = container_of(bo, struct amdgpu_bo, tbo); amdgpu_vm_bo_invalidate(adev, abo); + amdgpu_bo_kunmap(abo); + /* remember the eviction */ if (evict) atomic64_inc(&adev->num_evictions); -- cgit v1.2.3 From 0a096fb66a60def858d1d893dad92b3dd0564b79 Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 12 Jul 2017 10:01:48 +0200 Subject: drm/amdgpu: map VM BOs for CPU based updates only once MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No need to try to map them every time. Signed-off-by: Christian König Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 87 ++++++++++++++++++++-------------- 1 file changed, 51 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 24879cf3da9b..b017b54e45ba 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -159,11 +159,17 @@ void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm, */ static int amdgpu_vm_validate_level(struct amdgpu_vm_pt *parent, int (*validate)(void *, struct amdgpu_bo *), - void *param) + void *param, bool use_cpu_for_update) { unsigned i; int r; + if (use_cpu_for_update) { + r = amdgpu_bo_kmap(parent->bo, NULL); + if (r) + return r; + } + if (!parent->entries) return 0; @@ -181,7 +187,8 @@ static int amdgpu_vm_validate_level(struct amdgpu_vm_pt *parent, * Recurse into the sub directory. This is harmless because we * have only a maximum of 5 layers. */ - r = amdgpu_vm_validate_level(entry, validate, param); + r = amdgpu_vm_validate_level(entry, validate, param, + use_cpu_for_update); if (r) return r; } @@ -212,7 +219,8 @@ int amdgpu_vm_validate_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm, if (num_evictions == vm->last_eviction_counter) return 0; - return amdgpu_vm_validate_level(&vm->root, validate, param); + return amdgpu_vm_validate_level(&vm->root, validate, param, + vm->use_cpu_for_update); } /** @@ -329,6 +337,14 @@ static int amdgpu_vm_alloc_levels(struct amdgpu_device *adev, if (r) return r; + if (vm->use_cpu_for_update) { + r = amdgpu_bo_kmap(pt, NULL); + if (r) { + amdgpu_bo_unref(&pt); + return r; + } + } + /* Keep a reference to the root directory to avoid * freeing them up in the wrong order. */ @@ -1043,14 +1059,11 @@ static int amdgpu_vm_update_level(struct amdgpu_device *adev, shadow = parent->bo->shadow; if (vm->use_cpu_for_update) { - r = amdgpu_bo_kmap(parent->bo, (void **)&pd_addr); - if (r) - return r; + pd_addr = (unsigned long)parent->bo->kptr; r = amdgpu_vm_wait_pd(adev, vm, AMDGPU_FENCE_OWNER_VM); - if (unlikely(r)) { - amdgpu_bo_kunmap(parent->bo); + if (unlikely(r)) return r; - } + params.func = amdgpu_vm_cpu_set_ptes; } else { if (shadow) { @@ -1145,28 +1158,29 @@ static int amdgpu_vm_update_level(struct amdgpu_device *adev, count, incr, AMDGPU_PTE_VALID); } - if (params.func == amdgpu_vm_cpu_set_ptes) - amdgpu_bo_kunmap(parent->bo); - else if (params.ib->length_dw == 0) { - amdgpu_job_free(job); - } else { - amdgpu_ring_pad_ib(ring, params.ib); - amdgpu_sync_resv(adev, &job->sync, parent->bo->tbo.resv, - AMDGPU_FENCE_OWNER_VM); - if (shadow) - amdgpu_sync_resv(adev, &job->sync, shadow->tbo.resv, + if (!vm->use_cpu_for_update) { + if (params.ib->length_dw == 0) { + amdgpu_job_free(job); + } else { + amdgpu_ring_pad_ib(ring, params.ib); + amdgpu_sync_resv(adev, &job->sync, parent->bo->tbo.resv, AMDGPU_FENCE_OWNER_VM); + if (shadow) + amdgpu_sync_resv(adev, &job->sync, + shadow->tbo.resv, + AMDGPU_FENCE_OWNER_VM); + + WARN_ON(params.ib->length_dw > ndw); + r = amdgpu_job_submit(job, ring, &vm->entity, + AMDGPU_FENCE_OWNER_VM, &fence); + if (r) + goto error_free; - WARN_ON(params.ib->length_dw > ndw); - r = amdgpu_job_submit(job, ring, &vm->entity, - AMDGPU_FENCE_OWNER_VM, &fence); - if (r) - goto error_free; - - amdgpu_bo_fence(parent->bo, fence, true); - dma_fence_put(vm->last_dir_update); - vm->last_dir_update = dma_fence_get(fence); - dma_fence_put(fence); + amdgpu_bo_fence(parent->bo, fence, true); + dma_fence_put(vm->last_dir_update); + vm->last_dir_update = dma_fence_get(fence); + dma_fence_put(fence); + } } /* * Recurse into the subdirectories. This recursion is harmless because @@ -1292,7 +1306,6 @@ static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params, uint64_t addr, pe_start; struct amdgpu_bo *pt; unsigned nptes; - int r; bool use_cpu_update = (params->func == amdgpu_vm_cpu_set_ptes); @@ -1310,9 +1323,7 @@ static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params, nptes = AMDGPU_VM_PTE_COUNT(adev) - (addr & mask); if (use_cpu_update) { - r = amdgpu_bo_kmap(pt, (void *)&pe_start); - if (r) - return r; + pe_start = (unsigned long)pt->kptr; } else { if (pt->shadow) { pe_start = amdgpu_bo_gpu_offset(pt->shadow); @@ -1328,9 +1339,6 @@ static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params, AMDGPU_GPU_PAGE_SIZE, flags); dst += nptes * AMDGPU_GPU_PAGE_SIZE; - - if (use_cpu_update) - amdgpu_bo_kunmap(pt); } return 0; @@ -2458,6 +2466,13 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, goto error_free_root; vm->last_eviction_counter = atomic64_read(&adev->num_evictions); + + if (vm->use_cpu_for_update) { + r = amdgpu_bo_kmap(vm->root.bo, NULL); + if (r) + goto error_free_root; + } + amdgpu_bo_unreserve(vm->root.bo); return 0; -- cgit v1.2.3 From 9d63c03444ac92d6412fd72429478b81a8378de7 Mon Sep 17 00:00:00 2001 From: Christian König Date: Thu, 13 Jul 2017 12:21:00 +0200 Subject: drm/amdgpu: fix amdgpu_bo_gpu_accessible() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The test was relaxed a bit to much. Signed-off-by: Christian König Acked-by: Tom St Denis Reviewed-and-Tested-by: Roger He Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h index 382485115b06..833b172a2c2a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h @@ -120,7 +120,11 @@ static inline u64 amdgpu_bo_mmap_offset(struct amdgpu_bo *bo) */ static inline bool amdgpu_bo_gpu_accessible(struct amdgpu_bo *bo) { - return bo->tbo.mem.mem_type != TTM_PL_SYSTEM; + switch (bo->tbo.mem.mem_type) { + case TTM_PL_TT: return amdgpu_ttm_is_bound(bo->tbo.ttm); + case TTM_PL_VRAM: return true; + default: return false; + } } int amdgpu_bo_create(struct amdgpu_device *adev, -- cgit v1.2.3 From 53a4b90d26044541e4051c5a83397b6eb9e1f6d4 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Wed, 12 Jul 2017 19:28:03 +0800 Subject: drm/amd/powerplay: add profile mode for vega10. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c | 130 +++++++++++++++++---- drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h | 4 + 2 files changed, 109 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c index 8d567620576a..aca4a7cb1d9c 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c @@ -78,6 +78,8 @@ uint32_t channel_number[] = {1, 2, 0, 4, 0, 8, 0, 16, 2}; #define DF_CS_AON0_DramBaseAddress0__IntLvNumChan_MASK 0x000000F0L #define DF_CS_AON0_DramBaseAddress0__IntLvAddrSel_MASK 0x00000700L #define DF_CS_AON0_DramBaseAddress0__DramBaseAddr_MASK 0xFFFFF000L +static int vega10_force_clock_level(struct pp_hwmgr *hwmgr, + enum pp_clock_type type, uint32_t mask); const ULONG PhwVega10_Magic = (ULONG)(PHM_VIslands_Magic); @@ -4224,34 +4226,30 @@ static int vega10_unforce_dpm_levels(struct pp_hwmgr *hwmgr) return 0; } -static int vega10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, - enum amd_dpm_forced_level level) +static int vega10_get_profiling_clk_mask(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level, + uint32_t *sclk_mask, uint32_t *mclk_mask, uint32_t *soc_mask) { - int ret = 0; + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)(hwmgr->pptable); - switch (level) { - case AMD_DPM_FORCED_LEVEL_HIGH: - ret = vega10_force_dpm_highest(hwmgr); - if (ret) - return ret; - break; - case AMD_DPM_FORCED_LEVEL_LOW: - ret = vega10_force_dpm_lowest(hwmgr); - if (ret) - return ret; - break; - case AMD_DPM_FORCED_LEVEL_AUTO: - ret = vega10_unforce_dpm_levels(hwmgr); - if (ret) - return ret; - break; - default: - break; + if (table_info->vdd_dep_on_sclk->count > VEGA10_UMD_PSTATE_GFXCLK_LEVEL && + table_info->vdd_dep_on_socclk->count > VEGA10_UMD_PSTATE_SOCCLK_LEVEL && + table_info->vdd_dep_on_mclk->count > VEGA10_UMD_PSTATE_MCLK_LEVEL) { + *sclk_mask = VEGA10_UMD_PSTATE_GFXCLK_LEVEL; + *soc_mask = VEGA10_UMD_PSTATE_SOCCLK_LEVEL; + *mclk_mask = VEGA10_UMD_PSTATE_MCLK_LEVEL; } - hwmgr->dpm_level = level; - - return ret; + if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { + *sclk_mask = 0; + } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { + *mclk_mask = 0; + } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { + *sclk_mask = table_info->vdd_dep_on_sclk->count - 1; + *soc_mask = table_info->vdd_dep_on_socclk->count - 1; + *mclk_mask = table_info->vdd_dep_on_mclk->count - 1; + } + return 0; } static int vega10_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode) @@ -4278,6 +4276,86 @@ static int vega10_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode) return result; } +static int vega10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, + enum amd_dpm_forced_level level) +{ + int ret = 0; + uint32_t sclk_mask = 0; + uint32_t mclk_mask = 0; + uint32_t soc_mask = 0; + uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | + AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | + AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | + AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; + + if (level == hwmgr->dpm_level) + return ret; + + if (!(hwmgr->dpm_level & profile_mode_mask)) { + /* enter profile mode, save current level, disable gfx cg*/ + if (level & profile_mode_mask) { + hwmgr->saved_dpm_level = hwmgr->dpm_level; + cgs_set_clockgating_state(hwmgr->device, + AMD_IP_BLOCK_TYPE_GFX, + AMD_CG_STATE_UNGATE); + } + } else { + /* exit profile mode, restore level, enable gfx cg*/ + if (!(level & profile_mode_mask)) { + if (level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT) + level = hwmgr->saved_dpm_level; + cgs_set_clockgating_state(hwmgr->device, + AMD_IP_BLOCK_TYPE_GFX, + AMD_CG_STATE_GATE); + } + } + + switch (level) { + case AMD_DPM_FORCED_LEVEL_HIGH: + ret = vega10_force_dpm_highest(hwmgr); + if (ret) + return ret; + hwmgr->dpm_level = level; + break; + case AMD_DPM_FORCED_LEVEL_LOW: + ret = vega10_force_dpm_lowest(hwmgr); + if (ret) + return ret; + hwmgr->dpm_level = level; + break; + case AMD_DPM_FORCED_LEVEL_AUTO: + ret = vega10_unforce_dpm_levels(hwmgr); + if (ret) + return ret; + hwmgr->dpm_level = level; + break; + case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: + case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: + case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: + case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: + ret = vega10_get_profiling_clk_mask(hwmgr, level, &sclk_mask, &mclk_mask, &soc_mask); + if (ret) + return ret; + hwmgr->dpm_level = level; + vega10_force_clock_level(hwmgr, PP_SCLK, 1<dpm_level = level; + break; + case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: + default: + break; + } + + if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->saved_dpm_level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) + vega10_set_fan_control_mode(hwmgr, AMD_FAN_CTRL_NONE); + else if (level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->saved_dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) + vega10_set_fan_control_mode(hwmgr, AMD_FAN_CTRL_AUTO); + + return 0; +} + static int vega10_get_fan_control_mode(struct pp_hwmgr *hwmgr) { struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend); @@ -4523,7 +4601,9 @@ static int vega10_force_clock_level(struct pp_hwmgr *hwmgr, struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend); int i; - if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) + if (hwmgr->dpm_level & (AMD_DPM_FORCED_LEVEL_AUTO | + AMD_DPM_FORCED_LEVEL_LOW | + AMD_DPM_FORCED_LEVEL_HIGH)) return -EINVAL; switch (type) { diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h index 5c97a8b6c46a..676cd7735883 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h @@ -434,6 +434,10 @@ struct vega10_hwmgr { #define PPVEGA10_VEGA10UCLKCLKAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */ #define PPVEGA10_VEGA10GFXACTIVITYAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */ +#define VEGA10_UMD_PSTATE_GFXCLK_LEVEL 0x3 +#define VEGA10_UMD_PSTATE_SOCCLK_LEVEL 0x3 +#define VEGA10_UMD_PSTATE_MCLK_LEVEL 0x2 + extern int tonga_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr); extern int tonga_hwmgr_backend_fini(struct pp_hwmgr *hwmgr); extern int tonga_get_mc_microcode_version (struct pp_hwmgr *hwmgr); -- cgit v1.2.3 From 379ea9a1a59a5a32c8db6f164e80a3fd00cb3781 Mon Sep 17 00:00:00 2001 From: Noralf Trønnes Date: Thu, 8 Jun 2017 17:14:34 +0200 Subject: drm/tinydrm: Add tinydrm_xrgb8888_to_gray8() helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drm has no monochrome or greyscale support so add a conversion from the common format XR24. Also reorder includes into the common order. Acked-by: Daniel Vetter Signed-off-by: Noralf Trønnes Link: http://patchwork.freedesktop.org/patch/msgid/1496934875-51984-4-git-send-email-noralf@tronnes.org --- drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c | 74 +++++++++++++++++++++++++- include/drm/tinydrm/tinydrm-helpers.h | 1 + 2 files changed, 73 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c b/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c index d4cda3308ac7..75808bb84c9a 100644 --- a/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c +++ b/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c @@ -7,13 +7,15 @@ * (at your option) any later version. */ -#include -#include #include +#include #include #include #include +#include +#include + static unsigned int spi_max; module_param(spi_max, uint, 0400); MODULE_PARM_DESC(spi_max, "Set a lower SPI max transfer size"); @@ -180,6 +182,74 @@ void tinydrm_xrgb8888_to_rgb565(u16 *dst, void *vaddr, } EXPORT_SYMBOL(tinydrm_xrgb8888_to_rgb565); +/** + * tinydrm_xrgb8888_to_gray8 - Convert XRGB8888 to grayscale + * @dst: 8-bit grayscale destination buffer + * @fb: DRM framebuffer + * + * Drm doesn't have native monochrome or grayscale support. + * Such drivers can announce the commonly supported XR24 format to userspace + * and use this function to convert to the native format. + * + * Monochrome drivers will use the most significant bit, + * where 1 means foreground color and 0 background color. + * + * ITU BT.601 is used for the RGB -> luma (brightness) conversion. + * + * Returns: + * Zero on success, negative error code on failure. + */ +int tinydrm_xrgb8888_to_gray8(u8 *dst, struct drm_framebuffer *fb) +{ + struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); + struct dma_buf_attachment *import_attach = cma_obj->base.import_attach; + unsigned int x, y, pitch = fb->pitches[0]; + int ret = 0; + void *buf; + u32 *src; + + if (WARN_ON(fb->format->format != DRM_FORMAT_XRGB8888)) + return -EINVAL; + /* + * The cma memory is write-combined so reads are uncached. + * Speed up by fetching one line at a time. + */ + buf = kmalloc(pitch, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + if (import_attach) { + ret = dma_buf_begin_cpu_access(import_attach->dmabuf, + DMA_FROM_DEVICE); + if (ret) + goto err_free; + } + + for (y = 0; y < fb->height; y++) { + src = cma_obj->vaddr + (y * pitch); + memcpy(buf, src, pitch); + src = buf; + for (x = 0; x < fb->width; x++) { + u8 r = (*src & 0x00ff0000) >> 16; + u8 g = (*src & 0x0000ff00) >> 8; + u8 b = *src & 0x000000ff; + + /* ITU BT.601: Y = 0.299 R + 0.587 G + 0.114 B */ + *dst++ = (3 * r + 6 * g + b) / 10; + src++; + } + } + + if (import_attach) + ret = dma_buf_end_cpu_access(import_attach->dmabuf, + DMA_FROM_DEVICE); +err_free: + kfree(buf); + + return ret; +} +EXPORT_SYMBOL(tinydrm_xrgb8888_to_gray8); + /** * tinydrm_of_find_backlight - Find backlight device in device-tree * @dev: Device diff --git a/include/drm/tinydrm/tinydrm-helpers.h b/include/drm/tinydrm/tinydrm-helpers.h index 9b9b6cfe3ba5..a6c387f91eff 100644 --- a/include/drm/tinydrm/tinydrm-helpers.h +++ b/include/drm/tinydrm/tinydrm-helpers.h @@ -43,6 +43,7 @@ void tinydrm_swab16(u16 *dst, void *vaddr, struct drm_framebuffer *fb, void tinydrm_xrgb8888_to_rgb565(u16 *dst, void *vaddr, struct drm_framebuffer *fb, struct drm_clip_rect *clip, bool swap); +int tinydrm_xrgb8888_to_gray8(u8 *dst, struct drm_framebuffer *fb); struct backlight_device *tinydrm_of_find_backlight(struct device *dev); int tinydrm_enable_backlight(struct backlight_device *backlight); -- cgit v1.2.3 From 3589211e9b0316884f55acf3aeb0a979db79db9c Mon Sep 17 00:00:00 2001 From: Noralf Trønnes Date: Thu, 8 Jun 2017 17:14:35 +0200 Subject: drm/tinydrm: Add RePaper e-ink driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds support for the Pervasive Displays RePaper branded displays. The controller code is taken from the userspace driver available through repaper.org. Only the V231 film is supported since the others are EOL. Acked-by: Daniel Vetter Signed-off-by: Noralf Trønnes Link: http://patchwork.freedesktop.org/patch/msgid/1496934875-51984-5-git-send-email-noralf@tronnes.org --- MAINTAINERS | 6 + drivers/gpu/drm/tinydrm/Kconfig | 12 + drivers/gpu/drm/tinydrm/Makefile | 1 + drivers/gpu/drm/tinydrm/repaper.c | 1095 +++++++++++++++++++++++++++++++++++++ 4 files changed, 1114 insertions(+) create mode 100644 drivers/gpu/drm/tinydrm/repaper.c (limited to 'drivers') diff --git a/MAINTAINERS b/MAINTAINERS index 068fd67bb637..0e1efa0bd46a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4453,6 +4453,12 @@ M: Dave Airlie S: Odd Fixes F: drivers/gpu/drm/mgag200/ +DRM DRIVER FOR PERVASIVE DISPLAYS REPAPER PANELS +M: Noralf Trønnes +S: Maintained +F: drivers/gpu/drm/tinydrm/repaper.c +F: Documentation/devicetree/bindings/display/repaper.txt + DRM DRIVER FOR RAGE 128 VIDEO CARDS S: Orphan / Obsolete F: drivers/gpu/drm/r128/ diff --git a/drivers/gpu/drm/tinydrm/Kconfig b/drivers/gpu/drm/tinydrm/Kconfig index 3504c53846da..9596e447f877 100644 --- a/drivers/gpu/drm/tinydrm/Kconfig +++ b/drivers/gpu/drm/tinydrm/Kconfig @@ -19,3 +19,15 @@ config TINYDRM_MI0283QT help DRM driver for the Multi-Inno MI0283QT display panel If M is selected the module will be called mi0283qt. + +config TINYDRM_REPAPER + tristate "DRM support for Pervasive Displays RePaper panels (V231)" + depends on DRM_TINYDRM && SPI + help + DRM driver for the following Pervasive Displays panels: + 1.44" TFT EPD Panel (E1144CS021) + 1.90" TFT EPD Panel (E1190CS021) + 2.00" TFT EPD Panel (E2200CS021) + 2.71" TFT EPD Panel (E2271CS021) + + If M is selected the module will be called repaper. diff --git a/drivers/gpu/drm/tinydrm/Makefile b/drivers/gpu/drm/tinydrm/Makefile index 7a3604cf4fc2..95bb4d4fa785 100644 --- a/drivers/gpu/drm/tinydrm/Makefile +++ b/drivers/gpu/drm/tinydrm/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_TINYDRM_MIPI_DBI) += mipi-dbi.o # Displays obj-$(CONFIG_TINYDRM_MI0283QT) += mi0283qt.o +obj-$(CONFIG_TINYDRM_REPAPER) += repaper.o diff --git a/drivers/gpu/drm/tinydrm/repaper.c b/drivers/gpu/drm/tinydrm/repaper.c new file mode 100644 index 000000000000..3343d3f15a90 --- /dev/null +++ b/drivers/gpu/drm/tinydrm/repaper.c @@ -0,0 +1,1095 @@ +/* + * DRM driver for Pervasive Displays RePaper branded e-ink panels + * + * Copyright 2013-2017 Pervasive Displays, Inc. + * Copyright 2017 Noralf Trønnes + * + * The driver supports: + * Material Film: Aurora Mb (V231) + * Driver IC: G2 (eTC) + * + * The controller code was taken from the userspace driver: + * https://github.com/repaper/gratis + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define REPAPER_RID_G2_COG_ID 0x12 + +enum repaper_model { + E1144CS021 = 1, + E1190CS021, + E2200CS021, + E2271CS021, +}; + +enum repaper_stage { /* Image pixel -> Display pixel */ + REPAPER_COMPENSATE, /* B -> W, W -> B (Current Image) */ + REPAPER_WHITE, /* B -> N, W -> W (Current Image) */ + REPAPER_INVERSE, /* B -> N, W -> B (New Image) */ + REPAPER_NORMAL /* B -> B, W -> W (New Image) */ +}; + +enum repaper_epd_border_byte { + REPAPER_BORDER_BYTE_NONE, + REPAPER_BORDER_BYTE_ZERO, + REPAPER_BORDER_BYTE_SET, +}; + +struct repaper_epd { + struct tinydrm_device tinydrm; + struct spi_device *spi; + + struct gpio_desc *panel_on; + struct gpio_desc *border; + struct gpio_desc *discharge; + struct gpio_desc *reset; + struct gpio_desc *busy; + + struct thermal_zone_device *thermal; + + unsigned int height; + unsigned int width; + unsigned int bytes_per_scan; + const u8 *channel_select; + unsigned int stage_time; + unsigned int factored_stage_time; + bool middle_scan; + bool pre_border_byte; + enum repaper_epd_border_byte border_byte; + + u8 *line_buffer; + void *current_frame; + + bool enabled; + bool cleared; + bool partial; +}; + +static inline struct repaper_epd * +epd_from_tinydrm(struct tinydrm_device *tdev) +{ + return container_of(tdev, struct repaper_epd, tinydrm); +} + +static int repaper_spi_transfer(struct spi_device *spi, u8 header, + const void *tx, void *rx, size_t len) +{ + void *txbuf = NULL, *rxbuf = NULL; + struct spi_transfer tr[2] = {}; + u8 *headerbuf; + int ret; + + headerbuf = kmalloc(1, GFP_KERNEL); + if (!headerbuf) + return -ENOMEM; + + headerbuf[0] = header; + tr[0].tx_buf = headerbuf; + tr[0].len = 1; + + /* Stack allocated tx? */ + if (tx && len <= 32) { + txbuf = kmalloc(len, GFP_KERNEL); + if (!txbuf) { + ret = -ENOMEM; + goto out_free; + } + memcpy(txbuf, tx, len); + } + + if (rx) { + rxbuf = kmalloc(len, GFP_KERNEL); + if (!rxbuf) { + ret = -ENOMEM; + goto out_free; + } + } + + tr[1].tx_buf = txbuf ? txbuf : tx; + tr[1].rx_buf = rxbuf; + tr[1].len = len; + + ndelay(80); + ret = spi_sync_transfer(spi, tr, 2); + if (rx && !ret) + memcpy(rx, rxbuf, len); + +out_free: + kfree(headerbuf); + kfree(txbuf); + kfree(rxbuf); + + return ret; +} + +static int repaper_write_buf(struct spi_device *spi, u8 reg, + const u8 *buf, size_t len) +{ + int ret; + + ret = repaper_spi_transfer(spi, 0x70, ®, NULL, 1); + if (ret) + return ret; + + return repaper_spi_transfer(spi, 0x72, buf, NULL, len); +} + +static int repaper_write_val(struct spi_device *spi, u8 reg, u8 val) +{ + return repaper_write_buf(spi, reg, &val, 1); +} + +static int repaper_read_val(struct spi_device *spi, u8 reg) +{ + int ret; + u8 val; + + ret = repaper_spi_transfer(spi, 0x70, ®, NULL, 1); + if (ret) + return ret; + + ret = repaper_spi_transfer(spi, 0x73, NULL, &val, 1); + + return ret ? ret : val; +} + +static int repaper_read_id(struct spi_device *spi) +{ + int ret; + u8 id; + + ret = repaper_spi_transfer(spi, 0x71, NULL, &id, 1); + + return ret ? ret : id; +} + +static void repaper_spi_mosi_low(struct spi_device *spi) +{ + const u8 buf[1] = { 0 }; + + spi_write(spi, buf, 1); +} + +/* pixels on display are numbered from 1 so even is actually bits 1,3,5,... */ +static void repaper_even_pixels(struct repaper_epd *epd, u8 **pp, + const u8 *data, u8 fixed_value, const u8 *mask, + enum repaper_stage stage) +{ + unsigned int b; + + for (b = 0; b < (epd->width / 8); b++) { + if (data) { + u8 pixels = data[b] & 0xaa; + u8 pixel_mask = 0xff; + u8 p1, p2, p3, p4; + + if (mask) { + pixel_mask = (mask[b] ^ pixels) & 0xaa; + pixel_mask |= pixel_mask >> 1; + } + + switch (stage) { + case REPAPER_COMPENSATE: /* B -> W, W -> B (Current) */ + pixels = 0xaa | ((pixels ^ 0xaa) >> 1); + break; + case REPAPER_WHITE: /* B -> N, W -> W (Current) */ + pixels = 0x55 + ((pixels ^ 0xaa) >> 1); + break; + case REPAPER_INVERSE: /* B -> N, W -> B (New) */ + pixels = 0x55 | (pixels ^ 0xaa); + break; + case REPAPER_NORMAL: /* B -> B, W -> W (New) */ + pixels = 0xaa | (pixels >> 1); + break; + } + + pixels = (pixels & pixel_mask) | (~pixel_mask & 0x55); + p1 = (pixels >> 6) & 0x03; + p2 = (pixels >> 4) & 0x03; + p3 = (pixels >> 2) & 0x03; + p4 = (pixels >> 0) & 0x03; + pixels = (p1 << 0) | (p2 << 2) | (p3 << 4) | (p4 << 6); + *(*pp)++ = pixels; + } else { + *(*pp)++ = fixed_value; + } + } +} + +/* pixels on display are numbered from 1 so odd is actually bits 0,2,4,... */ +static void repaper_odd_pixels(struct repaper_epd *epd, u8 **pp, + const u8 *data, u8 fixed_value, const u8 *mask, + enum repaper_stage stage) +{ + unsigned int b; + + for (b = epd->width / 8; b > 0; b--) { + if (data) { + u8 pixels = data[b - 1] & 0x55; + u8 pixel_mask = 0xff; + + if (mask) { + pixel_mask = (mask[b - 1] ^ pixels) & 0x55; + pixel_mask |= pixel_mask << 1; + } + + switch (stage) { + case REPAPER_COMPENSATE: /* B -> W, W -> B (Current) */ + pixels = 0xaa | (pixels ^ 0x55); + break; + case REPAPER_WHITE: /* B -> N, W -> W (Current) */ + pixels = 0x55 + (pixels ^ 0x55); + break; + case REPAPER_INVERSE: /* B -> N, W -> B (New) */ + pixels = 0x55 | ((pixels ^ 0x55) << 1); + break; + case REPAPER_NORMAL: /* B -> B, W -> W (New) */ + pixels = 0xaa | pixels; + break; + } + + pixels = (pixels & pixel_mask) | (~pixel_mask & 0x55); + *(*pp)++ = pixels; + } else { + *(*pp)++ = fixed_value; + } + } +} + +/* interleave bits: (byte)76543210 -> (16 bit).7.6.5.4.3.2.1 */ +static inline u16 repaper_interleave_bits(u16 value) +{ + value = (value | (value << 4)) & 0x0f0f; + value = (value | (value << 2)) & 0x3333; + value = (value | (value << 1)) & 0x5555; + + return value; +} + +/* pixels on display are numbered from 1 */ +static void repaper_all_pixels(struct repaper_epd *epd, u8 **pp, + const u8 *data, u8 fixed_value, const u8 *mask, + enum repaper_stage stage) +{ + unsigned int b; + + for (b = epd->width / 8; b > 0; b--) { + if (data) { + u16 pixels = repaper_interleave_bits(data[b - 1]); + u16 pixel_mask = 0xffff; + + if (mask) { + pixel_mask = repaper_interleave_bits(mask[b - 1]); + + pixel_mask = (pixel_mask ^ pixels) & 0x5555; + pixel_mask |= pixel_mask << 1; + } + + switch (stage) { + case REPAPER_COMPENSATE: /* B -> W, W -> B (Current) */ + pixels = 0xaaaa | (pixels ^ 0x5555); + break; + case REPAPER_WHITE: /* B -> N, W -> W (Current) */ + pixels = 0x5555 + (pixels ^ 0x5555); + break; + case REPAPER_INVERSE: /* B -> N, W -> B (New) */ + pixels = 0x5555 | ((pixels ^ 0x5555) << 1); + break; + case REPAPER_NORMAL: /* B -> B, W -> W (New) */ + pixels = 0xaaaa | pixels; + break; + } + + pixels = (pixels & pixel_mask) | (~pixel_mask & 0x5555); + *(*pp)++ = pixels >> 8; + *(*pp)++ = pixels; + } else { + *(*pp)++ = fixed_value; + *(*pp)++ = fixed_value; + } + } +} + +/* output one line of scan and data bytes to the display */ +static void repaper_one_line(struct repaper_epd *epd, unsigned int line, + const u8 *data, u8 fixed_value, const u8 *mask, + enum repaper_stage stage) +{ + u8 *p = epd->line_buffer; + unsigned int b; + + repaper_spi_mosi_low(epd->spi); + + if (epd->pre_border_byte) + *p++ = 0x00; + + if (epd->middle_scan) { + /* data bytes */ + repaper_odd_pixels(epd, &p, data, fixed_value, mask, stage); + + /* scan line */ + for (b = epd->bytes_per_scan; b > 0; b--) { + if (line / 4 == b - 1) + *p++ = 0x03 << (2 * (line & 0x03)); + else + *p++ = 0x00; + } + + /* data bytes */ + repaper_even_pixels(epd, &p, data, fixed_value, mask, stage); + } else { + /* + * even scan line, but as lines on display are numbered from 1, + * line: 1,3,5,... + */ + for (b = 0; b < epd->bytes_per_scan; b++) { + if (0 != (line & 0x01) && line / 8 == b) + *p++ = 0xc0 >> (line & 0x06); + else + *p++ = 0x00; + } + + /* data bytes */ + repaper_all_pixels(epd, &p, data, fixed_value, mask, stage); + + /* + * odd scan line, but as lines on display are numbered from 1, + * line: 0,2,4,6,... + */ + for (b = epd->bytes_per_scan; b > 0; b--) { + if (0 == (line & 0x01) && line / 8 == b - 1) + *p++ = 0x03 << (line & 0x06); + else + *p++ = 0x00; + } + } + + switch (epd->border_byte) { + case REPAPER_BORDER_BYTE_NONE: + break; + + case REPAPER_BORDER_BYTE_ZERO: + *p++ = 0x00; + break; + + case REPAPER_BORDER_BYTE_SET: + switch (stage) { + case REPAPER_COMPENSATE: + case REPAPER_WHITE: + case REPAPER_INVERSE: + *p++ = 0x00; + break; + case REPAPER_NORMAL: + *p++ = 0xaa; + break; + } + break; + } + + repaper_write_buf(epd->spi, 0x0a, epd->line_buffer, + p - epd->line_buffer); + + /* Output data to panel */ + repaper_write_val(epd->spi, 0x02, 0x07); + + repaper_spi_mosi_low(epd->spi); +} + +static void repaper_frame_fixed(struct repaper_epd *epd, u8 fixed_value, + enum repaper_stage stage) +{ + unsigned int line; + + for (line = 0; line < epd->height; line++) + repaper_one_line(epd, line, NULL, fixed_value, NULL, stage); +} + +static void repaper_frame_data(struct repaper_epd *epd, const u8 *image, + const u8 *mask, enum repaper_stage stage) +{ + unsigned int line; + + if (!mask) { + for (line = 0; line < epd->height; line++) { + repaper_one_line(epd, line, + &image[line * (epd->width / 8)], + 0, NULL, stage); + } + } else { + for (line = 0; line < epd->height; line++) { + size_t n = line * epd->width / 8; + + repaper_one_line(epd, line, &image[n], 0, &mask[n], + stage); + } + } +} + +static void repaper_frame_fixed_repeat(struct repaper_epd *epd, u8 fixed_value, + enum repaper_stage stage) +{ + u64 start = local_clock(); + u64 end = start + (epd->factored_stage_time * 1000 * 1000); + + do { + repaper_frame_fixed(epd, fixed_value, stage); + } while (local_clock() < end); +} + +static void repaper_frame_data_repeat(struct repaper_epd *epd, const u8 *image, + const u8 *mask, enum repaper_stage stage) +{ + u64 start = local_clock(); + u64 end = start + (epd->factored_stage_time * 1000 * 1000); + + do { + repaper_frame_data(epd, image, mask, stage); + } while (local_clock() < end); +} + +static void repaper_get_temperature(struct repaper_epd *epd) +{ + int ret, temperature = 0; + unsigned int factor10x; + + if (!epd->thermal) + return; + + ret = thermal_zone_get_temp(epd->thermal, &temperature); + if (ret) { + dev_err(&epd->spi->dev, "Failed to get temperature (%d)\n", + ret); + return; + } + + temperature /= 1000; + + if (temperature <= -10) + factor10x = 170; + else if (temperature <= -5) + factor10x = 120; + else if (temperature <= 5) + factor10x = 80; + else if (temperature <= 10) + factor10x = 40; + else if (temperature <= 15) + factor10x = 30; + else if (temperature <= 20) + factor10x = 20; + else if (temperature <= 40) + factor10x = 10; + else + factor10x = 7; + + epd->factored_stage_time = epd->stage_time * factor10x / 10; +} + +static void repaper_gray8_to_mono_reversed(u8 *buf, u32 width, u32 height) +{ + u8 *gray8 = buf, *mono = buf; + int y, xb, i; + + for (y = 0; y < height; y++) + for (xb = 0; xb < width / 8; xb++) { + u8 byte = 0x00; + + for (i = 0; i < 8; i++) { + int x = xb * 8 + i; + + byte >>= 1; + if (gray8[y * width + x] >> 7) + byte |= BIT(7); + } + *mono++ = byte; + } +} + +static int repaper_fb_dirty(struct drm_framebuffer *fb, + struct drm_file *file_priv, + unsigned int flags, unsigned int color, + struct drm_clip_rect *clips, + unsigned int num_clips) +{ + struct tinydrm_device *tdev = fb->dev->dev_private; + struct repaper_epd *epd = epd_from_tinydrm(tdev); + u8 *buf = NULL; + int ret = 0; + + mutex_lock(&tdev->dirty_lock); + + if (!epd->enabled) + goto out_unlock; + + /* fbdev can flush even when we're not interested */ + if (tdev->pipe.plane.fb != fb) + goto out_unlock; + + repaper_get_temperature(epd); + + DRM_DEBUG("Flushing [FB:%d] st=%ums\n", fb->base.id, + epd->factored_stage_time); + + buf = kmalloc(fb->width * fb->height, GFP_KERNEL); + if (!buf) { + ret = -ENOMEM; + goto out_unlock; + } + + ret = tinydrm_xrgb8888_to_gray8(buf, fb); + if (ret) + goto out_unlock; + + repaper_gray8_to_mono_reversed(buf, fb->width, fb->height); + + if (epd->partial) { + repaper_frame_data_repeat(epd, buf, epd->current_frame, + REPAPER_NORMAL); + } else if (epd->cleared) { + repaper_frame_data_repeat(epd, epd->current_frame, NULL, + REPAPER_COMPENSATE); + repaper_frame_data_repeat(epd, epd->current_frame, NULL, + REPAPER_WHITE); + repaper_frame_data_repeat(epd, buf, NULL, REPAPER_INVERSE); + repaper_frame_data_repeat(epd, buf, NULL, REPAPER_NORMAL); + + epd->partial = true; + } else { + /* Clear display (anything -> white) */ + repaper_frame_fixed_repeat(epd, 0xff, REPAPER_COMPENSATE); + repaper_frame_fixed_repeat(epd, 0xff, REPAPER_WHITE); + repaper_frame_fixed_repeat(epd, 0xaa, REPAPER_INVERSE); + repaper_frame_fixed_repeat(epd, 0xaa, REPAPER_NORMAL); + + /* Assuming a clear (white) screen output an image */ + repaper_frame_fixed_repeat(epd, 0xaa, REPAPER_COMPENSATE); + repaper_frame_fixed_repeat(epd, 0xaa, REPAPER_WHITE); + repaper_frame_data_repeat(epd, buf, NULL, REPAPER_INVERSE); + repaper_frame_data_repeat(epd, buf, NULL, REPAPER_NORMAL); + + epd->cleared = true; + epd->partial = true; + } + + memcpy(epd->current_frame, buf, fb->width * fb->height / 8); + + /* + * An extra frame write is needed if pixels are set in the bottom line, + * or else grey lines rises up from the pixels + */ + if (epd->pre_border_byte) { + unsigned int x; + + for (x = 0; x < (fb->width / 8); x++) + if (buf[x + (fb->width * (fb->height - 1) / 8)]) { + repaper_frame_data_repeat(epd, buf, + epd->current_frame, + REPAPER_NORMAL); + break; + } + } + +out_unlock: + mutex_unlock(&tdev->dirty_lock); + + if (ret) + dev_err(fb->dev->dev, "Failed to update display (%d)\n", ret); + kfree(buf); + + return ret; +} + +static const struct drm_framebuffer_funcs repaper_fb_funcs = { + .destroy = drm_fb_cma_destroy, + .create_handle = drm_fb_cma_create_handle, + .dirty = repaper_fb_dirty, +}; + +static void power_off(struct repaper_epd *epd) +{ + /* Turn off power and all signals */ + gpiod_set_value_cansleep(epd->reset, 0); + gpiod_set_value_cansleep(epd->panel_on, 0); + if (epd->border) + gpiod_set_value_cansleep(epd->border, 0); + + /* Ensure SPI MOSI and CLOCK are Low before CS Low */ + repaper_spi_mosi_low(epd->spi); + + /* Discharge pulse */ + gpiod_set_value_cansleep(epd->discharge, 1); + msleep(150); + gpiod_set_value_cansleep(epd->discharge, 0); +} + +static void repaper_pipe_enable(struct drm_simple_display_pipe *pipe, + struct drm_crtc_state *crtc_state) +{ + struct tinydrm_device *tdev = pipe_to_tinydrm(pipe); + struct repaper_epd *epd = epd_from_tinydrm(tdev); + struct spi_device *spi = epd->spi; + struct device *dev = &spi->dev; + bool dc_ok = false; + int i, ret; + + DRM_DEBUG_DRIVER("\n"); + + /* Power up sequence */ + gpiod_set_value_cansleep(epd->reset, 0); + gpiod_set_value_cansleep(epd->panel_on, 0); + gpiod_set_value_cansleep(epd->discharge, 0); + if (epd->border) + gpiod_set_value_cansleep(epd->border, 0); + repaper_spi_mosi_low(spi); + usleep_range(5000, 10000); + + gpiod_set_value_cansleep(epd->panel_on, 1); + /* + * This delay comes from the repaper.org userspace driver, it's not + * mentioned in the datasheet. + */ + usleep_range(10000, 15000); + gpiod_set_value_cansleep(epd->reset, 1); + if (epd->border) + gpiod_set_value_cansleep(epd->border, 1); + usleep_range(5000, 10000); + gpiod_set_value_cansleep(epd->reset, 0); + usleep_range(5000, 10000); + gpiod_set_value_cansleep(epd->reset, 1); + usleep_range(5000, 10000); + + /* Wait for COG to become ready */ + for (i = 100; i > 0; i--) { + if (!gpiod_get_value_cansleep(epd->busy)) + break; + + usleep_range(10, 100); + } + + if (!i) { + dev_err(dev, "timeout waiting for panel to become ready.\n"); + power_off(epd); + return; + } + + repaper_read_id(spi); + ret = repaper_read_id(spi); + if (ret != REPAPER_RID_G2_COG_ID) { + if (ret < 0) + dev_err(dev, "failed to read chip (%d)\n", ret); + else + dev_err(dev, "wrong COG ID 0x%02x\n", ret); + power_off(epd); + return; + } + + /* Disable OE */ + repaper_write_val(spi, 0x02, 0x40); + + ret = repaper_read_val(spi, 0x0f); + if (ret < 0 || !(ret & 0x80)) { + if (ret < 0) + dev_err(dev, "failed to read chip (%d)\n", ret); + else + dev_err(dev, "panel is reported broken\n"); + power_off(epd); + return; + } + + /* Power saving mode */ + repaper_write_val(spi, 0x0b, 0x02); + /* Channel select */ + repaper_write_buf(spi, 0x01, epd->channel_select, 8); + /* High power mode osc */ + repaper_write_val(spi, 0x07, 0xd1); + /* Power setting */ + repaper_write_val(spi, 0x08, 0x02); + /* Vcom level */ + repaper_write_val(spi, 0x09, 0xc2); + /* Power setting */ + repaper_write_val(spi, 0x04, 0x03); + /* Driver latch on */ + repaper_write_val(spi, 0x03, 0x01); + /* Driver latch off */ + repaper_write_val(spi, 0x03, 0x00); + usleep_range(5000, 10000); + + /* Start chargepump */ + for (i = 0; i < 4; ++i) { + /* Charge pump positive voltage on - VGH/VDL on */ + repaper_write_val(spi, 0x05, 0x01); + msleep(240); + + /* Charge pump negative voltage on - VGL/VDL on */ + repaper_write_val(spi, 0x05, 0x03); + msleep(40); + + /* Charge pump Vcom on - Vcom driver on */ + repaper_write_val(spi, 0x05, 0x0f); + msleep(40); + + /* check DC/DC */ + ret = repaper_read_val(spi, 0x0f); + if (ret < 0) { + dev_err(dev, "failed to read chip (%d)\n", ret); + power_off(epd); + return; + } + + if (ret & 0x40) { + dc_ok = true; + break; + } + } + + if (!dc_ok) { + dev_err(dev, "dc/dc failed\n"); + power_off(epd); + return; + } + + /* + * Output enable to disable + * The userspace driver sets this to 0x04, but the datasheet says 0x06 + */ + repaper_write_val(spi, 0x02, 0x04); + + epd->enabled = true; + epd->partial = false; +} + +static void repaper_pipe_disable(struct drm_simple_display_pipe *pipe) +{ + struct tinydrm_device *tdev = pipe_to_tinydrm(pipe); + struct repaper_epd *epd = epd_from_tinydrm(tdev); + struct spi_device *spi = epd->spi; + unsigned int line; + + DRM_DEBUG_DRIVER("\n"); + + mutex_lock(&tdev->dirty_lock); + epd->enabled = false; + mutex_unlock(&tdev->dirty_lock); + + /* Nothing frame */ + for (line = 0; line < epd->height; line++) + repaper_one_line(epd, 0x7fffu, NULL, 0x00, NULL, + REPAPER_COMPENSATE); + + /* 2.7" */ + if (epd->border) { + /* Dummy line */ + repaper_one_line(epd, 0x7fffu, NULL, 0x00, NULL, + REPAPER_COMPENSATE); + msleep(25); + gpiod_set_value_cansleep(epd->border, 0); + msleep(200); + gpiod_set_value_cansleep(epd->border, 1); + } else { + /* Border dummy line */ + repaper_one_line(epd, 0x7fffu, NULL, 0x00, NULL, + REPAPER_NORMAL); + msleep(200); + } + + /* not described in datasheet */ + repaper_write_val(spi, 0x0b, 0x00); + /* Latch reset turn on */ + repaper_write_val(spi, 0x03, 0x01); + /* Power off charge pump Vcom */ + repaper_write_val(spi, 0x05, 0x03); + /* Power off charge pump neg voltage */ + repaper_write_val(spi, 0x05, 0x01); + msleep(120); + /* Discharge internal */ + repaper_write_val(spi, 0x04, 0x80); + /* turn off all charge pumps */ + repaper_write_val(spi, 0x05, 0x00); + /* Turn off osc */ + repaper_write_val(spi, 0x07, 0x01); + msleep(50); + + power_off(epd); +} + +static const struct drm_simple_display_pipe_funcs repaper_pipe_funcs = { + .enable = repaper_pipe_enable, + .disable = repaper_pipe_disable, + .update = tinydrm_display_pipe_update, + .prepare_fb = tinydrm_display_pipe_prepare_fb, +}; + +static const uint32_t repaper_formats[] = { + DRM_FORMAT_XRGB8888, +}; + +static const struct drm_display_mode repaper_e1144cs021_mode = { + TINYDRM_MODE(128, 96, 29, 22), +}; + +static const u8 repaper_e1144cs021_cs[] = { 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0f, 0xff, 0x00 }; + +static const struct drm_display_mode repaper_e1190cs021_mode = { + TINYDRM_MODE(144, 128, 36, 32), +}; + +static const u8 repaper_e1190cs021_cs[] = { 0x00, 0x00, 0x00, 0x03, + 0xfc, 0x00, 0x00, 0xff }; + +static const struct drm_display_mode repaper_e2200cs021_mode = { + TINYDRM_MODE(200, 96, 46, 22), +}; + +static const u8 repaper_e2200cs021_cs[] = { 0x00, 0x00, 0x00, 0x00, + 0x01, 0xff, 0xe0, 0x00 }; + +static const struct drm_display_mode repaper_e2271cs021_mode = { + TINYDRM_MODE(264, 176, 57, 38), +}; + +static const u8 repaper_e2271cs021_cs[] = { 0x00, 0x00, 0x00, 0x7f, + 0xff, 0xfe, 0x00, 0x00 }; + +DEFINE_DRM_GEM_CMA_FOPS(repaper_fops); + +static struct drm_driver repaper_driver = { + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | + DRIVER_ATOMIC, + .fops = &repaper_fops, + TINYDRM_GEM_DRIVER_OPS, + .name = "repaper", + .desc = "Pervasive Displays RePaper e-ink panels", + .date = "20170405", + .major = 1, + .minor = 0, +}; + +static const struct of_device_id repaper_of_match[] = { + { .compatible = "pervasive,e1144cs021", .data = (void *)E1144CS021 }, + { .compatible = "pervasive,e1190cs021", .data = (void *)E1190CS021 }, + { .compatible = "pervasive,e2200cs021", .data = (void *)E2200CS021 }, + { .compatible = "pervasive,e2271cs021", .data = (void *)E2271CS021 }, + {}, +}; +MODULE_DEVICE_TABLE(of, repaper_of_match); + +static const struct spi_device_id repaper_id[] = { + { "e1144cs021", E1144CS021 }, + { "e1190cs021", E1190CS021 }, + { "e2200cs021", E2200CS021 }, + { "e2271cs021", E2271CS021 }, + { }, +}; +MODULE_DEVICE_TABLE(spi, repaper_id); + +static int repaper_probe(struct spi_device *spi) +{ + const struct drm_display_mode *mode; + const struct spi_device_id *spi_id; + const struct of_device_id *match; + struct device *dev = &spi->dev; + struct tinydrm_device *tdev; + enum repaper_model model; + const char *thermal_zone; + struct repaper_epd *epd; + size_t line_buffer_size; + int ret; + + match = of_match_device(repaper_of_match, dev); + if (match) { + model = (enum repaper_model)match->data; + } else { + spi_id = spi_get_device_id(spi); + model = spi_id->driver_data; + } + + /* The SPI device is used to allocate dma memory */ + if (!dev->coherent_dma_mask) { + ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32)); + if (ret) { + dev_warn(dev, "Failed to set dma mask %d\n", ret); + return ret; + } + } + + epd = devm_kzalloc(dev, sizeof(*epd), GFP_KERNEL); + if (!epd) + return -ENOMEM; + + epd->spi = spi; + + epd->panel_on = devm_gpiod_get(dev, "panel-on", GPIOD_OUT_LOW); + if (IS_ERR(epd->panel_on)) { + ret = PTR_ERR(epd->panel_on); + if (ret != -EPROBE_DEFER) + dev_err(dev, "Failed to get gpio 'panel-on'\n"); + return ret; + } + + epd->discharge = devm_gpiod_get(dev, "discharge", GPIOD_OUT_LOW); + if (IS_ERR(epd->discharge)) { + ret = PTR_ERR(epd->discharge); + if (ret != -EPROBE_DEFER) + dev_err(dev, "Failed to get gpio 'discharge'\n"); + return ret; + } + + epd->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(epd->reset)) { + ret = PTR_ERR(epd->reset); + if (ret != -EPROBE_DEFER) + dev_err(dev, "Failed to get gpio 'reset'\n"); + return ret; + } + + epd->busy = devm_gpiod_get(dev, "busy", GPIOD_IN); + if (IS_ERR(epd->busy)) { + ret = PTR_ERR(epd->busy); + if (ret != -EPROBE_DEFER) + dev_err(dev, "Failed to get gpio 'busy'\n"); + return ret; + } + + if (!device_property_read_string(dev, "pervasive,thermal-zone", + &thermal_zone)) { + epd->thermal = thermal_zone_get_zone_by_name(thermal_zone); + if (IS_ERR(epd->thermal)) { + dev_err(dev, "Failed to get thermal zone: %s\n", + thermal_zone); + return PTR_ERR(epd->thermal); + } + } + + switch (model) { + case E1144CS021: + mode = &repaper_e1144cs021_mode; + epd->channel_select = repaper_e1144cs021_cs; + epd->stage_time = 480; + epd->bytes_per_scan = 96 / 4; + epd->middle_scan = true; /* data-scan-data */ + epd->pre_border_byte = false; + epd->border_byte = REPAPER_BORDER_BYTE_ZERO; + break; + + case E1190CS021: + mode = &repaper_e1190cs021_mode; + epd->channel_select = repaper_e1190cs021_cs; + epd->stage_time = 480; + epd->bytes_per_scan = 128 / 4 / 2; + epd->middle_scan = false; /* scan-data-scan */ + epd->pre_border_byte = false; + epd->border_byte = REPAPER_BORDER_BYTE_SET; + break; + + case E2200CS021: + mode = &repaper_e2200cs021_mode; + epd->channel_select = repaper_e2200cs021_cs; + epd->stage_time = 480; + epd->bytes_per_scan = 96 / 4; + epd->middle_scan = true; /* data-scan-data */ + epd->pre_border_byte = true; + epd->border_byte = REPAPER_BORDER_BYTE_NONE; + break; + + case E2271CS021: + epd->border = devm_gpiod_get(dev, "border", GPIOD_OUT_LOW); + if (IS_ERR(epd->border)) { + ret = PTR_ERR(epd->border); + if (ret != -EPROBE_DEFER) + dev_err(dev, "Failed to get gpio 'border'\n"); + return ret; + } + + mode = &repaper_e2271cs021_mode; + epd->channel_select = repaper_e2271cs021_cs; + epd->stage_time = 630; + epd->bytes_per_scan = 176 / 4; + epd->middle_scan = true; /* data-scan-data */ + epd->pre_border_byte = true; + epd->border_byte = REPAPER_BORDER_BYTE_NONE; + break; + + default: + return -ENODEV; + } + + epd->width = mode->hdisplay; + epd->height = mode->vdisplay; + epd->factored_stage_time = epd->stage_time; + + line_buffer_size = 2 * epd->width / 8 + epd->bytes_per_scan + 2; + epd->line_buffer = devm_kzalloc(dev, line_buffer_size, GFP_KERNEL); + if (!epd->line_buffer) + return -ENOMEM; + + epd->current_frame = devm_kzalloc(dev, epd->width * epd->height / 8, + GFP_KERNEL); + if (!epd->current_frame) + return -ENOMEM; + + tdev = &epd->tinydrm; + + ret = devm_tinydrm_init(dev, tdev, &repaper_fb_funcs, &repaper_driver); + if (ret) + return ret; + + ret = tinydrm_display_pipe_init(tdev, &repaper_pipe_funcs, + DRM_MODE_CONNECTOR_VIRTUAL, + repaper_formats, + ARRAY_SIZE(repaper_formats), mode, 0); + if (ret) + return ret; + + drm_mode_config_reset(tdev->drm); + + ret = devm_tinydrm_register(tdev); + if (ret) + return ret; + + spi_set_drvdata(spi, tdev); + + DRM_DEBUG_DRIVER("Initialized %s:%s @%uMHz on minor %d\n", + tdev->drm->driver->name, dev_name(dev), + spi->max_speed_hz / 1000000, + tdev->drm->primary->index); + + return 0; +} + +static void repaper_shutdown(struct spi_device *spi) +{ + struct tinydrm_device *tdev = spi_get_drvdata(spi); + + tinydrm_shutdown(tdev); +} + +static struct spi_driver repaper_spi_driver = { + .driver = { + .name = "repaper", + .owner = THIS_MODULE, + .of_match_table = repaper_of_match, + }, + .id_table = repaper_id, + .probe = repaper_probe, + .shutdown = repaper_shutdown, +}; +module_spi_driver(repaper_spi_driver); + +MODULE_DESCRIPTION("Pervasive Displays RePaper DRM driver"); +MODULE_AUTHOR("Noralf Trønnes"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 0c1f528cb13708ff3ba462a5c757d5588fc47d36 Mon Sep 17 00:00:00 2001 From: Shashank Sharma Date: Thu, 13 Jul 2017 21:03:07 +0530 Subject: drm: handle HDMI 2.0 VICs in AVI info-frames MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HDMI 1.4b support the CEA video modes as per range of CEA-861-D (VIC 1-64). For any other mode, the VIC filed in AVI infoframes should be 0. HDMI 2.0 sinks, support video modes range as per CEA-861-F spec, which is extended to (VIC 1-107). This patch adds a bool input variable, which indicates if the connected sink is a HDMI 2.0 sink or not. This will make sure that we don't pass a HDMI 2.0 VIC to a HDMI 1.4 sink. This patch touches all drm drivers, who are callers of this function drm_hdmi_avi_infoframe_from_display_mode but to make sure there is no change in current behavior, is_hdmi2 is kept as false. In case of I915 driver, this patch: - checks if the connected display is HDMI 2.0. - HDMI infoframes carry one of this two type of information: - VIC for 4K modes for HDMI 1.4 sinks - S3D information for S3D modes As CEA-861-F has already defined VICs for 4K videomodes, this patch doesn't allow sending HDMI infoframes for HDMI 2.0 sinks, until the mode is 3D. Cc: Ville Syrjala Cc: Jose Abreu Cc: Andrzej Hajda Cc: Alex Deucher Cc: Daniel Vetter PS: This patch touches a few lines in few files, which were already above 80 char, so checkpatch gives 80 char warning again. - gpu/drm/omapdrm/omap_encoder.c - gpu/drm/i915/intel_sdvo.c V2: Rebase, Added r-b from Andrzej V3: Addressed review comment from Ville: - Do not send VICs in both AVI-IF and HDMI-IF send only one of it. V4: Rebase V5: Added r-b from Neil. Addressed review comments from Ville - Do not block HDMI vendor IF, instead check for VIC while handling AVI infoframes V6: Rebase V7: Rebase Reviewed-by: Andrzej Hajda Reviewed-by: Neil Armstrong Signed-off-by: Shashank Sharma Link: http://patchwork.freedesktop.org/patch/msgid/1499960000-9232-2-git-send-email-shashank.sharma@intel.com Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/amd/amdgpu/dce_v10_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/dce_v11_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/dce_v8_0.c | 2 +- drivers/gpu/drm/bridge/analogix-anx78xx.c | 3 ++- drivers/gpu/drm/bridge/sii902x.c | 2 +- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 2 +- drivers/gpu/drm/drm_edid.c | 26 +++++++++++++++++++++++++- drivers/gpu/drm/exynos/exynos_hdmi.c | 2 +- drivers/gpu/drm/i2c/tda998x_drv.c | 2 +- drivers/gpu/drm/i915/intel_hdmi.c | 5 ++++- drivers/gpu/drm/i915/intel_sdvo.c | 3 ++- drivers/gpu/drm/mediatek/mtk_hdmi.c | 2 +- drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 2 +- drivers/gpu/drm/nouveau/nv50_display.c | 3 ++- drivers/gpu/drm/omapdrm/omap_encoder.c | 3 ++- drivers/gpu/drm/radeon/radeon_audio.c | 2 +- drivers/gpu/drm/rockchip/inno_hdmi.c | 2 +- drivers/gpu/drm/sti/sti_hdmi.c | 2 +- drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c | 2 +- drivers/gpu/drm/tegra/hdmi.c | 2 +- drivers/gpu/drm/tegra/sor.c | 2 +- drivers/gpu/drm/vc4/vc4_hdmi.c | 2 +- drivers/gpu/drm/zte/zx_hdmi.c | 2 +- include/drm/drm_edid.h | 3 ++- 25 files changed, 57 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index 9f78c03a2e31..aff1f48c947e 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c @@ -1867,7 +1867,7 @@ static void dce_v10_0_afmt_setmode(struct drm_encoder *encoder, dce_v10_0_audio_write_sad_regs(encoder); dce_v10_0_audio_write_latency_fields(encoder, mode); - err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); + err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false); if (err < 0) { DRM_ERROR("failed to setup AVI infoframe: %zd\n", err); return; diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index 4bcf01dc567a..2df650dfa727 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c @@ -1851,7 +1851,7 @@ static void dce_v11_0_afmt_setmode(struct drm_encoder *encoder, dce_v11_0_audio_write_sad_regs(encoder); dce_v11_0_audio_write_latency_fields(encoder, mode); - err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); + err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false); if (err < 0) { DRM_ERROR("failed to setup AVI infoframe: %zd\n", err); return; diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index fd134a4629d7..0c3891fa62f1 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -1597,7 +1597,7 @@ static void dce_v6_0_audio_set_avi_infoframe(struct drm_encoder *encoder, ssize_t err; u32 tmp; - err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); + err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false); if (err < 0) { DRM_ERROR("failed to setup AVI infoframe: %zd\n", err); return; diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c index a9e869554627..c164bef82846 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c @@ -1750,7 +1750,7 @@ static void dce_v8_0_afmt_setmode(struct drm_encoder *encoder, dce_v8_0_audio_write_sad_regs(encoder); dce_v8_0_audio_write_latency_fields(encoder, mode); - err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); + err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false); if (err < 0) { DRM_ERROR("failed to setup AVI infoframe: %zd\n", err); return; diff --git a/drivers/gpu/drm/bridge/analogix-anx78xx.c b/drivers/gpu/drm/bridge/analogix-anx78xx.c index c2fac3947006..dc045e0c32fc 100644 --- a/drivers/gpu/drm/bridge/analogix-anx78xx.c +++ b/drivers/gpu/drm/bridge/analogix-anx78xx.c @@ -1097,7 +1097,8 @@ static void anx78xx_bridge_mode_set(struct drm_bridge *bridge, mutex_lock(&anx78xx->lock); - err = drm_hdmi_avi_infoframe_from_display_mode(&frame, adjusted_mode); + err = drm_hdmi_avi_infoframe_from_display_mode(&frame, adjusted_mode, + false); if (err) { DRM_ERROR("Failed to setup AVI infoframe: %d\n", err); goto unlock; diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c index b8d10e599df0..9efb7b8fad57 100644 --- a/drivers/gpu/drm/bridge/sii902x.c +++ b/drivers/gpu/drm/bridge/sii902x.c @@ -269,7 +269,7 @@ static void sii902x_bridge_mode_set(struct drm_bridge *bridge, if (ret) return; - ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, adj); + ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, adj, false); if (ret < 0) { DRM_ERROR("couldn't fill AVI infoframe\n"); return; diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index de1308b61390..60faf2d2bc6b 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -1317,7 +1317,7 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode) u8 val; /* Initialise info frame from DRM mode */ - drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); + drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false); if (hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format)) frame.colorspace = HDMI_COLORSPACE_YUV444; diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 2e55599816aa..0667b0744b17 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -4334,12 +4334,14 @@ EXPORT_SYMBOL(drm_set_preferred_mode); * data from a DRM display mode * @frame: HDMI AVI infoframe * @mode: DRM display mode + * @is_hdmi2_sink: Sink is HDMI 2.0 compliant * * Return: 0 on success or a negative error code on failure. */ int drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame, - const struct drm_display_mode *mode) + const struct drm_display_mode *mode, + bool is_hdmi2_sink) { int err; @@ -4355,6 +4357,28 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame, frame->video_code = drm_match_cea_mode(mode); + /* + * HDMI 1.4 VIC range: 1 <= VIC <= 64 (CEA-861-D) but + * HDMI 2.0 VIC range: 1 <= VIC <= 107 (CEA-861-F). So we + * have to make sure we dont break HDMI 1.4 sinks. + */ + if (!is_hdmi2_sink && frame->video_code > 64) + frame->video_code = 0; + + /* + * HDMI spec says if a mode is found in HDMI 1.4b 4K modes + * we should send its VIC in vendor infoframes, else send the + * VIC in AVI infoframes. Lets check if this mode is present in + * HDMI 1.4b 4K modes + */ + if (frame->video_code) { + u8 vendor_if_vic = drm_match_hdmi_mode(mode); + bool is_s3d = mode->flags & DRM_MODE_FLAG_3D_MASK; + + if (drm_valid_hdmi_vic(vendor_if_vic) && !is_s3d) + frame->video_code = 0; + } + frame->picture_aspect = HDMI_PICTURE_ASPECT_NONE; /* diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 06bfbe400cf1..c953927fb0cb 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -784,7 +784,7 @@ static void hdmi_reg_infoframes(struct hdmi_context *hdata) } ret = drm_hdmi_avi_infoframe_from_display_mode(&frm.avi, - &hdata->current_mode); + &hdata->current_mode, false); if (!ret) ret = hdmi_avi_infoframe_pack(&frm.avi, buf, sizeof(buf)); if (ret > 0) { diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index 86f47e190309..d1e7ac540199 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -712,7 +712,7 @@ tda998x_write_avi(struct tda998x_priv *priv, struct drm_display_mode *mode) { union hdmi_infoframe frame; - drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode); + drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false); frame.avi.quantization_range = HDMI_QUANTIZATION_RANGE_FULL; tda998x_write_if(priv, DIP_IF_FLAGS_IF2, REG_IF2_HB0, &frame); diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 916340f03882..2f831cfdd243 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -459,11 +459,14 @@ static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder, struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); const struct drm_display_mode *adjusted_mode = &crtc_state->base.adjusted_mode; + struct drm_connector *connector = &intel_hdmi->attached_connector->base; + bool is_hdmi2_sink = connector->display_info.hdmi.scdc.supported; union hdmi_infoframe frame; int ret; ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, - adjusted_mode); + adjusted_mode, + is_hdmi2_sink); if (ret < 0) { DRM_ERROR("couldn't fill AVI infoframe\n"); return; diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 3f8f30b412cd..85d9ff361e74 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -996,7 +996,8 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo, ssize_t len; ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, - &pipe_config->base.adjusted_mode); + &pipe_config->base.adjusted_mode, + false); if (ret < 0) { DRM_ERROR("couldn't fill AVI infoframe\n"); return false; diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c index 0a4ffd724146..5c0d02444bd3 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c @@ -975,7 +975,7 @@ static int mtk_hdmi_setup_avi_infoframe(struct mtk_hdmi *hdmi, u8 buffer[17]; ssize_t err; - err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); + err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false); if (err < 0) { dev_err(hdmi->dev, "Failed to get AVI infoframe from mode: %zd\n", err); diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c index ae40e7179d4f..13ac822dee5d 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c @@ -97,7 +97,7 @@ static void msm_hdmi_config_avi_infoframe(struct hdmi *hdmi) u32 val; int len; - drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode); + drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false); len = hdmi_infoframe_pack(&frame, buffer, sizeof(buffer)); if (len < 0) { diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 42a85c14aea0..5f71e304022e 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -2762,7 +2762,8 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode) if (!drm_detect_hdmi_monitor(nv_connector->edid)) return; - ret = drm_hdmi_avi_infoframe_from_display_mode(&avi_frame.avi, mode); + ret = drm_hdmi_avi_infoframe_from_display_mode(&avi_frame.avi, mode, + false); if (!ret) { /* We have an AVI InfoFrame, populate it to the display */ args.pwr.avi_infoframe_length diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c index 86c977b7189a..624f5b50b755 100644 --- a/drivers/gpu/drm/omapdrm/omap_encoder.c +++ b/drivers/gpu/drm/omapdrm/omap_encoder.c @@ -85,7 +85,8 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder, if (hdmi_mode && dssdev->driver->set_hdmi_infoframe) { struct hdmi_avi_infoframe avi; - r = drm_hdmi_avi_infoframe_from_display_mode(&avi, adjusted_mode); + r = drm_hdmi_avi_infoframe_from_display_mode(&avi, adjusted_mode, + false); if (r == 0) dssdev->driver->set_hdmi_infoframe(dssdev, &avi); } diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c index aaacac190d26..770e31f5fd1b 100644 --- a/drivers/gpu/drm/radeon/radeon_audio.c +++ b/drivers/gpu/drm/radeon/radeon_audio.c @@ -516,7 +516,7 @@ static int radeon_audio_set_avi_packet(struct drm_encoder *encoder, if (!connector) return -EINVAL; - err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); + err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false); if (err < 0) { DRM_ERROR("failed to setup AVI infoframe: %d\n", err); return err; diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index 7d9b75eb6c44..7149968aa25a 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -294,7 +294,7 @@ static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi, union hdmi_infoframe frame; int rc; - rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode); + rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false); if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV444) frame.avi.colorspace = HDMI_COLORSPACE_YUV444; diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c index a59c95a8081b..dbc6a195d6f9 100644 --- a/drivers/gpu/drm/sti/sti_hdmi.c +++ b/drivers/gpu/drm/sti/sti_hdmi.c @@ -434,7 +434,7 @@ static int hdmi_avi_infoframe_config(struct sti_hdmi *hdmi) DRM_DEBUG_DRIVER("\n"); - ret = drm_hdmi_avi_infoframe_from_display_mode(&infoframe, mode); + ret = drm_hdmi_avi_infoframe_from_display_mode(&infoframe, mode, false); if (ret < 0) { DRM_ERROR("failed to setup AVI infoframe: %d\n", ret); return ret; diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c index d3398f6250ef..83b7a2a025f2 100644 --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c @@ -52,7 +52,7 @@ static int sun4i_hdmi_setup_avi_infoframes(struct sun4i_hdmi *hdmi, u8 buffer[17]; int i, ret; - ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); + ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false); if (ret < 0) { DRM_ERROR("Failed to get infoframes from mode\n"); return ret; diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c index cda0491ed6bf..718d8db406a6 100644 --- a/drivers/gpu/drm/tegra/hdmi.c +++ b/drivers/gpu/drm/tegra/hdmi.c @@ -734,7 +734,7 @@ static void tegra_hdmi_setup_avi_infoframe(struct tegra_hdmi *hdmi, u8 buffer[17]; ssize_t err; - err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); + err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false); if (err < 0) { dev_err(hdmi->dev, "failed to setup AVI infoframe: %zd\n", err); return; diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c index a8f528925009..fb2709c0c461 100644 --- a/drivers/gpu/drm/tegra/sor.c +++ b/drivers/gpu/drm/tegra/sor.c @@ -1904,7 +1904,7 @@ tegra_sor_hdmi_setup_avi_infoframe(struct tegra_sor *sor, value &= ~INFOFRAME_CTRL_ENABLE; tegra_sor_writel(sor, value, SOR_HDMI_AVI_INFOFRAME_CTRL); - err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); + err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false); if (err < 0) { dev_err(sor->dev, "failed to setup AVI infoframe: %d\n", err); return err; diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index ed63d4e85762..406d6d83b6c6 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -395,7 +395,7 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder) union hdmi_infoframe frame; int ret; - ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode); + ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false); if (ret < 0) { DRM_ERROR("couldn't fill AVI infoframe\n"); return; diff --git a/drivers/gpu/drm/zte/zx_hdmi.c b/drivers/gpu/drm/zte/zx_hdmi.c index 0df7366e594b..7e834e3eeed9 100644 --- a/drivers/gpu/drm/zte/zx_hdmi.c +++ b/drivers/gpu/drm/zte/zx_hdmi.c @@ -124,7 +124,7 @@ static int zx_hdmi_config_video_avi(struct zx_hdmi *hdmi, union hdmi_infoframe frame; int ret; - ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode); + ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false); if (ret) { DRM_DEV_ERROR(hdmi->dev, "failed to get avi infoframe: %d\n", ret); diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index 7b9f48b62e07..89c00626d654 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -343,7 +343,8 @@ drm_load_edid_firmware(struct drm_connector *connector) int drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame, - const struct drm_display_mode *mode); + const struct drm_display_mode *mode, + bool is_hdmi2_sink); int drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame, const struct drm_display_mode *mode); -- cgit v1.2.3 From 8ec6e0755565192b328059b64f982adabbecda78 Mon Sep 17 00:00:00 2001 From: Shashank Sharma Date: Thu, 13 Jul 2017 21:03:08 +0530 Subject: drm/edid: complete CEA modedb(VIC 1-107) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CEA-861-F specs defines new video modes to be used with HDMI 2.0 EDIDs. The VIC range has been extended from 1-64 to 1-107. Our existing CEA modedb contains only 64 modes (VIC=1 to VIC=64). Now to be able to parse new CEA modes using the existing methods, we have to complete the modedb (VIC=65 onwards). This patch adds: - Timings for existing CEA video modes (from VIC=65 till VIC=92) - Newly added 4k modes (from VIC=93 to VIC=107). The patch was originaly discussed and reviewed here: https://patchwork.freedesktop.org/patch/135810/ Cc: Ville Syrjala Cc: Jose Abreu Cc: Andrzej Hajda Cc: Alex Deucher Cc: Harry Wentland V2: Rebase V3: Rebase V4: Added native bit handling as per CEA-861-F spec (Ville) V5: Fix timings for VIC 77:1920x1080 and 104:3840x2160p (Ville) Remove unnecessary paranthesis from function svd_to_vic (Ville) Added r-b (Neil) V6: Rebase V7: Fix indentation for modes from VIC 80 Reviewed-by: Jose Abreu Reviewed-by: Alex Deucher Reviewed-by: Neil Armstrong Acked-by: Harry Wentland Signed-off-by: Shashank Sharma Link: http://patchwork.freedesktop.org/patch/msgid/1499960000-9232-3-git-send-email-shashank.sharma@intel.com [vsyrjala: Fix up remaining formatting/indentation issues] Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/drm_edid.c | 226 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 225 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 0667b0744b17..42c83add9d37 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1006,6 +1006,221 @@ static const struct drm_display_mode edid_cea_modes[] = { 2492, 2640, 0, 1080, 1084, 1089, 1125, 0, DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, + /* 65 - 1280x720@24Hz */ + { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 59400, 1280, 3040, + 3080, 3300, 0, 720, 725, 730, 750, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 66 - 1280x720@25Hz */ + { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 3700, + 3740, 3960, 0, 720, 725, 730, 750, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 67 - 1280x720@30Hz */ + { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 3040, + 3080, 3300, 0, 720, 725, 730, 750, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 68 - 1280x720@50Hz */ + { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1720, + 1760, 1980, 0, 720, 725, 730, 750, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 69 - 1280x720@60Hz */ + { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1390, + 1430, 1650, 0, 720, 725, 730, 750, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 70 - 1280x720@100Hz */ + { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1720, + 1760, 1980, 0, 720, 725, 730, 750, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 71 - 1280x720@120Hz */ + { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1390, + 1430, 1650, 0, 720, 725, 730, 750, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 72 - 1920x1080@24Hz */ + { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2558, + 2602, 2750, 0, 1080, 1084, 1089, 1125, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 73 - 1920x1080@25Hz */ + { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2448, + 2492, 2640, 0, 1080, 1084, 1089, 1125, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 74 - 1920x1080@30Hz */ + { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2008, + 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 75 - 1920x1080@50Hz */ + { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2448, + 2492, 2640, 0, 1080, 1084, 1089, 1125, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 76 - 1920x1080@60Hz */ + { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2008, + 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 77 - 1920x1080@100Hz */ + { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2448, + 2492, 2640, 0, 1080, 1084, 1089, 1125, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 78 - 1920x1080@120Hz */ + { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2008, + 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 79 - 1680x720@24Hz */ + { DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 59400, 1680, 3040, + 3080, 3300, 0, 720, 725, 730, 750, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 80 - 1680x720@25Hz */ + { DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 59400, 1680, 2908, + 2948, 3168, 0, 720, 725, 730, 750, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 81 - 1680x720@30Hz */ + { DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 59400, 1680, 2380, + 2420, 2640, 0, 720, 725, 730, 750, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 82 - 1680x720@50Hz */ + { DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 82500, 1680, 1940, + 1980, 2200, 0, 720, 725, 730, 750, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 83 - 1680x720@60Hz */ + { DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 99000, 1680, 1940, + 1980, 2200, 0, 720, 725, 730, 750, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 84 - 1680x720@100Hz */ + { DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 165000, 1680, 1740, + 1780, 2000, 0, 720, 725, 730, 825, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 85 - 1680x720@120Hz */ + { DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 198000, 1680, 1740, + 1780, 2000, 0, 720, 725, 730, 825, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 86 - 2560x1080@24Hz */ + { DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 99000, 2560, 3558, + 3602, 3750, 0, 1080, 1084, 1089, 1100, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 87 - 2560x1080@25Hz */ + { DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 90000, 2560, 3008, + 3052, 3200, 0, 1080, 1084, 1089, 1125, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 88 - 2560x1080@30Hz */ + { DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 118800, 2560, 3328, + 3372, 3520, 0, 1080, 1084, 1089, 1125, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 89 - 2560x1080@50Hz */ + { DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 185625, 2560, 3108, + 3152, 3300, 0, 1080, 1084, 1089, 1125, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 90 - 2560x1080@60Hz */ + { DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 198000, 2560, 2808, + 2852, 3000, 0, 1080, 1084, 1089, 1100, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 91 - 2560x1080@100Hz */ + { DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 371250, 2560, 2778, + 2822, 2970, 0, 1080, 1084, 1089, 1250, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 92 - 2560x1080@120Hz */ + { DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 495000, 2560, 3108, + 3152, 3300, 0, 1080, 1084, 1089, 1250, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 93 - 3840x2160p@24Hz 16:9 */ + { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 5116, + 5204, 5500, 0, 2160, 2168, 2178, 2250, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, + /* 94 - 3840x2160p@25Hz 16:9 */ + { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4896, + 4984, 5280, 0, 2160, 2168, 2178, 2250, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, + /* 95 - 3840x2160p@30Hz 16:9 */ + { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4016, + 4104, 4400, 0, 2160, 2168, 2178, 2250, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, + /* 96 - 3840x2160p@50Hz 16:9 */ + { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4896, + 4984, 5280, 0, 2160, 2168, 2178, 2250, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, + /* 97 - 3840x2160p@60Hz 16:9 */ + { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4016, + 4104, 4400, 0, 2160, 2168, 2178, 2250, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, + /* 98 - 4096x2160p@24Hz 256:135 */ + { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 297000, 4096, 5116, + 5204, 5500, 0, 2160, 2168, 2178, 2250, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, }, + /* 99 - 4096x2160p@25Hz 256:135 */ + { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 297000, 4096, 5064, + 5152, 5280, 0, 2160, 2168, 2178, 2250, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, }, + /* 100 - 4096x2160p@30Hz 256:135 */ + { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 297000, 4096, 4184, + 4272, 4400, 0, 2160, 2168, 2178, 2250, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, }, + /* 101 - 4096x2160p@50Hz 256:135 */ + { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 594000, 4096, 5064, + 5152, 5280, 0, 2160, 2168, 2178, 2250, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, }, + /* 102 - 4096x2160p@60Hz 256:135 */ + { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 594000, 4096, 4184, + 4272, 4400, 0, 2160, 2168, 2178, 2250, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, }, + /* 103 - 3840x2160p@24Hz 64:27 */ + { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 5116, + 5204, 5500, 0, 2160, 2168, 2178, 2250, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 104 - 3840x2160p@25Hz 64:27 */ + { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4896, + 4984, 5280, 0, 2160, 2168, 2178, 2250, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 105 - 3840x2160p@30Hz 64:27 */ + { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4016, + 4104, 4400, 0, 2160, 2168, 2178, 2250, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 106 - 3840x2160p@50Hz 64:27 */ + { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4896, + 4984, 5280, 0, 2160, 2168, 2178, 2250, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 107 - 3840x2160p@60Hz 64:27 */ + { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4016, + 4104, 4400, 0, 2160, 2168, 2178, 2250, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, }; /* @@ -2902,6 +3117,15 @@ add_alternate_cea_modes(struct drm_connector *connector, struct edid *edid) return modes; } +static u8 svd_to_vic(u8 svd) +{ + /* 0-6 bit vic, 7th bit native mode indicator */ + if ((svd >= 1 && svd <= 64) || (svd >= 129 && svd <= 192)) + return svd & 127; + + return svd; +} + static struct drm_display_mode * drm_display_mode_from_vic_index(struct drm_connector *connector, const u8 *video_db, u8 video_len, @@ -2915,7 +3139,7 @@ drm_display_mode_from_vic_index(struct drm_connector *connector, return NULL; /* CEA modes are numbered 1..127 */ - vic = (video_db[video_index] & 127); + vic = svd_to_vic(video_db[video_index]); if (!drm_valid_cea_vic(vic)) return NULL; -- cgit v1.2.3 From 0f0f87083015af9bcfd4dc04bae92258c980861c Mon Sep 17 00:00:00 2001 From: Shashank Sharma Date: Thu, 13 Jul 2017 21:03:09 +0530 Subject: drm/edid: parse sink information before CEA blocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CEA-861-F adds ycbcr capability map block, for HDMI 2.0 sinks. This block contains a map of indexes of CEA modes, which can support YCBCR 420 output also. To avoid multiple parsing of same CEA block, let's parse the sink information and get this map, before parsing CEA modes. This patch moves the call to drm_add_display_info function, before the mode parsing block. V4: Introduced new patch in the series V5: Move this patch before 4:2:0 parsing patch (ville) Added r-b from Ville V6: Rebase V7: Rebase Reviewed-by: Ville Syrjälä Signed-off-by: Shashank Sharma Link: http://patchwork.freedesktop.org/patch/msgid/1499960000-9232-4-git-send-email-shashank.sharma@intel.com Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/drm_edid.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 42c83add9d37..dc0eb31355c9 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -4438,6 +4438,13 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) quirks = edid_get_quirks(edid); + /* + * CEA-861-F adds ycbcr capability map block, for HDMI 2.0 sinks. + * To avoid multiple parsing of same block, lets parse that map + * from sink info, before parsing CEA modes. + */ + drm_add_display_info(connector, edid); + /* * EDID spec says modes should be preferred in this order: * - preferred detailed mode @@ -4465,8 +4472,6 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75)) edid_fixup_preferred(connector, quirks); - drm_add_display_info(connector, edid); - if (quirks & EDID_QUIRK_FORCE_6BPC) connector->display_info.bpc = 6; -- cgit v1.2.3 From 87563fc0301f44f7a37ecba9490a60507ae9bbf2 Mon Sep 17 00:00:00 2001 From: Shashank Sharma Date: Thu, 13 Jul 2017 21:03:10 +0530 Subject: drm/edid: cleanup patch for CEA extended-tag macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CEA-861-F introduces extended tag codes for EDID extension blocks, which indicates the actual type of the data block. The code for using exteded tag is 0x7, whereas in the existing code, the corresponding macro is named as "VIDEO_CAPABILITY_BLOCK" This patch renames the macro and usages from "VIDEO_CAPABILITY_BLOCK" to "USE_EXTENDED_TAG" V2: Add extended tag code check for video capabilitiy block (ville) V3: Ville: - Use suggested names for macros - Check the block length first, before checking the extended tag V4: Fix commit message (David) V5: Introduced this patch into HDMI-YCBCR-output series V6: Rebase V7: Rebase Cc: Ville Syrjala Signed-off-by: Shashank Sharma Link: http://patchwork.freedesktop.org/patch/msgid/1499960000-9232-5-git-send-email-shashank.sharma@intel.com Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/drm_edid.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index dc0eb31355c9..9a3937527058 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2781,7 +2781,8 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid, #define VIDEO_BLOCK 0x02 #define VENDOR_BLOCK 0x03 #define SPEAKER_BLOCK 0x04 -#define VIDEO_CAPABILITY_BLOCK 0x07 +#define USE_EXTENDED_TAG 0x07 +#define EXT_VIDEO_CAPABILITY_BLOCK 0x00 #define EDID_BASIC_AUDIO (1 << 6) #define EDID_CEA_YCRCB444 (1 << 5) #define EDID_CEA_YCRCB422 (1 << 4) @@ -3441,6 +3442,12 @@ cea_db_payload_len(const u8 *db) return db[0] & 0x1f; } +static int +cea_db_extended_tag(const u8 *db) +{ + return db[1]; +} + static int cea_db_tag(const u8 *db) { @@ -4017,8 +4024,10 @@ bool drm_rgb_quant_range_selectable(struct edid *edid) return false; for_each_cea_db(edid_ext, i, start, end) { - if (cea_db_tag(&edid_ext[i]) == VIDEO_CAPABILITY_BLOCK && - cea_db_payload_len(&edid_ext[i]) == 2) { + if (cea_db_tag(&edid_ext[i]) == USE_EXTENDED_TAG && + cea_db_payload_len(&edid_ext[i]) == 2 && + cea_db_extended_tag(&edid_ext[i]) == + EXT_VIDEO_CAPABILITY_BLOCK) { DRM_DEBUG_KMS("CEA VCDB 0x%02x\n", edid_ext[i + 2]); return edid_ext[i + 2] & EDID_CEA_VCDB_QS; } -- cgit v1.2.3 From d85231530b0719e23a62d92ee35712da966e281a Mon Sep 17 00:00:00 2001 From: Shashank Sharma Date: Thu, 13 Jul 2017 21:03:11 +0530 Subject: drm: add helper to validate YCBCR420 modes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit YCBCR420 modes are supported only on HDMI 2.0 capable sources. This patch adds: - A drm helper to validate YCBCR420-only mode on a particular connector. This function will help pruning the YCBCR420-only modes from the connector's modelist. - A bool variable (ycbcr_420_allowed) in the drm connector structure. While handling the EDID from HDMI 2.0 sinks, its important to know if the source is capable of handling YCBCR420 output, so that no YCBCR 420 modes will be listed for sources which can't handle it. A driver should set this variable if it wants to see YCBCR420 modes in the modedb. V5: Introduced the patch in series. V6: Squashed two patches (validate YCBCR420 and add YCBCR420 identifier) V7: Addressed review comments from Vile: - Move this patch before we add 420 modes from EDID. - No need for drm_valid_cea_vic() check, function back to non-static. - Update MODE_STATUS with NO_420 condition. - Introduce y420_vdb_modes variable in this patch Cc: Ville Syrjala Signed-off-by: Shashank Sharma Link: http://patchwork.freedesktop.org/patch/msgid/1499960000-9232-6-git-send-email-shashank.sharma@intel.com [vsyrjala: Drop the now bogus EXPORT_SYMBOL(drm_valid_cea_vic)] Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/drm_modes.c | 29 +++++++++++++++++++++++++++++ drivers/gpu/drm/drm_probe_helper.c | 4 ++++ include/drm/drm_connector.h | 17 +++++++++++++++++ include/drm/drm_modes.h | 5 +++++ 4 files changed, 55 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index f2493b9b82e6..35630b80cd48 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1083,6 +1083,34 @@ drm_mode_validate_size(const struct drm_display_mode *mode, } EXPORT_SYMBOL(drm_mode_validate_size); +/** + * drm_mode_validate_ycbcr420 - add 'ycbcr420-only' modes only when allowed + * @mode: mode to check + * @connector: drm connector under action + * + * This function is a helper which can be used to filter out any YCBCR420 + * only mode, when the source doesn't support it. + * + * Returns: + * The mode status + */ +enum drm_mode_status +drm_mode_validate_ycbcr420(const struct drm_display_mode *mode, + struct drm_connector *connector) +{ + u8 vic = drm_match_cea_mode(mode); + enum drm_mode_status status = MODE_OK; + struct drm_hdmi_info *hdmi = &connector->display_info.hdmi; + + if (test_bit(vic, hdmi->y420_vdb_modes)) { + if (!connector->ycbcr_420_allowed) + status = MODE_NO_420; + } + + return status; +} +EXPORT_SYMBOL(drm_mode_validate_ycbcr420); + #define MODE_STATUS(status) [MODE_ ## status + 3] = #status static const char * const drm_mode_status_names[] = { @@ -1122,6 +1150,7 @@ static const char * const drm_mode_status_names[] = { MODE_STATUS(ONE_SIZE), MODE_STATUS(NO_REDUCED), MODE_STATUS(NO_STEREO), + MODE_STATUS(NO_420), MODE_STATUS(STALE), MODE_STATUS(BAD), MODE_STATUS(ERROR), diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index 00e6832a8c1a..904966cde32b 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -528,6 +528,10 @@ retry: if (mode->status == MODE_OK) mode->status = drm_mode_validate_pipeline(mode, connector); + + if (mode->status == MODE_OK) + mode->status = drm_mode_validate_ycbcr420(mode, + connector); } prune: diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index ae5b7dc316c8..26dd3eb9767d 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -135,6 +135,14 @@ struct drm_scdc { struct drm_hdmi_info { /** @scdc: sink's scdc support and capabilities */ struct drm_scdc scdc; + + /** + * @y420_vdb_modes: bitmap of modes which can support ycbcr420 + * output only (not normal RGB/YCBCR444/422 outputs). There are total + * 107 VICs defined by CEA-861-F spec, so the size is 128 bits to map + * upto 128 VICs; + */ + unsigned long y420_vdb_modes[BITS_TO_LONGS(128)]; }; /** @@ -726,6 +734,15 @@ struct drm_connector { bool interlace_allowed; bool doublescan_allowed; bool stereo_allowed; + + /** + * @ycbcr_420_allowed : This bool indicates if this connector is + * capable of handling YCBCR 420 output. While parsing the EDID + * blocks, its very helpful to know, if the source is capable of + * handling YCBCR 420 outputs. + */ + bool ycbcr_420_allowed; + /** * @registered: Is this connector exposed (registered) with userspace? * Protected by @mutex. diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h index 94ac771fe460..f8a1268dfbcb 100644 --- a/include/drm/drm_modes.h +++ b/include/drm/drm_modes.h @@ -80,6 +80,7 @@ struct videomode; * @MODE_ONE_SIZE: only one resolution is supported * @MODE_NO_REDUCED: monitor doesn't accept reduced blanking * @MODE_NO_STEREO: stereo modes not supported + * @MODE_NO_420: ycbcr 420 modes not supported * @MODE_STALE: mode has become stale * @MODE_BAD: unspecified reason * @MODE_ERROR: error condition @@ -124,6 +125,7 @@ enum drm_mode_status { MODE_ONE_SIZE, MODE_NO_REDUCED, MODE_NO_STEREO, + MODE_NO_420, MODE_STALE = -3, MODE_BAD = -2, MODE_ERROR = -1 @@ -496,6 +498,9 @@ bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1, enum drm_mode_status drm_mode_validate_basic(const struct drm_display_mode *mode); enum drm_mode_status drm_mode_validate_size(const struct drm_display_mode *mode, int maxX, int maxY); +enum drm_mode_status +drm_mode_validate_ycbcr420(const struct drm_display_mode *mode, + struct drm_connector *connector); void drm_mode_prune_invalid(struct drm_device *dev, struct list_head *mode_list, bool verbose); void drm_mode_sort(struct list_head *mode_list); -- cgit v1.2.3 From 832d4f2f417d1786769c7a91a0a6363ea58cfc10 Mon Sep 17 00:00:00 2001 From: Shashank Sharma Date: Fri, 14 Jul 2017 16:03:46 +0530 Subject: drm/edid: parse YCBCR420 videomodes from EDID MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HDMI 2.0 spec adds support for YCBCR420 sub-sampled output. CEA-861-F adds two new blocks in EDID's CEA extension blocks, to provide information about sink's YCBCR420 output capabilities. These blocks are: - YCBCR420vdb(YCBCR 420 video data block): This block contains VICs of video modes, which can be sopported only in YCBCR420 output mode (Not in RGB/YCBCR444/422. Its like a normal SVD block, valid for YCBCR420 modes only. - YCBCR420cmdb(YCBCR 420 capability map data block): This block gives information about video modes which can support YCBCR420 output mode also (along with RGB,YCBCR444/422 etc) This block contains a bitmap index of normal svd videomodes, which can support YCBCR420 output too. So if bit 0 from first vcb byte is set, first video mode in the svd list can support YCBCR420 output too. Bit 1 means second video mode from svd list can support YCBCR420 output too, and so on. This patch adds two bitmaps in display's hdmi_info structure, one each for VCB and VDB modes. If the source is HDMI 2.0 capable, this patch adds: - VDB modes (YCBCR 420 only modes) in connector's mode list, also makes an entry in the vdb_bitmap per vic. - VCB modes (YCBCR 420 also modes) only entry in the vcb_bitmap. Cc: Ville Syrjala Cc: Jose Abreu Cc: Emil Velikov V2: Addressed Review comments from Emil: - Use 1ULL< 64 modes in capability map block. - Use y420cmdb in function names and macros while dealing with vcb to be aligned with spec. - Move the display information parsing block ahead of mode parsing blocks. V3: Addressed design/review comments from Ville - Do not add flags in video modes, else we have to expose them to user - There should not be a UABI change, and kernel should detect the choice of the output based on type of mode, and the bitmaps. - Use standard bitops from kernel bitmap header, instead of calculating bit positions manually. V4: Addressed review comments from Ville: - s/ycbcr_420_vdb/y420vdb - s/ycbcr_420_vcb/y420cmdb - Be less verbose on description of do_y420vdb_modes - Move newmode variable in the loop scope. - Use svd_to_vic() to get a VIC, instead of 0x7f - Remove bitmap description for CMDB modes & VDB modes - Dont add connector->ycbcr_420_allowed check for cmdb modes - Remove 'len' variable, in is_y420cmdb function, which is used only once - Add length check in is_y420vdb function - Remove unnecessary if (!db) check in function parse_y420cmdb_bitmap - Do not add print about YCBCR 420 modes - Fix indentation in few places - Move ycbcr420_dc_modes in next patch, where its used - Add a separate patch for movement of drm_add_display_info() V5: Addressed review comments from Ville: - Add the patch which cleans up the current EXTENDED_TAG usage - Make y420_cmdb_map u64 - Do not block ycbcr420 modes while parsing the EDID, rather add a separate helper function to prune ycbcr420-only modes from connector's probed modes. V6: Rebase V7: Move this patch after the 420_only validation patch (Ville) V8: Addressed review comments from Ville - use cea_vic_valid check before adding cmdb/vdb modes - add check for i < 64 while adding cmdb modes - use 1ULL while checking bitmap Signed-off-by: Shashank Sharma Link: http://patchwork.freedesktop.org/patch/msgid/1500028426-14883-1-git-send-email-shashank.sharma@intel.com [vsyrjala: Fix checkpatch complaints and indentation] Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/drm_edid.c | 152 +++++++++++++++++++++++++++++++++++++++++++- include/drm/drm_connector.h | 12 ++++ 2 files changed, 162 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 9a3937527058..31881a71118d 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2783,6 +2783,8 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid, #define SPEAKER_BLOCK 0x04 #define USE_EXTENDED_TAG 0x07 #define EXT_VIDEO_CAPABILITY_BLOCK 0x00 +#define EXT_VIDEO_DATA_BLOCK_420 0x0E +#define EXT_VIDEO_CAP_BLOCK_Y420CMDB 0x0F #define EDID_BASIC_AUDIO (1 << 6) #define EDID_CEA_YCRCB444 (1 << 5) #define EDID_CEA_YCRCB422 (1 << 4) @@ -3153,15 +3155,85 @@ drm_display_mode_from_vic_index(struct drm_connector *connector, return newmode; } +/* + * do_y420vdb_modes - Parse YCBCR 420 only modes + * @connector: connector corresponding to the HDMI sink + * @svds: start of the data block of CEA YCBCR 420 VDB + * @len: length of the CEA YCBCR 420 VDB + * + * Parse the CEA-861-F YCBCR 420 Video Data Block (Y420VDB) + * which contains modes which can be supported in YCBCR 420 + * output format only. + */ +static int do_y420vdb_modes(struct drm_connector *connector, + const u8 *svds, u8 svds_len) +{ + int modes = 0, i; + struct drm_device *dev = connector->dev; + struct drm_display_info *info = &connector->display_info; + struct drm_hdmi_info *hdmi = &info->hdmi; + + for (i = 0; i < svds_len; i++) { + u8 vic = svd_to_vic(svds[i]); + struct drm_display_mode *newmode; + + if (!drm_valid_cea_vic(vic)) + continue; + + newmode = drm_mode_duplicate(dev, &edid_cea_modes[vic]); + if (!newmode) + break; + bitmap_set(hdmi->y420_vdb_modes, vic, 1); + drm_mode_probed_add(connector, newmode); + modes++; + } + + if (modes > 0) + info->color_formats |= DRM_COLOR_FORMAT_YCRCB420; + return modes; +} + +/* + * drm_add_cmdb_modes - Add a YCBCR 420 mode into bitmap + * @connector: connector corresponding to the HDMI sink + * @vic: CEA vic for the video mode to be added in the map + * + * Makes an entry for a videomode in the YCBCR 420 bitmap + */ +static void +drm_add_cmdb_modes(struct drm_connector *connector, u8 svd) +{ + u8 vic = svd_to_vic(svd); + struct drm_hdmi_info *hdmi = &connector->display_info.hdmi; + + if (!drm_valid_cea_vic(vic)) + return; + + bitmap_set(hdmi->y420_cmdb_modes, vic, 1); +} + static int do_cea_modes(struct drm_connector *connector, const u8 *db, u8 len) { int i, modes = 0; + struct drm_hdmi_info *hdmi = &connector->display_info.hdmi; for (i = 0; i < len; i++) { struct drm_display_mode *mode; mode = drm_display_mode_from_vic_index(connector, db, len, i); if (mode) { + /* + * YCBCR420 capability block contains a bitmap which + * gives the index of CEA modes from CEA VDB, which + * can support YCBCR 420 sampling output also (apart + * from RGB/YCBCR444 etc). + * For example, if the bit 0 in bitmap is set, + * first mode in VDB can support YCBCR420 output too. + * Add YCBCR420 modes only if sink is HDMI 2.0 capable. + */ + if (i < 64 && hdmi->y420_cmdb_map & (1ULL << i)) + drm_add_cmdb_modes(connector, db[i]); + drm_mode_probed_add(connector, mode); modes++; } @@ -3503,9 +3575,77 @@ static bool cea_db_is_hdmi_forum_vsdb(const u8 *db) return oui == HDMI_FORUM_IEEE_OUI; } +static bool cea_db_is_y420cmdb(const u8 *db) +{ + if (cea_db_tag(db) != USE_EXTENDED_TAG) + return false; + + if (!cea_db_payload_len(db)) + return false; + + if (cea_db_extended_tag(db) != EXT_VIDEO_CAP_BLOCK_Y420CMDB) + return false; + + return true; +} + +static bool cea_db_is_y420vdb(const u8 *db) +{ + if (cea_db_tag(db) != USE_EXTENDED_TAG) + return false; + + if (!cea_db_payload_len(db)) + return false; + + if (cea_db_extended_tag(db) != EXT_VIDEO_DATA_BLOCK_420) + return false; + + return true; +} + #define for_each_cea_db(cea, i, start, end) \ for ((i) = (start); (i) < (end) && (i) + cea_db_payload_len(&(cea)[(i)]) < (end); (i) += cea_db_payload_len(&(cea)[(i)]) + 1) +static void drm_parse_y420cmdb_bitmap(struct drm_connector *connector, + const u8 *db) +{ + struct drm_display_info *info = &connector->display_info; + struct drm_hdmi_info *hdmi = &info->hdmi; + u8 map_len = cea_db_payload_len(db) - 1; + u8 count; + u64 map = 0; + + if (map_len == 0) { + /* All CEA modes support ycbcr420 sampling also.*/ + hdmi->y420_cmdb_map = U64_MAX; + info->color_formats |= DRM_COLOR_FORMAT_YCRCB420; + return; + } + + /* + * This map indicates which of the existing CEA block modes + * from VDB can support YCBCR420 output too. So if bit=0 is + * set, first mode from VDB can support YCBCR420 output too. + * We will parse and keep this map, before parsing VDB itself + * to avoid going through the same block again and again. + * + * Spec is not clear about max possible size of this block. + * Clamping max bitmap block size at 8 bytes. Every byte can + * address 8 CEA modes, in this way this map can address + * 8*8 = first 64 SVDs. + */ + if (WARN_ON_ONCE(map_len > 8)) + map_len = 8; + + for (count = 0; count < map_len; count++) + map |= (u64)db[2 + count] << (8 * count); + + if (map) + info->color_formats |= DRM_COLOR_FORMAT_YCRCB420; + + hdmi->y420_cmdb_map = map; +} + static int add_cea_modes(struct drm_connector *connector, struct edid *edid) { @@ -3528,10 +3668,16 @@ add_cea_modes(struct drm_connector *connector, struct edid *edid) video = db + 1; video_len = dbl; modes += do_cea_modes(connector, video, dbl); - } - else if (cea_db_is_hdmi_vsdb(db)) { + } else if (cea_db_is_hdmi_vsdb(db)) { hdmi = db; hdmi_len = dbl; + } else if (cea_db_is_y420vdb(db)) { + const u8 *vdb420 = &db[2]; + + /* Add 4:2:0(only) modes present in EDID */ + modes += do_y420vdb_modes(connector, + vdb420, + dbl - 1); } } } @@ -4214,6 +4360,8 @@ static void drm_parse_cea_ext(struct drm_connector *connector, drm_parse_hdmi_vsdb_video(connector, db); if (cea_db_is_hdmi_forum_vsdb(db)) drm_parse_hdmi_forum_vsdb(connector, db); + if (cea_db_is_y420cmdb(db)) + drm_parse_y420cmdb_bitmap(connector, db); } } diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 26dd3eb9767d..225e09256645 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -143,6 +143,17 @@ struct drm_hdmi_info { * upto 128 VICs; */ unsigned long y420_vdb_modes[BITS_TO_LONGS(128)]; + + /** + * @y420_cmdb_modes: bitmap of modes which can support ycbcr420 + * output also, along with normal HDMI outputs. There are total 107 + * VICs defined by CEA-861-F spec, so the size is 128 bits to map upto + * 128 VICs; + */ + unsigned long y420_cmdb_modes[BITS_TO_LONGS(128)]; + + /** @y420_cmdb_map: bitmap of SVD index, to extraxt vcb modes */ + u64 y420_cmdb_map; }; /** @@ -206,6 +217,7 @@ struct drm_display_info { #define DRM_COLOR_FORMAT_RGB444 (1<<0) #define DRM_COLOR_FORMAT_YCRCB444 (1<<1) #define DRM_COLOR_FORMAT_YCRCB422 (1<<2) +#define DRM_COLOR_FORMAT_YCRCB420 (1<<3) /** * @color_formats: HDMI Color formats, selects between RGB and YCrCb -- cgit v1.2.3 From e6a9a2c3dc4377f62650faf1c978d073c55d62ec Mon Sep 17 00:00:00 2001 From: Shashank Sharma Date: Thu, 13 Jul 2017 21:03:13 +0530 Subject: drm/edid: parse ycbcr 420 deep color information MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CEA-861-F spec adds ycbcr420 deep color support information in hf-vsdb block. This patch extends the existing hf-vsdb parsing function by adding parsing of ycbcr420 deep color support from the EDID and adding it into display information stored. V2: Rebase V3: Rebase V4: Moved definition of y420_dc_modes into this patch, where its used (Ville) V5: Optimize function, if(conditions) not reqd (Ville) V6: Rebase V7: Rebase Cc: Ville Syrjälä Cc: Jose Abreu Signed-off-by: Shashank Sharma Link: http://patchwork.freedesktop.org/patch/msgid/1499960000-9232-8-git-send-email-shashank.sharma@intel.com [vsyrjala: Fix sparse indentation warn] Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/drm_edid.c | 12 ++++++++++++ include/drm/drm_connector.h | 3 +++ include/drm/drm_edid.h | 8 ++++++++ 3 files changed, 23 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 31881a71118d..6bb6337be920 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -4202,6 +4202,16 @@ drm_default_rgb_quant_range(const struct drm_display_mode *mode) } EXPORT_SYMBOL(drm_default_rgb_quant_range); +static void drm_parse_ycbcr420_deep_color_info(struct drm_connector *connector, + const u8 *db) +{ + u8 dc_mask; + struct drm_hdmi_info *hdmi = &connector->display_info.hdmi; + + dc_mask = db[7] & DRM_EDID_YCBCR420_DC_MASK; + hdmi->y420_dc_modes |= dc_mask; +} + static void drm_parse_hdmi_forum_vsdb(struct drm_connector *connector, const u8 *hf_vsdb) { @@ -4242,6 +4252,8 @@ static void drm_parse_hdmi_forum_vsdb(struct drm_connector *connector, scdc->scrambling.low_rates = true; } } + + drm_parse_ycbcr420_deep_color_info(connector, hf_vsdb); } static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector, diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 225e09256645..4bc088269d05 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -154,6 +154,9 @@ struct drm_hdmi_info { /** @y420_cmdb_map: bitmap of SVD index, to extraxt vcb modes */ u64 y420_cmdb_map; + + /** @y420_dc_modes: bitmap of deep color support index */ + u8 y420_dc_modes; }; /** diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index 89c00626d654..1e1908a6b1d6 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -213,6 +213,14 @@ struct detailed_timing { #define DRM_EDID_HDMI_DC_30 (1 << 4) #define DRM_EDID_HDMI_DC_Y444 (1 << 3) +/* YCBCR 420 deep color modes */ +#define DRM_EDID_YCBCR420_DC_48 (1 << 6) +#define DRM_EDID_YCBCR420_DC_36 (1 << 5) +#define DRM_EDID_YCBCR420_DC_30 (1 << 4) +#define DRM_EDID_YCBCR420_DC_MASK (DRM_EDID_YCBCR420_DC_48 | \ + DRM_EDID_YCBCR420_DC_36 | \ + DRM_EDID_YCBCR420_DC_30) + /* ELD Header Block */ #define DRM_ELD_HEADER_BLOCK_SIZE 4 -- cgit v1.2.3 From 2570fe2586254ff174c2ba5a20dabbde707dbb9b Mon Sep 17 00:00:00 2001 From: Shashank Sharma Date: Thu, 13 Jul 2017 21:03:14 +0530 Subject: drm: add helper functions for YCBCR420 handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds helper functions for YCBCR 420 handling. These functions do: - check if a given video mode is YCBCR 420 only mode. - check if a given video mode is YCBCR 420 also mode. V2: Added YCBCR functions as helpers in DRM layer, instead of keeping it in I915 layer. V3: Added handling for YCBCR-420 only modes too. V4: EXPORT_SYMBOL(drm_find_hdmi_output_type) V5: Addressed review comments from Danvet: - %s/drm_find_hdmi_output_type/drm_display_info_hdmi_output_type - %s/drm_can_support_ycbcr_output/drm_display_supports_ycbcr_output - %s/drm_can_support_this_ycbcr_output/ drm_display_supports_this_ycbcr_output - pass drm_display_info instead of drm_connector for consistency - For drm_get_highest_quality_ycbcr_supported doc, move the variable description above, and then the function description. V6: Add only YCBCR420 helpers (Ville) V7: Addressed review comments from Ville - Remove cea_vic_valid() check. - Fix indentation. - Make input parameters to helpers, const. Cc: Ville Syrjala Cc: Jose Abreu Cc: Daniel Vetter Signed-off-by: Shashank Sharma Link: http://patchwork.freedesktop.org/patch/msgid/1499960000-9232-9-git-send-email-shashank.sharma@intel.com [vsyrjala: Fix sparse indentation warn] Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/drm_modes.c | 58 +++++++++++++++++++++++++++++++++++++++++++++ include/drm/drm_modes.h | 6 +++++ 2 files changed, 64 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 35630b80cd48..c1aec532281c 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1605,3 +1605,61 @@ int drm_mode_convert_umode(struct drm_display_mode *out, out: return ret; } + +/** + * drm_mode_is_420_only - if a given videomode can be only supported in YCBCR420 + * output format + * + * @connector: drm connector under action. + * @mode: video mode to be tested. + * + * Returns: + * true if the mode can be supported in YCBCR420 format + * false if not. + */ +bool drm_mode_is_420_only(const struct drm_display_info *display, + const struct drm_display_mode *mode) +{ + u8 vic = drm_match_cea_mode(mode); + + return test_bit(vic, display->hdmi.y420_vdb_modes); +} +EXPORT_SYMBOL(drm_mode_is_420_only); + +/** + * drm_mode_is_420_also - if a given videomode can be supported in YCBCR420 + * output format also (along with RGB/YCBCR444/422) + * + * @display: display under action. + * @mode: video mode to be tested. + * + * Returns: + * true if the mode can be support YCBCR420 format + * false if not. + */ +bool drm_mode_is_420_also(const struct drm_display_info *display, + const struct drm_display_mode *mode) +{ + u8 vic = drm_match_cea_mode(mode); + + return test_bit(vic, display->hdmi.y420_cmdb_modes); +} +EXPORT_SYMBOL(drm_mode_is_420_also); +/** + * drm_mode_is_420 - if a given videomode can be supported in YCBCR420 + * output format + * + * @display: display under action. + * @mode: video mode to be tested. + * + * Returns: + * true if the mode can be supported in YCBCR420 format + * false if not. + */ +bool drm_mode_is_420(const struct drm_display_info *display, + const struct drm_display_mode *mode) +{ + return drm_mode_is_420_only(display, mode) || + drm_mode_is_420_also(display, mode); +} +EXPORT_SYMBOL(drm_mode_is_420); diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h index f8a1268dfbcb..9f3421c8efcd 100644 --- a/include/drm/drm_modes.h +++ b/include/drm/drm_modes.h @@ -452,6 +452,12 @@ int drm_mode_convert_umode(struct drm_display_mode *out, const struct drm_mode_modeinfo *in); void drm_mode_probed_add(struct drm_connector *connector, struct drm_display_mode *mode); void drm_mode_debug_printmodeline(const struct drm_display_mode *mode); +bool drm_mode_is_420_only(const struct drm_display_info *display, + const struct drm_display_mode *mode); +bool drm_mode_is_420_also(const struct drm_display_info *display, + const struct drm_display_mode *mode); +bool drm_mode_is_420(const struct drm_display_info *display, + const struct drm_display_mode *mode); struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay, int vdisplay, int vrefresh, -- cgit v1.2.3 From e65d51126f89a0d67ee6c5df58363730b1410ab5 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 27 Jun 2017 12:58:32 -0700 Subject: drm/vc4: Fix DSI T_INIT timing. The DPHY spec requires a much larger T_INIT than I was specifying before. In the absence of clear specs from the slave of what their timing is, just use the value that the firmware was using. Signed-off-by: Eric Anholt Link: http://patchwork.freedesktop.org/patch/msgid/20170627195839.3338-2-eric@anholt.net Reviewed-by: Andrzej Hajda --- drivers/gpu/drm/vc4/vc4_dsi.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c index 5e8b81eaa168..15f6d5005ab9 100644 --- a/drivers/gpu/drm/vc4/vc4_dsi.c +++ b/drivers/gpu/drm/vc4/vc4_dsi.c @@ -1035,7 +1035,17 @@ static void vc4_dsi_encoder_enable(struct drm_encoder *encoder) DSI_HS_DLT4_TRAIL) | VC4_SET_FIELD(0, DSI_HS_DLT4_ANLAT)); - DSI_PORT_WRITE(HS_DLT5, VC4_SET_FIELD(dsi_hs_timing(ui_ns, 1000, 5000), + /* T_INIT is how long STOP is driven after power-up to + * indicate to the slave (also coming out of power-up) that + * master init is complete, and should be greater than the + * maximum of two value: T_INIT,MASTER and T_INIT,SLAVE. The + * D-PHY spec gives a minimum 100us for T_INIT,MASTER and + * T_INIT,SLAVE, while allowing protocols on top of it to give + * greater minimums. The vc4 firmware uses an extremely + * conservative 5ms, and we maintain that here. + */ + DSI_PORT_WRITE(HS_DLT5, VC4_SET_FIELD(dsi_hs_timing(ui_ns, + 5 * 1000 * 1000, 0), DSI_HS_DLT5_INIT)); DSI_PORT_WRITE(HS_DLT6, -- cgit v1.2.3 From ec878c0756a0c202e86256dca1de307ab1189ab8 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 27 Jun 2017 12:58:33 -0700 Subject: drm/vc4: Fix misleading name of the continuous flag. The logic was all right in the end, the name was just backwards. Signed-off-by: Eric Anholt Link: http://patchwork.freedesktop.org/patch/msgid/20170627195839.3338-3-eric@anholt.net Reviewed-by: Andrzej Hajda --- drivers/gpu/drm/vc4/vc4_dsi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c index 15f6d5005ab9..629d372633e6 100644 --- a/drivers/gpu/drm/vc4/vc4_dsi.c +++ b/drivers/gpu/drm/vc4/vc4_dsi.c @@ -736,18 +736,18 @@ static void vc4_dsi_latch_ulps(struct vc4_dsi *dsi, bool latch) /* Enters or exits Ultra Low Power State. */ static void vc4_dsi_ulps(struct vc4_dsi *dsi, bool ulps) { - bool continuous = dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS; - u32 phyc_ulps = ((continuous ? DSI_PORT_BIT(PHYC_CLANE_ULPS) : 0) | + bool non_continuous = dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS; + u32 phyc_ulps = ((non_continuous ? DSI_PORT_BIT(PHYC_CLANE_ULPS) : 0) | DSI_PHYC_DLANE0_ULPS | (dsi->lanes > 1 ? DSI_PHYC_DLANE1_ULPS : 0) | (dsi->lanes > 2 ? DSI_PHYC_DLANE2_ULPS : 0) | (dsi->lanes > 3 ? DSI_PHYC_DLANE3_ULPS : 0)); - u32 stat_ulps = ((continuous ? DSI1_STAT_PHY_CLOCK_ULPS : 0) | + u32 stat_ulps = ((non_continuous ? DSI1_STAT_PHY_CLOCK_ULPS : 0) | DSI1_STAT_PHY_D0_ULPS | (dsi->lanes > 1 ? DSI1_STAT_PHY_D1_ULPS : 0) | (dsi->lanes > 2 ? DSI1_STAT_PHY_D2_ULPS : 0) | (dsi->lanes > 3 ? DSI1_STAT_PHY_D3_ULPS : 0)); - u32 stat_stop = ((continuous ? DSI1_STAT_PHY_CLOCK_STOP : 0) | + u32 stat_stop = ((non_continuous ? DSI1_STAT_PHY_CLOCK_STOP : 0) | DSI1_STAT_PHY_D0_STOP | (dsi->lanes > 1 ? DSI1_STAT_PHY_D1_STOP : 0) | (dsi->lanes > 2 ? DSI1_STAT_PHY_D2_STOP : 0) | -- cgit v1.2.3 From 0c1a1b6cba85de405cd4c656f8bd65e54724a3cb Mon Sep 17 00:00:00 2001 From: Fabrice Gasnier Date: Mon, 10 Jul 2017 15:23:58 +0200 Subject: iio: dac: stm32: fix error message Fix error message, there's no 'st,dac-channel' property, but 'reg' (see https://lkml.org/lkml/2017/4/3/567). Signed-off-by: Fabrice Gasnier Signed-off-by: Jonathan Cameron --- drivers/iio/dac/stm32-dac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/dac/stm32-dac.c b/drivers/iio/dac/stm32-dac.c index 50f8ec091058..c1864e8aa851 100644 --- a/drivers/iio/dac/stm32-dac.c +++ b/drivers/iio/dac/stm32-dac.c @@ -268,7 +268,7 @@ static int stm32_dac_chan_of_init(struct iio_dev *indio_dev) break; } if (i >= ARRAY_SIZE(stm32_dac_channels)) { - dev_err(&indio_dev->dev, "Invalid st,dac-channel\n"); + dev_err(&indio_dev->dev, "Invalid reg property\n"); return -EINVAL; } -- cgit v1.2.3 From 9d9ebe64dc2e1b3cb6411c817527409fe94227b1 Mon Sep 17 00:00:00 2001 From: Fabrice Gasnier Date: Mon, 10 Jul 2017 15:23:59 +0200 Subject: iio: dac: stm32: add support for stm32f4 This adds support for STM32F4 Digital-To-Analog converter. Add compatible configuration data to handle hfsel (not present in stm32f4). Signed-off-by: Fabrice Gasnier Signed-off-by: Jonathan Cameron --- drivers/iio/dac/stm32-dac-core.c | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/dac/stm32-dac-core.c b/drivers/iio/dac/stm32-dac-core.c index 75e48788c7ea..32701be71cf7 100644 --- a/drivers/iio/dac/stm32-dac-core.c +++ b/drivers/iio/dac/stm32-dac-core.c @@ -42,6 +42,14 @@ struct stm32_dac_priv { struct stm32_dac_common common; }; +/** + * struct stm32_dac_cfg - DAC configuration + * @has_hfsel: DAC has high frequency control + */ +struct stm32_dac_cfg { + bool has_hfsel; +}; + static struct stm32_dac_priv *to_stm32_dac_priv(struct stm32_dac_common *com) { return container_of(com, struct stm32_dac_priv, common); @@ -57,6 +65,7 @@ static const struct regmap_config stm32_dac_regmap_cfg = { static int stm32_dac_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + const struct stm32_dac_cfg *cfg; struct stm32_dac_priv *priv; struct regmap *regmap; struct resource *res; @@ -69,6 +78,8 @@ static int stm32_dac_probe(struct platform_device *pdev) priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; + cfg = (const struct stm32_dac_cfg *) + of_match_device(dev->driver->of_match_table, dev)->data; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); mmio = devm_ioremap_resource(dev, res); @@ -121,12 +132,16 @@ static int stm32_dac_probe(struct platform_device *pdev) reset_control_deassert(priv->rst); } - /* When clock speed is higher than 80MHz, set HFSEL */ - priv->common.hfsel = (clk_get_rate(priv->pclk) > 80000000UL); - ret = regmap_update_bits(regmap, STM32_DAC_CR, STM32H7_DAC_CR_HFSEL, - priv->common.hfsel ? STM32H7_DAC_CR_HFSEL : 0); - if (ret) - goto err_pclk; + if (cfg && cfg->has_hfsel) { + /* When clock speed is higher than 80MHz, set HFSEL */ + priv->common.hfsel = (clk_get_rate(priv->pclk) > 80000000UL); + ret = regmap_update_bits(regmap, STM32_DAC_CR, + STM32H7_DAC_CR_HFSEL, + priv->common.hfsel ? + STM32H7_DAC_CR_HFSEL : 0); + if (ret) + goto err_pclk; + } platform_set_drvdata(pdev, &priv->common); @@ -158,8 +173,17 @@ static int stm32_dac_remove(struct platform_device *pdev) return 0; } +static const struct stm32_dac_cfg stm32h7_dac_cfg = { + .has_hfsel = true, +}; + static const struct of_device_id stm32_dac_of_match[] = { - { .compatible = "st,stm32h7-dac-core", }, + { + .compatible = "st,stm32f4-dac-core", + }, { + .compatible = "st,stm32h7-dac-core", + .data = (void *)&stm32h7_dac_cfg, + }, {}, }; MODULE_DEVICE_TABLE(of, stm32_dac_of_match); -- cgit v1.2.3 From 105967ad68d2eb1a041bc041f9cf96af2a653b65 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 14 Jul 2017 11:31:03 +0200 Subject: staging:iio:resolver:ad2s1210 fix negative IIO_ANGL_VEL read gcc-7 points out an older regression: drivers/staging/iio/resolver/ad2s1210.c: In function 'ad2s1210_read_raw': drivers/staging/iio/resolver/ad2s1210.c:515:42: error: '<<' in boolean context, did you mean '<' ? [-Werror=int-in-bool-context] The original code had 'unsigned short' here, but incorrectly got converted to 'bool'. This reverts the regression and uses a normal type instead. Fixes: 29148543c521 ("staging:iio:resolver:ad2s1210 minimal chan spec conversion.") Cc: stable@vger.kernel.org Signed-off-by: Arnd Bergmann Signed-off-by: Jonathan Cameron --- drivers/staging/iio/resolver/ad2s1210.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c index a6a8393d6664..3e00df74b18c 100644 --- a/drivers/staging/iio/resolver/ad2s1210.c +++ b/drivers/staging/iio/resolver/ad2s1210.c @@ -472,7 +472,7 @@ static int ad2s1210_read_raw(struct iio_dev *indio_dev, long m) { struct ad2s1210_state *st = iio_priv(indio_dev); - bool negative; + u16 negative; int ret = 0; u16 pos; s16 vel; -- cgit v1.2.3 From bc4b2a518f20508d866b55b5ea2739f3ced18cb6 Mon Sep 17 00:00:00 2001 From: Gaurav Gupta Date: Tue, 27 Jun 2017 09:46:01 -0700 Subject: iio: core: Fix mapping of iio channels to entry numbers When adding maps to the list, they were added using list_add, which adds them in LIFO order. When parsing using iio_channel_get_all(), these elements are hence returned in reverse order. As a result, the iio_hwmon mapping maps the first entry to the last channel and so on. Signed-off-by: Gaurav Gupta Signed-off-by: Jonathan Cameron --- drivers/iio/inkern.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c index a3941bade6a7..487bf6b75172 100644 --- a/drivers/iio/inkern.c +++ b/drivers/iio/inkern.c @@ -44,7 +44,7 @@ int iio_map_array_register(struct iio_dev *indio_dev, struct iio_map *maps) } mapi->map = &maps[i]; mapi->indio_dev = indio_dev; - list_add(&mapi->l, &iio_map_list); + list_add_tail(&mapi->l, &iio_map_list); i++; } error_ret: -- cgit v1.2.3 From c95a05f9f359c895dc6bd63862923ceba059ef22 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 4 Jul 2017 22:09:21 -0500 Subject: cpufreq: speedstep: remove unnecessary static in speedstep_detect_chipset() Remove unnecessary static on local variable hostbridge. Such variable is initialized before being used, on every execution path throughout the function. The static has no benefit and, removing it reduces the code size. This issue was detected using Coccinelle and the following semantic patch: @bad exists@ position p; identifier x; type T; @@ static T x@p; ... x = <+...x...+> @@ identifier x; expression e; type T; position p != bad.p; @@ -static T x@p; ... when != x when strict ?x = e; In the following log you can see the difference in the code size. Also, there is a significant difference in the bss segment. This log is the output of the size command, before and after the code change: before: text data bss dec hex filename 5084 3392 256 8732 221c drivers/cpufreq/speedstep-ich.o after: text data bss dec hex filename 5062 3304 192 8558 216e drivers/cpufreq/speedstep-ich.o Signed-off-by: Gustavo A. R. Silva Acked-by: Viresh Kumar Acked-by: Dominik Brodowski Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/speedstep-ich.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/cpufreq/speedstep-ich.c b/drivers/cpufreq/speedstep-ich.c index b86953a3ddc4..0412a246a785 100644 --- a/drivers/cpufreq/speedstep-ich.c +++ b/drivers/cpufreq/speedstep-ich.c @@ -207,7 +207,7 @@ static unsigned int speedstep_detect_chipset(void) * 8100 which use a pretty old revision of the 82815 * host bridge. Abort on these systems. */ - static struct pci_dev *hostbridge; + struct pci_dev *hostbridge; hostbridge = pci_get_subsys(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_MC, -- cgit v1.2.3 From a5685781dfe9e7c2391d004f6a725042e7121c3e Mon Sep 17 00:00:00 2001 From: Shubhrajyoti Datta Date: Thu, 13 Jul 2017 11:19:10 +0200 Subject: cpufreq: dt: Add zynqmp to the cpufreq dt platdev Add zynqmp to the cpufreq dt platform device. Signed-off-by: Shubhrajyoti Datta Signed-off-by: Michal Simek Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq-dt-platdev.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index 1c262923fe58..2eb40d46d357 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -94,6 +94,7 @@ static const struct of_device_id machines[] __initconst = { { .compatible = "ti,omap5", }, { .compatible = "xlnx,zynq-7000", }, + { .compatible = "xlnx,zynqmp", }, { .compatible = "zte,zx296718", }, -- cgit v1.2.3 From 5b60697cd89cf5a438b2984e11859228e5ec1c6b Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 12 Jul 2017 09:21:49 +0530 Subject: PM / OPP: OF: Use pr_debug() instead of pr_err() while adding OPP table Some platforms add the OPPs dynamically from platform specific drivers instead of getting them statically from DT. The cpufreq-dt driver already ignores the return value of dev_pm_opp_of_cpumask_add_table() to not error out for such cases, but we still end up printing error message from that routine. That's not nice. Convert the print message to use pr_debug() instead. Reported-by: Mason Signed-off-by: Viresh Kumar Reviewed-by: Stephen Boyd Signed-off-by: Rafael J. Wysocki --- drivers/base/power/opp/of.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/base/power/opp/of.c b/drivers/base/power/opp/of.c index 57eec1ca0569..6f0497b377c7 100644 --- a/drivers/base/power/opp/of.c +++ b/drivers/base/power/opp/of.c @@ -539,8 +539,12 @@ int dev_pm_opp_of_cpumask_add_table(const struct cpumask *cpumask) ret = dev_pm_opp_of_add_table(cpu_dev); if (ret) { - pr_err("%s: couldn't find opp table for cpu:%d, %d\n", - __func__, cpu, ret); + /* + * OPP may get registered dynamically, don't print error + * message here. + */ + pr_debug("%s: couldn't find opp table for cpu:%d, %d\n", + __func__, cpu, ret); /* Free all other OPPs */ dev_pm_opp_of_cpumask_remove_table(cpumask); -- cgit v1.2.3 From 1f59ab2783aed04f1318b840950801e38b2bebdf Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Wed, 12 Jul 2017 17:45:57 -0700 Subject: ACPI / video: Add force_none quirk for Dell OptiPlex 9020M Dell OptiPlex 9020M is a micro PC desktop that has no built-in LCD panel and its acpi_video does not work. Signed-off-by: Alex Hung Signed-off-by: Rafael J. Wysocki --- drivers/acpi/video_detect.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index d179e8d9177d..601e5d372887 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -103,6 +103,12 @@ static int video_detect_force_native(const struct dmi_system_id *d) return 0; } +static int video_detect_force_none(const struct dmi_system_id *d) +{ + acpi_backlight_dmi = acpi_backlight_none; + return 0; +} + static const struct dmi_system_id video_detect_dmi_table[] = { /* On Samsung X360, the BIOS will set a flag (VDRV) if generic * ACPI backlight device is used. This flag will definitively break @@ -313,6 +319,14 @@ static const struct dmi_system_id video_detect_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Precision 7510"), }, }, + { + .callback = video_detect_force_none, + .ident = "Dell OptiPlex 9020M", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 9020M"), + }, + }, { }, }; -- cgit v1.2.3 From ff890bc00830830799a72ed7481836f0dd9c3be9 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Thu, 6 Jul 2017 22:25:56 +0530 Subject: extcon: int3496: Constify acpi_device_id acpi_device_id are not supposed to change at runtime. All functions working with acpi_device_id provided by work with const acpi_device_id. So mark the non-const structs as const. File size before: text data bss dec hex filename 1733 352 0 2085 825 drivers/extcon/extcon-intel-int3496.o File size After adding 'const': text data bss dec hex filename 1797 272 0 2069 815 drivers/extcon/extcon-intel-int3496.o Signed-off-by: Arvind Yadav Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-intel-int3496.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/extcon/extcon-intel-int3496.c b/drivers/extcon/extcon-intel-int3496.c index d9f9afe45961..1a45e745717d 100644 --- a/drivers/extcon/extcon-intel-int3496.c +++ b/drivers/extcon/extcon-intel-int3496.c @@ -171,7 +171,7 @@ static int int3496_remove(struct platform_device *pdev) return 0; } -static struct acpi_device_id int3496_acpi_match[] = { +static const struct acpi_device_id int3496_acpi_match[] = { { "INT3496" }, { } }; -- cgit v1.2.3 From f0b5c2c963708dfbcbb5e2871aca35fa71664d3a Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Wed, 22 Mar 2017 19:08:37 +0900 Subject: phy: qcom-usb-hs: Replace the extcon API This patch uses the resource-managed extcon API for extcon_register_notifier() and replaces the deprecated extcon API as following: - (deprecated) extcon_get_cable_state_() -> extcon_get_state() Acked-by: Kishon Vijay Abraham I Signed-off-by: Chanwoo Choi --- drivers/phy/qualcomm/phy-qcom-usb-hs.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/phy/qualcomm/phy-qcom-usb-hs.c b/drivers/phy/qualcomm/phy-qcom-usb-hs.c index 4b20abc3ae2f..2d0c70b5589f 100644 --- a/drivers/phy/qualcomm/phy-qcom-usb-hs.c +++ b/drivers/phy/qualcomm/phy-qcom-usb-hs.c @@ -155,12 +155,12 @@ static int qcom_usb_hs_phy_power_on(struct phy *phy) } if (uphy->vbus_edev) { - state = extcon_get_cable_state_(uphy->vbus_edev, EXTCON_USB); + state = extcon_get_state(uphy->vbus_edev, EXTCON_USB); /* setup initial state */ qcom_usb_hs_phy_vbus_notifier(&uphy->vbus_notify, state, uphy->vbus_edev); - ret = extcon_register_notifier(uphy->vbus_edev, EXTCON_USB, - &uphy->vbus_notify); + ret = devm_extcon_register_notifier(&ulpi->dev, uphy->vbus_edev, + EXTCON_USB, &uphy->vbus_notify); if (ret) goto err_ulpi; } @@ -179,16 +179,8 @@ err_sleep: static int qcom_usb_hs_phy_power_off(struct phy *phy) { - int ret; struct qcom_usb_hs_phy *uphy = phy_get_drvdata(phy); - if (uphy->vbus_edev) { - ret = extcon_unregister_notifier(uphy->vbus_edev, EXTCON_USB, - &uphy->vbus_notify); - if (ret) - return ret; - } - regulator_disable(uphy->v3p3); regulator_disable(uphy->v1p8); clk_disable_unprepare(uphy->sleep_clk); -- cgit v1.2.3 From f7d0879f10080d52b1af383f049b880c78e4fa82 Mon Sep 17 00:00:00 2001 From: Karthik Tummala Date: Thu, 29 Jun 2017 22:38:45 +0530 Subject: staging: ccree: Use __func__ instead of function name Fixed following checkpatch.pl warning: WARNING: Prefer using '"%s...", __func__' to using the function's name, in a string It is prefered to use '%s & __func__' instead of function name for logging. Signed-off-by: Karthik Tummala Acked-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_aead.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_aead.c b/drivers/staging/ccree/ssi_aead.c index 1fc0b05ea0d5..116816125466 100644 --- a/drivers/staging/ccree/ssi_aead.c +++ b/drivers/staging/ccree/ssi_aead.c @@ -1886,7 +1886,7 @@ static int config_gcm_context(struct aead_request *req) (req->cryptlen - ctx->authsize); __be32 counter = cpu_to_be32(2); - SSI_LOG_DEBUG("config_gcm_context() cryptlen = %d, req->assoclen = %d ctx->authsize = %d\n", cryptlen, req->assoclen, ctx->authsize); + SSI_LOG_DEBUG("%s() cryptlen = %d, req->assoclen = %d ctx->authsize = %d\n", __func__, cryptlen, req->assoclen, ctx->authsize); memset(req_ctx->hkey, 0, AES_BLOCK_SIZE); @@ -2198,7 +2198,7 @@ static int ssi_rfc4106_gcm_setkey(struct crypto_aead *tfm, const u8 *key, unsign struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); int rc = 0; - SSI_LOG_DEBUG("ssi_rfc4106_gcm_setkey() keylen %d, key %p\n", keylen, key); + SSI_LOG_DEBUG("%s() keylen %d, key %p\n", __func__, keylen, key); if (keylen < 4) return -EINVAL; @@ -2216,7 +2216,7 @@ static int ssi_rfc4543_gcm_setkey(struct crypto_aead *tfm, const u8 *key, unsign struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); int rc = 0; - SSI_LOG_DEBUG("ssi_rfc4543_gcm_setkey() keylen %d, key %p\n", keylen, key); + SSI_LOG_DEBUG("%s() keylen %d, key %p\n", __func__, keylen, key); if (keylen < 4) return -EINVAL; -- cgit v1.2.3 From 60ba7c7c26b8df3688a952cf4bcfbc8dcdafdb9b Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sun, 9 Jul 2017 00:43:37 -0500 Subject: staging: ccree: remove unnecessary cast on kmalloc The assignment operator implicitly converts a void pointer to the type of the pointer it is assigned to. This issue was detected using Coccinelle and the following semantic patch: @@ expression * e; expression arg1, arg2; type T; @@ - e=(T*) + e= kmalloc(arg1, arg2); Signed-off-by: Gustavo A. R. Silva Acked-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_buffer_mgr.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_buffer_mgr.c b/drivers/staging/ccree/ssi_buffer_mgr.c index b35871eeabd1..18a86942134c 100644 --- a/drivers/staging/ccree/ssi_buffer_mgr.c +++ b/drivers/staging/ccree/ssi_buffer_mgr.c @@ -1725,8 +1725,7 @@ int ssi_buffer_mgr_init(struct ssi_drvdata *drvdata) struct buff_mgr_handle *buff_mgr_handle; struct device *dev = &drvdata->plat_dev->dev; - buff_mgr_handle = (struct buff_mgr_handle *) - kmalloc(sizeof(struct buff_mgr_handle), GFP_KERNEL); + buff_mgr_handle = kmalloc(sizeof(struct buff_mgr_handle), GFP_KERNEL); if (!buff_mgr_handle) return -ENOMEM; -- cgit v1.2.3 From 4a73bb48ded88adfc7180cb5a00a0b89dd41c7fb Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sun, 9 Jul 2017 00:45:59 -0500 Subject: staging: ccree: use sizeof(*var) in kmalloc Fix the following checkpatch warning: CHECK: Prefer kmalloc(sizeof(*buff_mgr_handle)...) over kmalloc(sizeof(struct buff_mgr_handle)...) Signed-off-by: Gustavo A. R. Silva Acked-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_buffer_mgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_buffer_mgr.c b/drivers/staging/ccree/ssi_buffer_mgr.c index 18a86942134c..9caff9b096db 100644 --- a/drivers/staging/ccree/ssi_buffer_mgr.c +++ b/drivers/staging/ccree/ssi_buffer_mgr.c @@ -1725,7 +1725,7 @@ int ssi_buffer_mgr_init(struct ssi_drvdata *drvdata) struct buff_mgr_handle *buff_mgr_handle; struct device *dev = &drvdata->plat_dev->dev; - buff_mgr_handle = kmalloc(sizeof(struct buff_mgr_handle), GFP_KERNEL); + buff_mgr_handle = kmalloc(sizeof(*buff_mgr_handle), GFP_KERNEL); if (!buff_mgr_handle) return -ENOMEM; -- cgit v1.2.3 From 113f0d6a71eb6744fd45818b08dd29d306e117b6 Mon Sep 17 00:00:00 2001 From: Tyler Olivieri Date: Sun, 9 Jul 2017 17:10:43 -0400 Subject: staging: ccree: remove redudant semicolons Patch to remove checkpatch warning: WARNING: Statements terminations use 1 semicolon Signed-off-by: Tyler Olivieri Acked-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_buffer_mgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_buffer_mgr.c b/drivers/staging/ccree/ssi_buffer_mgr.c index 9caff9b096db..c9c0e77becb3 100644 --- a/drivers/staging/ccree/ssi_buffer_mgr.c +++ b/drivers/staging/ccree/ssi_buffer_mgr.c @@ -150,7 +150,7 @@ static inline int ssi_buffer_mgr_render_buff_to_mlli( u32 **mlli_entry_pp) { u32 *mlli_entry_p = *mlli_entry_pp; - u32 new_nents;; + u32 new_nents; /* Verify there is no memory overflow*/ new_nents = (*curr_nents + buff_size / CC_MAX_MLLI_ENTRY_SIZE + 1); -- cgit v1.2.3 From 85420e0bce239d915b4985abfbfc90b4ececf3dd Mon Sep 17 00:00:00 2001 From: Tyler Olivieri Date: Sun, 9 Jul 2017 17:10:44 -0400 Subject: staging: ccree: fix placement of curly braces Patch to fix checkpatch errors: ERROR: that open brace { should be on the previous line ERROR: open brace '{' following function declarations go on the next line Signed-off-by: Tyler Olivieri Acked-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_buffer_mgr.c | 12 ++--- drivers/staging/ccree/ssi_cipher.c | 6 ++- drivers/staging/ccree/ssi_driver.c | 5 +- drivers/staging/ccree/ssi_fips_ll.c | 85 +++++++++++----------------------- drivers/staging/ccree/ssi_hash.c | 3 +- drivers/staging/ccree/ssi_sysfs.c | 3 +- 6 files changed, 40 insertions(+), 74 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_buffer_mgr.c b/drivers/staging/ccree/ssi_buffer_mgr.c index c9c0e77becb3..363a38f87c49 100644 --- a/drivers/staging/ccree/ssi_buffer_mgr.c +++ b/drivers/staging/ccree/ssi_buffer_mgr.c @@ -696,8 +696,7 @@ void ssi_buffer_mgr_unmap_aead_request( } if (drvdata->coherent && (areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) && - likely(req->src == req->dst)) - { + likely(req->src == req->dst)) { u32 size_to_skip = req->assoclen; if (areq_ctx->is_gcm4543) @@ -1134,8 +1133,7 @@ static inline int ssi_buffer_mgr_aead_chain_data( sg_index += areq_ctx->srcSgl->length; src_mapped_nents--; } - if (unlikely(src_mapped_nents > LLI_MAX_NUM_OF_DATA_ENTRIES)) - { + if (unlikely(src_mapped_nents > LLI_MAX_NUM_OF_DATA_ENTRIES)) { SSI_LOG_ERR("Too many fragments. current %d max %d\n", src_mapped_nents, LLI_MAX_NUM_OF_DATA_ENTRIES); return -ENOMEM; @@ -1177,8 +1175,7 @@ static inline int ssi_buffer_mgr_aead_chain_data( sg_index += areq_ctx->dstSgl->length; dst_mapped_nents--; } - if (unlikely(dst_mapped_nents > LLI_MAX_NUM_OF_DATA_ENTRIES)) - { + if (unlikely(dst_mapped_nents > LLI_MAX_NUM_OF_DATA_ENTRIES)) { SSI_LOG_ERR("Too many fragments. current %d max %d\n", dst_mapped_nents, LLI_MAX_NUM_OF_DATA_ENTRIES); return -ENOMEM; @@ -1274,8 +1271,7 @@ int ssi_buffer_mgr_map_aead_request( if (drvdata->coherent && (areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) && - likely(req->src == req->dst)) - { + likely(req->src == req->dst)) { u32 size_to_skip = req->assoclen; if (is_gcm4543) diff --git a/drivers/staging/ccree/ssi_cipher.c b/drivers/staging/ccree/ssi_cipher.c index cd2eafc04232..4ef0c9ba8678 100644 --- a/drivers/staging/ccree/ssi_cipher.c +++ b/drivers/staging/ccree/ssi_cipher.c @@ -68,7 +68,8 @@ struct ssi_ablkcipher_ctx { static void ssi_ablkcipher_complete(struct device *dev, void *ssi_req, void __iomem *cc_base); -static int validate_keys_sizes(struct ssi_ablkcipher_ctx *ctx_p, u32 size) { +static int validate_keys_sizes(struct ssi_ablkcipher_ctx *ctx_p, u32 size) +{ switch (ctx_p->flow_mode) { case S_DIN_to_AES: switch (size) { @@ -108,7 +109,8 @@ static int validate_keys_sizes(struct ssi_ablkcipher_ctx *ctx_p, u32 size) { return -EINVAL; } -static int validate_data_size(struct ssi_ablkcipher_ctx *ctx_p, unsigned int size) { +static int validate_data_size(struct ssi_ablkcipher_ctx *ctx_p, unsigned int size) +{ switch (ctx_p->flow_mode) { case S_DIN_to_AES: switch (ctx_p->cipher_mode) { diff --git a/drivers/staging/ccree/ssi_driver.c b/drivers/staging/ccree/ssi_driver.c index 78709b92736d..d3964740ec9e 100644 --- a/drivers/staging/ccree/ssi_driver.c +++ b/drivers/staging/ccree/ssi_driver.c @@ -301,13 +301,10 @@ static int init_cc_resources(struct platform_device *plat_dev) goto init_cc_res_err; if (!new_drvdata->plat_dev->dev.dma_mask) - { new_drvdata->plat_dev->dev.dma_mask = &new_drvdata->plat_dev->dev.coherent_dma_mask; - } + if (!new_drvdata->plat_dev->dev.coherent_dma_mask) - { new_drvdata->plat_dev->dev.coherent_dma_mask = DMA_BIT_MASK(DMA_BIT_MASK_LEN); - } /* Verify correct mapping */ signature_val = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_SIGNATURE)); diff --git a/drivers/staging/ccree/ssi_fips_ll.c b/drivers/staging/ccree/ssi_fips_ll.c index 3557e20c9e36..4a7a1a61e117 100644 --- a/drivers/staging/ccree/ssi_fips_ll.c +++ b/drivers/staging/ccree/ssi_fips_ll.c @@ -270,8 +270,7 @@ static const FipsGcmData FipsGcmDataTable[] = { static inline enum cc_fips_error FIPS_CipherToFipsError(enum drv_cipher_mode mode, bool is_aes) { - switch (mode) - { + switch (mode) { case DRV_CIPHER_ECB: return is_aes ? CC_REE_FIPS_ERROR_AES_ECB_PUT : CC_REE_FIPS_ERROR_DES_ECB_PUT; case DRV_CIPHER_CBC: @@ -422,8 +421,7 @@ ssi_cipher_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffe dma_addr_t din_dma_addr = dma_coherent_buffer + offsetof(struct fips_cipher_ctx, din); dma_addr_t dout_dma_addr = dma_coherent_buffer + offsetof(struct fips_cipher_ctx, dout); - for (i = 0; i < FIPS_CIPHER_NUM_OF_TESTS; ++i) - { + for (i = 0; i < FIPS_CIPHER_NUM_OF_TESTS; ++i) { FipsCipherData *cipherData = (FipsCipherData *)&FipsCipherDataTable[i]; int rc = 0; size_t iv_size = cipherData->isAes ? NIST_AES_IV_SIZE : NIST_TDES_IV_SIZE; @@ -447,21 +445,18 @@ ssi_cipher_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffe din_dma_addr, dout_dma_addr, cipherData->dataInSize); - if (rc != 0) - { + if (rc != 0) { FIPS_LOG("ssi_cipher_fips_run_test %d returned error - rc = %d \n", i, rc); error = FIPS_CipherToFipsError(cipherData->oprMode, cipherData->isAes); break; } /* compare actual dout to expected */ - if (memcmp(virt_ctx->dout, cipherData->dataOut, cipherData->dataInSize) != 0) - { + if (memcmp(virt_ctx->dout, cipherData->dataOut, cipherData->dataInSize) != 0) { FIPS_LOG("dout comparison error %d - oprMode=%d, isAes=%d\n", i, cipherData->oprMode, cipherData->isAes); FIPS_LOG(" i expected received \n"); FIPS_LOG(" i 0x%08x 0x%08x (size=%d) \n", (size_t)cipherData->dataOut, (size_t)virt_ctx->dout, cipherData->dataInSize); - for (i = 0; i < cipherData->dataInSize; ++i) - { + for (i = 0; i < cipherData->dataInSize; ++i) { FIPS_LOG(" %d 0x%02x 0x%02x \n", i, cipherData->dataOut[i], virt_ctx->dout[i]); } @@ -548,8 +543,7 @@ ssi_cmac_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t din_dma_addr = dma_coherent_buffer + offsetof(struct fips_cmac_ctx, din); dma_addr_t mac_res_dma_addr = dma_coherent_buffer + offsetof(struct fips_cmac_ctx, mac_res); - for (i = 0; i < FIPS_CMAC_NUM_OF_TESTS; ++i) - { + for (i = 0; i < FIPS_CMAC_NUM_OF_TESTS; ++i) { FipsCmacData *cmac_data = (FipsCmacData *)&FipsCmacDataTable[i]; int rc = 0; @@ -569,21 +563,18 @@ ssi_cmac_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, cmac_data->data_in_size, mac_res_dma_addr, cmac_data->mac_res_size); - if (rc != 0) - { + if (rc != 0) { FIPS_LOG("ssi_cmac_fips_run_test %d returned error - rc = %d \n", i, rc); error = CC_REE_FIPS_ERROR_AES_CMAC_PUT; break; } /* compare actual mac result to expected */ - if (memcmp(virt_ctx->mac_res, cmac_data->mac_res, cmac_data->mac_res_size) != 0) - { + if (memcmp(virt_ctx->mac_res, cmac_data->mac_res, cmac_data->mac_res_size) != 0) { FIPS_LOG("comparison error %d - digest_size=%d \n", i, cmac_data->mac_res_size); FIPS_LOG(" i expected received \n"); FIPS_LOG(" i 0x%08x 0x%08x \n", (size_t)cmac_data->mac_res, (size_t)virt_ctx->mac_res); - for (i = 0; i < cmac_data->mac_res_size; ++i) - { + for (i = 0; i < cmac_data->mac_res_size; ++i) { FIPS_LOG(" %d 0x%02x 0x%02x \n", i, cmac_data->mac_res[i], virt_ctx->mac_res[i]); } @@ -693,8 +684,7 @@ ssi_hash_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t din_dma_addr = dma_coherent_buffer + offsetof(struct fips_hash_ctx, din); dma_addr_t mac_res_dma_addr = dma_coherent_buffer + offsetof(struct fips_hash_ctx, mac_res); - for (i = 0; i < FIPS_HASH_NUM_OF_TESTS; ++i) - { + for (i = 0; i < FIPS_HASH_NUM_OF_TESTS; ++i) { FipsHashData *hash_data = (FipsHashData *)&FipsHashDataTable[i]; int rc = 0; enum drv_hash_hw_mode hw_mode = 0; @@ -744,21 +734,18 @@ ssi_hash_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, hw_mode, digest_size, inter_digestsize); - if (rc != 0) - { + if (rc != 0) { FIPS_LOG("ssi_hash_fips_run_test %d returned error - rc = %d \n", i, rc); error = FIPS_HashToFipsError(hash_data->hash_mode); break; } /* compare actual mac result to expected */ - if (memcmp(virt_ctx->mac_res, hash_data->mac_res, digest_size) != 0) - { + if (memcmp(virt_ctx->mac_res, hash_data->mac_res, digest_size) != 0) { FIPS_LOG("comparison error %d - hash_mode=%d digest_size=%d \n", i, hash_data->hash_mode, digest_size); FIPS_LOG(" i expected received \n"); FIPS_LOG(" i 0x%08x 0x%08x \n", (size_t)hash_data->mac_res, (size_t)virt_ctx->mac_res); - for (i = 0; i < digest_size; ++i) - { + for (i = 0; i < digest_size; ++i) { FIPS_LOG(" %d 0x%02x 0x%02x \n", i, hash_data->mac_res[i], virt_ctx->mac_res[i]); } @@ -1010,8 +997,7 @@ ssi_hmac_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t din_dma_addr = dma_coherent_buffer + offsetof(struct fips_hmac_ctx, din); dma_addr_t mac_res_dma_addr = dma_coherent_buffer + offsetof(struct fips_hmac_ctx, mac_res); - for (i = 0; i < FIPS_HMAC_NUM_OF_TESTS; ++i) - { + for (i = 0; i < FIPS_HMAC_NUM_OF_TESTS; ++i) { FipsHmacData *hmac_data = (FipsHmacData *)&FipsHmacDataTable[i]; int rc = 0; enum drv_hash_hw_mode hw_mode = 0; @@ -1074,21 +1060,18 @@ ssi_hmac_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, k0_dma_addr, tmp_digest_dma_addr, digest_bytes_len_dma_addr); - if (rc != 0) - { + if (rc != 0) { FIPS_LOG("ssi_hmac_fips_run_test %d returned error - rc = %d \n", i, rc); error = FIPS_HmacToFipsError(hmac_data->hash_mode); break; } /* compare actual mac result to expected */ - if (memcmp(virt_ctx->mac_res, hmac_data->mac_res, digest_size) != 0) - { + if (memcmp(virt_ctx->mac_res, hmac_data->mac_res, digest_size) != 0) { FIPS_LOG("comparison error %d - hash_mode=%d digest_size=%d \n", i, hmac_data->hash_mode, digest_size); FIPS_LOG(" i expected received \n"); FIPS_LOG(" i 0x%08x 0x%08x \n", (size_t)hmac_data->mac_res, (size_t)virt_ctx->mac_res); - for (i = 0; i < digest_size; ++i) - { + for (i = 0; i < digest_size; ++i) { FIPS_LOG(" %d 0x%02x 0x%02x \n", i, hmac_data->mac_res[i], virt_ctx->mac_res[i]); } @@ -1251,8 +1234,7 @@ ssi_ccm_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dout_dma_addr = dma_coherent_buffer + offsetof(struct fips_ccm_ctx, dout); dma_addr_t mac_res_dma_addr = dma_coherent_buffer + offsetof(struct fips_ccm_ctx, mac_res); - for (i = 0; i < FIPS_CCM_NUM_OF_TESTS; ++i) - { + for (i = 0; i < FIPS_CCM_NUM_OF_TESTS; ++i) { FipsCcmData *ccmData = (FipsCcmData *)&FipsCcmDataTable[i]; int rc = 0; @@ -1294,29 +1276,25 @@ ssi_ccm_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, ccmData->dataInSize, dout_dma_addr, mac_res_dma_addr); - if (rc != 0) - { + if (rc != 0) { FIPS_LOG("ssi_ccm_fips_run_test %d returned error - rc = %d \n", i, rc); error = CC_REE_FIPS_ERROR_AESCCM_PUT; break; } /* compare actual dout to expected */ - if (memcmp(virt_ctx->dout, ccmData->dataOut, ccmData->dataInSize) != 0) - { + if (memcmp(virt_ctx->dout, ccmData->dataOut, ccmData->dataInSize) != 0) { FIPS_LOG("dout comparison error %d - size=%d \n", i, ccmData->dataInSize); error = CC_REE_FIPS_ERROR_AESCCM_PUT; break; } /* compare actual mac result to expected */ - if (memcmp(virt_ctx->mac_res, ccmData->macResOut, ccmData->tagSize) != 0) - { + if (memcmp(virt_ctx->mac_res, ccmData->macResOut, ccmData->tagSize) != 0) { FIPS_LOG("mac_res comparison error %d - mac_size=%d \n", i, ccmData->tagSize); FIPS_LOG(" i expected received \n"); FIPS_LOG(" i 0x%08x 0x%08x \n", (size_t)ccmData->macResOut, (size_t)virt_ctx->mac_res); - for (i = 0; i < ccmData->tagSize; ++i) - { + for (i = 0; i < ccmData->tagSize; ++i) { FIPS_LOG(" %d 0x%02x 0x%02x \n", i, ccmData->macResOut[i], virt_ctx->mac_res[i]); } @@ -1546,8 +1524,7 @@ ssi_gcm_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t iv_inc1_dma_addr = dma_coherent_buffer + offsetof(struct fips_gcm_ctx, iv_inc1); dma_addr_t iv_inc2_dma_addr = dma_coherent_buffer + offsetof(struct fips_gcm_ctx, iv_inc2); - for (i = 0; i < FIPS_GCM_NUM_OF_TESTS; ++i) - { + for (i = 0; i < FIPS_GCM_NUM_OF_TESTS; ++i) { FipsGcmData *gcmData = (FipsGcmData *)&FipsGcmDataTable[i]; int rc = 0; @@ -1593,8 +1570,7 @@ ssi_gcm_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, gcmData->dataInSize, dout_dma_addr, mac_res_dma_addr); - if (rc != 0) - { + if (rc != 0) { FIPS_LOG("ssi_gcm_fips_run_test %d returned error - rc = %d \n", i, rc); error = CC_REE_FIPS_ERROR_AESGCM_PUT; break; @@ -1602,13 +1578,11 @@ ssi_gcm_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, if (gcmData->direction == DRV_CRYPTO_DIRECTION_ENCRYPT) { /* compare actual dout to expected */ - if (memcmp(virt_ctx->dout, gcmData->dataOut, gcmData->dataInSize) != 0) - { + if (memcmp(virt_ctx->dout, gcmData->dataOut, gcmData->dataInSize) != 0) { FIPS_LOG("dout comparison error %d - size=%d \n", i, gcmData->dataInSize); FIPS_LOG(" i expected received \n"); FIPS_LOG(" i 0x%08x 0x%08x \n", (size_t)gcmData->dataOut, (size_t)virt_ctx->dout); - for (i = 0; i < gcmData->dataInSize; ++i) - { + for (i = 0; i < gcmData->dataInSize; ++i) { FIPS_LOG(" %d 0x%02x 0x%02x \n", i, gcmData->dataOut[i], virt_ctx->dout[i]); } @@ -1618,16 +1592,13 @@ ssi_gcm_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, } /* compare actual mac result to expected */ - if (memcmp(virt_ctx->mac_res, gcmData->macResOut, gcmData->tagSize) != 0) - { + if (memcmp(virt_ctx->mac_res, gcmData->macResOut, gcmData->tagSize) != 0) { FIPS_LOG("mac_res comparison error %d - mac_size=%d \n", i, gcmData->tagSize); FIPS_LOG(" i expected received \n"); FIPS_LOG(" i 0x%08x 0x%08x \n", (size_t)gcmData->macResOut, (size_t)virt_ctx->mac_res); - for (i = 0; i < gcmData->tagSize; ++i) - { + for (i = 0; i < gcmData->tagSize; ++i) { FIPS_LOG(" %d 0x%02x 0x%02x \n", i, gcmData->macResOut[i], virt_ctx->mac_res[i]); } - error = CC_REE_FIPS_ERROR_AESGCM_PUT; break; } diff --git a/drivers/staging/ccree/ssi_hash.c b/drivers/staging/ccree/ssi_hash.c index ae8f36af3837..7e9f273bd629 100644 --- a/drivers/staging/ccree/ssi_hash.c +++ b/drivers/staging/ccree/ssi_hash.c @@ -2366,7 +2366,8 @@ int ssi_hash_free(struct ssi_drvdata *drvdata) static void ssi_hash_create_xcbc_setup(struct ahash_request *areq, struct cc_hw_desc desc[], - unsigned int *seq_size) { + unsigned int *seq_size) +{ unsigned int idx = *seq_size; struct ahash_req_ctx *state = ahash_request_ctx(areq); struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); diff --git a/drivers/staging/ccree/ssi_sysfs.c b/drivers/staging/ccree/ssi_sysfs.c index dbcd1634aad1..07b634c84787 100644 --- a/drivers/staging/ccree/ssi_sysfs.c +++ b/drivers/staging/ccree/ssi_sysfs.c @@ -40,8 +40,7 @@ struct stat_name { const char *stat_phase_name[MAX_STAT_PHASES]; }; -static struct stat_name stat_name_db[MAX_STAT_OP_TYPES] = -{ +static struct stat_name stat_name_db[MAX_STAT_OP_TYPES] = { { /* STAT_OP_TYPE_NULL */ .op_type_name = "NULL", -- cgit v1.2.3 From 462ba38cb7b6b71d9ee4f87428090e564869ffab Mon Sep 17 00:00:00 2001 From: Tyler Olivieri Date: Sun, 9 Jul 2017 17:10:45 -0400 Subject: staging: ccree: remove assignement in conditional Patch to fix following checkpatch error: ERROR: do not use assignment in if condition Signed-off-by: Tyler Olivieri Acked-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_hash.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_hash.c b/drivers/staging/ccree/ssi_hash.c index 7e9f273bd629..c66314fda012 100644 --- a/drivers/staging/ccree/ssi_hash.c +++ b/drivers/staging/ccree/ssi_hash.c @@ -602,7 +602,8 @@ static int ssi_hash_update(struct ahash_req_ctx *state, return 0; } - if (unlikely(rc = ssi_buffer_mgr_map_hash_request_update(ctx->drvdata, state, src, nbytes, block_size))) { + rc = ssi_buffer_mgr_map_hash_request_update(ctx->drvdata, state, src, nbytes, block_size); + if (unlikely(rc)) { if (rc == 1) { SSI_LOG_DEBUG(" data size not require HW update %x\n", nbytes); @@ -1404,7 +1405,8 @@ static int ssi_mac_update(struct ahash_request *req) state->xcbc_count++; - if (unlikely(rc = ssi_buffer_mgr_map_hash_request_update(ctx->drvdata, state, req->src, req->nbytes, block_size))) { + rc = ssi_buffer_mgr_map_hash_request_update(ctx->drvdata, state, req->src, req->nbytes, block_size); + if (unlikely(rc)) { if (rc == 1) { SSI_LOG_DEBUG(" data size not require HW update %x\n", req->nbytes); -- cgit v1.2.3 From 9c0d87230bde794f2543b95ba93c1840a938119b Mon Sep 17 00:00:00 2001 From: Tyler Olivieri Date: Sun, 9 Jul 2017 17:10:46 -0400 Subject: staging: ccree: export symbol immediately following function Patch to fix following checkpatch warning: WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable Signed-off-by: Tyler Olivieri Acked-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_fips.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_fips.c b/drivers/staging/ccree/ssi_fips.c index fdc40f38332a..523057c4d791 100644 --- a/drivers/staging/ccree/ssi_fips.c +++ b/drivers/staging/ccree/ssi_fips.c @@ -39,7 +39,6 @@ int ssi_fips_get_state(enum cc_fips_state_t *p_state) return rc; } - EXPORT_SYMBOL(ssi_fips_get_state); /* @@ -57,5 +56,4 @@ int ssi_fips_get_error(enum cc_fips_error *p_err) return rc; } - EXPORT_SYMBOL(ssi_fips_get_error); -- cgit v1.2.3 From 07642a075f2743a0ebebde1163da6a2f0aa98d14 Mon Sep 17 00:00:00 2001 From: Tyler Olivieri Date: Sun, 9 Jul 2017 17:10:47 -0400 Subject: staging: ccree: fix switch case indentation Patch to fix following checkpatch error: ERROR: switch and case should be at the same indent Signed-off-by: Tyler Olivieri Acked-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_hash.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_hash.c b/drivers/staging/ccree/ssi_hash.c index c66314fda012..4f596eb3af46 100644 --- a/drivers/staging/ccree/ssi_hash.c +++ b/drivers/staging/ccree/ssi_hash.c @@ -1177,12 +1177,12 @@ static int ssi_xcbc_setkey(struct crypto_ahash *ahash, CHECK_AND_RETURN_UPON_FIPS_ERROR(); switch (keylen) { - case AES_KEYSIZE_128: - case AES_KEYSIZE_192: - case AES_KEYSIZE_256: - break; - default: - return -EINVAL; + case AES_KEYSIZE_128: + case AES_KEYSIZE_192: + case AES_KEYSIZE_256: + break; + default: + return -EINVAL; } ctx->key_params.keylen = keylen; @@ -1265,12 +1265,12 @@ static int ssi_cmac_setkey(struct crypto_ahash *ahash, ctx->is_hmac = true; switch (keylen) { - case AES_KEYSIZE_128: - case AES_KEYSIZE_192: - case AES_KEYSIZE_256: - break; - default: - return -EINVAL; + case AES_KEYSIZE_128: + case AES_KEYSIZE_192: + case AES_KEYSIZE_256: + break; + default: + return -EINVAL; } ctx->key_params.keylen = keylen; -- cgit v1.2.3 From b7e607bf33a2f18507c7f35f7c7abfd45f55047f Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Tue, 11 Jul 2017 18:11:37 +0300 Subject: staging: ccree: move FIPS support to kernel infrastructure The ccree driver had its own FIPS support, complete with a test harness comparable to crypto testmgr and an implementation which disables crypto functionality on FIPS test error detection, either in Linux or from TEE. This patch removes the duplication, while reimplementing the handling of TEE reported FIPS errors according to the kernel policy of inducing a panic in such an event. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/Kconfig | 9 - drivers/staging/ccree/Makefile | 2 +- drivers/staging/ccree/ssi_aead.c | 6 - drivers/staging/ccree/ssi_cipher.c | 30 +- drivers/staging/ccree/ssi_driver.c | 8 +- drivers/staging/ccree/ssi_driver.h | 1 - drivers/staging/ccree/ssi_fips.c | 121 ++- drivers/staging/ccree/ssi_fips.h | 58 +- drivers/staging/ccree/ssi_fips_data.h | 306 ------ drivers/staging/ccree/ssi_fips_ext.c | 92 -- drivers/staging/ccree/ssi_fips_ll.c | 1620 ------------------------------- drivers/staging/ccree/ssi_fips_local.c | 357 ------- drivers/staging/ccree/ssi_fips_local.h | 67 -- drivers/staging/ccree/ssi_hash.c | 21 - drivers/staging/ccree/ssi_request_mgr.c | 2 - 15 files changed, 130 insertions(+), 2570 deletions(-) delete mode 100644 drivers/staging/ccree/ssi_fips_data.h delete mode 100644 drivers/staging/ccree/ssi_fips_ext.c delete mode 100644 drivers/staging/ccree/ssi_fips_ll.c delete mode 100644 drivers/staging/ccree/ssi_fips_local.c delete mode 100644 drivers/staging/ccree/ssi_fips_local.h (limited to 'drivers') diff --git a/drivers/staging/ccree/Kconfig b/drivers/staging/ccree/Kconfig index 36a87c686a2a..0b3092ba2fcb 100644 --- a/drivers/staging/ccree/Kconfig +++ b/drivers/staging/ccree/Kconfig @@ -23,12 +23,3 @@ config CRYPTO_DEV_CCREE Choose this if you wish to use hardware acceleration of cryptographic operations on the system REE. If unsure say Y. - -config CCREE_FIPS_SUPPORT - bool "Turn on CryptoCell 7XX REE FIPS mode support" - depends on CRYPTO_DEV_CCREE - default n - help - Say 'Y' to enable support for FIPS compliant mode by the - CCREE driver. - If unsure say N. diff --git a/drivers/staging/ccree/Makefile b/drivers/staging/ccree/Makefile index 318c2b39acf6..ae702f3b5369 100644 --- a/drivers/staging/ccree/Makefile +++ b/drivers/staging/ccree/Makefile @@ -1,3 +1,3 @@ obj-$(CONFIG_CRYPTO_DEV_CCREE) := ccree.o ccree-y := ssi_driver.o ssi_sysfs.o ssi_buffer_mgr.o ssi_request_mgr.o ssi_cipher.o ssi_hash.o ssi_aead.o ssi_ivgen.o ssi_sram_mgr.o ssi_pm.o -ccree-$(CCREE_FIPS_SUPPORT) += ssi_fips.o ssi_fips_ll.o ssi_fips_ext.o ssi_fips_local.o +ccree-$(CONFIG_CRYPTO_FIPS) += ssi_fips.o diff --git a/drivers/staging/ccree/ssi_aead.c b/drivers/staging/ccree/ssi_aead.c index 116816125466..3a10c31e73ec 100644 --- a/drivers/staging/ccree/ssi_aead.c +++ b/drivers/staging/ccree/ssi_aead.c @@ -36,7 +36,6 @@ #include "ssi_hash.h" #include "ssi_sysfs.h" #include "ssi_sram_mgr.h" -#include "ssi_fips_local.h" #define template_aead template_u.aead @@ -146,8 +145,6 @@ static int ssi_aead_init(struct crypto_aead *tfm) container_of(alg, struct ssi_crypto_alg, aead_alg); SSI_LOG_DEBUG("Initializing context @%p for %s\n", ctx, crypto_tfm_alg_name(&(tfm->base))); - CHECK_AND_RETURN_UPON_FIPS_ERROR(); - /* Initialize modes in instance */ ctx->cipher_mode = ssi_alg->cipher_mode; ctx->flow_mode = ssi_alg->flow_mode; @@ -538,7 +535,6 @@ ssi_aead_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen) SSI_LOG_DEBUG("Setting key in context @%p for %s. key=%p keylen=%u\n", ctx, crypto_tfm_alg_name(crypto_aead_tfm(tfm)), key, keylen); - CHECK_AND_RETURN_UPON_FIPS_ERROR(); /* STAT_PHASE_0: Init and sanity checks */ if (ctx->auth_mode != DRV_HASH_NULL) { /* authenc() alg. */ @@ -654,7 +650,6 @@ static int ssi_aead_setauthsize( { struct ssi_aead_ctx *ctx = crypto_aead_ctx(authenc); - CHECK_AND_RETURN_UPON_FIPS_ERROR(); /* Unsupported auth. sizes */ if ((authsize == 0) || (authsize > crypto_aead_maxauthsize(authenc))) { @@ -1946,7 +1941,6 @@ static int ssi_aead_process(struct aead_request *req, enum drv_crypto_direction SSI_LOG_DEBUG("%s context=%p req=%p iv=%p src=%p src_ofs=%d dst=%p dst_ofs=%d cryptolen=%d\n", ((direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ? "Encrypt" : "Decrypt"), ctx, req, req->iv, sg_virt(req->src), req->src->offset, sg_virt(req->dst), req->dst->offset, req->cryptlen); - CHECK_AND_RETURN_UPON_FIPS_ERROR(); /* STAT_PHASE_0: Init and sanity checks */ diff --git a/drivers/staging/ccree/ssi_cipher.c b/drivers/staging/ccree/ssi_cipher.c index 4ef0c9ba8678..af16bd02397c 100644 --- a/drivers/staging/ccree/ssi_cipher.c +++ b/drivers/staging/ccree/ssi_cipher.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "ssi_config.h" #include "ssi_driver.h" @@ -31,7 +32,6 @@ #include "ssi_cipher.h" #include "ssi_request_mgr.h" #include "ssi_sysfs.h" -#include "ssi_fips_local.h" #define MAX_ABLKCIPHER_SEQ_LEN 6 @@ -188,7 +188,6 @@ static int ssi_blkcipher_init(struct crypto_tfm *tfm) SSI_LOG_DEBUG("Initializing context @%p for %s\n", ctx_p, crypto_tfm_alg_name(tfm)); - CHECK_AND_RETURN_UPON_FIPS_ERROR(); ctx_p->cipher_mode = ssi_alg->cipher_mode; ctx_p->flow_mode = ssi_alg->flow_mode; ctx_p->drvdata = ssi_alg->drvdata; @@ -265,9 +264,8 @@ static const u8 zero_buff[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; /* The function verifies that tdes keys are not weak.*/ -static int ssi_fips_verify_3des_keys(const u8 *key, unsigned int keylen) +static int ssi_verify_3des_keys(const u8 *key, unsigned int keylen) { -#ifdef CCREE_FIPS_SUPPORT struct tdes_keys *tdes_key = (struct tdes_keys *)key; /* verify key1 != key2 and key3 != key2*/ @@ -275,21 +273,6 @@ static int ssi_fips_verify_3des_keys(const u8 *key, unsigned int keylen) (memcmp((u8 *)tdes_key->key3, (u8 *)tdes_key->key2, sizeof(tdes_key->key3)) == 0))) { return -ENOEXEC; } -#endif /* CCREE_FIPS_SUPPORT */ - - return 0; -} - -/* The function verifies that xts keys are not weak.*/ -static int ssi_fips_verify_xts_keys(const u8 *key, unsigned int keylen) -{ -#ifdef CCREE_FIPS_SUPPORT - /* Weak key is define as key that its first half (128/256 lsb) equals its second half (128/256 msb) */ - int singleKeySize = keylen >> 1; - - if (unlikely(memcmp(key, &key[singleKeySize], singleKeySize) == 0)) - return -ENOEXEC; -#endif /* CCREE_FIPS_SUPPORT */ return 0; } @@ -322,8 +305,6 @@ static int ssi_blkcipher_setkey(struct crypto_tfm *tfm, ctx_p, crypto_tfm_alg_name(tfm), keylen); dump_byte_array("key", (u8 *)key, keylen); - CHECK_AND_RETURN_UPON_FIPS_ERROR(); - SSI_LOG_DEBUG("ssi_blkcipher_setkey: after FIPS check"); /* STAT_PHASE_0: Init and sanity checks */ @@ -385,13 +366,13 @@ static int ssi_blkcipher_setkey(struct crypto_tfm *tfm, } } if ((ctx_p->cipher_mode == DRV_CIPHER_XTS) && - ssi_fips_verify_xts_keys(key, keylen) != 0) { + xts_check_key(tfm, key, keylen) != 0) { SSI_LOG_DEBUG("ssi_blkcipher_setkey: weak XTS key"); return -EINVAL; } if ((ctx_p->flow_mode == S_DIN_to_DES) && (keylen == DES3_EDE_KEY_SIZE) && - ssi_fips_verify_3des_keys(key, keylen) != 0) { + ssi_verify_3des_keys(key, keylen) != 0) { SSI_LOG_DEBUG("ssi_blkcipher_setkey: weak 3DES key"); return -EINVAL; } @@ -754,7 +735,6 @@ static int ssi_blkcipher_process( ((direction == DRV_CRYPTO_DIRECTION_ENCRYPT) ? "Encrypt" : "Decrypt"), areq, info, nbytes); - CHECK_AND_RETURN_UPON_FIPS_ERROR(); /* STAT_PHASE_0: Init and sanity checks */ /* TODO: check data length according to mode */ @@ -855,8 +835,6 @@ static void ssi_ablkcipher_complete(struct device *dev, void *ssi_req, void __io struct ssi_ablkcipher_ctx *ctx_p = crypto_ablkcipher_ctx(tfm); unsigned int ivsize = crypto_ablkcipher_ivsize(tfm); - CHECK_AND_RETURN_VOID_UPON_FIPS_ERROR(); - ssi_blkcipher_complete(dev, ctx_p, req_ctx, areq->dst, areq->src, ivsize, areq, cc_base); } diff --git a/drivers/staging/ccree/ssi_driver.c b/drivers/staging/ccree/ssi_driver.c index d3964740ec9e..d66f5de732a4 100644 --- a/drivers/staging/ccree/ssi_driver.c +++ b/drivers/staging/ccree/ssi_driver.c @@ -71,7 +71,7 @@ #include "ssi_ivgen.h" #include "ssi_sram_mgr.h" #include "ssi_pm.h" -#include "ssi_fips_local.h" +#include "ssi_fips.h" #ifdef DX_DUMP_BYTES void dump_byte_array(const char *name, const u8 *the_array, unsigned long size) @@ -398,6 +398,12 @@ static int init_cc_resources(struct platform_device *plat_dev) goto init_cc_res_err; } + /* If we got here and FIPS mode is enabled + * it means all FIPS test passed, so let TEE + * know we're good. + */ + cc_set_ree_fips_status(new_drvdata, true); + return 0; init_cc_res_err: diff --git a/drivers/staging/ccree/ssi_driver.h b/drivers/staging/ccree/ssi_driver.h index c1ed61f1a202..b6ad89ae9bee 100644 --- a/drivers/staging/ccree/ssi_driver.h +++ b/drivers/staging/ccree/ssi_driver.h @@ -48,7 +48,6 @@ #include "cc_crypto_ctx.h" #include "ssi_sysfs.h" #include "hash_defs.h" -#include "ssi_fips_local.h" #include "cc_hw_queue_defs.h" #include "ssi_sram_mgr.h" diff --git a/drivers/staging/ccree/ssi_fips.c b/drivers/staging/ccree/ssi_fips.c index 523057c4d791..33d53d64603d 100644 --- a/drivers/staging/ccree/ssi_fips.c +++ b/drivers/staging/ccree/ssi_fips.c @@ -14,46 +14,115 @@ * along with this program; if not, see . */ -/************************************************************** - * This file defines the driver FIPS APIs * - **************************************************************/ +#include +#include -#include +#include "ssi_config.h" +#include "ssi_driver.h" +#include "cc_hal.h" #include "ssi_fips.h" -extern int ssi_fips_ext_get_state(enum cc_fips_state_t *p_state); -extern int ssi_fips_ext_get_error(enum cc_fips_error *p_err); +static void fips_dsr(unsigned long devarg); + +struct ssi_fips_handle { + struct tasklet_struct tasklet; +}; + +/* The function called once at driver entry point to check + * whether TEE FIPS error occurred. + */ +static bool cc_get_tee_fips_status(struct ssi_drvdata *drvdata) +{ + u32 reg; + void __iomem *cc_base = drvdata->cc_base; + + reg = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, GPR_HOST)); + return (reg == (CC_FIPS_SYNC_TEE_STATUS | CC_FIPS_SYNC_MODULE_OK)); +} /* - * This function returns the REE FIPS state. - * It should be called by kernel module. + * This function should push the FIPS REE library status towards the TEE library + * by writing the error state to HOST_GPR0 register. */ -int ssi_fips_get_state(enum cc_fips_state_t *p_state) +void cc_set_ree_fips_status(struct ssi_drvdata *drvdata, bool status) { - int rc = 0; + void __iomem *cc_base = drvdata->cc_base; + int val = CC_FIPS_SYNC_REE_STATUS; - if (!p_state) - return -EINVAL; + val |= (status ? CC_FIPS_SYNC_MODULE_OK : CC_FIPS_SYNC_MODULE_ERROR); - rc = ssi_fips_ext_get_state(p_state); + CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_GPR0), val); +} - return rc; +void ssi_fips_fini(struct ssi_drvdata *drvdata) +{ + struct ssi_fips_handle *fips_h = drvdata->fips_handle; + + if (!fips_h) + return; /* Not allocated */ + + /* Kill tasklet */ + tasklet_kill(&fips_h->tasklet); + + kfree(fips_h); + drvdata->fips_handle = NULL; } -EXPORT_SYMBOL(ssi_fips_get_state); -/* - * This function returns the REE FIPS error. - * It should be called by kernel module. - */ -int ssi_fips_get_error(enum cc_fips_error *p_err) +void fips_handler(struct ssi_drvdata *drvdata) { - int rc = 0; + struct ssi_fips_handle *fips_handle_ptr = + drvdata->fips_handle; + + tasklet_schedule(&fips_handle_ptr->tasklet); +} + +static inline void tee_fips_error(void) +{ + if (fips_enabled) + panic("ccree: TEE reported cryptographic error in fips mode!\n"); + else + SSI_LOG_ERR("TEE reported error!\n"); +} + +/* Deferred service handler, run as interrupt-fired tasklet */ +static void fips_dsr(unsigned long devarg) +{ + struct ssi_drvdata *drvdata = (struct ssi_drvdata *)devarg; + void __iomem *cc_base = drvdata->cc_base; + u32 irq, state, val; + + irq = (drvdata->irq & (SSI_GPR0_IRQ_MASK)); + + if (irq) { + state = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, GPR_HOST)); + + if (state != (CC_FIPS_SYNC_TEE_STATUS | CC_FIPS_SYNC_MODULE_OK)) + tee_fips_error(); + } + + /* after verifing that there is nothing to do, + * unmask AXI completion interrupt. + */ + val = (CC_REG_OFFSET(HOST_RGF, HOST_IMR) & ~irq); + CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_IMR), val); +} + +/* The function called once at driver entry point .*/ +int ssi_fips_init(struct ssi_drvdata *p_drvdata) +{ + struct ssi_fips_handle *fips_h; + + fips_h = kzalloc(sizeof(*fips_h), GFP_KERNEL); + if (!fips_h) + return -ENOMEM; + + p_drvdata->fips_handle = fips_h; - if (!p_err) - return -EINVAL; + SSI_LOG_DEBUG("Initializing fips tasklet\n"); + tasklet_init(&fips_h->tasklet, fips_dsr, (unsigned long)p_drvdata); - rc = ssi_fips_ext_get_error(p_err); + if (!cc_get_tee_fips_status(p_drvdata)) + tee_fips_error(); - return rc; + return 0; } -EXPORT_SYMBOL(ssi_fips_get_error); diff --git a/drivers/staging/ccree/ssi_fips.h b/drivers/staging/ccree/ssi_fips.h index 4f5c6a9a8363..369ddf9478e7 100644 --- a/drivers/staging/ccree/ssi_fips.h +++ b/drivers/staging/ccree/ssi_fips.h @@ -17,45 +17,33 @@ #ifndef __SSI_FIPS_H__ #define __SSI_FIPS_H__ -/*! - * @file - * @brief This file contains FIPS related defintions and APIs. - */ +#ifdef CONFIG_CRYPTO_FIPS -enum cc_fips_state { - CC_FIPS_STATE_NOT_SUPPORTED = 0, - CC_FIPS_STATE_SUPPORTED, - CC_FIPS_STATE_ERROR, - CC_FIPS_STATE_RESERVE32B = S32_MAX +enum cc_fips_status { + CC_FIPS_SYNC_MODULE_OK = 0x0, + CC_FIPS_SYNC_MODULE_ERROR = 0x1, + CC_FIPS_SYNC_REE_STATUS = 0x4, + CC_FIPS_SYNC_TEE_STATUS = 0x8, + CC_FIPS_SYNC_STATUS_RESERVE32B = S32_MAX }; -enum cc_fips_error { - CC_REE_FIPS_ERROR_OK = 0, - CC_REE_FIPS_ERROR_GENERAL, - CC_REE_FIPS_ERROR_FROM_TEE, - CC_REE_FIPS_ERROR_AES_ECB_PUT, - CC_REE_FIPS_ERROR_AES_CBC_PUT, - CC_REE_FIPS_ERROR_AES_OFB_PUT, - CC_REE_FIPS_ERROR_AES_CTR_PUT, - CC_REE_FIPS_ERROR_AES_CBC_CTS_PUT, - CC_REE_FIPS_ERROR_AES_XTS_PUT, - CC_REE_FIPS_ERROR_AES_CMAC_PUT, - CC_REE_FIPS_ERROR_AESCCM_PUT, - CC_REE_FIPS_ERROR_AESGCM_PUT, - CC_REE_FIPS_ERROR_DES_ECB_PUT, - CC_REE_FIPS_ERROR_DES_CBC_PUT, - CC_REE_FIPS_ERROR_SHA1_PUT, - CC_REE_FIPS_ERROR_SHA256_PUT, - CC_REE_FIPS_ERROR_SHA512_PUT, - CC_REE_FIPS_ERROR_HMAC_SHA1_PUT, - CC_REE_FIPS_ERROR_HMAC_SHA256_PUT, - CC_REE_FIPS_ERROR_HMAC_SHA512_PUT, - CC_REE_FIPS_ERROR_ROM_CHECKSUM, - CC_REE_FIPS_ERROR_RESERVE32B = S32_MAX -}; +int ssi_fips_init(struct ssi_drvdata *p_drvdata); +void ssi_fips_fini(struct ssi_drvdata *drvdata); +void fips_handler(struct ssi_drvdata *drvdata); +void cc_set_ree_fips_status(struct ssi_drvdata *drvdata, bool ok); + +#else /* CONFIG_CRYPTO_FIPS */ + +static inline int ssi_fips_init(struct ssi_drvdata *p_drvdata) +{ + return 0; +} + +static inline void ssi_fips_fini(struct ssi_drvdata *drvdata) {} +void cc_set_ree_fips_status(struct ssi_drvdata *drvdata, bool ok) {} +void fips_handler(struct ssi_drvdata *drvdata) {} -int ssi_fips_get_state(enum cc_fips_state *p_state); -int ssi_fips_get_error(enum cc_fips_error *p_err); +#endif /* CONFIG_CRYPTO_FIPS */ #endif /*__SSI_FIPS_H__*/ diff --git a/drivers/staging/ccree/ssi_fips_data.h b/drivers/staging/ccree/ssi_fips_data.h deleted file mode 100644 index c41671dbee40..000000000000 --- a/drivers/staging/ccree/ssi_fips_data.h +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Copyright (C) 2012-2017 ARM Limited or its affiliates. - * - * 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 . - */ - -/* - * The test vectors were taken from: - * - * * AES - * NIST Special Publication 800-38A 2001 Edition - * Recommendation for Block Cipher Modes of Operation - * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - * Appendix F: Example Vectors for Modes of Operation of the AES - * - * * AES CTS - * Advanced Encryption Standard (AES) Encryption for Kerberos 5 - * February 2005 - * https://tools.ietf.org/html/rfc3962#appendix-B - * B. Sample Test Vectors - * - * * AES XTS - * http://csrc.nist.gov/groups/STM/cavp/#08 - * http://csrc.nist.gov/groups/STM/cavp/documents/aes/XTSTestVectors.zip - * - * * AES CMAC - * http://csrc.nist.gov/groups/STM/cavp/index.html#07 - * http://csrc.nist.gov/groups/STM/cavp/documents/mac/cmactestvectors.zip - * - * * AES-CCM - * http://csrc.nist.gov/groups/STM/cavp/#07 - * http://csrc.nist.gov/groups/STM/cavp/documents/mac/ccmtestvectors.zip - * - * * AES-GCM - * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip - * - * * Triple-DES - * NIST Special Publication 800-67 January 2012 - * Recommendation for the Triple Data Encryption Algorithm (TDEA) Block Cipher - * http://csrc.nist.gov/publications/nistpubs/800-67-Rev1/SP-800-67-Rev1.pdf - * APPENDIX B: EXAMPLE OF TDEA FORWARD AND INVERSE CIPHER OPERATIONS - * and - * http://csrc.nist.gov/groups/STM/cavp/#01 - * http://csrc.nist.gov/groups/STM/cavp/documents/des/tdesmct_intermediate.zip - * - * * HASH - * http://csrc.nist.gov/groups/STM/cavp/#03 - * http://csrc.nist.gov/groups/STM/cavp/documents/shs/shabytetestvectors.zip - * - * * HMAC - * http://csrc.nist.gov/groups/STM/cavp/#07 - * http://csrc.nist.gov/groups/STM/cavp/documents/mac/hmactestvectors.zip - */ - -/* NIST AES */ -#define AES_128_BIT_KEY_SIZE 16 -#define AES_192_BIT_KEY_SIZE 24 -#define AES_256_BIT_KEY_SIZE 32 -#define AES_512_BIT_KEY_SIZE 64 - -#define NIST_AES_IV_SIZE 16 - -#define NIST_AES_128_KEY { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c } -#define NIST_AES_192_KEY { 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, \ - 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b } -#define NIST_AES_256_KEY { 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, \ - 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 } -#define NIST_AES_VECTOR_SIZE 16 -#define NIST_AES_PLAIN_DATA { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a } - -#define NIST_AES_ECB_IV { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } -#define NIST_AES_128_ECB_CIPHER { 0x3a, 0xd7, 0x7b, 0xb4, 0x0d, 0x7a, 0x36, 0x60, 0xa8, 0x9e, 0xca, 0xf3, 0x24, 0x66, 0xef, 0x97 } -#define NIST_AES_192_ECB_CIPHER { 0xbd, 0x33, 0x4f, 0x1d, 0x6e, 0x45, 0xf2, 0x5f, 0xf7, 0x12, 0xa2, 0x14, 0x57, 0x1f, 0xa5, 0xcc } -#define NIST_AES_256_ECB_CIPHER { 0xf3, 0xee, 0xd1, 0xbd, 0xb5, 0xd2, 0xa0, 0x3c, 0x06, 0x4b, 0x5a, 0x7e, 0x3d, 0xb1, 0x81, 0xf8 } - -#define NIST_AES_CBC_IV { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f } -#define NIST_AES_128_CBC_CIPHER { 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d } -#define NIST_AES_192_CBC_CIPHER { 0x4f, 0x02, 0x1d, 0xb2, 0x43, 0xbc, 0x63, 0x3d, 0x71, 0x78, 0x18, 0x3a, 0x9f, 0xa0, 0x71, 0xe8 } -#define NIST_AES_256_CBC_CIPHER { 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba, 0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6 } - -#define NIST_AES_OFB_IV { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f } -#define NIST_AES_128_OFB_CIPHER { 0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20, 0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a } -#define NIST_AES_192_OFB_CIPHER { 0xcd, 0xc8, 0x0d, 0x6f, 0xdd, 0xf1, 0x8c, 0xab, 0x34, 0xc2, 0x59, 0x09, 0xc9, 0x9a, 0x41, 0x74 } -#define NIST_AES_256_OFB_CIPHER { 0xdc, 0x7e, 0x84, 0xbf, 0xda, 0x79, 0x16, 0x4b, 0x7e, 0xcd, 0x84, 0x86, 0x98, 0x5d, 0x38, 0x60 } - -#define NIST_AES_CTR_IV { 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff } -#define NIST_AES_128_CTR_CIPHER { 0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26, 0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce } -#define NIST_AES_192_CTR_CIPHER { 0x1a, 0xbc, 0x93, 0x24, 0x17, 0x52, 0x1c, 0xa2, 0x4f, 0x2b, 0x04, 0x59, 0xfe, 0x7e, 0x6e, 0x0b } -#define NIST_AES_256_CTR_CIPHER { 0x60, 0x1e, 0xc3, 0x13, 0x77, 0x57, 0x89, 0xa5, 0xb7, 0xa7, 0xf5, 0x04, 0xbb, 0xf3, 0xd2, 0x28 } - -#define RFC3962_AES_128_KEY { 0x63, 0x68, 0x69, 0x63, 0x6b, 0x65, 0x6e, 0x20, 0x74, 0x65, 0x72, 0x69, 0x79, 0x61, 0x6b, 0x69 } -#define RFC3962_AES_VECTOR_SIZE 17 -#define RFC3962_AES_PLAIN_DATA { 0x49, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20 } -#define RFC3962_AES_CBC_CTS_IV { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } -#define RFC3962_AES_128_CBC_CTS_CIPHER { 0xc6, 0x35, 0x35, 0x68, 0xf2, 0xbf, 0x8c, 0xb4, 0xd8, 0xa5, 0x80, 0x36, 0x2d, 0xa7, 0xff, 0x7f, 0x97 } - -#define NIST_AES_256_XTS_KEY { 0xa1, 0xb9, 0x0c, 0xba, 0x3f, 0x06, 0xac, 0x35, 0x3b, 0x2c, 0x34, 0x38, 0x76, 0x08, 0x17, 0x62, \ - 0x09, 0x09, 0x23, 0x02, 0x6e, 0x91, 0x77, 0x18, 0x15, 0xf2, 0x9d, 0xab, 0x01, 0x93, 0x2f, 0x2f } -#define NIST_AES_256_XTS_IV { 0x4f, 0xae, 0xf7, 0x11, 0x7c, 0xda, 0x59, 0xc6, 0x6e, 0x4b, 0x92, 0x01, 0x3e, 0x76, 0x8a, 0xd5 } -#define NIST_AES_256_XTS_VECTOR_SIZE 16 -#define NIST_AES_256_XTS_PLAIN { 0xeb, 0xab, 0xce, 0x95, 0xb1, 0x4d, 0x3c, 0x8d, 0x6f, 0xb3, 0x50, 0x39, 0x07, 0x90, 0x31, 0x1c } -#define NIST_AES_256_XTS_CIPHER { 0x77, 0x8a, 0xe8, 0xb4, 0x3c, 0xb9, 0x8d, 0x5a, 0x82, 0x50, 0x81, 0xd5, 0xbe, 0x47, 0x1c, 0x63 } - -#define NIST_AES_512_XTS_KEY { 0x1e, 0xa6, 0x61, 0xc5, 0x8d, 0x94, 0x3a, 0x0e, 0x48, 0x01, 0xe4, 0x2f, 0x4b, 0x09, 0x47, 0x14, \ - 0x9e, 0x7f, 0x9f, 0x8e, 0x3e, 0x68, 0xd0, 0xc7, 0x50, 0x52, 0x10, 0xbd, 0x31, 0x1a, 0x0e, 0x7c, \ - 0xd6, 0xe1, 0x3f, 0xfd, 0xf2, 0x41, 0x8d, 0x8d, 0x19, 0x11, 0xc0, 0x04, 0xcd, 0xa5, 0x8d, 0xa3, \ - 0xd6, 0x19, 0xb7, 0xe2, 0xb9, 0x14, 0x1e, 0x58, 0x31, 0x8e, 0xea, 0x39, 0x2c, 0xf4, 0x1b, 0x08 } -#define NIST_AES_512_XTS_IV { 0xad, 0xf8, 0xd9, 0x26, 0x27, 0x46, 0x4a, 0xd2, 0xf0, 0x42, 0x8e, 0x84, 0xa9, 0xf8, 0x75, 0x64, } -#define NIST_AES_512_XTS_VECTOR_SIZE 32 -#define NIST_AES_512_XTS_PLAIN { 0x2e, 0xed, 0xea, 0x52, 0xcd, 0x82, 0x15, 0xe1, 0xac, 0xc6, 0x47, 0xe8, 0x10, 0xbb, 0xc3, 0x64, \ - 0x2e, 0x87, 0x28, 0x7f, 0x8d, 0x2e, 0x57, 0xe3, 0x6c, 0x0a, 0x24, 0xfb, 0xc1, 0x2a, 0x20, 0x2e } -#define NIST_AES_512_XTS_CIPHER { 0xcb, 0xaa, 0xd0, 0xe2, 0xf6, 0xce, 0xa3, 0xf5, 0x0b, 0x37, 0xf9, 0x34, 0xd4, 0x6a, 0x9b, 0x13, \ - 0x0b, 0x9d, 0x54, 0xf0, 0x7e, 0x34, 0xf3, 0x6a, 0xf7, 0x93, 0xe8, 0x6f, 0x73, 0xc6, 0xd7, 0xdb } - -/* NIST AES-CMAC */ -#define NIST_AES_128_CMAC_KEY { 0x67, 0x08, 0xc9, 0x88, 0x7b, 0x84, 0x70, 0x84, 0xf1, 0x23, 0xd3, 0xdd, 0x9c, 0x3a, 0x81, 0x36 } -#define NIST_AES_128_CMAC_PLAIN_DATA { 0xa8, 0xde, 0x55, 0x17, 0x0c, 0x6d, 0xc0, 0xd8, 0x0d, 0xe3, 0x2f, 0x50, 0x8b, 0xf4, 0x9b, 0x70 } -#define NIST_AES_128_CMAC_MAC { 0xcf, 0xef, 0x9b, 0x78, 0x39, 0x84, 0x1f, 0xdb, 0xcc, 0xbb, 0x6c, 0x2c, 0xf2, 0x38, 0xf7 } -#define NIST_AES_128_CMAC_VECTOR_SIZE 16 -#define NIST_AES_128_CMAC_OUTPUT_SIZE 15 - -#define NIST_AES_192_CMAC_KEY { 0x20, 0x51, 0xaf, 0x34, 0x76, 0x2e, 0xbe, 0x55, 0x6f, 0x72, 0xa5, 0xc6, 0xed, 0xc7, 0x77, 0x1e, \ - 0xb9, 0x24, 0x5f, 0xad, 0x76, 0xf0, 0x34, 0xbe } -#define NIST_AES_192_CMAC_PLAIN_DATA { 0xae, 0x8e, 0x93, 0xc9, 0xc9, 0x91, 0xcf, 0x89, 0x6a, 0x49, 0x1a, 0x89, 0x07, 0xdf, 0x4e, 0x4b, \ - 0xe5, 0x18, 0x6a, 0xe4, 0x96, 0xcd, 0x34, 0x0d, 0xc1, 0x9b, 0x23, 0x78, 0x21, 0xdb, 0x7b, 0x60 } -#define NIST_AES_192_CMAC_MAC { 0x74, 0xf7, 0x46, 0x08, 0xc0, 0x4f, 0x0f, 0x4e, 0x47, 0xfa, 0x64, 0x04, 0x33, 0xb6, 0xe6, 0xfb } -#define NIST_AES_192_CMAC_VECTOR_SIZE 32 -#define NIST_AES_192_CMAC_OUTPUT_SIZE 16 - -#define NIST_AES_256_CMAC_KEY { 0x3a, 0x75, 0xa9, 0xd2, 0xbd, 0xb8, 0xc8, 0x04, 0xba, 0x4a, 0xb4, 0x98, 0x35, 0x73, 0xa6, 0xb2, \ - 0x53, 0x16, 0x0d, 0xd9, 0x0f, 0x8e, 0xdd, 0xfb, 0x2f, 0xdc, 0x2a, 0xb1, 0x76, 0x04, 0xf5, 0xc5 } -#define NIST_AES_256_CMAC_PLAIN_DATA { 0x42, 0xf3, 0x5d, 0x5a, 0xa5, 0x33, 0xa7, 0xa0, 0xa5, 0xf7, 0x4e, 0x14, 0x4f, 0x2a, 0x5f, 0x20 } -#define NIST_AES_256_CMAC_MAC { 0xf1, 0x53, 0x2f, 0x87, 0x32, 0xd9, 0xf5, 0x90, 0x30, 0x07 } -#define NIST_AES_256_CMAC_VECTOR_SIZE 16 -#define NIST_AES_256_CMAC_OUTPUT_SIZE 10 - -/* NIST TDES */ -#define TDES_NUM_OF_KEYS 3 -#define NIST_TDES_VECTOR_SIZE 8 -#define NIST_TDES_IV_SIZE 8 - -#define NIST_TDES_ECB_IV { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } - -#define NIST_TDES_ECB3_KEY { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, \ - 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, \ - 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23 } -#define NIST_TDES_ECB3_PLAIN_DATA { 0x54, 0x68, 0x65, 0x20, 0x71, 0x75, 0x66, 0x63 } -#define NIST_TDES_ECB3_CIPHER { 0xa8, 0x26, 0xfd, 0x8c, 0xe5, 0x3b, 0x85, 0x5f } - -#define NIST_TDES_CBC3_IV { 0xf8, 0xee, 0xe1, 0x35, 0x9c, 0x6e, 0x54, 0x40 } -#define NIST_TDES_CBC3_KEY { 0xe9, 0xda, 0x37, 0xf8, 0xdc, 0x97, 0x6d, 0x5b, \ - 0xb6, 0x8c, 0x04, 0xe3, 0xec, 0x98, 0x20, 0x15, \ - 0xf4, 0x0e, 0x08, 0xb5, 0x97, 0x29, 0xf2, 0x8f } -#define NIST_TDES_CBC3_PLAIN_DATA { 0x3b, 0xb7, 0xa7, 0xdb, 0xa3, 0xd5, 0x92, 0x91 } -#define NIST_TDES_CBC3_CIPHER { 0x5b, 0x84, 0x24, 0xd2, 0x39, 0x3e, 0x55, 0xa2 } - -/* NIST AES-CCM */ -#define NIST_AESCCM_128_BIT_KEY_SIZE 16 -#define NIST_AESCCM_192_BIT_KEY_SIZE 24 -#define NIST_AESCCM_256_BIT_KEY_SIZE 32 - -#define NIST_AESCCM_B0_VAL 0x79 /* L'[0:2]=1 , M'[3-5]=7 , Adata[6]=1, reserved[7]=0 */ -#define NIST_AESCCM_NONCE_SIZE 13 -#define NIST_AESCCM_IV_SIZE 16 -#define NIST_AESCCM_ADATA_SIZE 32 -#define NIST_AESCCM_TEXT_SIZE 16 -#define NIST_AESCCM_TAG_SIZE 16 - -#define NIST_AESCCM_128_KEY { 0x70, 0x01, 0x0e, 0xd9, 0x0e, 0x61, 0x86, 0xec, 0xad, 0x41, 0xf0, 0xd3, 0xc7, 0xc4, 0x2f, 0xf8 } -#define NIST_AESCCM_128_NONCE { 0xa5, 0xf4, 0xf4, 0x98, 0x6e, 0x98, 0x47, 0x29, 0x65, 0xf5, 0xab, 0xcc, 0x4b } -#define NIST_AESCCM_128_ADATA { 0x3f, 0xec, 0x0e, 0x5c, 0xc2, 0x4d, 0x67, 0x13, 0x94, 0x37, 0xcb, 0xc8, 0x11, 0x24, 0x14, 0xfc, \ - 0x8d, 0xac, 0xcd, 0x1a, 0x94, 0xb4, 0x9a, 0x4c, 0x76, 0xe2, 0xd3, 0x93, 0x03, 0x54, 0x73, 0x17 } -#define NIST_AESCCM_128_PLAIN_TEXT { 0xbe, 0x32, 0x2f, 0x58, 0xef, 0xa7, 0xf8, 0xc6, 0x8a, 0x63, 0x5e, 0x0b, 0x9c, 0xce, 0x77, 0xf2 } -#define NIST_AESCCM_128_CIPHER { 0x8e, 0x44, 0x25, 0xae, 0x57, 0x39, 0x74, 0xf0, 0xf0, 0x69, 0x3a, 0x18, 0x8b, 0x52, 0x58, 0x12 } -#define NIST_AESCCM_128_MAC { 0xee, 0xf0, 0x8e, 0x3f, 0xb1, 0x5f, 0x42, 0x27, 0xe0, 0xd9, 0x89, 0xa4, 0xd5, 0x87, 0xa8, 0xcf } - -#define NIST_AESCCM_192_KEY { 0x68, 0x73, 0xf1, 0xc6, 0xc3, 0x09, 0x75, 0xaf, 0xf6, 0xf0, 0x84, 0x70, 0x26, 0x43, 0x21, 0x13, \ - 0x0a, 0x6e, 0x59, 0x84, 0xad, 0xe3, 0x24, 0xe9 } -#define NIST_AESCCM_192_NONCE { 0x7c, 0x4d, 0x2f, 0x7c, 0xec, 0x04, 0x36, 0x1f, 0x18, 0x7f, 0x07, 0x26, 0xd5 } -#define NIST_AESCCM_192_ADATA { 0x77, 0x74, 0x3b, 0x5d, 0x83, 0xa0, 0x0d, 0x2c, 0x8d, 0x5f, 0x7e, 0x10, 0x78, 0x15, 0x31, 0xb4, \ - 0x96, 0xe0, 0x9f, 0x3b, 0xc9, 0x29, 0x5d, 0x7a, 0xe9, 0x79, 0x9e, 0x64, 0x66, 0x8e, 0xf8, 0xc5 } -#define NIST_AESCCM_192_PLAIN_TEXT { 0x50, 0x51, 0xa0, 0xb0, 0xb6, 0x76, 0x6c, 0xd6, 0xea, 0x29, 0xa6, 0x72, 0x76, 0x9d, 0x40, 0xfe } -#define NIST_AESCCM_192_CIPHER { 0x0c, 0xe5, 0xac, 0x8d, 0x6b, 0x25, 0x6f, 0xb7, 0x58, 0x0b, 0xf6, 0xac, 0xc7, 0x64, 0x26, 0xaf } -#define NIST_AESCCM_192_MAC { 0x40, 0xbc, 0xe5, 0x8f, 0xd4, 0xcd, 0x65, 0x48, 0xdf, 0x90, 0xa0, 0x33, 0x7c, 0x84, 0x20, 0x04 } - -#define NIST_AESCCM_256_KEY { 0xee, 0x8c, 0xe1, 0x87, 0x16, 0x97, 0x79, 0xd1, 0x3e, 0x44, 0x3d, 0x64, 0x28, 0xe3, 0x8b, 0x38, \ - 0xb5, 0x5d, 0xfb, 0x90, 0xf0, 0x22, 0x8a, 0x8a, 0x4e, 0x62, 0xf8, 0xf5, 0x35, 0x80, 0x6e, 0x62 } -#define NIST_AESCCM_256_NONCE { 0x12, 0x16, 0x42, 0xc4, 0x21, 0x8b, 0x39, 0x1c, 0x98, 0xe6, 0x26, 0x9c, 0x8a } -#define NIST_AESCCM_256_ADATA { 0x71, 0x8d, 0x13, 0xe4, 0x75, 0x22, 0xac, 0x4c, 0xdf, 0x3f, 0x82, 0x80, 0x63, 0x98, 0x0b, 0x6d, \ - 0x45, 0x2f, 0xcd, 0xcd, 0x6e, 0x1a, 0x19, 0x04, 0xbf, 0x87, 0xf5, 0x48, 0xa5, 0xfd, 0x5a, 0x05 } -#define NIST_AESCCM_256_PLAIN_TEXT { 0xd1, 0x5f, 0x98, 0xf2, 0xc6, 0xd6, 0x70, 0xf5, 0x5c, 0x78, 0xa0, 0x66, 0x48, 0x33, 0x2b, 0xc9 } -#define NIST_AESCCM_256_CIPHER { 0xcc, 0x17, 0xbf, 0x87, 0x94, 0xc8, 0x43, 0x45, 0x7d, 0x89, 0x93, 0x91, 0x89, 0x8e, 0xd2, 0x2a } -#define NIST_AESCCM_256_MAC { 0x6f, 0x9d, 0x28, 0xfc, 0xb6, 0x42, 0x34, 0xe1, 0xcd, 0x79, 0x3c, 0x41, 0x44, 0xf1, 0xda, 0x50 } - -/* NIST AES-GCM */ -#define NIST_AESGCM_128_BIT_KEY_SIZE 16 -#define NIST_AESGCM_192_BIT_KEY_SIZE 24 -#define NIST_AESGCM_256_BIT_KEY_SIZE 32 - -#define NIST_AESGCM_IV_SIZE 12 -#define NIST_AESGCM_ADATA_SIZE 16 -#define NIST_AESGCM_TEXT_SIZE 16 -#define NIST_AESGCM_TAG_SIZE 16 - -#define NIST_AESGCM_128_KEY { 0x81, 0x6e, 0x39, 0x07, 0x04, 0x10, 0xcf, 0x21, 0x84, 0x90, 0x4d, 0xa0, 0x3e, 0xa5, 0x07, 0x5a } -#define NIST_AESGCM_128_IV { 0x32, 0xc3, 0x67, 0xa3, 0x36, 0x26, 0x13, 0xb2, 0x7f, 0xc3, 0xe6, 0x7e } -#define NIST_AESGCM_128_ADATA { 0xf2, 0xa3, 0x07, 0x28, 0xed, 0x87, 0x4e, 0xe0, 0x29, 0x83, 0xc2, 0x94, 0x43, 0x5d, 0x3c, 0x16 } -#define NIST_AESGCM_128_PLAIN_TEXT { 0xec, 0xaf, 0xe9, 0x6c, 0x67, 0xa1, 0x64, 0x67, 0x44, 0xf1, 0xc8, 0x91, 0xf5, 0xe6, 0x94, 0x27 } -#define NIST_AESGCM_128_CIPHER { 0x55, 0x2e, 0xbe, 0x01, 0x2e, 0x7b, 0xcf, 0x90, 0xfc, 0xef, 0x71, 0x2f, 0x83, 0x44, 0xe8, 0xf1 } -#define NIST_AESGCM_128_MAC { 0xec, 0xaa, 0xe9, 0xfc, 0x68, 0x27, 0x6a, 0x45, 0xab, 0x0c, 0xa3, 0xcb, 0x9d, 0xd9, 0x53, 0x9f } - -#define NIST_AESGCM_192_KEY { 0x0c, 0x44, 0xd6, 0xc9, 0x28, 0xee, 0x11, 0x2c, 0xe6, 0x65, 0xfe, 0x54, 0x7e, 0xbd, 0x38, 0x72, \ - 0x98, 0xa9, 0x54, 0xb4, 0x62, 0xf6, 0x95, 0xd8 } -#define NIST_AESGCM_192_IV { 0x18, 0xb8, 0xf3, 0x20, 0xfe, 0xf4, 0xae, 0x8c, 0xcb, 0xe8, 0xf9, 0x52 } -#define NIST_AESGCM_192_ADATA { 0x73, 0x41, 0xd4, 0x3f, 0x98, 0xcf, 0x38, 0x82, 0x21, 0x18, 0x09, 0x41, 0x97, 0x03, 0x76, 0xe8 } -#define NIST_AESGCM_192_PLAIN_TEXT { 0x96, 0xad, 0x07, 0xf9, 0xb6, 0x28, 0xb6, 0x52, 0xcf, 0x86, 0xcb, 0x73, 0x17, 0x88, 0x6f, 0x51 } -#define NIST_AESGCM_192_CIPHER { 0xa6, 0x64, 0x07, 0x81, 0x33, 0x40, 0x5e, 0xb9, 0x09, 0x4d, 0x36, 0xf7, 0xe0, 0x70, 0x19, 0x1f } -#define NIST_AESGCM_192_MAC { 0xe8, 0xf9, 0xc3, 0x17, 0x84, 0x7c, 0xe3, 0xf3, 0xc2, 0x39, 0x94, 0xa4, 0x02, 0xf0, 0x65, 0x81 } - -#define NIST_AESGCM_256_KEY { 0x54, 0xe3, 0x52, 0xea, 0x1d, 0x84, 0xbf, 0xe6, 0x4a, 0x10, 0x11, 0x09, 0x61, 0x11, 0xfb, 0xe7, \ - 0x66, 0x8a, 0xd2, 0x20, 0x3d, 0x90, 0x2a, 0x01, 0x45, 0x8c, 0x3b, 0xbd, 0x85, 0xbf, 0xce, 0x14 } -#define NIST_AESGCM_256_IV { 0xdf, 0x7c, 0x3b, 0xca, 0x00, 0x39, 0x6d, 0x0c, 0x01, 0x84, 0x95, 0xd9 } -#define NIST_AESGCM_256_ADATA { 0x7e, 0x96, 0x8d, 0x71, 0xb5, 0x0c, 0x1f, 0x11, 0xfd, 0x00, 0x1f, 0x3f, 0xef, 0x49, 0xd0, 0x45 } -#define NIST_AESGCM_256_PLAIN_TEXT { 0x85, 0xfc, 0x3d, 0xfa, 0xd9, 0xb5, 0xa8, 0xd3, 0x25, 0x8e, 0x4f, 0xc4, 0x45, 0x71, 0xbd, 0x3b } -#define NIST_AESGCM_256_CIPHER { 0x42, 0x6e, 0x0e, 0xfc, 0x69, 0x3b, 0x7b, 0xe1, 0xf3, 0x01, 0x8d, 0xb7, 0xdd, 0xbb, 0x7e, 0x4d } -#define NIST_AESGCM_256_MAC { 0xee, 0x82, 0x57, 0x79, 0x5b, 0xe6, 0xa1, 0x16, 0x4d, 0x7e, 0x1d, 0x2d, 0x6c, 0xac, 0x77, 0xa7 } - -/* NIST HASH */ -#define NIST_SHA_MSG_SIZE 16 - -#define NIST_SHA_1_MSG { 0x35, 0x52, 0x69, 0x4c, 0xdf, 0x66, 0x3f, 0xd9, 0x4b, 0x22, 0x47, 0x47, 0xac, 0x40, 0x6a, 0xaf } -#define NIST_SHA_1_MD { 0xa1, 0x50, 0xde, 0x92, 0x74, 0x54, 0x20, 0x2d, 0x94, 0xe6, 0x56, 0xde, 0x4c, 0x7c, 0x0c, 0xa6, \ - 0x91, 0xde, 0x95, 0x5d } - -#define NIST_SHA_256_MSG { 0x0a, 0x27, 0x84, 0x7c, 0xdc, 0x98, 0xbd, 0x6f, 0x62, 0x22, 0x0b, 0x04, 0x6e, 0xdd, 0x76, 0x2b } -#define NIST_SHA_256_MD { 0x80, 0xc2, 0x5e, 0xc1, 0x60, 0x05, 0x87, 0xe7, 0xf2, 0x8b, 0x18, 0xb1, 0xb1, 0x8e, 0x3c, 0xdc, \ - 0x89, 0x92, 0x8e, 0x39, 0xca, 0xb3, 0xbc, 0x25, 0xe4, 0xd4, 0xa4, 0xc1, 0x39, 0xbc, 0xed, 0xc4 } - -#define NIST_SHA_512_MSG { 0xcd, 0x67, 0xbd, 0x40, 0x54, 0xaa, 0xa3, 0xba, 0xa0, 0xdb, 0x17, 0x8c, 0xe2, 0x32, 0xfd, 0x5a } -#define NIST_SHA_512_MD { 0x0d, 0x85, 0x21, 0xf8, 0xf2, 0xf3, 0x90, 0x03, 0x32, 0xd1, 0xa1, 0xa5, 0x5c, 0x60, 0xba, 0x81, \ - 0xd0, 0x4d, 0x28, 0xdf, 0xe8, 0xc5, 0x04, 0xb6, 0x32, 0x8a, 0xe7, 0x87, 0x92, 0x5f, 0xe0, 0x18, \ - 0x8f, 0x2b, 0xa9, 0x1c, 0x3a, 0x9f, 0x0c, 0x16, 0x53, 0xc4, 0xbf, 0x0a, 0xda, 0x35, 0x64, 0x55, \ - 0xea, 0x36, 0xfd, 0x31, 0xf8, 0xe7, 0x3e, 0x39, 0x51, 0xca, 0xd4, 0xeb, 0xba, 0x8c, 0x6e, 0x04 } - -/* NIST HMAC */ -#define NIST_HMAC_MSG_SIZE 128 - -#define NIST_HMAC_SHA1_KEY_SIZE 10 -#define NIST_HMAC_SHA1_KEY { 0x59, 0x78, 0x59, 0x28, 0xd7, 0x25, 0x16, 0xe3, 0x12, 0x72 } -#define NIST_HMAC_SHA1_MSG { 0xa3, 0xce, 0x88, 0x99, 0xdf, 0x10, 0x22, 0xe8, 0xd2, 0xd5, 0x39, 0xb4, 0x7b, 0xf0, 0xe3, 0x09, \ - 0xc6, 0x6f, 0x84, 0x09, 0x5e, 0x21, 0x43, 0x8e, 0xc3, 0x55, 0xbf, 0x11, 0x9c, 0xe5, 0xfd, 0xcb, \ - 0x4e, 0x73, 0xa6, 0x19, 0xcd, 0xf3, 0x6f, 0x25, 0xb3, 0x69, 0xd8, 0xc3, 0x8f, 0xf4, 0x19, 0x99, \ - 0x7f, 0x0c, 0x59, 0x83, 0x01, 0x08, 0x22, 0x36, 0x06, 0xe3, 0x12, 0x23, 0x48, 0x3f, 0xd3, 0x9e, \ - 0xde, 0xaa, 0x4d, 0x3f, 0x0d, 0x21, 0x19, 0x88, 0x62, 0xd2, 0x39, 0xc9, 0xfd, 0x26, 0x07, 0x41, \ - 0x30, 0xff, 0x6c, 0x86, 0x49, 0x3f, 0x52, 0x27, 0xab, 0x89, 0x5c, 0x8f, 0x24, 0x4b, 0xd4, 0x2c, \ - 0x7a, 0xfc, 0xe5, 0xd1, 0x47, 0xa2, 0x0a, 0x59, 0x07, 0x98, 0xc6, 0x8e, 0x70, 0x8e, 0x96, 0x49, \ - 0x02, 0xd1, 0x24, 0xda, 0xde, 0xcd, 0xbd, 0xa9, 0xdb, 0xd0, 0x05, 0x1e, 0xd7, 0x10, 0xe9, 0xbf } -#define NIST_HMAC_SHA1_MD { 0x3c, 0x81, 0x62, 0x58, 0x9a, 0xaf, 0xae, 0xe0, 0x24, 0xfc, 0x9a, 0x5c, 0xa5, 0x0d, 0xd2, 0x33, \ - 0x6f, 0xe3, 0xeb, 0x28 } - -#define NIST_HMAC_SHA256_KEY_SIZE 40 -#define NIST_HMAC_SHA256_KEY { 0x97, 0x79, 0xd9, 0x12, 0x06, 0x42, 0x79, 0x7f, 0x17, 0x47, 0x02, 0x5d, 0x5b, 0x22, 0xb7, 0xac, \ - 0x60, 0x7c, 0xab, 0x08, 0xe1, 0x75, 0x8f, 0x2f, 0x3a, 0x46, 0xc8, 0xbe, 0x1e, 0x25, 0xc5, 0x3b, \ - 0x8c, 0x6a, 0x8f, 0x58, 0xff, 0xef, 0xa1, 0x76 } -#define NIST_HMAC_SHA256_MSG { 0xb1, 0x68, 0x9c, 0x25, 0x91, 0xea, 0xf3, 0xc9, 0xe6, 0x60, 0x70, 0xf8, 0xa7, 0x79, 0x54, 0xff, \ - 0xb8, 0x17, 0x49, 0xf1, 0xb0, 0x03, 0x46, 0xf9, 0xdf, 0xe0, 0xb2, 0xee, 0x90, 0x5d, 0xcc, 0x28, \ - 0x8b, 0xaf, 0x4a, 0x92, 0xde, 0x3f, 0x40, 0x01, 0xdd, 0x9f, 0x44, 0xc4, 0x68, 0xc3, 0xd0, 0x7d, \ - 0x6c, 0x6e, 0xe8, 0x2f, 0xac, 0xea, 0xfc, 0x97, 0xc2, 0xfc, 0x0f, 0xc0, 0x60, 0x17, 0x19, 0xd2, \ - 0xdc, 0xd0, 0xaa, 0x2a, 0xec, 0x92, 0xd1, 0xb0, 0xae, 0x93, 0x3c, 0x65, 0xeb, 0x06, 0xa0, 0x3c, \ - 0x9c, 0x93, 0x5c, 0x2b, 0xad, 0x04, 0x59, 0x81, 0x02, 0x41, 0x34, 0x7a, 0xb8, 0x7e, 0x9f, 0x11, \ - 0xad, 0xb3, 0x04, 0x15, 0x42, 0x4c, 0x6c, 0x7f, 0x5f, 0x22, 0xa0, 0x03, 0xb8, 0xab, 0x8d, 0xe5, \ - 0x4f, 0x6d, 0xed, 0x0e, 0x3a, 0xb9, 0x24, 0x5f, 0xa7, 0x95, 0x68, 0x45, 0x1d, 0xfa, 0x25, 0x8e } -#define NIST_HMAC_SHA256_MD { 0x76, 0x9f, 0x00, 0xd3, 0xe6, 0xa6, 0xcc, 0x1f, 0xb4, 0x26, 0xa1, 0x4a, 0x4f, 0x76, 0xc6, 0x46, \ - 0x2e, 0x61, 0x49, 0x72, 0x6e, 0x0d, 0xee, 0x0e, 0xc0, 0xcf, 0x97, 0xa1, 0x66, 0x05, 0xac, 0x8b } - -#define NIST_HMAC_SHA512_KEY_SIZE 100 -#define NIST_HMAC_SHA512_KEY { 0x57, 0xc2, 0xeb, 0x67, 0x7b, 0x50, 0x93, 0xb9, 0xe8, 0x29, 0xea, 0x4b, 0xab, 0xb5, 0x0b, 0xde, \ - 0x55, 0xd0, 0xad, 0x59, 0xfe, 0xc3, 0x4a, 0x61, 0x89, 0x73, 0x80, 0x2b, 0x2a, 0xd9, 0xb7, 0x8e, \ - 0x26, 0xb2, 0x04, 0x5d, 0xda, 0x78, 0x4d, 0xf3, 0xff, 0x90, 0xae, 0x0f, 0x2c, 0xc5, 0x1c, 0xe3, \ - 0x9c, 0xf5, 0x48, 0x67, 0x32, 0x0a, 0xc6, 0xf3, 0xba, 0x2c, 0x6f, 0x0d, 0x72, 0x36, 0x04, 0x80, \ - 0xc9, 0x66, 0x14, 0xae, 0x66, 0x58, 0x1f, 0x26, 0x6c, 0x35, 0xfb, 0x79, 0xfd, 0x28, 0x77, 0x4a, \ - 0xfd, 0x11, 0x3f, 0xa5, 0x18, 0x7e, 0xff, 0x92, 0x06, 0xd7, 0xcb, 0xe9, 0x0d, 0xd8, 0xbf, 0x67, \ - 0xc8, 0x44, 0xe2, 0x02 } -#define NIST_HMAC_SHA512_MSG { 0x24, 0x23, 0xdf, 0xf4, 0x8b, 0x31, 0x2b, 0xe8, 0x64, 0xcb, 0x34, 0x90, 0x64, 0x1f, 0x79, 0x3d, \ - 0x2b, 0x9f, 0xb6, 0x8a, 0x77, 0x63, 0xb8, 0xe2, 0x98, 0xc8, 0x6f, 0x42, 0x24, 0x5e, 0x45, 0x40, \ - 0xeb, 0x01, 0xae, 0x4d, 0x2d, 0x45, 0x00, 0x37, 0x0b, 0x18, 0x86, 0xf2, 0x3c, 0xa2, 0xcf, 0x97, \ - 0x01, 0x70, 0x4c, 0xad, 0x5b, 0xd2, 0x1b, 0xa8, 0x7b, 0x81, 0x1d, 0xaf, 0x7a, 0x85, 0x4e, 0xa2, \ - 0x4a, 0x56, 0x56, 0x5c, 0xed, 0x42, 0x5b, 0x35, 0xe4, 0x0e, 0x1a, 0xcb, 0xeb, 0xe0, 0x36, 0x03, \ - 0xe3, 0x5d, 0xcf, 0x4a, 0x10, 0x0e, 0x57, 0x21, 0x84, 0x08, 0xa1, 0xd8, 0xdb, 0xcc, 0x3b, 0x99, \ - 0x29, 0x6c, 0xfe, 0xa9, 0x31, 0xef, 0xe3, 0xeb, 0xd8, 0xf7, 0x19, 0xa6, 0xd9, 0xa1, 0x54, 0x87, \ - 0xb9, 0xad, 0x67, 0xea, 0xfe, 0xdf, 0x15, 0x55, 0x9c, 0xa4, 0x24, 0x45, 0xb0, 0xf9, 0xb4, 0x2e } -#define NIST_HMAC_SHA512_MD { 0x33, 0xc5, 0x11, 0xe9, 0xbc, 0x23, 0x07, 0xc6, 0x27, 0x58, 0xdf, 0x61, 0x12, 0x5a, 0x98, 0x0e, \ - 0xe6, 0x4c, 0xef, 0xeb, 0xd9, 0x09, 0x31, 0xcb, 0x91, 0xc1, 0x37, 0x42, 0xd4, 0x71, 0x4c, 0x06, \ - 0xde, 0x40, 0x03, 0xfa, 0xf3, 0xc4, 0x1c, 0x06, 0xae, 0xfc, 0x63, 0x8a, 0xd4, 0x7b, 0x21, 0x90, \ - 0x6e, 0x6b, 0x10, 0x48, 0x16, 0xb7, 0x2d, 0xe6, 0x26, 0x9e, 0x04, 0x5a, 0x1f, 0x44, 0x29, 0xd4 } - diff --git a/drivers/staging/ccree/ssi_fips_ext.c b/drivers/staging/ccree/ssi_fips_ext.c deleted file mode 100644 index e7bf1843f60c..000000000000 --- a/drivers/staging/ccree/ssi_fips_ext.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2012-2017 ARM Limited or its affiliates. - * - * 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 . - */ - -/************************************************************** - * This file defines the driver FIPS functions that should be - * implemented by the driver user. Current implementation is sample code only. - ***************************************************************/ - -#include -#include "ssi_fips_local.h" -#include "ssi_driver.h" - -static bool tee_error; -module_param(tee_error, bool, 0644); -MODULE_PARM_DESC(tee_error, "Simulate TEE library failure flag: 0 - no error (default), 1 - TEE error occured "); - -static enum cc_fips_state_t fips_state = CC_FIPS_STATE_NOT_SUPPORTED; -static enum cc_fips_error fips_error = CC_REE_FIPS_ERROR_OK; - -/* - * This function returns the FIPS REE state. - * The function should be implemented by the driver user, depends on where - * the state value is stored. - * The reference code uses global variable. - */ -int ssi_fips_ext_get_state(enum cc_fips_state_t *p_state) -{ - int rc = 0; - - if (!p_state) - return -EINVAL; - - *p_state = fips_state; - - return rc; -} - -/* - * This function returns the FIPS REE error. - * The function should be implemented by the driver user, depends on where - * the error value is stored. - * The reference code uses global variable. - */ -int ssi_fips_ext_get_error(enum cc_fips_error *p_err) -{ - int rc = 0; - - if (!p_err) - return -EINVAL; - - *p_err = fips_error; - - return rc; -} - -/* - * This function sets the FIPS REE state. - * The function should be implemented by the driver user, depends on where - * the state value is stored. - * The reference code uses global variable. - */ -int ssi_fips_ext_set_state(enum cc_fips_state_t state) -{ - fips_state = state; - return 0; -} - -/* - * This function sets the FIPS REE error. - * The function should be implemented by the driver user, depends on where - * the error value is stored. - * The reference code uses global variable. - */ -int ssi_fips_ext_set_error(enum cc_fips_error err) -{ - fips_error = err; - return 0; -} - diff --git a/drivers/staging/ccree/ssi_fips_ll.c b/drivers/staging/ccree/ssi_fips_ll.c deleted file mode 100644 index 4a7a1a61e117..000000000000 --- a/drivers/staging/ccree/ssi_fips_ll.c +++ /dev/null @@ -1,1620 +0,0 @@ -/* - * Copyright (C) 2012-2017 ARM Limited or its affiliates. - * - * 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 . - */ - -/************************************************************** - * This file defines the driver FIPS Low Level implmentaion functions, - * that executes the KAT. - ***************************************************************/ -#include - -#include "ssi_driver.h" -#include "ssi_fips_local.h" -#include "ssi_fips_data.h" -#include "cc_crypto_ctx.h" -#include "ssi_hash.h" -#include "ssi_request_mgr.h" - -static const u32 digest_len_init[] = { - 0x00000040, 0x00000000, 0x00000000, 0x00000000 }; -static const u32 sha1_init[] = { - SHA1_H4, SHA1_H3, SHA1_H2, SHA1_H1, SHA1_H0 }; -static const u32 sha256_init[] = { - SHA256_H7, SHA256_H6, SHA256_H5, SHA256_H4, - SHA256_H3, SHA256_H2, SHA256_H1, SHA256_H0 }; -#if (CC_SUPPORT_SHA > 256) -static const u32 digest_len_sha512_init[] = { - 0x00000080, 0x00000000, 0x00000000, 0x00000000 }; -static const u64 sha512_init[] = { - SHA512_H7, SHA512_H6, SHA512_H5, SHA512_H4, - SHA512_H3, SHA512_H2, SHA512_H1, SHA512_H0 }; -#endif - -#define NIST_CIPHER_AES_MAX_VECTOR_SIZE 32 - -struct fips_cipher_ctx { - u8 iv[CC_AES_IV_SIZE]; - u8 key[AES_512_BIT_KEY_SIZE]; - u8 din[NIST_CIPHER_AES_MAX_VECTOR_SIZE]; - u8 dout[NIST_CIPHER_AES_MAX_VECTOR_SIZE]; -}; - -typedef struct _FipsCipherData { - u8 isAes; - u8 key[AES_512_BIT_KEY_SIZE]; - size_t keySize; - u8 iv[CC_AES_IV_SIZE]; - enum drv_crypto_direction direction; - enum drv_cipher_mode oprMode; - u8 dataIn[NIST_CIPHER_AES_MAX_VECTOR_SIZE]; - u8 dataOut[NIST_CIPHER_AES_MAX_VECTOR_SIZE]; - size_t dataInSize; -} FipsCipherData; - -struct fips_cmac_ctx { - u8 key[AES_256_BIT_KEY_SIZE]; - u8 din[NIST_CIPHER_AES_MAX_VECTOR_SIZE]; - u8 mac_res[CC_DIGEST_SIZE_MAX]; -}; - -typedef struct _FipsCmacData { - enum drv_crypto_direction direction; - u8 key[AES_256_BIT_KEY_SIZE]; - size_t key_size; - u8 data_in[NIST_CIPHER_AES_MAX_VECTOR_SIZE]; - size_t data_in_size; - u8 mac_res[CC_DIGEST_SIZE_MAX]; - size_t mac_res_size; -} FipsCmacData; - -struct fips_hash_ctx { - u8 initial_digest[CC_DIGEST_SIZE_MAX]; - u8 din[NIST_SHA_MSG_SIZE]; - u8 mac_res[CC_DIGEST_SIZE_MAX]; -}; - -typedef struct _FipsHashData { - enum drv_hash_mode hash_mode; - u8 data_in[NIST_SHA_MSG_SIZE]; - size_t data_in_size; - u8 mac_res[CC_DIGEST_SIZE_MAX]; -} FipsHashData; - -/* note that the hmac key length must be equal or less than block size (block size is 64 up to sha256 and 128 for sha384/512) */ -struct fips_hmac_ctx { - u8 initial_digest[CC_DIGEST_SIZE_MAX]; - u8 key[CC_HMAC_BLOCK_SIZE_MAX]; - u8 k0[CC_HMAC_BLOCK_SIZE_MAX]; - u8 digest_bytes_len[HASH_LEN_SIZE]; - u8 tmp_digest[CC_DIGEST_SIZE_MAX]; - u8 din[NIST_HMAC_MSG_SIZE]; - u8 mac_res[CC_DIGEST_SIZE_MAX]; -}; - -typedef struct _FipsHmacData { - enum drv_hash_mode hash_mode; - u8 key[CC_HMAC_BLOCK_SIZE_MAX]; - size_t key_size; - u8 data_in[NIST_HMAC_MSG_SIZE]; - size_t data_in_size; - u8 mac_res[CC_DIGEST_SIZE_MAX]; -} FipsHmacData; - -#define FIPS_CCM_B0_A0_ADATA_SIZE (NIST_AESCCM_IV_SIZE + NIST_AESCCM_IV_SIZE + NIST_AESCCM_ADATA_SIZE) - -struct fips_ccm_ctx { - u8 b0_a0_adata[FIPS_CCM_B0_A0_ADATA_SIZE]; - u8 iv[NIST_AESCCM_IV_SIZE]; - u8 ctr_cnt_0[NIST_AESCCM_IV_SIZE]; - u8 key[CC_AES_KEY_SIZE_MAX]; - u8 din[NIST_AESCCM_TEXT_SIZE]; - u8 dout[NIST_AESCCM_TEXT_SIZE]; - u8 mac_res[NIST_AESCCM_TAG_SIZE]; -}; - -typedef struct _FipsCcmData { - enum drv_crypto_direction direction; - u8 key[CC_AES_KEY_SIZE_MAX]; - size_t keySize; - u8 nonce[NIST_AESCCM_NONCE_SIZE]; - u8 adata[NIST_AESCCM_ADATA_SIZE]; - size_t adataSize; - u8 dataIn[NIST_AESCCM_TEXT_SIZE]; - size_t dataInSize; - u8 dataOut[NIST_AESCCM_TEXT_SIZE]; - u8 tagSize; - u8 macResOut[NIST_AESCCM_TAG_SIZE]; -} FipsCcmData; - -struct fips_gcm_ctx { - u8 adata[NIST_AESGCM_ADATA_SIZE]; - u8 key[CC_AES_KEY_SIZE_MAX]; - u8 hkey[CC_AES_KEY_SIZE_MAX]; - u8 din[NIST_AESGCM_TEXT_SIZE]; - u8 dout[NIST_AESGCM_TEXT_SIZE]; - u8 mac_res[NIST_AESGCM_TAG_SIZE]; - u8 len_block[AES_BLOCK_SIZE]; - u8 iv_inc1[AES_BLOCK_SIZE]; - u8 iv_inc2[AES_BLOCK_SIZE]; -}; - -typedef struct _FipsGcmData { - enum drv_crypto_direction direction; - u8 key[CC_AES_KEY_SIZE_MAX]; - size_t keySize; - u8 iv[NIST_AESGCM_IV_SIZE]; - u8 adata[NIST_AESGCM_ADATA_SIZE]; - size_t adataSize; - u8 dataIn[NIST_AESGCM_TEXT_SIZE]; - size_t dataInSize; - u8 dataOut[NIST_AESGCM_TEXT_SIZE]; - u8 tagSize; - u8 macResOut[NIST_AESGCM_TAG_SIZE]; -} FipsGcmData; - -typedef union _fips_ctx { - struct fips_cipher_ctx cipher; - struct fips_cmac_ctx cmac; - struct fips_hash_ctx hash; - struct fips_hmac_ctx hmac; - struct fips_ccm_ctx ccm; - struct fips_gcm_ctx gcm; -} fips_ctx; - -/* test data tables */ -static const FipsCipherData FipsCipherDataTable[] = { - /* AES */ - { 1, NIST_AES_128_KEY, CC_AES_128_BIT_KEY_SIZE, NIST_AES_ECB_IV, DRV_CRYPTO_DIRECTION_ENCRYPT, DRV_CIPHER_ECB, NIST_AES_PLAIN_DATA, NIST_AES_128_ECB_CIPHER, NIST_AES_VECTOR_SIZE }, - { 1, NIST_AES_128_KEY, CC_AES_128_BIT_KEY_SIZE, NIST_AES_ECB_IV, DRV_CRYPTO_DIRECTION_DECRYPT, DRV_CIPHER_ECB, NIST_AES_128_ECB_CIPHER, NIST_AES_PLAIN_DATA, NIST_AES_VECTOR_SIZE }, - { 1, NIST_AES_192_KEY, CC_AES_192_BIT_KEY_SIZE, NIST_AES_ECB_IV, DRV_CRYPTO_DIRECTION_ENCRYPT, DRV_CIPHER_ECB, NIST_AES_PLAIN_DATA, NIST_AES_192_ECB_CIPHER, NIST_AES_VECTOR_SIZE }, - { 1, NIST_AES_192_KEY, CC_AES_192_BIT_KEY_SIZE, NIST_AES_ECB_IV, DRV_CRYPTO_DIRECTION_DECRYPT, DRV_CIPHER_ECB, NIST_AES_192_ECB_CIPHER, NIST_AES_PLAIN_DATA, NIST_AES_VECTOR_SIZE }, - { 1, NIST_AES_256_KEY, CC_AES_256_BIT_KEY_SIZE, NIST_AES_ECB_IV, DRV_CRYPTO_DIRECTION_ENCRYPT, DRV_CIPHER_ECB, NIST_AES_PLAIN_DATA, NIST_AES_256_ECB_CIPHER, NIST_AES_VECTOR_SIZE }, - { 1, NIST_AES_256_KEY, CC_AES_256_BIT_KEY_SIZE, NIST_AES_ECB_IV, DRV_CRYPTO_DIRECTION_DECRYPT, DRV_CIPHER_ECB, NIST_AES_256_ECB_CIPHER, NIST_AES_PLAIN_DATA, NIST_AES_VECTOR_SIZE }, - { 1, NIST_AES_128_KEY, CC_AES_128_BIT_KEY_SIZE, NIST_AES_CBC_IV, DRV_CRYPTO_DIRECTION_ENCRYPT, DRV_CIPHER_CBC, NIST_AES_PLAIN_DATA, NIST_AES_128_CBC_CIPHER, NIST_AES_VECTOR_SIZE }, - { 1, NIST_AES_128_KEY, CC_AES_128_BIT_KEY_SIZE, NIST_AES_CBC_IV, DRV_CRYPTO_DIRECTION_DECRYPT, DRV_CIPHER_CBC, NIST_AES_128_CBC_CIPHER, NIST_AES_PLAIN_DATA, NIST_AES_VECTOR_SIZE }, - { 1, NIST_AES_192_KEY, CC_AES_192_BIT_KEY_SIZE, NIST_AES_CBC_IV, DRV_CRYPTO_DIRECTION_ENCRYPT, DRV_CIPHER_CBC, NIST_AES_PLAIN_DATA, NIST_AES_192_CBC_CIPHER, NIST_AES_VECTOR_SIZE }, - { 1, NIST_AES_192_KEY, CC_AES_192_BIT_KEY_SIZE, NIST_AES_CBC_IV, DRV_CRYPTO_DIRECTION_DECRYPT, DRV_CIPHER_CBC, NIST_AES_192_CBC_CIPHER, NIST_AES_PLAIN_DATA, NIST_AES_VECTOR_SIZE }, - { 1, NIST_AES_256_KEY, CC_AES_256_BIT_KEY_SIZE, NIST_AES_CBC_IV, DRV_CRYPTO_DIRECTION_ENCRYPT, DRV_CIPHER_CBC, NIST_AES_PLAIN_DATA, NIST_AES_256_CBC_CIPHER, NIST_AES_VECTOR_SIZE }, - { 1, NIST_AES_256_KEY, CC_AES_256_BIT_KEY_SIZE, NIST_AES_CBC_IV, DRV_CRYPTO_DIRECTION_DECRYPT, DRV_CIPHER_CBC, NIST_AES_256_CBC_CIPHER, NIST_AES_PLAIN_DATA, NIST_AES_VECTOR_SIZE }, - { 1, NIST_AES_128_KEY, CC_AES_128_BIT_KEY_SIZE, NIST_AES_OFB_IV, DRV_CRYPTO_DIRECTION_ENCRYPT, DRV_CIPHER_OFB, NIST_AES_PLAIN_DATA, NIST_AES_128_OFB_CIPHER, NIST_AES_VECTOR_SIZE }, - { 1, NIST_AES_128_KEY, CC_AES_128_BIT_KEY_SIZE, NIST_AES_OFB_IV, DRV_CRYPTO_DIRECTION_ENCRYPT, DRV_CIPHER_OFB, NIST_AES_128_OFB_CIPHER, NIST_AES_PLAIN_DATA, NIST_AES_VECTOR_SIZE }, - { 1, NIST_AES_192_KEY, CC_AES_192_BIT_KEY_SIZE, NIST_AES_OFB_IV, DRV_CRYPTO_DIRECTION_ENCRYPT, DRV_CIPHER_OFB, NIST_AES_PLAIN_DATA, NIST_AES_192_OFB_CIPHER, NIST_AES_VECTOR_SIZE }, - { 1, NIST_AES_192_KEY, CC_AES_192_BIT_KEY_SIZE, NIST_AES_OFB_IV, DRV_CRYPTO_DIRECTION_DECRYPT, DRV_CIPHER_OFB, NIST_AES_192_OFB_CIPHER, NIST_AES_PLAIN_DATA, NIST_AES_VECTOR_SIZE }, - { 1, NIST_AES_256_KEY, CC_AES_256_BIT_KEY_SIZE, NIST_AES_OFB_IV, DRV_CRYPTO_DIRECTION_ENCRYPT, DRV_CIPHER_OFB, NIST_AES_PLAIN_DATA, NIST_AES_256_OFB_CIPHER, NIST_AES_VECTOR_SIZE }, - { 1, NIST_AES_256_KEY, CC_AES_256_BIT_KEY_SIZE, NIST_AES_OFB_IV, DRV_CRYPTO_DIRECTION_DECRYPT, DRV_CIPHER_OFB, NIST_AES_256_OFB_CIPHER, NIST_AES_PLAIN_DATA, NIST_AES_VECTOR_SIZE }, - { 1, NIST_AES_128_KEY, CC_AES_128_BIT_KEY_SIZE, NIST_AES_CTR_IV, DRV_CRYPTO_DIRECTION_ENCRYPT, DRV_CIPHER_CTR, NIST_AES_PLAIN_DATA, NIST_AES_128_CTR_CIPHER, NIST_AES_VECTOR_SIZE }, - { 1, NIST_AES_128_KEY, CC_AES_128_BIT_KEY_SIZE, NIST_AES_CTR_IV, DRV_CRYPTO_DIRECTION_DECRYPT, DRV_CIPHER_CTR, NIST_AES_128_CTR_CIPHER, NIST_AES_PLAIN_DATA, NIST_AES_VECTOR_SIZE }, - { 1, NIST_AES_192_KEY, CC_AES_192_BIT_KEY_SIZE, NIST_AES_CTR_IV, DRV_CRYPTO_DIRECTION_ENCRYPT, DRV_CIPHER_CTR, NIST_AES_PLAIN_DATA, NIST_AES_192_CTR_CIPHER, NIST_AES_VECTOR_SIZE }, - { 1, NIST_AES_192_KEY, CC_AES_192_BIT_KEY_SIZE, NIST_AES_CTR_IV, DRV_CRYPTO_DIRECTION_DECRYPT, DRV_CIPHER_CTR, NIST_AES_192_CTR_CIPHER, NIST_AES_PLAIN_DATA, NIST_AES_VECTOR_SIZE }, - { 1, NIST_AES_256_KEY, CC_AES_256_BIT_KEY_SIZE, NIST_AES_CTR_IV, DRV_CRYPTO_DIRECTION_ENCRYPT, DRV_CIPHER_CTR, NIST_AES_PLAIN_DATA, NIST_AES_256_CTR_CIPHER, NIST_AES_VECTOR_SIZE }, - { 1, NIST_AES_256_KEY, CC_AES_256_BIT_KEY_SIZE, NIST_AES_CTR_IV, DRV_CRYPTO_DIRECTION_DECRYPT, DRV_CIPHER_CTR, NIST_AES_256_CTR_CIPHER, NIST_AES_PLAIN_DATA, NIST_AES_VECTOR_SIZE }, - { 1, RFC3962_AES_128_KEY, CC_AES_128_BIT_KEY_SIZE, RFC3962_AES_CBC_CTS_IV, DRV_CRYPTO_DIRECTION_ENCRYPT, DRV_CIPHER_CBC_CTS, RFC3962_AES_PLAIN_DATA, RFC3962_AES_128_CBC_CTS_CIPHER, RFC3962_AES_VECTOR_SIZE }, - { 1, RFC3962_AES_128_KEY, CC_AES_128_BIT_KEY_SIZE, RFC3962_AES_CBC_CTS_IV, DRV_CRYPTO_DIRECTION_DECRYPT, DRV_CIPHER_CBC_CTS, RFC3962_AES_128_CBC_CTS_CIPHER, RFC3962_AES_PLAIN_DATA, RFC3962_AES_VECTOR_SIZE }, - { 1, NIST_AES_256_XTS_KEY, CC_AES_256_BIT_KEY_SIZE, NIST_AES_256_XTS_IV, DRV_CRYPTO_DIRECTION_ENCRYPT, DRV_CIPHER_XTS, NIST_AES_256_XTS_PLAIN, NIST_AES_256_XTS_CIPHER, NIST_AES_256_XTS_VECTOR_SIZE }, - { 1, NIST_AES_256_XTS_KEY, CC_AES_256_BIT_KEY_SIZE, NIST_AES_256_XTS_IV, DRV_CRYPTO_DIRECTION_DECRYPT, DRV_CIPHER_XTS, NIST_AES_256_XTS_CIPHER, NIST_AES_256_XTS_PLAIN, NIST_AES_256_XTS_VECTOR_SIZE }, -#if (CC_SUPPORT_SHA > 256) - { 1, NIST_AES_512_XTS_KEY, 2 * CC_AES_256_BIT_KEY_SIZE, NIST_AES_512_XTS_IV, DRV_CRYPTO_DIRECTION_ENCRYPT, DRV_CIPHER_XTS, NIST_AES_512_XTS_PLAIN, NIST_AES_512_XTS_CIPHER, NIST_AES_512_XTS_VECTOR_SIZE }, - { 1, NIST_AES_512_XTS_KEY, 2 * CC_AES_256_BIT_KEY_SIZE, NIST_AES_512_XTS_IV, DRV_CRYPTO_DIRECTION_DECRYPT, DRV_CIPHER_XTS, NIST_AES_512_XTS_CIPHER, NIST_AES_512_XTS_PLAIN, NIST_AES_512_XTS_VECTOR_SIZE }, -#endif - /* DES */ - { 0, NIST_TDES_ECB3_KEY, CC_DRV_DES_TRIPLE_KEY_SIZE, NIST_TDES_ECB_IV, DRV_CRYPTO_DIRECTION_ENCRYPT, DRV_CIPHER_ECB, NIST_TDES_ECB3_PLAIN_DATA, NIST_TDES_ECB3_CIPHER, NIST_TDES_VECTOR_SIZE }, - { 0, NIST_TDES_ECB3_KEY, CC_DRV_DES_TRIPLE_KEY_SIZE, NIST_TDES_ECB_IV, DRV_CRYPTO_DIRECTION_DECRYPT, DRV_CIPHER_ECB, NIST_TDES_ECB3_CIPHER, NIST_TDES_ECB3_PLAIN_DATA, NIST_TDES_VECTOR_SIZE }, - { 0, NIST_TDES_CBC3_KEY, CC_DRV_DES_TRIPLE_KEY_SIZE, NIST_TDES_CBC3_IV, DRV_CRYPTO_DIRECTION_ENCRYPT, DRV_CIPHER_CBC, NIST_TDES_CBC3_PLAIN_DATA, NIST_TDES_CBC3_CIPHER, NIST_TDES_VECTOR_SIZE }, - { 0, NIST_TDES_CBC3_KEY, CC_DRV_DES_TRIPLE_KEY_SIZE, NIST_TDES_CBC3_IV, DRV_CRYPTO_DIRECTION_DECRYPT, DRV_CIPHER_CBC, NIST_TDES_CBC3_CIPHER, NIST_TDES_CBC3_PLAIN_DATA, NIST_TDES_VECTOR_SIZE }, -}; - -#define FIPS_CIPHER_NUM_OF_TESTS (sizeof(FipsCipherDataTable) / sizeof(FipsCipherData)) - -static const FipsCmacData FipsCmacDataTable[] = { - { DRV_CRYPTO_DIRECTION_ENCRYPT, NIST_AES_128_CMAC_KEY, AES_128_BIT_KEY_SIZE, NIST_AES_128_CMAC_PLAIN_DATA, NIST_AES_128_CMAC_VECTOR_SIZE, NIST_AES_128_CMAC_MAC, NIST_AES_128_CMAC_OUTPUT_SIZE }, - { DRV_CRYPTO_DIRECTION_ENCRYPT, NIST_AES_192_CMAC_KEY, AES_192_BIT_KEY_SIZE, NIST_AES_192_CMAC_PLAIN_DATA, NIST_AES_192_CMAC_VECTOR_SIZE, NIST_AES_192_CMAC_MAC, NIST_AES_192_CMAC_OUTPUT_SIZE }, - { DRV_CRYPTO_DIRECTION_ENCRYPT, NIST_AES_256_CMAC_KEY, AES_256_BIT_KEY_SIZE, NIST_AES_256_CMAC_PLAIN_DATA, NIST_AES_256_CMAC_VECTOR_SIZE, NIST_AES_256_CMAC_MAC, NIST_AES_256_CMAC_OUTPUT_SIZE }, -}; - -#define FIPS_CMAC_NUM_OF_TESTS (sizeof(FipsCmacDataTable) / sizeof(FipsCmacData)) - -static const FipsHashData FipsHashDataTable[] = { - { DRV_HASH_SHA1, NIST_SHA_1_MSG, NIST_SHA_MSG_SIZE, NIST_SHA_1_MD }, - { DRV_HASH_SHA256, NIST_SHA_256_MSG, NIST_SHA_MSG_SIZE, NIST_SHA_256_MD }, -#if (CC_SUPPORT_SHA > 256) -// { DRV_HASH_SHA512, NIST_SHA_512_MSG, NIST_SHA_MSG_SIZE, NIST_SHA_512_MD }, -#endif -}; - -#define FIPS_HASH_NUM_OF_TESTS (sizeof(FipsHashDataTable) / sizeof(FipsHashData)) - -static const FipsHmacData FipsHmacDataTable[] = { - { DRV_HASH_SHA1, NIST_HMAC_SHA1_KEY, NIST_HMAC_SHA1_KEY_SIZE, NIST_HMAC_SHA1_MSG, NIST_HMAC_MSG_SIZE, NIST_HMAC_SHA1_MD }, - { DRV_HASH_SHA256, NIST_HMAC_SHA256_KEY, NIST_HMAC_SHA256_KEY_SIZE, NIST_HMAC_SHA256_MSG, NIST_HMAC_MSG_SIZE, NIST_HMAC_SHA256_MD }, -#if (CC_SUPPORT_SHA > 256) -// { DRV_HASH_SHA512, NIST_HMAC_SHA512_KEY, NIST_HMAC_SHA512_KEY_SIZE, NIST_HMAC_SHA512_MSG, NIST_HMAC_MSG_SIZE, NIST_HMAC_SHA512_MD }, -#endif -}; - -#define FIPS_HMAC_NUM_OF_TESTS (sizeof(FipsHmacDataTable) / sizeof(FipsHmacData)) - -static const FipsCcmData FipsCcmDataTable[] = { - { DRV_CRYPTO_DIRECTION_ENCRYPT, NIST_AESCCM_128_KEY, NIST_AESCCM_128_BIT_KEY_SIZE, NIST_AESCCM_128_NONCE, NIST_AESCCM_128_ADATA, NIST_AESCCM_ADATA_SIZE, NIST_AESCCM_128_PLAIN_TEXT, NIST_AESCCM_TEXT_SIZE, NIST_AESCCM_128_CIPHER, NIST_AESCCM_TAG_SIZE, NIST_AESCCM_128_MAC }, - { DRV_CRYPTO_DIRECTION_DECRYPT, NIST_AESCCM_128_KEY, NIST_AESCCM_128_BIT_KEY_SIZE, NIST_AESCCM_128_NONCE, NIST_AESCCM_128_ADATA, NIST_AESCCM_ADATA_SIZE, NIST_AESCCM_128_CIPHER, NIST_AESCCM_TEXT_SIZE, NIST_AESCCM_128_PLAIN_TEXT, NIST_AESCCM_TAG_SIZE, NIST_AESCCM_128_MAC }, - { DRV_CRYPTO_DIRECTION_ENCRYPT, NIST_AESCCM_192_KEY, NIST_AESCCM_192_BIT_KEY_SIZE, NIST_AESCCM_192_NONCE, NIST_AESCCM_192_ADATA, NIST_AESCCM_ADATA_SIZE, NIST_AESCCM_192_PLAIN_TEXT, NIST_AESCCM_TEXT_SIZE, NIST_AESCCM_192_CIPHER, NIST_AESCCM_TAG_SIZE, NIST_AESCCM_192_MAC }, - { DRV_CRYPTO_DIRECTION_DECRYPT, NIST_AESCCM_192_KEY, NIST_AESCCM_192_BIT_KEY_SIZE, NIST_AESCCM_192_NONCE, NIST_AESCCM_192_ADATA, NIST_AESCCM_ADATA_SIZE, NIST_AESCCM_192_CIPHER, NIST_AESCCM_TEXT_SIZE, NIST_AESCCM_192_PLAIN_TEXT, NIST_AESCCM_TAG_SIZE, NIST_AESCCM_192_MAC }, - { DRV_CRYPTO_DIRECTION_ENCRYPT, NIST_AESCCM_256_KEY, NIST_AESCCM_256_BIT_KEY_SIZE, NIST_AESCCM_256_NONCE, NIST_AESCCM_256_ADATA, NIST_AESCCM_ADATA_SIZE, NIST_AESCCM_256_PLAIN_TEXT, NIST_AESCCM_TEXT_SIZE, NIST_AESCCM_256_CIPHER, NIST_AESCCM_TAG_SIZE, NIST_AESCCM_256_MAC }, - { DRV_CRYPTO_DIRECTION_DECRYPT, NIST_AESCCM_256_KEY, NIST_AESCCM_256_BIT_KEY_SIZE, NIST_AESCCM_256_NONCE, NIST_AESCCM_256_ADATA, NIST_AESCCM_ADATA_SIZE, NIST_AESCCM_256_CIPHER, NIST_AESCCM_TEXT_SIZE, NIST_AESCCM_256_PLAIN_TEXT, NIST_AESCCM_TAG_SIZE, NIST_AESCCM_256_MAC }, -}; - -#define FIPS_CCM_NUM_OF_TESTS (sizeof(FipsCcmDataTable) / sizeof(FipsCcmData)) - -static const FipsGcmData FipsGcmDataTable[] = { - { DRV_CRYPTO_DIRECTION_ENCRYPT, NIST_AESGCM_128_KEY, NIST_AESGCM_128_BIT_KEY_SIZE, NIST_AESGCM_128_IV, NIST_AESGCM_128_ADATA, NIST_AESGCM_ADATA_SIZE, NIST_AESGCM_128_PLAIN_TEXT, NIST_AESGCM_TEXT_SIZE, NIST_AESGCM_128_CIPHER, NIST_AESGCM_TAG_SIZE, NIST_AESGCM_128_MAC }, - { DRV_CRYPTO_DIRECTION_DECRYPT, NIST_AESGCM_128_KEY, NIST_AESGCM_128_BIT_KEY_SIZE, NIST_AESGCM_128_IV, NIST_AESGCM_128_ADATA, NIST_AESGCM_ADATA_SIZE, NIST_AESGCM_128_CIPHER, NIST_AESGCM_TEXT_SIZE, NIST_AESGCM_128_PLAIN_TEXT, NIST_AESGCM_TAG_SIZE, NIST_AESGCM_128_MAC }, - { DRV_CRYPTO_DIRECTION_ENCRYPT, NIST_AESGCM_192_KEY, NIST_AESGCM_192_BIT_KEY_SIZE, NIST_AESGCM_192_IV, NIST_AESGCM_192_ADATA, NIST_AESGCM_ADATA_SIZE, NIST_AESGCM_192_PLAIN_TEXT, NIST_AESGCM_TEXT_SIZE, NIST_AESGCM_192_CIPHER, NIST_AESGCM_TAG_SIZE, NIST_AESGCM_192_MAC }, - { DRV_CRYPTO_DIRECTION_DECRYPT, NIST_AESGCM_192_KEY, NIST_AESGCM_192_BIT_KEY_SIZE, NIST_AESGCM_192_IV, NIST_AESGCM_192_ADATA, NIST_AESGCM_ADATA_SIZE, NIST_AESGCM_192_CIPHER, NIST_AESGCM_TEXT_SIZE, NIST_AESGCM_192_PLAIN_TEXT, NIST_AESGCM_TAG_SIZE, NIST_AESGCM_192_MAC }, - { DRV_CRYPTO_DIRECTION_ENCRYPT, NIST_AESGCM_256_KEY, NIST_AESGCM_256_BIT_KEY_SIZE, NIST_AESGCM_256_IV, NIST_AESGCM_256_ADATA, NIST_AESGCM_ADATA_SIZE, NIST_AESGCM_256_PLAIN_TEXT, NIST_AESGCM_TEXT_SIZE, NIST_AESGCM_256_CIPHER, NIST_AESGCM_TAG_SIZE, NIST_AESGCM_256_MAC }, - { DRV_CRYPTO_DIRECTION_DECRYPT, NIST_AESGCM_256_KEY, NIST_AESGCM_256_BIT_KEY_SIZE, NIST_AESGCM_256_IV, NIST_AESGCM_256_ADATA, NIST_AESGCM_ADATA_SIZE, NIST_AESGCM_256_CIPHER, NIST_AESGCM_TEXT_SIZE, NIST_AESGCM_256_PLAIN_TEXT, NIST_AESGCM_TAG_SIZE, NIST_AESGCM_256_MAC }, -}; - -#define FIPS_GCM_NUM_OF_TESTS (sizeof(FipsGcmDataTable) / sizeof(FipsGcmData)) - -static inline enum cc_fips_error -FIPS_CipherToFipsError(enum drv_cipher_mode mode, bool is_aes) -{ - switch (mode) { - case DRV_CIPHER_ECB: - return is_aes ? CC_REE_FIPS_ERROR_AES_ECB_PUT : CC_REE_FIPS_ERROR_DES_ECB_PUT; - case DRV_CIPHER_CBC: - return is_aes ? CC_REE_FIPS_ERROR_AES_CBC_PUT : CC_REE_FIPS_ERROR_DES_CBC_PUT; - case DRV_CIPHER_OFB: - return CC_REE_FIPS_ERROR_AES_OFB_PUT; - case DRV_CIPHER_CTR: - return CC_REE_FIPS_ERROR_AES_CTR_PUT; - case DRV_CIPHER_CBC_CTS: - return CC_REE_FIPS_ERROR_AES_CBC_CTS_PUT; - case DRV_CIPHER_XTS: - return CC_REE_FIPS_ERROR_AES_XTS_PUT; - default: - return CC_REE_FIPS_ERROR_GENERAL; - } - - return CC_REE_FIPS_ERROR_GENERAL; -} - -static inline int -ssi_cipher_fips_run_test(struct ssi_drvdata *drvdata, - bool is_aes, - int cipher_mode, - int direction, - dma_addr_t key_dma_addr, - size_t key_len, - dma_addr_t iv_dma_addr, - size_t iv_len, - dma_addr_t din_dma_addr, - dma_addr_t dout_dma_addr, - size_t data_size) -{ - /* max number of descriptors used for the flow */ - #define FIPS_CIPHER_MAX_SEQ_LEN 6 - - int rc; - struct ssi_crypto_req ssi_req = {0}; - struct cc_hw_desc desc[FIPS_CIPHER_MAX_SEQ_LEN]; - int idx = 0; - int s_flow_mode = is_aes ? S_DIN_to_AES : S_DIN_to_DES; - - /* create setup descriptors */ - switch (cipher_mode) { - case DRV_CIPHER_CBC: - case DRV_CIPHER_CBC_CTS: - case DRV_CIPHER_CTR: - case DRV_CIPHER_OFB: - /* Load cipher state */ - hw_desc_init(&desc[idx]); - set_din_type(&desc[idx], DMA_DLLI, - iv_dma_addr, iv_len, NS_BIT); - set_cipher_config0(&desc[idx], direction); - set_flow_mode(&desc[idx], s_flow_mode); - set_cipher_mode(&desc[idx], cipher_mode); - if ((cipher_mode == DRV_CIPHER_CTR) || - (cipher_mode == DRV_CIPHER_OFB)) { - set_setup_mode(&desc[idx], SETUP_LOAD_STATE1); - } else { - set_setup_mode(&desc[idx], SETUP_LOAD_STATE0); - } - idx++; - /*FALLTHROUGH*/ - case DRV_CIPHER_ECB: - /* Load key */ - hw_desc_init(&desc[idx]); - set_cipher_mode(&desc[idx], cipher_mode); - set_cipher_config0(&desc[idx], direction); - if (is_aes) { - set_din_type(&desc[idx], DMA_DLLI, key_dma_addr, - ((key_len == 24) ? AES_MAX_KEY_SIZE : - key_len), NS_BIT); - set_key_size_aes(&desc[idx], key_len); - } else {/*des*/ - set_din_type(&desc[idx], DMA_DLLI, key_dma_addr, - key_len, NS_BIT); - set_key_size_des(&desc[idx], key_len); - } - set_flow_mode(&desc[idx], s_flow_mode); - set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); - idx++; - break; - case DRV_CIPHER_XTS: - /* Load AES key */ - hw_desc_init(&desc[idx]); - set_cipher_mode(&desc[idx], cipher_mode); - set_cipher_config0(&desc[idx], direction); - set_din_type(&desc[idx], DMA_DLLI, key_dma_addr, (key_len / 2), - NS_BIT); - set_key_size_aes(&desc[idx], (key_len / 2)); - set_flow_mode(&desc[idx], s_flow_mode); - set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); - idx++; - - /* load XEX key */ - hw_desc_init(&desc[idx]); - set_cipher_mode(&desc[idx], cipher_mode); - set_cipher_config0(&desc[idx], direction); - set_din_type(&desc[idx], DMA_DLLI, - (key_dma_addr + (key_len / 2)), - (key_len / 2), NS_BIT); - set_xex_data_unit_size(&desc[idx], data_size); - set_flow_mode(&desc[idx], s_flow_mode); - set_key_size_aes(&desc[idx], (key_len / 2)); - set_setup_mode(&desc[idx], SETUP_LOAD_XEX_KEY); - idx++; - - /* Set state */ - hw_desc_init(&desc[idx]); - set_setup_mode(&desc[idx], SETUP_LOAD_STATE1); - set_cipher_mode(&desc[idx], cipher_mode); - set_cipher_config0(&desc[idx], direction); - set_key_size_aes(&desc[idx], (key_len / 2)); - set_flow_mode(&desc[idx], s_flow_mode); - set_din_type(&desc[idx], DMA_DLLI, iv_dma_addr, - CC_AES_BLOCK_SIZE, NS_BIT); - idx++; - break; - default: - FIPS_LOG("Unsupported cipher mode (%d)\n", cipher_mode); - BUG(); - } - - /* create data descriptor */ - hw_desc_init(&desc[idx]); - set_din_type(&desc[idx], DMA_DLLI, din_dma_addr, data_size, NS_BIT); - set_dout_dlli(&desc[idx], dout_dma_addr, data_size, NS_BIT, 0); - set_flow_mode(&desc[idx], is_aes ? DIN_AES_DOUT : DIN_DES_DOUT); - idx++; - - /* perform the operation - Lock HW and push sequence */ - BUG_ON(idx > FIPS_CIPHER_MAX_SEQ_LEN); - rc = send_request(drvdata, &ssi_req, desc, idx, false); - - // send_request returns error just in some corner cases which should not appear in this flow. - return rc; -} - -enum cc_fips_error -ssi_cipher_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer) -{ - enum cc_fips_error error = CC_REE_FIPS_ERROR_OK; - size_t i; - struct fips_cipher_ctx *virt_ctx = (struct fips_cipher_ctx *)cpu_addr_buffer; - - /* set the phisical pointers for iv, key, din, dout */ - dma_addr_t iv_dma_addr = dma_coherent_buffer + offsetof(struct fips_cipher_ctx, iv); - dma_addr_t key_dma_addr = dma_coherent_buffer + offsetof(struct fips_cipher_ctx, key); - dma_addr_t din_dma_addr = dma_coherent_buffer + offsetof(struct fips_cipher_ctx, din); - dma_addr_t dout_dma_addr = dma_coherent_buffer + offsetof(struct fips_cipher_ctx, dout); - - for (i = 0; i < FIPS_CIPHER_NUM_OF_TESTS; ++i) { - FipsCipherData *cipherData = (FipsCipherData *)&FipsCipherDataTable[i]; - int rc = 0; - size_t iv_size = cipherData->isAes ? NIST_AES_IV_SIZE : NIST_TDES_IV_SIZE; - - memset(cpu_addr_buffer, 0, sizeof(struct fips_cipher_ctx)); - - /* copy into the allocated buffer */ - memcpy(virt_ctx->iv, cipherData->iv, iv_size); - memcpy(virt_ctx->key, cipherData->key, cipherData->keySize); - memcpy(virt_ctx->din, cipherData->dataIn, cipherData->dataInSize); - - FIPS_DBG("ssi_cipher_fips_run_test - (i = %d) \n", i); - rc = ssi_cipher_fips_run_test(drvdata, - cipherData->isAes, - cipherData->oprMode, - cipherData->direction, - key_dma_addr, - cipherData->keySize, - iv_dma_addr, - iv_size, - din_dma_addr, - dout_dma_addr, - cipherData->dataInSize); - if (rc != 0) { - FIPS_LOG("ssi_cipher_fips_run_test %d returned error - rc = %d \n", i, rc); - error = FIPS_CipherToFipsError(cipherData->oprMode, cipherData->isAes); - break; - } - - /* compare actual dout to expected */ - if (memcmp(virt_ctx->dout, cipherData->dataOut, cipherData->dataInSize) != 0) { - FIPS_LOG("dout comparison error %d - oprMode=%d, isAes=%d\n", i, cipherData->oprMode, cipherData->isAes); - FIPS_LOG(" i expected received \n"); - FIPS_LOG(" i 0x%08x 0x%08x (size=%d) \n", (size_t)cipherData->dataOut, (size_t)virt_ctx->dout, cipherData->dataInSize); - for (i = 0; i < cipherData->dataInSize; ++i) { - FIPS_LOG(" %d 0x%02x 0x%02x \n", i, cipherData->dataOut[i], virt_ctx->dout[i]); - } - - error = FIPS_CipherToFipsError(cipherData->oprMode, cipherData->isAes); - break; - } - } - - return error; -} - -static inline int -ssi_cmac_fips_run_test(struct ssi_drvdata *drvdata, - dma_addr_t key_dma_addr, - size_t key_len, - dma_addr_t din_dma_addr, - size_t din_len, - dma_addr_t digest_dma_addr, - size_t digest_len) -{ - /* max number of descriptors used for the flow */ - #define FIPS_CMAC_MAX_SEQ_LEN 4 - - int rc; - struct ssi_crypto_req ssi_req = {0}; - struct cc_hw_desc desc[FIPS_CMAC_MAX_SEQ_LEN]; - int idx = 0; - - /* Setup CMAC Key */ - hw_desc_init(&desc[idx]); - set_din_type(&desc[idx], DMA_DLLI, key_dma_addr, - ((key_len == 24) ? AES_MAX_KEY_SIZE : key_len), NS_BIT); - set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); - set_cipher_mode(&desc[idx], DRV_CIPHER_CMAC); - set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT); - set_key_size_aes(&desc[idx], key_len); - set_flow_mode(&desc[idx], S_DIN_to_AES); - idx++; - - /* Load MAC state */ - hw_desc_init(&desc[idx]); - set_din_type(&desc[idx], DMA_DLLI, digest_dma_addr, CC_AES_BLOCK_SIZE, - NS_BIT); - set_setup_mode(&desc[idx], SETUP_LOAD_STATE0); - set_cipher_mode(&desc[idx], DRV_CIPHER_CMAC); - set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT); - set_key_size_aes(&desc[idx], key_len); - set_flow_mode(&desc[idx], S_DIN_to_AES); - idx++; - - //ssi_hash_create_data_desc(state, ctx, DIN_AES_DOUT, desc, false, &idx); - hw_desc_init(&desc[idx]); - set_din_type(&desc[idx], DMA_DLLI, din_dma_addr, din_len, NS_BIT); - set_flow_mode(&desc[idx], DIN_AES_DOUT); - idx++; - - /* Get final MAC result */ - hw_desc_init(&desc[idx]); - set_dout_dlli(&desc[idx], digest_dma_addr, CC_AES_BLOCK_SIZE, NS_BIT, - 0); - set_flow_mode(&desc[idx], S_AES_to_DOUT); - set_setup_mode(&desc[idx], SETUP_WRITE_STATE0); - set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT); - set_cipher_mode(&desc[idx], DRV_CIPHER_CMAC); - idx++; - - /* perform the operation - Lock HW and push sequence */ - BUG_ON(idx > FIPS_CMAC_MAX_SEQ_LEN); - rc = send_request(drvdata, &ssi_req, desc, idx, false); - - // send_request returns error just in some corner cases which should not appear in this flow. - return rc; -} - -enum cc_fips_error -ssi_cmac_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer) -{ - enum cc_fips_error error = CC_REE_FIPS_ERROR_OK; - size_t i; - struct fips_cmac_ctx *virt_ctx = (struct fips_cmac_ctx *)cpu_addr_buffer; - - /* set the phisical pointers for key, din, dout */ - dma_addr_t key_dma_addr = dma_coherent_buffer + offsetof(struct fips_cmac_ctx, key); - dma_addr_t din_dma_addr = dma_coherent_buffer + offsetof(struct fips_cmac_ctx, din); - dma_addr_t mac_res_dma_addr = dma_coherent_buffer + offsetof(struct fips_cmac_ctx, mac_res); - - for (i = 0; i < FIPS_CMAC_NUM_OF_TESTS; ++i) { - FipsCmacData *cmac_data = (FipsCmacData *)&FipsCmacDataTable[i]; - int rc = 0; - - memset(cpu_addr_buffer, 0, sizeof(struct fips_cmac_ctx)); - - /* copy into the allocated buffer */ - memcpy(virt_ctx->key, cmac_data->key, cmac_data->key_size); - memcpy(virt_ctx->din, cmac_data->data_in, cmac_data->data_in_size); - - BUG_ON(cmac_data->direction != DRV_CRYPTO_DIRECTION_ENCRYPT); - - FIPS_DBG("ssi_cmac_fips_run_test - (i = %d) \n", i); - rc = ssi_cmac_fips_run_test(drvdata, - key_dma_addr, - cmac_data->key_size, - din_dma_addr, - cmac_data->data_in_size, - mac_res_dma_addr, - cmac_data->mac_res_size); - if (rc != 0) { - FIPS_LOG("ssi_cmac_fips_run_test %d returned error - rc = %d \n", i, rc); - error = CC_REE_FIPS_ERROR_AES_CMAC_PUT; - break; - } - - /* compare actual mac result to expected */ - if (memcmp(virt_ctx->mac_res, cmac_data->mac_res, cmac_data->mac_res_size) != 0) { - FIPS_LOG("comparison error %d - digest_size=%d \n", i, cmac_data->mac_res_size); - FIPS_LOG(" i expected received \n"); - FIPS_LOG(" i 0x%08x 0x%08x \n", (size_t)cmac_data->mac_res, (size_t)virt_ctx->mac_res); - for (i = 0; i < cmac_data->mac_res_size; ++i) { - FIPS_LOG(" %d 0x%02x 0x%02x \n", i, cmac_data->mac_res[i], virt_ctx->mac_res[i]); - } - - error = CC_REE_FIPS_ERROR_AES_CMAC_PUT; - break; - } - } - - return error; -} - -static inline enum cc_fips_error -FIPS_HashToFipsError(enum drv_hash_mode hash_mode) -{ - switch (hash_mode) { - case DRV_HASH_SHA1: - return CC_REE_FIPS_ERROR_SHA1_PUT; - case DRV_HASH_SHA256: - return CC_REE_FIPS_ERROR_SHA256_PUT; -#if (CC_SUPPORT_SHA > 256) - case DRV_HASH_SHA512: - return CC_REE_FIPS_ERROR_SHA512_PUT; -#endif - default: - return CC_REE_FIPS_ERROR_GENERAL; - } - - return CC_REE_FIPS_ERROR_GENERAL; -} - -static inline int -ssi_hash_fips_run_test(struct ssi_drvdata *drvdata, - dma_addr_t initial_digest_dma_addr, - dma_addr_t din_dma_addr, - size_t data_in_size, - dma_addr_t mac_res_dma_addr, - enum drv_hash_mode hash_mode, - enum drv_hash_hw_mode hw_mode, - int digest_size, - int inter_digestsize) -{ - /* max number of descriptors used for the flow */ - #define FIPS_HASH_MAX_SEQ_LEN 4 - - int rc; - struct ssi_crypto_req ssi_req = {0}; - struct cc_hw_desc desc[FIPS_HASH_MAX_SEQ_LEN]; - int idx = 0; - - /* Load initial digest */ - hw_desc_init(&desc[idx]); - set_cipher_mode(&desc[idx], hw_mode); - set_din_type(&desc[idx], DMA_DLLI, initial_digest_dma_addr, - inter_digestsize, NS_BIT); - set_flow_mode(&desc[idx], S_DIN_to_HASH); - set_setup_mode(&desc[idx], SETUP_LOAD_STATE0); - idx++; - - /* Load the hash current length */ - hw_desc_init(&desc[idx]); - set_cipher_mode(&desc[idx], hw_mode); - set_din_const(&desc[idx], 0, HASH_LEN_SIZE); - set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED); - set_flow_mode(&desc[idx], S_DIN_to_HASH); - set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); - idx++; - - /* data descriptor */ - hw_desc_init(&desc[idx]); - set_din_type(&desc[idx], DMA_DLLI, din_dma_addr, data_in_size, NS_BIT); - set_flow_mode(&desc[idx], DIN_HASH); - idx++; - - /* Get final MAC result */ - hw_desc_init(&desc[idx]); - set_cipher_mode(&desc[idx], hw_mode); - set_dout_dlli(&desc[idx], mac_res_dma_addr, digest_size, NS_BIT, 0); - set_flow_mode(&desc[idx], S_HASH_to_DOUT); - set_setup_mode(&desc[idx], SETUP_WRITE_STATE0); - set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED); - if (unlikely((hash_mode == DRV_HASH_MD5) || - (hash_mode == DRV_HASH_SHA384) || - (hash_mode == DRV_HASH_SHA512))) { - set_bytes_swap(&desc[idx], 1); - } else { - set_cipher_config0(&desc[idx], - HASH_DIGEST_RESULT_LITTLE_ENDIAN); - } - idx++; - - /* perform the operation - Lock HW and push sequence */ - BUG_ON(idx > FIPS_HASH_MAX_SEQ_LEN); - rc = send_request(drvdata, &ssi_req, desc, idx, false); - - return rc; -} - -enum cc_fips_error -ssi_hash_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer) -{ - enum cc_fips_error error = CC_REE_FIPS_ERROR_OK; - size_t i; - struct fips_hash_ctx *virt_ctx = (struct fips_hash_ctx *)cpu_addr_buffer; - - /* set the phisical pointers for initial_digest, din, mac_res */ - dma_addr_t initial_digest_dma_addr = dma_coherent_buffer + offsetof(struct fips_hash_ctx, initial_digest); - dma_addr_t din_dma_addr = dma_coherent_buffer + offsetof(struct fips_hash_ctx, din); - dma_addr_t mac_res_dma_addr = dma_coherent_buffer + offsetof(struct fips_hash_ctx, mac_res); - - for (i = 0; i < FIPS_HASH_NUM_OF_TESTS; ++i) { - FipsHashData *hash_data = (FipsHashData *)&FipsHashDataTable[i]; - int rc = 0; - enum drv_hash_hw_mode hw_mode = 0; - int digest_size = 0; - int inter_digestsize = 0; - - memset(cpu_addr_buffer, 0, sizeof(struct fips_hash_ctx)); - - switch (hash_data->hash_mode) { - case DRV_HASH_SHA1: - hw_mode = DRV_HASH_HW_SHA1; - digest_size = CC_SHA1_DIGEST_SIZE; - inter_digestsize = CC_SHA1_DIGEST_SIZE; - /* copy the initial digest into the allocated cache coherent buffer */ - memcpy(virt_ctx->initial_digest, (void *)sha1_init, CC_SHA1_DIGEST_SIZE); - break; - case DRV_HASH_SHA256: - hw_mode = DRV_HASH_HW_SHA256; - digest_size = CC_SHA256_DIGEST_SIZE; - inter_digestsize = CC_SHA256_DIGEST_SIZE; - memcpy(virt_ctx->initial_digest, (void *)sha256_init, CC_SHA256_DIGEST_SIZE); - break; -#if (CC_SUPPORT_SHA > 256) - case DRV_HASH_SHA512: - hw_mode = DRV_HASH_HW_SHA512; - digest_size = CC_SHA512_DIGEST_SIZE; - inter_digestsize = CC_SHA512_DIGEST_SIZE; - memcpy(virt_ctx->initial_digest, (void *)sha512_init, CC_SHA512_DIGEST_SIZE); - break; -#endif - default: - error = FIPS_HashToFipsError(hash_data->hash_mode); - break; - } - - /* copy the din data into the allocated buffer */ - memcpy(virt_ctx->din, hash_data->data_in, hash_data->data_in_size); - - /* run the test on HW */ - FIPS_DBG("ssi_hash_fips_run_test - (i = %d) \n", i); - rc = ssi_hash_fips_run_test(drvdata, - initial_digest_dma_addr, - din_dma_addr, - hash_data->data_in_size, - mac_res_dma_addr, - hash_data->hash_mode, - hw_mode, - digest_size, - inter_digestsize); - if (rc != 0) { - FIPS_LOG("ssi_hash_fips_run_test %d returned error - rc = %d \n", i, rc); - error = FIPS_HashToFipsError(hash_data->hash_mode); - break; - } - - /* compare actual mac result to expected */ - if (memcmp(virt_ctx->mac_res, hash_data->mac_res, digest_size) != 0) { - FIPS_LOG("comparison error %d - hash_mode=%d digest_size=%d \n", i, hash_data->hash_mode, digest_size); - FIPS_LOG(" i expected received \n"); - FIPS_LOG(" i 0x%08x 0x%08x \n", (size_t)hash_data->mac_res, (size_t)virt_ctx->mac_res); - for (i = 0; i < digest_size; ++i) { - FIPS_LOG(" %d 0x%02x 0x%02x \n", i, hash_data->mac_res[i], virt_ctx->mac_res[i]); - } - - error = FIPS_HashToFipsError(hash_data->hash_mode); - break; - } - } - - return error; -} - -static inline enum cc_fips_error -FIPS_HmacToFipsError(enum drv_hash_mode hash_mode) -{ - switch (hash_mode) { - case DRV_HASH_SHA1: - return CC_REE_FIPS_ERROR_HMAC_SHA1_PUT; - case DRV_HASH_SHA256: - return CC_REE_FIPS_ERROR_HMAC_SHA256_PUT; -#if (CC_SUPPORT_SHA > 256) - case DRV_HASH_SHA512: - return CC_REE_FIPS_ERROR_HMAC_SHA512_PUT; -#endif - default: - return CC_REE_FIPS_ERROR_GENERAL; - } - - return CC_REE_FIPS_ERROR_GENERAL; -} - -static inline int -ssi_hmac_fips_run_test(struct ssi_drvdata *drvdata, - dma_addr_t initial_digest_dma_addr, - dma_addr_t key_dma_addr, - size_t key_size, - dma_addr_t din_dma_addr, - size_t data_in_size, - dma_addr_t mac_res_dma_addr, - enum drv_hash_mode hash_mode, - enum drv_hash_hw_mode hw_mode, - size_t digest_size, - size_t inter_digestsize, - size_t block_size, - dma_addr_t k0_dma_addr, - dma_addr_t tmp_digest_dma_addr, - dma_addr_t digest_bytes_len_dma_addr) -{ - /* The implemented flow is not the same as the one implemented in ssi_hash.c (setkey + digest flows). - * In this flow, there is no need to store and reload some of the intermidiate results. - */ - - /* max number of descriptors used for the flow */ - #define FIPS_HMAC_MAX_SEQ_LEN 12 - - int rc; - struct ssi_crypto_req ssi_req = {0}; - struct cc_hw_desc desc[FIPS_HMAC_MAX_SEQ_LEN]; - int idx = 0; - int i; - /* calc the hash opad first and ipad only afterwards (unlike the flow in ssi_hash.c) */ - unsigned int hmacPadConst[2] = { HMAC_OPAD_CONST, HMAC_IPAD_CONST }; - - // assume (key_size <= block_size) - hw_desc_init(&desc[idx]); - set_din_type(&desc[idx], DMA_DLLI, key_dma_addr, key_size, NS_BIT); - set_flow_mode(&desc[idx], BYPASS); - set_dout_dlli(&desc[idx], k0_dma_addr, key_size, NS_BIT, 0); - idx++; - - // if needed, append Key with zeros to create K0 - if ((block_size - key_size) != 0) { - hw_desc_init(&desc[idx]); - set_din_const(&desc[idx], 0, (block_size - key_size)); - set_flow_mode(&desc[idx], BYPASS); - set_dout_dlli(&desc[idx], (k0_dma_addr + key_size), - (block_size - key_size), NS_BIT, 0); - idx++; - } - - BUG_ON(idx > FIPS_HMAC_MAX_SEQ_LEN); - rc = send_request(drvdata, &ssi_req, desc, idx, 0); - if (unlikely(rc != 0)) { - SSI_LOG_ERR("send_request() failed (rc=%d)\n", rc); - return rc; - } - idx = 0; - - /* calc derived HMAC key */ - for (i = 0; i < 2; i++) { - /* Load hash initial state */ - hw_desc_init(&desc[idx]); - set_cipher_mode(&desc[idx], hw_mode); - set_din_type(&desc[idx], DMA_DLLI, initial_digest_dma_addr, - inter_digestsize, NS_BIT); - set_flow_mode(&desc[idx], S_DIN_to_HASH); - set_setup_mode(&desc[idx], SETUP_LOAD_STATE0); - idx++; - - /* Load the hash current length*/ - hw_desc_init(&desc[idx]); - set_cipher_mode(&desc[idx], hw_mode); - set_din_const(&desc[idx], 0, HASH_LEN_SIZE); - set_flow_mode(&desc[idx], S_DIN_to_HASH); - set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); - idx++; - - /* Prepare opad/ipad key */ - hw_desc_init(&desc[idx]); - set_xor_val(&desc[idx], hmacPadConst[i]); - set_cipher_mode(&desc[idx], hw_mode); - set_flow_mode(&desc[idx], S_DIN_to_HASH); - set_setup_mode(&desc[idx], SETUP_LOAD_STATE1); - idx++; - - /* Perform HASH update */ - hw_desc_init(&desc[idx]); - set_din_type(&desc[idx], DMA_DLLI, k0_dma_addr, block_size, - NS_BIT); - set_cipher_mode(&desc[idx], hw_mode); - set_xor_active(&desc[idx]); - set_flow_mode(&desc[idx], DIN_HASH); - idx++; - - if (i == 0) { - /* First iteration - calc H(K0^opad) into tmp_digest_dma_addr */ - hw_desc_init(&desc[idx]); - set_cipher_mode(&desc[idx], hw_mode); - set_dout_dlli(&desc[idx], tmp_digest_dma_addr, - inter_digestsize, NS_BIT, 0); - set_flow_mode(&desc[idx], S_HASH_to_DOUT); - set_setup_mode(&desc[idx], SETUP_WRITE_STATE0); - idx++; - - // is this needed?? or continue with current descriptors?? - BUG_ON(idx > FIPS_HMAC_MAX_SEQ_LEN); - rc = send_request(drvdata, &ssi_req, desc, idx, 0); - if (unlikely(rc != 0)) { - SSI_LOG_ERR("send_request() failed (rc=%d)\n", rc); - return rc; - } - idx = 0; - } - } - - /* data descriptor */ - hw_desc_init(&desc[idx]); - set_din_type(&desc[idx], DMA_DLLI, din_dma_addr, data_in_size, NS_BIT); - set_flow_mode(&desc[idx], DIN_HASH); - idx++; - - /* HW last hash block padding (aka. "DO_PAD") */ - hw_desc_init(&desc[idx]); - set_cipher_mode(&desc[idx], hw_mode); - set_dout_dlli(&desc[idx], k0_dma_addr, HASH_LEN_SIZE, NS_BIT, 0); - set_flow_mode(&desc[idx], S_HASH_to_DOUT); - set_setup_mode(&desc[idx], SETUP_WRITE_STATE1); - set_cipher_do(&desc[idx], DO_PAD); - idx++; - - /* store the hash digest result in the context */ - hw_desc_init(&desc[idx]); - set_cipher_mode(&desc[idx], hw_mode); - set_dout_dlli(&desc[idx], k0_dma_addr, digest_size, NS_BIT, 0); - set_flow_mode(&desc[idx], S_HASH_to_DOUT); - if (unlikely((hash_mode == DRV_HASH_MD5) || - (hash_mode == DRV_HASH_SHA384) || - (hash_mode == DRV_HASH_SHA512))) { - set_bytes_swap(&desc[idx], 1); - } else { - set_cipher_config0(&desc[idx], - HASH_DIGEST_RESULT_LITTLE_ENDIAN); - } - set_setup_mode(&desc[idx], SETUP_WRITE_STATE0); - idx++; - - /* at this point: - * tmp_digest = H(o_key_pad) - * k0 = H(i_key_pad || m) - */ - - /* Loading hash opad xor key state */ - hw_desc_init(&desc[idx]); - set_cipher_mode(&desc[idx], hw_mode); - set_din_type(&desc[idx], DMA_DLLI, tmp_digest_dma_addr, - inter_digestsize, NS_BIT); - set_flow_mode(&desc[idx], S_DIN_to_HASH); - set_setup_mode(&desc[idx], SETUP_LOAD_STATE0); - idx++; - - /* Load the hash current length */ - hw_desc_init(&desc[idx]); - set_cipher_mode(&desc[idx], hw_mode); - set_din_type(&desc[idx], DMA_DLLI, digest_bytes_len_dma_addr, - HASH_LEN_SIZE, NS_BIT); - set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED); - set_flow_mode(&desc[idx], S_DIN_to_HASH); - set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); - idx++; - - /* Memory Barrier: wait for IPAD/OPAD axi write to complete */ - hw_desc_init(&desc[idx]); - set_din_no_dma(&desc[idx], 0, 0xfffff0); - set_dout_no_dma(&desc[idx], 0, 0, 1); - idx++; - - /* Perform HASH update */ - hw_desc_init(&desc[idx]); - set_din_type(&desc[idx], DMA_DLLI, k0_dma_addr, digest_size, NS_BIT); - set_flow_mode(&desc[idx], DIN_HASH); - idx++; - - /* Get final MAC result */ - hw_desc_init(&desc[idx]); - set_cipher_mode(&desc[idx], hw_mode); - set_dout_dlli(&desc[idx], mac_res_dma_addr, digest_size, NS_BIT, 0); - set_flow_mode(&desc[idx], S_HASH_to_DOUT); - set_setup_mode(&desc[idx], SETUP_WRITE_STATE0); - set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED); - if (unlikely((hash_mode == DRV_HASH_MD5) || - (hash_mode == DRV_HASH_SHA384) || - (hash_mode == DRV_HASH_SHA512))) { - set_bytes_swap(&desc[idx], 1); - } else { - set_cipher_config0(&desc[idx], - HASH_DIGEST_RESULT_LITTLE_ENDIAN); - } - idx++; - - /* perform the operation - Lock HW and push sequence */ - BUG_ON(idx > FIPS_HMAC_MAX_SEQ_LEN); - rc = send_request(drvdata, &ssi_req, desc, idx, false); - - return rc; -} - -enum cc_fips_error -ssi_hmac_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer) -{ - enum cc_fips_error error = CC_REE_FIPS_ERROR_OK; - size_t i; - struct fips_hmac_ctx *virt_ctx = (struct fips_hmac_ctx *)cpu_addr_buffer; - - /* set the phisical pointers */ - dma_addr_t initial_digest_dma_addr = dma_coherent_buffer + offsetof(struct fips_hmac_ctx, initial_digest); - dma_addr_t key_dma_addr = dma_coherent_buffer + offsetof(struct fips_hmac_ctx, key); - dma_addr_t k0_dma_addr = dma_coherent_buffer + offsetof(struct fips_hmac_ctx, k0); - dma_addr_t tmp_digest_dma_addr = dma_coherent_buffer + offsetof(struct fips_hmac_ctx, tmp_digest); - dma_addr_t digest_bytes_len_dma_addr = dma_coherent_buffer + offsetof(struct fips_hmac_ctx, digest_bytes_len); - dma_addr_t din_dma_addr = dma_coherent_buffer + offsetof(struct fips_hmac_ctx, din); - dma_addr_t mac_res_dma_addr = dma_coherent_buffer + offsetof(struct fips_hmac_ctx, mac_res); - - for (i = 0; i < FIPS_HMAC_NUM_OF_TESTS; ++i) { - FipsHmacData *hmac_data = (FipsHmacData *)&FipsHmacDataTable[i]; - int rc = 0; - enum drv_hash_hw_mode hw_mode = 0; - int digest_size = 0; - int block_size = 0; - int inter_digestsize = 0; - - memset(cpu_addr_buffer, 0, sizeof(struct fips_hmac_ctx)); - - switch (hmac_data->hash_mode) { - case DRV_HASH_SHA1: - hw_mode = DRV_HASH_HW_SHA1; - digest_size = CC_SHA1_DIGEST_SIZE; - block_size = CC_SHA1_BLOCK_SIZE; - inter_digestsize = CC_SHA1_DIGEST_SIZE; - memcpy(virt_ctx->initial_digest, (void *)sha1_init, CC_SHA1_DIGEST_SIZE); - memcpy(virt_ctx->digest_bytes_len, digest_len_init, HASH_LEN_SIZE); - break; - case DRV_HASH_SHA256: - hw_mode = DRV_HASH_HW_SHA256; - digest_size = CC_SHA256_DIGEST_SIZE; - block_size = CC_SHA256_BLOCK_SIZE; - inter_digestsize = CC_SHA256_DIGEST_SIZE; - memcpy(virt_ctx->initial_digest, (void *)sha256_init, CC_SHA256_DIGEST_SIZE); - memcpy(virt_ctx->digest_bytes_len, digest_len_init, HASH_LEN_SIZE); - break; -#if (CC_SUPPORT_SHA > 256) - case DRV_HASH_SHA512: - hw_mode = DRV_HASH_HW_SHA512; - digest_size = CC_SHA512_DIGEST_SIZE; - block_size = CC_SHA512_BLOCK_SIZE; - inter_digestsize = CC_SHA512_DIGEST_SIZE; - memcpy(virt_ctx->initial_digest, (void *)sha512_init, CC_SHA512_DIGEST_SIZE); - memcpy(virt_ctx->digest_bytes_len, digest_len_sha512_init, HASH_LEN_SIZE); - break; -#endif - default: - error = FIPS_HmacToFipsError(hmac_data->hash_mode); - break; - } - - /* copy into the allocated buffer */ - memcpy(virt_ctx->key, hmac_data->key, hmac_data->key_size); - memcpy(virt_ctx->din, hmac_data->data_in, hmac_data->data_in_size); - - /* run the test on HW */ - FIPS_DBG("ssi_hmac_fips_run_test - (i = %d) \n", i); - rc = ssi_hmac_fips_run_test(drvdata, - initial_digest_dma_addr, - key_dma_addr, - hmac_data->key_size, - din_dma_addr, - hmac_data->data_in_size, - mac_res_dma_addr, - hmac_data->hash_mode, - hw_mode, - digest_size, - inter_digestsize, - block_size, - k0_dma_addr, - tmp_digest_dma_addr, - digest_bytes_len_dma_addr); - if (rc != 0) { - FIPS_LOG("ssi_hmac_fips_run_test %d returned error - rc = %d \n", i, rc); - error = FIPS_HmacToFipsError(hmac_data->hash_mode); - break; - } - - /* compare actual mac result to expected */ - if (memcmp(virt_ctx->mac_res, hmac_data->mac_res, digest_size) != 0) { - FIPS_LOG("comparison error %d - hash_mode=%d digest_size=%d \n", i, hmac_data->hash_mode, digest_size); - FIPS_LOG(" i expected received \n"); - FIPS_LOG(" i 0x%08x 0x%08x \n", (size_t)hmac_data->mac_res, (size_t)virt_ctx->mac_res); - for (i = 0; i < digest_size; ++i) { - FIPS_LOG(" %d 0x%02x 0x%02x \n", i, hmac_data->mac_res[i], virt_ctx->mac_res[i]); - } - - error = FIPS_HmacToFipsError(hmac_data->hash_mode); - break; - } - } - - return error; -} - -static inline int -ssi_ccm_fips_run_test(struct ssi_drvdata *drvdata, - enum drv_crypto_direction direction, - dma_addr_t key_dma_addr, - size_t key_size, - dma_addr_t iv_dma_addr, - dma_addr_t ctr_cnt_0_dma_addr, - dma_addr_t b0_a0_adata_dma_addr, - size_t b0_a0_adata_size, - dma_addr_t din_dma_addr, - size_t din_size, - dma_addr_t dout_dma_addr, - dma_addr_t mac_res_dma_addr) -{ - /* max number of descriptors used for the flow */ - #define FIPS_CCM_MAX_SEQ_LEN 10 - - int rc; - struct ssi_crypto_req ssi_req = {0}; - struct cc_hw_desc desc[FIPS_CCM_MAX_SEQ_LEN]; - unsigned int idx = 0; - unsigned int cipher_flow_mode; - - if (direction == DRV_CRYPTO_DIRECTION_DECRYPT) { - cipher_flow_mode = AES_to_HASH_and_DOUT; - } else { /* Encrypt */ - cipher_flow_mode = AES_and_HASH; - } - - /* load key */ - hw_desc_init(&desc[idx]); - set_cipher_mode(&desc[idx], DRV_CIPHER_CTR); - set_din_type(&desc[idx], DMA_DLLI, key_dma_addr, - ((key_size == NIST_AESCCM_192_BIT_KEY_SIZE) ? - CC_AES_KEY_SIZE_MAX : key_size), NS_BIT) - set_key_size_aes(&desc[idx], key_size); - set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); - set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT); - set_flow_mode(&desc[idx], S_DIN_to_AES); - idx++; - - /* load ctr state */ - hw_desc_init(&desc[idx]); - set_cipher_mode(&desc[idx], DRV_CIPHER_CTR); - set_key_size_aes(&desc[idx], key_size); - set_din_type(&desc[idx], DMA_DLLI, iv_dma_addr, AES_BLOCK_SIZE, - NS_BIT); - set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT); - set_setup_mode(&desc[idx], SETUP_LOAD_STATE1); - set_flow_mode(&desc[idx], S_DIN_to_AES); - idx++; - - /* load MAC key */ - hw_desc_init(&desc[idx]); - set_cipher_mode(&desc[idx], DRV_CIPHER_CBC_MAC); - set_din_type(&desc[idx], DMA_DLLI, key_dma_addr, - ((key_size == NIST_AESCCM_192_BIT_KEY_SIZE) ? - CC_AES_KEY_SIZE_MAX : key_size), NS_BIT); - set_key_size_aes(&desc[idx], key_size); - set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); - set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT); - set_flow_mode(&desc[idx], S_DIN_to_HASH); - set_aes_not_hash_mode(&desc[idx]); - idx++; - - /* load MAC state */ - hw_desc_init(&desc[idx]); - set_cipher_mode(&desc[idx], DRV_CIPHER_CBC_MAC); - set_key_size_aes(&desc[idx], key_size); - set_din_type(&desc[idx], DMA_DLLI, mac_res_dma_addr, - NIST_AESCCM_TAG_SIZE, NS_BIT); - set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT); - set_setup_mode(&desc[idx], SETUP_LOAD_STATE0); - set_flow_mode(&desc[idx], S_DIN_to_HASH); - set_aes_not_hash_mode(&desc[idx]); - idx++; - - /* prcess assoc data */ - hw_desc_init(&desc[idx]); - set_din_type(&desc[idx], DMA_DLLI, b0_a0_adata_dma_addr, - b0_a0_adata_size, NS_BIT); - set_flow_mode(&desc[idx], DIN_HASH); - idx++; - - /* process the cipher */ - hw_desc_init(&desc[idx]); - set_din_type(&desc[idx], DMA_DLLI, din_dma_addr, din_size, NS_BIT); - set_dout_dlli(&desc[idx], dout_dma_addr, din_size, NS_BIT, 0); - set_flow_mode(&desc[idx], cipher_flow_mode); - idx++; - - /* Read temporal MAC */ - hw_desc_init(&desc[idx]); - set_cipher_mode(&desc[idx], DRV_CIPHER_CBC_MAC); - set_dout_dlli(&desc[idx], mac_res_dma_addr, NIST_AESCCM_TAG_SIZE, - NS_BIT, 0); - set_setup_mode(&desc[idx], SETUP_WRITE_STATE0); - set_cipher_config0(&desc[idx], HASH_DIGEST_RESULT_LITTLE_ENDIAN); - set_flow_mode(&desc[idx], S_HASH_to_DOUT); - set_aes_not_hash_mode(&desc[idx]); - idx++; - - /* load AES-CTR state (for last MAC calculation)*/ - hw_desc_init(&desc[idx]); - set_cipher_mode(&desc[idx], DRV_CIPHER_CTR); - set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT); - set_din_type(&desc[idx], DMA_DLLI, ctr_cnt_0_dma_addr, AES_BLOCK_SIZE, - NS_BIT); - set_key_size_aes(&desc[idx], key_size); - set_setup_mode(&desc[idx], SETUP_LOAD_STATE1); - set_flow_mode(&desc[idx], S_DIN_to_AES); - idx++; - - /* Memory Barrier */ - hw_desc_init(&desc[idx]); - set_din_no_dma(&desc[idx], 0, 0xfffff0); - set_dout_no_dma(&desc[idx], 0, 0, 1); - idx++; - - /* encrypt the "T" value and store MAC inplace */ - hw_desc_init(&desc[idx]); - set_din_type(&desc[idx], DMA_DLLI, mac_res_dma_addr, - NIST_AESCCM_TAG_SIZE, NS_BIT); - set_dout_dlli(&desc[idx], mac_res_dma_addr, NIST_AESCCM_TAG_SIZE, - NS_BIT, 0); - set_flow_mode(&desc[idx], DIN_AES_DOUT); - idx++; - - /* perform the operation - Lock HW and push sequence */ - BUG_ON(idx > FIPS_CCM_MAX_SEQ_LEN); - rc = send_request(drvdata, &ssi_req, desc, idx, false); - - return rc; -} - -enum cc_fips_error -ssi_ccm_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer) -{ - enum cc_fips_error error = CC_REE_FIPS_ERROR_OK; - size_t i; - struct fips_ccm_ctx *virt_ctx = (struct fips_ccm_ctx *)cpu_addr_buffer; - - /* set the phisical pointers */ - dma_addr_t b0_a0_adata_dma_addr = dma_coherent_buffer + offsetof(struct fips_ccm_ctx, b0_a0_adata); - dma_addr_t iv_dma_addr = dma_coherent_buffer + offsetof(struct fips_ccm_ctx, iv); - dma_addr_t ctr_cnt_0_dma_addr = dma_coherent_buffer + offsetof(struct fips_ccm_ctx, ctr_cnt_0); - dma_addr_t key_dma_addr = dma_coherent_buffer + offsetof(struct fips_ccm_ctx, key); - dma_addr_t din_dma_addr = dma_coherent_buffer + offsetof(struct fips_ccm_ctx, din); - dma_addr_t dout_dma_addr = dma_coherent_buffer + offsetof(struct fips_ccm_ctx, dout); - dma_addr_t mac_res_dma_addr = dma_coherent_buffer + offsetof(struct fips_ccm_ctx, mac_res); - - for (i = 0; i < FIPS_CCM_NUM_OF_TESTS; ++i) { - FipsCcmData *ccmData = (FipsCcmData *)&FipsCcmDataTable[i]; - int rc = 0; - - memset(cpu_addr_buffer, 0, sizeof(struct fips_ccm_ctx)); - - /* copy the nonce, key, adata, din data into the allocated buffer */ - memcpy(virt_ctx->key, ccmData->key, ccmData->keySize); - memcpy(virt_ctx->din, ccmData->dataIn, ccmData->dataInSize); - { - /* build B0 -- B0, nonce, l(m) */ - __be16 data = cpu_to_be16(NIST_AESCCM_TEXT_SIZE); - - virt_ctx->b0_a0_adata[0] = NIST_AESCCM_B0_VAL; - memcpy(virt_ctx->b0_a0_adata + 1, ccmData->nonce, NIST_AESCCM_NONCE_SIZE); - memcpy(virt_ctx->b0_a0_adata + 14, (u8 *)&data, sizeof(__be16)); - /* build A0+ADATA */ - virt_ctx->b0_a0_adata[NIST_AESCCM_IV_SIZE + 0] = (ccmData->adataSize >> 8) & 0xFF; - virt_ctx->b0_a0_adata[NIST_AESCCM_IV_SIZE + 1] = ccmData->adataSize & 0xFF; - memcpy(virt_ctx->b0_a0_adata + NIST_AESCCM_IV_SIZE + 2, ccmData->adata, ccmData->adataSize); - /* iv */ - virt_ctx->iv[0] = 1; /* L' */ - memcpy(virt_ctx->iv + 1, ccmData->nonce, NIST_AESCCM_NONCE_SIZE); - virt_ctx->iv[15] = 1; - /* ctr_count_0 */ - memcpy(virt_ctx->ctr_cnt_0, virt_ctx->iv, NIST_AESCCM_IV_SIZE); - virt_ctx->ctr_cnt_0[15] = 0; - } - - FIPS_DBG("ssi_ccm_fips_run_test - (i = %d) \n", i); - rc = ssi_ccm_fips_run_test(drvdata, - ccmData->direction, - key_dma_addr, - ccmData->keySize, - iv_dma_addr, - ctr_cnt_0_dma_addr, - b0_a0_adata_dma_addr, - FIPS_CCM_B0_A0_ADATA_SIZE, - din_dma_addr, - ccmData->dataInSize, - dout_dma_addr, - mac_res_dma_addr); - if (rc != 0) { - FIPS_LOG("ssi_ccm_fips_run_test %d returned error - rc = %d \n", i, rc); - error = CC_REE_FIPS_ERROR_AESCCM_PUT; - break; - } - - /* compare actual dout to expected */ - if (memcmp(virt_ctx->dout, ccmData->dataOut, ccmData->dataInSize) != 0) { - FIPS_LOG("dout comparison error %d - size=%d \n", i, ccmData->dataInSize); - error = CC_REE_FIPS_ERROR_AESCCM_PUT; - break; - } - - /* compare actual mac result to expected */ - if (memcmp(virt_ctx->mac_res, ccmData->macResOut, ccmData->tagSize) != 0) { - FIPS_LOG("mac_res comparison error %d - mac_size=%d \n", i, ccmData->tagSize); - FIPS_LOG(" i expected received \n"); - FIPS_LOG(" i 0x%08x 0x%08x \n", (size_t)ccmData->macResOut, (size_t)virt_ctx->mac_res); - for (i = 0; i < ccmData->tagSize; ++i) { - FIPS_LOG(" %d 0x%02x 0x%02x \n", i, ccmData->macResOut[i], virt_ctx->mac_res[i]); - } - - error = CC_REE_FIPS_ERROR_AESCCM_PUT; - break; - } - } - - return error; -} - -static inline int -ssi_gcm_fips_run_test(struct ssi_drvdata *drvdata, - enum drv_crypto_direction direction, - dma_addr_t key_dma_addr, - size_t key_size, - dma_addr_t hkey_dma_addr, - dma_addr_t block_len_dma_addr, - dma_addr_t iv_inc1_dma_addr, - dma_addr_t iv_inc2_dma_addr, - dma_addr_t adata_dma_addr, - size_t adata_size, - dma_addr_t din_dma_addr, - size_t din_size, - dma_addr_t dout_dma_addr, - dma_addr_t mac_res_dma_addr) -{ - /* max number of descriptors used for the flow */ - #define FIPS_GCM_MAX_SEQ_LEN 15 - - int rc; - struct ssi_crypto_req ssi_req = {0}; - struct cc_hw_desc desc[FIPS_GCM_MAX_SEQ_LEN]; - unsigned int idx = 0; - unsigned int cipher_flow_mode; - - if (direction == DRV_CRYPTO_DIRECTION_DECRYPT) { - cipher_flow_mode = AES_and_HASH; - } else { /* Encrypt */ - cipher_flow_mode = AES_to_HASH_and_DOUT; - } - -///////////////////////////////// 1 //////////////////////////////////// -// ssi_aead_gcm_setup_ghash_desc(req, desc, seq_size); -///////////////////////////////// 1 //////////////////////////////////// - - /* load key to AES */ - hw_desc_init(&desc[idx]); - set_cipher_mode(&desc[idx], DRV_CIPHER_ECB); - set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT); - set_din_type(&desc[idx], DMA_DLLI, key_dma_addr, key_size, NS_BIT); - set_key_size_aes(&desc[idx], key_size); - set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); - set_flow_mode(&desc[idx], S_DIN_to_AES); - idx++; - - /* process one zero block to generate hkey */ - hw_desc_init(&desc[idx]); - set_din_const(&desc[idx], 0x0, AES_BLOCK_SIZE); - set_dout_dlli(&desc[idx], hkey_dma_addr, AES_BLOCK_SIZE, NS_BIT, 0); - set_flow_mode(&desc[idx], DIN_AES_DOUT); - idx++; - - /* Memory Barrier */ - hw_desc_init(&desc[idx]); - set_din_no_dma(&desc[idx], 0, 0xfffff0); - set_dout_no_dma(&desc[idx], 0, 0, 1); - idx++; - - /* Load GHASH subkey */ - hw_desc_init(&desc[idx]); - set_din_type(&desc[idx], DMA_DLLI, hkey_dma_addr, AES_BLOCK_SIZE, - NS_BIT); - set_dout_no_dma(&desc[idx], 0, 0, 1); - set_flow_mode(&desc[idx], S_DIN_to_HASH); - set_aes_not_hash_mode(&desc[idx]); - set_cipher_mode(&desc[idx], DRV_HASH_HW_GHASH); - set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED); - set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); - idx++; - - /* Configure Hash Engine to work with GHASH. - * Since it was not possible to extend HASH submodes to add GHASH, - * The following command is necessary in order to - * select GHASH (according to HW designers) - */ - hw_desc_init(&desc[idx]); - set_din_no_dma(&desc[idx], 0, 0xfffff0); - set_dout_no_dma(&desc[idx], 0, 0, 1); - set_flow_mode(&desc[idx], S_DIN_to_HASH); - set_aes_not_hash_mode(&desc[idx]); - set_cipher_mode(&desc[idx], DRV_HASH_HW_GHASH); - set_cipher_do(&desc[idx], 1); //1=AES_SK RKEK - set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT); - set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED); - set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); - idx++; - - /* Load GHASH initial STATE (which is 0). (for any hash there is an initial state) */ - hw_desc_init(&desc[idx]); - set_din_const(&desc[idx], 0x0, AES_BLOCK_SIZE); - set_dout_no_dma(&desc[idx], 0, 0, 1); - set_flow_mode(&desc[idx], S_DIN_to_HASH); - set_aes_not_hash_mode(&desc[idx]); - set_cipher_mode(&desc[idx], DRV_HASH_HW_GHASH); - set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED); - set_setup_mode(&desc[idx], SETUP_LOAD_STATE0); - idx++; - -///////////////////////////////// 2 //////////////////////////////////// - /* prcess(ghash) assoc data */ -// if (req->assoclen > 0) -// ssi_aead_create_assoc_desc(req, DIN_HASH, desc, seq_size); -///////////////////////////////// 2 //////////////////////////////////// - - hw_desc_init(&desc[idx]); - set_din_type(&desc[idx], DMA_DLLI, adata_dma_addr, adata_size, NS_BIT); - set_flow_mode(&desc[idx], DIN_HASH); - idx++; - -///////////////////////////////// 3 //////////////////////////////////// -// ssi_aead_gcm_setup_gctr_desc(req, desc, seq_size); -///////////////////////////////// 3 //////////////////////////////////// - - /* load key to AES*/ - hw_desc_init(&desc[idx]); - set_cipher_mode(&desc[idx], DRV_CIPHER_GCTR); - set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT); - set_din_type(&desc[idx], DMA_DLLI, key_dma_addr, key_size, NS_BIT); - set_key_size_aes(&desc[idx], key_size); - set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); - set_flow_mode(&desc[idx], S_DIN_to_AES); - idx++; - - /* load AES/CTR initial CTR value inc by 2*/ - hw_desc_init(&desc[idx]); - set_cipher_mode(&desc[idx], DRV_CIPHER_GCTR); - set_key_size_aes(&desc[idx], key_size); - set_din_type(&desc[idx], DMA_DLLI, iv_inc2_dma_addr, AES_BLOCK_SIZE, - NS_BIT); - set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT); - set_setup_mode(&desc[idx], SETUP_LOAD_STATE1); - set_flow_mode(&desc[idx], S_DIN_to_AES); - idx++; - -///////////////////////////////// 4 //////////////////////////////////// - /* process(gctr+ghash) */ -// if (req_ctx->cryptlen != 0) -// ssi_aead_process_cipher_data_desc(req, cipher_flow_mode, desc, seq_size); -///////////////////////////////// 4 //////////////////////////////////// - - hw_desc_init(&desc[idx]); - set_din_type(&desc[idx], DMA_DLLI, din_dma_addr, din_size, NS_BIT); - set_dout_dlli(&desc[idx], dout_dma_addr, din_size, NS_BIT, 0); - set_flow_mode(&desc[idx], cipher_flow_mode); - idx++; - -///////////////////////////////// 5 //////////////////////////////////// -// ssi_aead_process_gcm_result_desc(req, desc, seq_size); -///////////////////////////////// 5 //////////////////////////////////// - - /* prcess(ghash) gcm_block_len */ - hw_desc_init(&desc[idx]); - set_din_type(&desc[idx], DMA_DLLI, block_len_dma_addr, AES_BLOCK_SIZE, - NS_BIT); - set_flow_mode(&desc[idx], DIN_HASH); - idx++; - - /* Store GHASH state after GHASH(Associated Data + Cipher +LenBlock) */ - hw_desc_init(&desc[idx]); - set_cipher_mode(&desc[idx], DRV_HASH_HW_GHASH); - set_din_no_dma(&desc[idx], 0, 0xfffff0); - set_dout_dlli(&desc[idx], mac_res_dma_addr, AES_BLOCK_SIZE, NS_BIT, 0); - set_setup_mode(&desc[idx], SETUP_WRITE_STATE0); - set_flow_mode(&desc[idx], S_HASH_to_DOUT); - set_aes_not_hash_mode(&desc[idx]); - idx++; - - /* load AES/CTR initial CTR value inc by 1*/ - hw_desc_init(&desc[idx]); - set_cipher_mode(&desc[idx], DRV_CIPHER_GCTR); - set_key_size_aes(&desc[idx], key_size); - set_din_type(&desc[idx], DMA_DLLI, iv_inc1_dma_addr, AES_BLOCK_SIZE, - NS_BIT); - set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT); - set_setup_mode(&desc[idx], SETUP_LOAD_STATE1); - set_flow_mode(&desc[idx], S_DIN_to_AES); - idx++; - - /* Memory Barrier */ - hw_desc_init(&desc[idx]); - set_din_no_dma(&desc[idx], 0, 0xfffff0); - set_dout_no_dma(&desc[idx], 0, 0, 1); - idx++; - - /* process GCTR on stored GHASH and store MAC inplace */ - hw_desc_init(&desc[idx]); - set_cipher_mode(&desc[idx], DRV_CIPHER_GCTR); - set_din_type(&desc[idx], DMA_DLLI, mac_res_dma_addr, AES_BLOCK_SIZE, - NS_BIT); - set_dout_dlli(&desc[idx], mac_res_dma_addr, AES_BLOCK_SIZE, NS_BIT, 0); - set_flow_mode(&desc[idx], DIN_AES_DOUT); - idx++; - - /* perform the operation - Lock HW and push sequence */ - BUG_ON(idx > FIPS_GCM_MAX_SEQ_LEN); - rc = send_request(drvdata, &ssi_req, desc, idx, false); - - return rc; -} - -enum cc_fips_error -ssi_gcm_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer) -{ - enum cc_fips_error error = CC_REE_FIPS_ERROR_OK; - size_t i; - struct fips_gcm_ctx *virt_ctx = (struct fips_gcm_ctx *)cpu_addr_buffer; - - /* set the phisical pointers */ - dma_addr_t adata_dma_addr = dma_coherent_buffer + offsetof(struct fips_gcm_ctx, adata); - dma_addr_t key_dma_addr = dma_coherent_buffer + offsetof(struct fips_gcm_ctx, key); - dma_addr_t hkey_dma_addr = dma_coherent_buffer + offsetof(struct fips_gcm_ctx, hkey); - dma_addr_t din_dma_addr = dma_coherent_buffer + offsetof(struct fips_gcm_ctx, din); - dma_addr_t dout_dma_addr = dma_coherent_buffer + offsetof(struct fips_gcm_ctx, dout); - dma_addr_t mac_res_dma_addr = dma_coherent_buffer + offsetof(struct fips_gcm_ctx, mac_res); - dma_addr_t len_block_dma_addr = dma_coherent_buffer + offsetof(struct fips_gcm_ctx, len_block); - dma_addr_t iv_inc1_dma_addr = dma_coherent_buffer + offsetof(struct fips_gcm_ctx, iv_inc1); - dma_addr_t iv_inc2_dma_addr = dma_coherent_buffer + offsetof(struct fips_gcm_ctx, iv_inc2); - - for (i = 0; i < FIPS_GCM_NUM_OF_TESTS; ++i) { - FipsGcmData *gcmData = (FipsGcmData *)&FipsGcmDataTable[i]; - int rc = 0; - - memset(cpu_addr_buffer, 0, sizeof(struct fips_gcm_ctx)); - - /* copy the key, adata, din data - into the allocated buffer */ - memcpy(virt_ctx->key, gcmData->key, gcmData->keySize); - memcpy(virt_ctx->adata, gcmData->adata, gcmData->adataSize); - memcpy(virt_ctx->din, gcmData->dataIn, gcmData->dataInSize); - - /* len_block */ - { - __be64 len_bits; - - len_bits = cpu_to_be64(gcmData->adataSize * 8); - memcpy(virt_ctx->len_block, &len_bits, sizeof(len_bits)); - len_bits = cpu_to_be64(gcmData->dataInSize * 8); - memcpy(virt_ctx->len_block + 8, &len_bits, sizeof(len_bits)); - } - /* iv_inc1, iv_inc2 */ - { - __be32 counter = cpu_to_be32(1); - - memcpy(virt_ctx->iv_inc1, gcmData->iv, NIST_AESGCM_IV_SIZE); - memcpy(virt_ctx->iv_inc1 + NIST_AESGCM_IV_SIZE, &counter, sizeof(counter)); - counter = cpu_to_be32(2); - memcpy(virt_ctx->iv_inc2, gcmData->iv, NIST_AESGCM_IV_SIZE); - memcpy(virt_ctx->iv_inc2 + NIST_AESGCM_IV_SIZE, &counter, sizeof(counter)); - } - - FIPS_DBG("ssi_gcm_fips_run_test - (i = %d) \n", i); - rc = ssi_gcm_fips_run_test(drvdata, - gcmData->direction, - key_dma_addr, - gcmData->keySize, - hkey_dma_addr, - len_block_dma_addr, - iv_inc1_dma_addr, - iv_inc2_dma_addr, - adata_dma_addr, - gcmData->adataSize, - din_dma_addr, - gcmData->dataInSize, - dout_dma_addr, - mac_res_dma_addr); - if (rc != 0) { - FIPS_LOG("ssi_gcm_fips_run_test %d returned error - rc = %d \n", i, rc); - error = CC_REE_FIPS_ERROR_AESGCM_PUT; - break; - } - - if (gcmData->direction == DRV_CRYPTO_DIRECTION_ENCRYPT) { - /* compare actual dout to expected */ - if (memcmp(virt_ctx->dout, gcmData->dataOut, gcmData->dataInSize) != 0) { - FIPS_LOG("dout comparison error %d - size=%d \n", i, gcmData->dataInSize); - FIPS_LOG(" i expected received \n"); - FIPS_LOG(" i 0x%08x 0x%08x \n", (size_t)gcmData->dataOut, (size_t)virt_ctx->dout); - for (i = 0; i < gcmData->dataInSize; ++i) { - FIPS_LOG(" %d 0x%02x 0x%02x \n", i, gcmData->dataOut[i], virt_ctx->dout[i]); - } - - error = CC_REE_FIPS_ERROR_AESGCM_PUT; - break; - } - } - - /* compare actual mac result to expected */ - if (memcmp(virt_ctx->mac_res, gcmData->macResOut, gcmData->tagSize) != 0) { - FIPS_LOG("mac_res comparison error %d - mac_size=%d \n", i, gcmData->tagSize); - FIPS_LOG(" i expected received \n"); - FIPS_LOG(" i 0x%08x 0x%08x \n", (size_t)gcmData->macResOut, (size_t)virt_ctx->mac_res); - for (i = 0; i < gcmData->tagSize; ++i) { - FIPS_LOG(" %d 0x%02x 0x%02x \n", i, gcmData->macResOut[i], virt_ctx->mac_res[i]); - } - error = CC_REE_FIPS_ERROR_AESGCM_PUT; - break; - } - } - return error; -} - -size_t ssi_fips_max_mem_alloc_size(void) -{ - FIPS_DBG("sizeof(struct fips_cipher_ctx) %d \n", sizeof(struct fips_cipher_ctx)); - FIPS_DBG("sizeof(struct fips_cmac_ctx) %d \n", sizeof(struct fips_cmac_ctx)); - FIPS_DBG("sizeof(struct fips_hash_ctx) %d \n", sizeof(struct fips_hash_ctx)); - FIPS_DBG("sizeof(struct fips_hmac_ctx) %d \n", sizeof(struct fips_hmac_ctx)); - FIPS_DBG("sizeof(struct fips_ccm_ctx) %d \n", sizeof(struct fips_ccm_ctx)); - FIPS_DBG("sizeof(struct fips_gcm_ctx) %d \n", sizeof(struct fips_gcm_ctx)); - - return sizeof(fips_ctx); -} - diff --git a/drivers/staging/ccree/ssi_fips_local.c b/drivers/staging/ccree/ssi_fips_local.c deleted file mode 100644 index aefb71dc9e9a..000000000000 --- a/drivers/staging/ccree/ssi_fips_local.c +++ /dev/null @@ -1,357 +0,0 @@ -/* - * Copyright (C) 2012-2017 ARM Limited or its affiliates. - * - * 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 . - */ - -/************************************************************** - * This file defines the driver FIPS internal function, used by the driver itself. - ***************************************************************/ -#include -#include -#include -#include - -#include "ssi_config.h" -#include "ssi_driver.h" -#include "cc_hal.h" - -#define FIPS_POWER_UP_TEST_CIPHER 1 -#define FIPS_POWER_UP_TEST_CMAC 1 -#define FIPS_POWER_UP_TEST_HASH 1 -#define FIPS_POWER_UP_TEST_HMAC 1 -#define FIPS_POWER_UP_TEST_CCM 1 -#define FIPS_POWER_UP_TEST_GCM 1 - -static bool ssi_fips_support = 1; -module_param(ssi_fips_support, bool, 0644); -MODULE_PARM_DESC(ssi_fips_support, "FIPS supported flag: 0 - off , 1 - on (default)"); - -static void fips_dsr(unsigned long devarg); - -struct ssi_fips_handle { -#ifdef COMP_IN_WQ - struct workqueue_struct *workq; - struct delayed_work fipswork; -#else - struct tasklet_struct fipstask; -#endif -}; - -extern int ssi_fips_get_state(enum cc_fips_state_t *p_state); -extern int ssi_fips_get_error(enum cc_fips_error *p_err); -extern int ssi_fips_ext_set_state(enum cc_fips_state_t state); -extern int ssi_fips_ext_set_error(enum cc_fips_error err); - -/* FIPS power-up tests */ -extern enum cc_fips_error ssi_cipher_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer); -extern enum cc_fips_error ssi_cmac_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer); -extern enum cc_fips_error ssi_hash_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer); -extern enum cc_fips_error ssi_hmac_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer); -extern enum cc_fips_error ssi_ccm_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer); -extern enum cc_fips_error ssi_gcm_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer); -extern size_t ssi_fips_max_mem_alloc_size(void); - -/* The function called once at driver entry point to check whether TEE FIPS error occured.*/ -static enum ssi_fips_error ssi_fips_get_tee_error(struct ssi_drvdata *drvdata) -{ - u32 regVal; - void __iomem *cc_base = drvdata->cc_base; - - regVal = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, GPR_HOST)); - if (regVal == (CC_FIPS_SYNC_TEE_STATUS | CC_FIPS_SYNC_MODULE_OK)) - return CC_REE_FIPS_ERROR_OK; - - return CC_REE_FIPS_ERROR_FROM_TEE; -} - -/* - * This function should push the FIPS REE library status towards the TEE library. - * By writing the error state to HOST_GPR0 register. The function is called from - * driver entry point so no need to protect by mutex. - */ -static void ssi_fips_update_tee_upon_ree_status(struct ssi_drvdata *drvdata, enum cc_fips_error err) -{ - void __iomem *cc_base = drvdata->cc_base; - - if (err == CC_REE_FIPS_ERROR_OK) - CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_GPR0), (CC_FIPS_SYNC_REE_STATUS | CC_FIPS_SYNC_MODULE_OK)); - else - CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_GPR0), (CC_FIPS_SYNC_REE_STATUS | CC_FIPS_SYNC_MODULE_ERROR)); -} - -void ssi_fips_fini(struct ssi_drvdata *drvdata) -{ - struct ssi_fips_handle *fips_h = drvdata->fips_handle; - - if (!fips_h) - return; /* Not allocated */ - -#ifdef COMP_IN_WQ - if (fips_h->workq) { - flush_workqueue(fips_h->workq); - destroy_workqueue(fips_h->workq); - } -#else - /* Kill tasklet */ - tasklet_kill(&fips_h->fipstask); -#endif - memset(fips_h, 0, sizeof(struct ssi_fips_handle)); - kfree(fips_h); - drvdata->fips_handle = NULL; -} - -void fips_handler(struct ssi_drvdata *drvdata) -{ - struct ssi_fips_handle *fips_handle_ptr = - drvdata->fips_handle; -#ifdef COMP_IN_WQ - queue_delayed_work(fips_handle_ptr->workq, &fips_handle_ptr->fipswork, 0); -#else - tasklet_schedule(&fips_handle_ptr->fipstask); -#endif -} - -#ifdef COMP_IN_WQ -static void fips_wq_handler(struct work_struct *work) -{ - struct ssi_drvdata *drvdata = - container_of(work, struct ssi_drvdata, fipswork.work); - - fips_dsr((unsigned long)drvdata); -} -#endif - -/* Deferred service handler, run as interrupt-fired tasklet */ -static void fips_dsr(unsigned long devarg) -{ - struct ssi_drvdata *drvdata = (struct ssi_drvdata *)devarg; - void __iomem *cc_base = drvdata->cc_base; - u32 irq; - u32 teeFipsError = 0; - - irq = (drvdata->irq & (SSI_GPR0_IRQ_MASK)); - - if (irq & SSI_GPR0_IRQ_MASK) { - teeFipsError = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, GPR_HOST)); - if (teeFipsError != (CC_FIPS_SYNC_TEE_STATUS | CC_FIPS_SYNC_MODULE_OK)) - ssi_fips_set_error(drvdata, CC_REE_FIPS_ERROR_FROM_TEE); - } - - /* after verifing that there is nothing to do, Unmask AXI completion interrupt */ - CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_IMR), - CC_HAL_READ_REGISTER( - CC_REG_OFFSET(HOST_RGF, HOST_IMR)) & ~irq); -} - -enum cc_fips_error cc_fips_run_power_up_tests(struct ssi_drvdata *drvdata) -{ - enum cc_fips_error fips_error = CC_REE_FIPS_ERROR_OK; - void *cpu_addr_buffer = NULL; - dma_addr_t dma_handle; - size_t alloc_buff_size = ssi_fips_max_mem_alloc_size(); - struct device *dev = &drvdata->plat_dev->dev; - - // allocate memory using dma_alloc_coherent - for phisical, consecutive and cache coherent buffer (memory map is not needed) - // the return value is the virtual address - use it to copy data into the buffer - // the dma_handle is the returned phy address - use it in the HW descriptor - FIPS_DBG("dma_alloc_coherent \n"); - cpu_addr_buffer = dma_alloc_coherent(dev, alloc_buff_size, &dma_handle, GFP_KERNEL); - if (!cpu_addr_buffer) - return CC_REE_FIPS_ERROR_GENERAL; - - FIPS_DBG("allocated coherent buffer - addr 0x%08X , size = %d \n", (size_t)cpu_addr_buffer, alloc_buff_size); - -#if FIPS_POWER_UP_TEST_CIPHER - FIPS_DBG("ssi_cipher_fips_power_up_tests ...\n"); - fips_error = ssi_cipher_fips_power_up_tests(drvdata, cpu_addr_buffer, dma_handle); - FIPS_DBG("ssi_cipher_fips_power_up_tests - done. (fips_error = %d) \n", fips_error); -#endif -#if FIPS_POWER_UP_TEST_CMAC - if (likely(fips_error == CC_REE_FIPS_ERROR_OK)) { - FIPS_DBG("ssi_cmac_fips_power_up_tests ...\n"); - fips_error = ssi_cmac_fips_power_up_tests(drvdata, cpu_addr_buffer, dma_handle); - FIPS_DBG("ssi_cmac_fips_power_up_tests - done. (fips_error = %d) \n", fips_error); - } -#endif -#if FIPS_POWER_UP_TEST_HASH - if (likely(fips_error == CC_REE_FIPS_ERROR_OK)) { - FIPS_DBG("ssi_hash_fips_power_up_tests ...\n"); - fips_error = ssi_hash_fips_power_up_tests(drvdata, cpu_addr_buffer, dma_handle); - FIPS_DBG("ssi_hash_fips_power_up_tests - done. (fips_error = %d) \n", fips_error); - } -#endif -#if FIPS_POWER_UP_TEST_HMAC - if (likely(fips_error == CC_REE_FIPS_ERROR_OK)) { - FIPS_DBG("ssi_hmac_fips_power_up_tests ...\n"); - fips_error = ssi_hmac_fips_power_up_tests(drvdata, cpu_addr_buffer, dma_handle); - FIPS_DBG("ssi_hmac_fips_power_up_tests - done. (fips_error = %d) \n", fips_error); - } -#endif -#if FIPS_POWER_UP_TEST_CCM - if (likely(fips_error == CC_REE_FIPS_ERROR_OK)) { - FIPS_DBG("ssi_ccm_fips_power_up_tests ...\n"); - fips_error = ssi_ccm_fips_power_up_tests(drvdata, cpu_addr_buffer, dma_handle); - FIPS_DBG("ssi_ccm_fips_power_up_tests - done. (fips_error = %d) \n", fips_error); - } -#endif -#if FIPS_POWER_UP_TEST_GCM - if (likely(fips_error == CC_REE_FIPS_ERROR_OK)) { - FIPS_DBG("ssi_gcm_fips_power_up_tests ...\n"); - fips_error = ssi_gcm_fips_power_up_tests(drvdata, cpu_addr_buffer, dma_handle); - FIPS_DBG("ssi_gcm_fips_power_up_tests - done. (fips_error = %d) \n", fips_error); - } -#endif - /* deallocate the buffer when all tests are done... */ - FIPS_DBG("dma_free_coherent \n"); - dma_free_coherent(dev, alloc_buff_size, cpu_addr_buffer, dma_handle); - - return fips_error; -} - -/* The function checks if FIPS supported and FIPS error exists.* - * It should be used in every driver API. - */ -int ssi_fips_check_fips_error(void) -{ - enum cc_fips_state_t fips_state; - - if (ssi_fips_get_state(&fips_state) != 0) { - FIPS_LOG("ssi_fips_get_state FAILED, returning.. \n"); - return -ENOEXEC; - } - if (fips_state == CC_FIPS_STATE_ERROR) { - FIPS_LOG("ssi_fips_get_state: fips_state is %d, returning.. \n", fips_state); - return -ENOEXEC; - } - return 0; -} - -/* The function sets the REE FIPS state.* - * It should be used while driver is being loaded. - */ -int ssi_fips_set_state(enum cc_fips_state_t state) -{ - return ssi_fips_ext_set_state(state); -} - -/* The function sets the REE FIPS error, and pushes the error to TEE library. * - * It should be used when any of the KAT tests fails. - */ -int ssi_fips_set_error(struct ssi_drvdata *p_drvdata, enum cc_fips_error err) -{ - int rc = 0; - enum cc_fips_error current_err; - - FIPS_LOG("ssi_fips_set_error - fips_error = %d \n", err); - - // setting no error is not allowed - if (err == CC_REE_FIPS_ERROR_OK) - return -ENOEXEC; - - // If error exists, do not set new error - if (ssi_fips_get_error(¤t_err) != 0) - return -ENOEXEC; - - if (current_err != CC_REE_FIPS_ERROR_OK) - return -ENOEXEC; - - // set REE internal error and state - rc = ssi_fips_ext_set_error(err); - if (rc != 0) - return -ENOEXEC; - - rc = ssi_fips_ext_set_state(CC_FIPS_STATE_ERROR); - if (rc != 0) - return -ENOEXEC; - - // push error towards TEE libraray, if it's not TEE error - if (err != CC_REE_FIPS_ERROR_FROM_TEE) - ssi_fips_update_tee_upon_ree_status(p_drvdata, err); - - return rc; -} - -/* The function called once at driver entry point .*/ -int ssi_fips_init(struct ssi_drvdata *p_drvdata) -{ - enum cc_fips_error rc = CC_REE_FIPS_ERROR_OK; - struct ssi_fips_handle *fips_h; - - FIPS_DBG("CC FIPS code .. (fips=%d) \n", ssi_fips_support); - - fips_h = kzalloc(sizeof(struct ssi_fips_handle), GFP_KERNEL); - if (!fips_h) { - ssi_fips_set_error(p_drvdata, CC_REE_FIPS_ERROR_GENERAL); - return -ENOMEM; - } - - p_drvdata->fips_handle = fips_h; - -#ifdef COMP_IN_WQ - SSI_LOG_DEBUG("Initializing fips workqueue\n"); - fips_h->workq = create_singlethread_workqueue("arm_cc7x_fips_wq"); - if (unlikely(!fips_h->workq)) { - SSI_LOG_ERR("Failed creating fips work queue\n"); - ssi_fips_set_error(p_drvdata, CC_REE_FIPS_ERROR_GENERAL); - rc = -ENOMEM; - goto ssi_fips_init_err; - } - INIT_DELAYED_WORK(&fips_h->fipswork, fips_wq_handler); -#else - SSI_LOG_DEBUG("Initializing fips tasklet\n"); - tasklet_init(&fips_h->fipstask, fips_dsr, (unsigned long)p_drvdata); -#endif - - /* init fips driver data */ - rc = ssi_fips_set_state((ssi_fips_support == 0) ? CC_FIPS_STATE_NOT_SUPPORTED : CC_FIPS_STATE_SUPPORTED); - if (unlikely(rc != 0)) { - ssi_fips_set_error(p_drvdata, CC_REE_FIPS_ERROR_GENERAL); - rc = -EAGAIN; - goto ssi_fips_init_err; - } - - /* Run power up tests (before registration and operating the HW engines) */ - FIPS_DBG("ssi_fips_get_tee_error \n"); - rc = ssi_fips_get_tee_error(p_drvdata); - if (unlikely(rc != CC_REE_FIPS_ERROR_OK)) { - ssi_fips_set_error(p_drvdata, CC_REE_FIPS_ERROR_FROM_TEE); - rc = -EAGAIN; - goto ssi_fips_init_err; - } - - FIPS_DBG("cc_fips_run_power_up_tests \n"); - rc = cc_fips_run_power_up_tests(p_drvdata); - if (unlikely(rc != CC_REE_FIPS_ERROR_OK)) { - ssi_fips_set_error(p_drvdata, rc); - rc = -EAGAIN; - goto ssi_fips_init_err; - } - FIPS_LOG("cc_fips_run_power_up_tests - done ... fips_error = %d \n", rc); - - /* when all tests passed, update TEE with fips OK status after power up tests */ - ssi_fips_update_tee_upon_ree_status(p_drvdata, CC_REE_FIPS_ERROR_OK); - - if (unlikely(rc != 0)) { - rc = -EAGAIN; - ssi_fips_set_error(p_drvdata, CC_REE_FIPS_ERROR_GENERAL); - goto ssi_fips_init_err; - } - - return 0; - -ssi_fips_init_err: - ssi_fips_fini(p_drvdata); - return rc; -} - diff --git a/drivers/staging/ccree/ssi_fips_local.h b/drivers/staging/ccree/ssi_fips_local.h deleted file mode 100644 index 8c7994fe9fae..000000000000 --- a/drivers/staging/ccree/ssi_fips_local.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2012-2017 ARM Limited or its affiliates. - * - * 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 . - */ - -#ifndef __SSI_FIPS_LOCAL_H__ -#define __SSI_FIPS_LOCAL_H__ - -#ifdef CONFIG_CCX7REE_FIPS_SUPPORT - -#include "ssi_fips.h" -struct ssi_drvdata; - -#define CHECK_AND_RETURN_UPON_FIPS_ERROR() {\ - if (ssi_fips_check_fips_error() != 0) {\ - return -ENOEXEC;\ - } \ -} - -#define CHECK_AND_RETURN_VOID_UPON_FIPS_ERROR() {\ - if (ssi_fips_check_fips_error() != 0) {\ - return;\ - } \ -} - -#define SSI_FIPS_INIT(p_drvData) (ssi_fips_init(p_drvData)) -#define SSI_FIPS_FINI(p_drvData) (ssi_fips_fini(p_drvData)) - -#define FIPS_LOG(...) SSI_LOG(KERN_INFO, __VA_ARGS__) -#define FIPS_DBG(...) //SSI_LOG(KERN_INFO, __VA_ARGS__) - -/* FIPS functions */ -int ssi_fips_init(struct ssi_drvdata *p_drvdata); -void ssi_fips_fini(struct ssi_drvdata *drvdata); -int ssi_fips_check_fips_error(void); -int ssi_fips_set_error(struct ssi_drvdata *p_drvdata, enum cc_fips_error err); -void fips_handler(struct ssi_drvdata *drvdata); - -#else /* CONFIG_CC7XXREE_FIPS_SUPPORT */ - -#define CHECK_AND_RETURN_UPON_FIPS_ERROR() -#define CHECK_AND_RETURN_VOID_UPON_FIPS_ERROR() - -static inline int ssi_fips_init(struct ssi_drvdata *p_drvdata) -{ - return 0; -} - -static inline void ssi_fips_fini(struct ssi_drvdata *drvdata) {} - -void fips_handler(struct ssi_drvdata *drvdata); - -#endif /* CONFIG_CC7XXREE_FIPS_SUPPORT */ - -#endif /*__SSI_FIPS_LOCAL_H__*/ - diff --git a/drivers/staging/ccree/ssi_hash.c b/drivers/staging/ccree/ssi_hash.c index 4f596eb3af46..ffd1f984fba5 100644 --- a/drivers/staging/ccree/ssi_hash.c +++ b/drivers/staging/ccree/ssi_hash.c @@ -30,7 +30,6 @@ #include "ssi_sysfs.h" #include "ssi_hash.h" #include "ssi_sram_mgr.h" -#include "ssi_fips_local.h" #define SSI_MAX_AHASH_SEQ_LEN 12 #define SSI_MAX_HASH_OPAD_TMP_KEYS_SIZE MAX(SSI_MAX_HASH_BLCK_SIZE, 3 * AES_BLOCK_SIZE) @@ -431,8 +430,6 @@ static int ssi_hash_digest(struct ahash_req_ctx *state, SSI_LOG_DEBUG("===== %s-digest (%d) ====\n", is_hmac ? "hmac" : "hash", nbytes); - CHECK_AND_RETURN_UPON_FIPS_ERROR(); - if (unlikely(ssi_hash_map_request(dev, state, ctx) != 0)) { SSI_LOG_ERR("map_ahash_source() failed\n"); return -ENOMEM; @@ -596,7 +593,6 @@ static int ssi_hash_update(struct ahash_req_ctx *state, SSI_LOG_DEBUG("===== %s-update (%d) ====\n", ctx->is_hmac ? "hmac" : "hash", nbytes); - CHECK_AND_RETURN_UPON_FIPS_ERROR(); if (nbytes == 0) { /* no real updates required */ return 0; @@ -694,8 +690,6 @@ static int ssi_hash_finup(struct ahash_req_ctx *state, SSI_LOG_DEBUG("===== %s-finup (%d) ====\n", is_hmac ? "hmac" : "hash", nbytes); - CHECK_AND_RETURN_UPON_FIPS_ERROR(); - if (unlikely(ssi_buffer_mgr_map_hash_request_final(ctx->drvdata, state, src, nbytes, 1) != 0)) { SSI_LOG_ERR("map_ahash_request_final() failed\n"); return -ENOMEM; @@ -830,8 +824,6 @@ static int ssi_hash_final(struct ahash_req_ctx *state, SSI_LOG_DEBUG("===== %s-final (%d) ====\n", is_hmac ? "hmac" : "hash", nbytes); - CHECK_AND_RETURN_UPON_FIPS_ERROR(); - if (unlikely(ssi_buffer_mgr_map_hash_request_final(ctx->drvdata, state, src, nbytes, 0) != 0)) { SSI_LOG_ERR("map_ahash_request_final() failed\n"); return -ENOMEM; @@ -965,7 +957,6 @@ static int ssi_hash_init(struct ahash_req_ctx *state, struct ssi_hash_ctx *ctx) state->xcbc_count = 0; - CHECK_AND_RETURN_UPON_FIPS_ERROR(); ssi_hash_map_request(dev, state, ctx); return 0; @@ -987,7 +978,6 @@ static int ssi_hash_setkey(void *hash, SSI_LOG_DEBUG("ssi_hash_setkey: start keylen: %d", keylen); - CHECK_AND_RETURN_UPON_FIPS_ERROR(); ctx = crypto_ahash_ctx(((struct crypto_ahash *)hash)); blocksize = crypto_tfm_alg_blocksize(&((struct crypto_ahash *)hash)->base); digestsize = crypto_ahash_digestsize(((struct crypto_ahash *)hash)); @@ -1174,7 +1164,6 @@ static int ssi_xcbc_setkey(struct crypto_ahash *ahash, struct cc_hw_desc desc[SSI_MAX_AHASH_SEQ_LEN]; SSI_LOG_DEBUG("===== setkey (%d) ====\n", keylen); - CHECK_AND_RETURN_UPON_FIPS_ERROR(); switch (keylen) { case AES_KEYSIZE_128: @@ -1260,7 +1249,6 @@ static int ssi_cmac_setkey(struct crypto_ahash *ahash, struct ssi_hash_ctx *ctx = crypto_ahash_ctx(ahash); SSI_LOG_DEBUG("===== setkey (%d) ====\n", keylen); - CHECK_AND_RETURN_UPON_FIPS_ERROR(); ctx->is_hmac = true; @@ -1365,7 +1353,6 @@ static int ssi_ahash_cra_init(struct crypto_tfm *tfm) struct ssi_hash_alg *ssi_alg = container_of(ahash_alg, struct ssi_hash_alg, ahash_alg); - CHECK_AND_RETURN_UPON_FIPS_ERROR(); crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), sizeof(struct ahash_req_ctx)); @@ -1397,7 +1384,6 @@ static int ssi_mac_update(struct ahash_request *req) int rc; u32 idx = 0; - CHECK_AND_RETURN_UPON_FIPS_ERROR(); if (req->nbytes == 0) { /* no real updates required */ return 0; @@ -1462,7 +1448,6 @@ static int ssi_mac_final(struct ahash_request *req) u32 rem_cnt = state->buff_index ? state->buff1_cnt : state->buff0_cnt; - CHECK_AND_RETURN_UPON_FIPS_ERROR(); if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC) { keySize = CC_AES_128_BIT_KEY_SIZE; keyLen = CC_AES_128_BIT_KEY_SIZE; @@ -1571,7 +1556,6 @@ static int ssi_mac_finup(struct ahash_request *req) u32 digestsize = crypto_ahash_digestsize(tfm); SSI_LOG_DEBUG("===== finup xcbc(%d) ====\n", req->nbytes); - CHECK_AND_RETURN_UPON_FIPS_ERROR(); if (state->xcbc_count > 0 && req->nbytes == 0) { SSI_LOG_DEBUG("No data to update. Call to fdx_mac_final \n"); return ssi_mac_final(req); @@ -1643,7 +1627,6 @@ static int ssi_mac_digest(struct ahash_request *req) int rc; SSI_LOG_DEBUG("===== -digest mac (%d) ====\n", req->nbytes); - CHECK_AND_RETURN_UPON_FIPS_ERROR(); if (unlikely(ssi_hash_map_request(dev, state, ctx) != 0)) { SSI_LOG_ERR("map_ahash_source() failed\n"); @@ -1766,8 +1749,6 @@ static int ssi_ahash_export(struct ahash_request *req, void *out) state->buff0_cnt; const u32 tmp = CC_EXPORT_MAGIC; - CHECK_AND_RETURN_UPON_FIPS_ERROR(); - memcpy(out, &tmp, sizeof(u32)); out += sizeof(u32); @@ -1807,8 +1788,6 @@ static int ssi_ahash_import(struct ahash_request *req, const void *in) u32 tmp; int rc; - CHECK_AND_RETURN_UPON_FIPS_ERROR(); - memcpy(&tmp, in, sizeof(u32)); if (tmp != CC_EXPORT_MAGIC) { rc = -EINVAL; diff --git a/drivers/staging/ccree/ssi_request_mgr.c b/drivers/staging/ccree/ssi_request_mgr.c index 46d9396f9ff9..f40dff2762f9 100644 --- a/drivers/staging/ccree/ssi_request_mgr.c +++ b/drivers/staging/ccree/ssi_request_mgr.c @@ -30,8 +30,6 @@ #include "ssi_sysfs.h" #include "ssi_ivgen.h" #include "ssi_pm.h" -#include "ssi_fips.h" -#include "ssi_fips_local.h" #define SSI_MAX_POLL_ITER 10 -- cgit v1.2.3 From 5dff9f5e69431aab1d607374638af59df5c05bf6 Mon Sep 17 00:00:00 2001 From: Simon Sandström Date: Sun, 2 Jul 2017 01:25:47 +0200 Subject: staging: ccree: Fix alignment issues in ssi_buffer_mgr.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes checkpatch.pl alignment warnings. Signed-off-by: Simon Sandström Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_buffer_mgr.c | 295 ++++++++++++++++++--------------- 1 file changed, 164 insertions(+), 131 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_buffer_mgr.c b/drivers/staging/ccree/ssi_buffer_mgr.c index 363a38f87c49..feeaf8db4b58 100644 --- a/drivers/staging/ccree/ssi_buffer_mgr.c +++ b/drivers/staging/ccree/ssi_buffer_mgr.c @@ -162,8 +162,8 @@ static inline int ssi_buffer_mgr_render_buff_to_mlli( cc_lli_set_addr(mlli_entry_p, buff_dma); cc_lli_set_size(mlli_entry_p, CC_MAX_MLLI_ENTRY_SIZE); SSI_LOG_DEBUG("entry[%d]: single_buff=0x%08X size=%08X\n", *curr_nents, - mlli_entry_p[LLI_WORD0_OFFSET], - mlli_entry_p[LLI_WORD1_OFFSET]); + mlli_entry_p[LLI_WORD0_OFFSET], + mlli_entry_p[LLI_WORD1_OFFSET]); buff_dma += CC_MAX_MLLI_ENTRY_SIZE; buff_size -= CC_MAX_MLLI_ENTRY_SIZE; mlli_entry_p = mlli_entry_p + 2; @@ -173,8 +173,8 @@ static inline int ssi_buffer_mgr_render_buff_to_mlli( cc_lli_set_addr(mlli_entry_p, buff_dma); cc_lli_set_size(mlli_entry_p, buff_size); SSI_LOG_DEBUG("entry[%d]: single_buff=0x%08X size=%08X\n", *curr_nents, - mlli_entry_p[LLI_WORD0_OFFSET], - mlli_entry_p[LLI_WORD1_OFFSET]); + mlli_entry_p[LLI_WORD0_OFFSET], + mlli_entry_p[LLI_WORD1_OFFSET]); mlli_entry_p = mlli_entry_p + 2; *mlli_entry_pp = mlli_entry_p; (*curr_nents)++; @@ -302,7 +302,7 @@ static inline void ssi_buffer_mgr_add_scatterlist_entry( unsigned int index = sgl_data->num_of_buffers; SSI_LOG_DEBUG("index=%u nents=%u sgl=%pK data_len=0x%08X is_last=%d\n", - index, nents, sgl, data_len, is_last_table); + index, nents, sgl, data_len, is_last_table); sgl_data->nents[index] = nents; sgl_data->entry[index].sgl = sgl; sgl_data->offset[index] = data_offset; @@ -317,7 +317,7 @@ static inline void ssi_buffer_mgr_add_scatterlist_entry( static int ssi_buffer_mgr_dma_map_sg(struct device *dev, struct scatterlist *sg, u32 nents, - enum dma_data_direction direction) + enum dma_data_direction direction) { u32 i, j; struct scatterlist *l_sg = sg; @@ -374,7 +374,7 @@ static int ssi_buffer_mgr_map_scatterlist( if (*nents > max_sg_nents) { *nents = 0; SSI_LOG_ERR("Too many fragments. current %d max %d\n", - *nents, max_sg_nents); + *nents, max_sg_nents); return -ENOMEM; } if (!is_chained) { @@ -408,10 +408,10 @@ static int ssi_buffer_mgr_map_scatterlist( static inline int ssi_aead_handle_config_buf(struct device *dev, - struct aead_req_ctx *areq_ctx, - u8 *config_data, - struct buffer_array *sg_data, - unsigned int assoclen) + struct aead_req_ctx *areq_ctx, + u8 *config_data, + struct buffer_array *sg_data, + unsigned int assoclen) { SSI_LOG_DEBUG(" handle additional data config set to DLLI\n"); /* create sg for the current buffer */ @@ -433,19 +433,18 @@ ssi_aead_handle_config_buf(struct device *dev, /* prepare for case of MLLI */ if (assoclen > 0) { ssi_buffer_mgr_add_scatterlist_entry(sg_data, 1, - &areq_ctx->ccm_adata_sg, - (AES_BLOCK_SIZE + - areq_ctx->ccm_hdr_size), 0, - false, NULL); + &areq_ctx->ccm_adata_sg, + (AES_BLOCK_SIZE + areq_ctx->ccm_hdr_size), + 0, false, NULL); } return 0; } static inline int ssi_ahash_handle_curr_buf(struct device *dev, - struct ahash_req_ctx *areq_ctx, - u8 *curr_buff, - u32 curr_buff_cnt, - struct buffer_array *sg_data) + struct ahash_req_ctx *areq_ctx, + u8 *curr_buff, + u32 curr_buff_cnt, + struct buffer_array *sg_data) { SSI_LOG_DEBUG(" handle curr buff %x set to DLLI\n", curr_buff_cnt); /* create sg for the current buffer */ @@ -469,7 +468,7 @@ static inline int ssi_ahash_handle_curr_buf(struct device *dev, areq_ctx->in_nents = 0; /* prepare for case of MLLI */ ssi_buffer_mgr_add_scatterlist_entry(sg_data, 1, areq_ctx->buff_sg, - curr_buff_cnt, 0, false, NULL); + curr_buff_cnt, 0, false, NULL); return 0; } @@ -484,8 +483,8 @@ void ssi_buffer_mgr_unmap_blkcipher_request( if (likely(req_ctx->gen_ctx.iv_dma_addr != 0)) { SSI_LOG_DEBUG("Unmapped iv: iv_dma_addr=0x%llX iv_size=%u\n", - (unsigned long long)req_ctx->gen_ctx.iv_dma_addr, - ivsize); + (unsigned long long)req_ctx->gen_ctx.iv_dma_addr, + ivsize); dma_unmap_single(dev, req_ctx->gen_ctx.iv_dma_addr, ivsize, req_ctx->is_giv ? DMA_BIDIRECTIONAL : @@ -498,16 +497,12 @@ void ssi_buffer_mgr_unmap_blkcipher_request( req_ctx->mlli_params.mlli_dma_addr); } - dma_unmap_sg(dev, src, req_ctx->in_nents, - DMA_BIDIRECTIONAL); - SSI_LOG_DEBUG("Unmapped req->src=%pK\n", - sg_virt(src)); + dma_unmap_sg(dev, src, req_ctx->in_nents, DMA_BIDIRECTIONAL); + SSI_LOG_DEBUG("Unmapped req->src=%pK\n", sg_virt(src)); if (src != dst) { - dma_unmap_sg(dev, dst, req_ctx->out_nents, - DMA_BIDIRECTIONAL); - SSI_LOG_DEBUG("Unmapped req->dst=%pK\n", - sg_virt(dst)); + dma_unmap_sg(dev, dst, req_ctx->out_nents, DMA_BIDIRECTIONAL); + SSI_LOG_DEBUG("Unmapped req->dst=%pK\n", sg_virt(dst)); } } @@ -542,22 +537,24 @@ int ssi_buffer_mgr_map_blkcipher_request( req_ctx->is_giv ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE); if (unlikely(dma_mapping_error(dev, - req_ctx->gen_ctx.iv_dma_addr))) { + req_ctx->gen_ctx.iv_dma_addr))) { SSI_LOG_ERR("Mapping iv %u B at va=%pK " "for DMA failed\n", ivsize, info); return -ENOMEM; } SSI_LOG_DEBUG("Mapped iv %u B at va=%pK to dma=0x%llX\n", - ivsize, info, - (unsigned long long)req_ctx->gen_ctx.iv_dma_addr); + ivsize, info, + (unsigned long long)req_ctx->gen_ctx.iv_dma_addr); } else { req_ctx->gen_ctx.iv_dma_addr = 0; } /* Map the src SGL */ rc = ssi_buffer_mgr_map_scatterlist(dev, src, - nbytes, DMA_BIDIRECTIONAL, &req_ctx->in_nents, - LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy, &mapped_nents); + nbytes, DMA_BIDIRECTIONAL, + &req_ctx->in_nents, + LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy, + &mapped_nents); if (unlikely(rc != 0)) { rc = -ENOMEM; goto ablkcipher_exit; @@ -570,8 +567,10 @@ int ssi_buffer_mgr_map_blkcipher_request( if (unlikely(req_ctx->dma_buf_type == SSI_DMA_BUF_MLLI)) { req_ctx->out_nents = 0; ssi_buffer_mgr_add_scatterlist_entry(&sg_data, - req_ctx->in_nents, src, - nbytes, 0, true, &req_ctx->in_mlli_nents); + req_ctx->in_nents, + src, nbytes, 0, + true, + &req_ctx->in_mlli_nents); } } else { /* Map the dst sg */ @@ -588,13 +587,15 @@ int ssi_buffer_mgr_map_blkcipher_request( if (unlikely((req_ctx->dma_buf_type == SSI_DMA_BUF_MLLI))) { ssi_buffer_mgr_add_scatterlist_entry(&sg_data, - req_ctx->in_nents, src, - nbytes, 0, true, - &req_ctx->in_mlli_nents); + req_ctx->in_nents, + src, nbytes, 0, + true, + &req_ctx->in_mlli_nents); ssi_buffer_mgr_add_scatterlist_entry(&sg_data, - req_ctx->out_nents, dst, - nbytes, 0, true, - &req_ctx->out_mlli_nents); + req_ctx->out_nents, + dst, nbytes, 0, + true, + &req_ctx->out_mlli_nents); } } @@ -606,7 +607,7 @@ int ssi_buffer_mgr_map_blkcipher_request( } SSI_LOG_DEBUG("areq_ctx->dma_buf_type = %s\n", - GET_DMA_BUFFER_TYPE(req_ctx->dma_buf_type)); + GET_DMA_BUFFER_TYPE(req_ctx->dma_buf_type)); return 0; @@ -628,7 +629,7 @@ void ssi_buffer_mgr_unmap_aead_request( if (areq_ctx->mac_buf_dma_addr != 0) { dma_unmap_single(dev, areq_ctx->mac_buf_dma_addr, - MAX_MAC_SIZE, DMA_BIDIRECTIONAL); + MAX_MAC_SIZE, DMA_BIDIRECTIONAL); } #if SSI_CC_HAS_AES_GCM @@ -645,12 +646,12 @@ void ssi_buffer_mgr_unmap_aead_request( if (areq_ctx->gcm_iv_inc1_dma_addr != 0) { dma_unmap_single(dev, areq_ctx->gcm_iv_inc1_dma_addr, - AES_BLOCK_SIZE, DMA_TO_DEVICE); + AES_BLOCK_SIZE, DMA_TO_DEVICE); } if (areq_ctx->gcm_iv_inc2_dma_addr != 0) { dma_unmap_single(dev, areq_ctx->gcm_iv_inc2_dma_addr, - AES_BLOCK_SIZE, DMA_TO_DEVICE); + AES_BLOCK_SIZE, DMA_TO_DEVICE); } } #endif @@ -658,7 +659,7 @@ void ssi_buffer_mgr_unmap_aead_request( if (areq_ctx->ccm_hdr_size != ccm_header_size_null) { if (areq_ctx->ccm_iv0_dma_addr != 0) { dma_unmap_single(dev, areq_ctx->ccm_iv0_dma_addr, - AES_BLOCK_SIZE, DMA_TO_DEVICE); + AES_BLOCK_SIZE, DMA_TO_DEVICE); } dma_unmap_sg(dev, &areq_ctx->ccm_adata_sg, 1, DMA_TO_DEVICE); @@ -673,8 +674,8 @@ void ssi_buffer_mgr_unmap_aead_request( */ if (areq_ctx->mlli_params.curr_pool) { SSI_LOG_DEBUG("free MLLI buffer: dma=0x%08llX virt=%pK\n", - (unsigned long long)areq_ctx->mlli_params.mlli_dma_addr, - areq_ctx->mlli_params.mlli_virt_addr); + (unsigned long long)areq_ctx->mlli_params.mlli_dma_addr, + areq_ctx->mlli_params.mlli_virt_addr); dma_pool_free(areq_ctx->mlli_params.curr_pool, areq_ctx->mlli_params.mlli_virt_addr, areq_ctx->mlli_params.mlli_dma_addr); @@ -690,9 +691,13 @@ void ssi_buffer_mgr_unmap_aead_request( dma_unmap_sg(dev, req->src, ssi_buffer_mgr_get_sgl_nents(req->src, size_to_unmap, &dummy, &chained), DMA_BIDIRECTIONAL); if (unlikely(req->src != req->dst)) { SSI_LOG_DEBUG("Unmapping dst sgl: req->dst=%pK\n", - sg_virt(req->dst)); - dma_unmap_sg(dev, req->dst, ssi_buffer_mgr_get_sgl_nents(req->dst, size_to_unmap, &dummy, &chained), - DMA_BIDIRECTIONAL); + sg_virt(req->dst)); + dma_unmap_sg(dev, req->dst, + ssi_buffer_mgr_get_sgl_nents(req->dst, + size_to_unmap, + &dummy, + &chained), + DMA_BIDIRECTIONAL); } if (drvdata->coherent && (areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) && @@ -752,11 +757,11 @@ static inline int ssi_buffer_mgr_get_aead_icv_nents( *is_icv_fragmented = true; } else { SSI_LOG_ERR("Unsupported num. of ICV fragments (> %d)\n", - MAX_ICV_NENTS_SUPPORTED); + MAX_ICV_NENTS_SUPPORTED); nents = -1; /*unsupported*/ } SSI_LOG_DEBUG("is_frag=%s icv_nents=%u\n", - (*is_icv_fragmented ? "true" : "false"), nents); + (*is_icv_fragmented ? "true" : "false"), nents); return nents; } @@ -781,14 +786,14 @@ static inline int ssi_buffer_mgr_aead_chain_iv( hw_iv_size, DMA_BIDIRECTIONAL); if (unlikely(dma_mapping_error(dev, areq_ctx->gen_ctx.iv_dma_addr))) { SSI_LOG_ERR("Mapping iv %u B at va=%pK for DMA failed\n", - hw_iv_size, req->iv); + hw_iv_size, req->iv); rc = -ENOMEM; goto chain_iv_exit; } SSI_LOG_DEBUG("Mapped iv %u B at va=%pK to dma=0x%llX\n", - hw_iv_size, req->iv, - (unsigned long long)areq_ctx->gen_ctx.iv_dma_addr); + hw_iv_size, req->iv, + (unsigned long long)areq_ctx->gen_ctx.iv_dma_addr); if (do_chain && areq_ctx->plaintext_authenticate_only) { // TODO: what about CTR?? ask Ron struct crypto_aead *tfm = crypto_aead_reqtfm(req); unsigned int iv_size_to_authenc = crypto_aead_ivsize(tfm); @@ -832,8 +837,8 @@ static inline int ssi_buffer_mgr_aead_chain_assoc( areq_ctx->assoc.nents = 0; areq_ctx->assoc.mlli_nents = 0; SSI_LOG_DEBUG("Chain assoc of length 0: buff_type=%s nents=%u\n", - GET_DMA_BUFFER_TYPE(areq_ctx->assoc_buff_type), - areq_ctx->assoc.nents); + GET_DMA_BUFFER_TYPE(areq_ctx->assoc_buff_type), + areq_ctx->assoc.nents); goto chain_assoc_exit; } @@ -867,10 +872,9 @@ static inline int ssi_buffer_mgr_aead_chain_assoc( if (areq_ctx->ccm_hdr_size != ccm_header_size_null) { if (unlikely((mapped_nents + 1) > LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES)) { - SSI_LOG_ERR("CCM case.Too many fragments. " - "Current %d max %d\n", - (areq_ctx->assoc.nents + 1), - LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES); + SSI_LOG_ERR("CCM case.Too many fragments. Current %d max %d\n", + (areq_ctx->assoc.nents + 1), + LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES); rc = -ENOMEM; goto chain_assoc_exit; } @@ -883,10 +887,10 @@ static inline int ssi_buffer_mgr_aead_chain_assoc( areq_ctx->assoc_buff_type = SSI_DMA_BUF_MLLI; if (unlikely((do_chain) || - (areq_ctx->assoc_buff_type == SSI_DMA_BUF_MLLI))) { + (areq_ctx->assoc_buff_type == SSI_DMA_BUF_MLLI))) { SSI_LOG_DEBUG("Chain assoc: buff_type=%s nents=%u\n", - GET_DMA_BUFFER_TYPE(areq_ctx->assoc_buff_type), - areq_ctx->assoc.nents); + GET_DMA_BUFFER_TYPE(areq_ctx->assoc_buff_type), + areq_ctx->assoc.nents); ssi_buffer_mgr_add_scatterlist_entry( sg_data, areq_ctx->assoc.nents, req->src, req->assoclen, 0, is_last, @@ -950,13 +954,18 @@ static inline int ssi_buffer_mgr_prepare_aead_data_mlli( if (likely(req->src == req->dst)) { /*INPLACE*/ ssi_buffer_mgr_add_scatterlist_entry(sg_data, - areq_ctx->src.nents, areq_ctx->srcSgl, - areq_ctx->cryptlen, areq_ctx->srcOffset, is_last_table, - &areq_ctx->src.mlli_nents); + areq_ctx->src.nents, + areq_ctx->srcSgl, + areq_ctx->cryptlen, + areq_ctx->srcOffset, + is_last_table, + &areq_ctx->src.mlli_nents); icv_nents = ssi_buffer_mgr_get_aead_icv_nents(areq_ctx->srcSgl, - areq_ctx->src.nents, authsize, *src_last_bytes, - &areq_ctx->is_icv_fragmented); + areq_ctx->src.nents, + authsize, + *src_last_bytes, + &areq_ctx->is_icv_fragmented); if (unlikely(icv_nents < 0)) { rc = -ENOTSUPP; goto prepare_data_mlli_exit; @@ -1004,17 +1013,25 @@ static inline int ssi_buffer_mgr_prepare_aead_data_mlli( } else if (direct == DRV_CRYPTO_DIRECTION_DECRYPT) { /*NON-INPLACE and DECRYPT*/ ssi_buffer_mgr_add_scatterlist_entry(sg_data, - areq_ctx->src.nents, areq_ctx->srcSgl, - areq_ctx->cryptlen, areq_ctx->srcOffset, is_last_table, - &areq_ctx->src.mlli_nents); + areq_ctx->src.nents, + areq_ctx->srcSgl, + areq_ctx->cryptlen, + areq_ctx->srcOffset, + is_last_table, + &areq_ctx->src.mlli_nents); ssi_buffer_mgr_add_scatterlist_entry(sg_data, - areq_ctx->dst.nents, areq_ctx->dstSgl, - areq_ctx->cryptlen, areq_ctx->dstOffset, is_last_table, - &areq_ctx->dst.mlli_nents); + areq_ctx->dst.nents, + areq_ctx->dstSgl, + areq_ctx->cryptlen, + areq_ctx->dstOffset, + is_last_table, + &areq_ctx->dst.mlli_nents); icv_nents = ssi_buffer_mgr_get_aead_icv_nents(areq_ctx->srcSgl, - areq_ctx->src.nents, authsize, *src_last_bytes, - &areq_ctx->is_icv_fragmented); + areq_ctx->src.nents, + authsize, + *src_last_bytes, + &areq_ctx->is_icv_fragmented); if (unlikely(icv_nents < 0)) { rc = -ENOTSUPP; goto prepare_data_mlli_exit; @@ -1048,16 +1065,24 @@ static inline int ssi_buffer_mgr_prepare_aead_data_mlli( } else { /*NON-INPLACE and ENCRYPT*/ ssi_buffer_mgr_add_scatterlist_entry(sg_data, - areq_ctx->dst.nents, areq_ctx->dstSgl, - areq_ctx->cryptlen, areq_ctx->dstOffset, is_last_table, - &areq_ctx->dst.mlli_nents); + areq_ctx->dst.nents, + areq_ctx->dstSgl, + areq_ctx->cryptlen, + areq_ctx->dstOffset, + is_last_table, + &areq_ctx->dst.mlli_nents); ssi_buffer_mgr_add_scatterlist_entry(sg_data, - areq_ctx->src.nents, areq_ctx->srcSgl, - areq_ctx->cryptlen, areq_ctx->srcOffset, is_last_table, - &areq_ctx->src.mlli_nents); + areq_ctx->src.nents, + areq_ctx->srcSgl, + areq_ctx->cryptlen, + areq_ctx->srcOffset, + is_last_table, + &areq_ctx->src.mlli_nents); icv_nents = ssi_buffer_mgr_get_aead_icv_nents(areq_ctx->dstSgl, - areq_ctx->dst.nents, authsize, *dst_last_bytes, + areq_ctx->dst.nents, + authsize, + *dst_last_bytes, &areq_ctx->is_icv_fragmented); if (unlikely(icv_nents < 0)) { rc = -ENOTSUPP; @@ -1135,7 +1160,7 @@ static inline int ssi_buffer_mgr_aead_chain_data( } if (unlikely(src_mapped_nents > LLI_MAX_NUM_OF_DATA_ENTRIES)) { SSI_LOG_ERR("Too many fragments. current %d max %d\n", - src_mapped_nents, LLI_MAX_NUM_OF_DATA_ENTRIES); + src_mapped_nents, LLI_MAX_NUM_OF_DATA_ENTRIES); return -ENOMEM; } @@ -1150,9 +1175,11 @@ static inline int ssi_buffer_mgr_aead_chain_data( size_for_map += crypto_aead_ivsize(tfm); rc = ssi_buffer_mgr_map_scatterlist(dev, req->dst, size_for_map, - DMA_BIDIRECTIONAL, &(areq_ctx->dst.nents), - LLI_MAX_NUM_OF_DATA_ENTRIES, &dst_last_bytes, - &dst_mapped_nents); + DMA_BIDIRECTIONAL, + &(areq_ctx->dst.nents), + LLI_MAX_NUM_OF_DATA_ENTRIES, + &dst_last_bytes, + &dst_mapped_nents); if (unlikely(rc != 0)) { rc = -ENOMEM; goto chain_data_exit; @@ -1186,8 +1213,11 @@ static inline int ssi_buffer_mgr_aead_chain_data( (dst_mapped_nents > 1) || do_chain) { areq_ctx->data_buff_type = SSI_DMA_BUF_MLLI; - rc = ssi_buffer_mgr_prepare_aead_data_mlli(drvdata, req, sg_data, - &src_last_bytes, &dst_last_bytes, is_last_table); + rc = ssi_buffer_mgr_prepare_aead_data_mlli(drvdata, req, + sg_data, + &src_last_bytes, + &dst_last_bytes, + is_last_table); } else { areq_ctx->data_buff_type = SSI_DMA_BUF_DLLI; ssi_buffer_mgr_prepare_aead_data_dlli( @@ -1199,7 +1229,7 @@ chain_data_exit: } static void ssi_buffer_mgr_update_aead_mlli_nents(struct ssi_drvdata *drvdata, - struct aead_request *req) + struct aead_request *req) { struct aead_req_ctx *areq_ctx = aead_request_ctx(req); u32 curr_mlli_size = 0; @@ -1296,7 +1326,7 @@ int ssi_buffer_mgr_map_aead_request( areq_ctx->mac_buf, MAX_MAC_SIZE, DMA_BIDIRECTIONAL); if (unlikely(dma_mapping_error(dev, areq_ctx->mac_buf_dma_addr))) { SSI_LOG_ERR("Mapping mac_buf %u B at va=%pK for DMA failed\n", - MAX_MAC_SIZE, areq_ctx->mac_buf); + MAX_MAC_SIZE, areq_ctx->mac_buf); rc = -ENOMEM; goto aead_map_failure; } @@ -1315,7 +1345,8 @@ int ssi_buffer_mgr_map_aead_request( goto aead_map_failure; } if (ssi_aead_handle_config_buf(dev, areq_ctx, - areq_ctx->ccm_config, &sg_data, req->assoclen) != 0) { + areq_ctx->ccm_config, &sg_data, + req->assoclen) != 0) { rc = -ENOMEM; goto aead_map_failure; } @@ -1327,7 +1358,7 @@ int ssi_buffer_mgr_map_aead_request( areq_ctx->hkey, AES_BLOCK_SIZE, DMA_BIDIRECTIONAL); if (unlikely(dma_mapping_error(dev, areq_ctx->hkey_dma_addr))) { SSI_LOG_ERR("Mapping hkey %u B at va=%pK for DMA failed\n", - AES_BLOCK_SIZE, areq_ctx->hkey); + AES_BLOCK_SIZE, areq_ctx->hkey); rc = -ENOMEM; goto aead_map_failure; } @@ -1336,7 +1367,7 @@ int ssi_buffer_mgr_map_aead_request( &areq_ctx->gcm_len_block, AES_BLOCK_SIZE, DMA_TO_DEVICE); if (unlikely(dma_mapping_error(dev, areq_ctx->gcm_block_len_dma_addr))) { SSI_LOG_ERR("Mapping gcm_len_block %u B at va=%pK for DMA failed\n", - AES_BLOCK_SIZE, &areq_ctx->gcm_len_block); + AES_BLOCK_SIZE, &areq_ctx->gcm_len_block); rc = -ENOMEM; goto aead_map_failure; } @@ -1487,18 +1518,18 @@ int ssi_buffer_mgr_map_hash_request_final( /* map the previous buffer */ if (*curr_buff_cnt != 0) { if (ssi_ahash_handle_curr_buf(dev, areq_ctx, curr_buff, - *curr_buff_cnt, &sg_data) != 0) { + *curr_buff_cnt, &sg_data) != 0) { return -ENOMEM; } } if (src && (nbytes > 0) && do_update) { - if (unlikely(ssi_buffer_mgr_map_scatterlist(dev, src, - nbytes, - DMA_TO_DEVICE, - &areq_ctx->in_nents, - LLI_MAX_NUM_OF_DATA_ENTRIES, - &dummy, &mapped_nents))){ + if (unlikely(ssi_buffer_mgr_map_scatterlist(dev, src, nbytes, + DMA_TO_DEVICE, + &areq_ctx->in_nents, + LLI_MAX_NUM_OF_DATA_ENTRIES, + &dummy, + &mapped_nents))){ goto unmap_curr_buff; } if (src && (mapped_nents == 1) @@ -1518,19 +1549,18 @@ int ssi_buffer_mgr_map_hash_request_final( mlli_params->curr_pool = buff_mgr->mlli_buffs_pool; /* add the src data to the sg_data */ ssi_buffer_mgr_add_scatterlist_entry(&sg_data, - areq_ctx->in_nents, - src, - nbytes, 0, - true, &areq_ctx->mlli_nents); + areq_ctx->in_nents, + src, nbytes, 0, true, + &areq_ctx->mlli_nents); if (unlikely(ssi_buffer_mgr_generate_mlli(dev, &sg_data, - mlli_params) != 0)) { + mlli_params) != 0)) { goto fail_unmap_din; } } /* change the buffer index for the unmap function */ areq_ctx->buff_index = (areq_ctx->buff_index ^ 1); SSI_LOG_DEBUG("areq_ctx->data_dma_buf_type = %s\n", - GET_DMA_BUFFER_TYPE(areq_ctx->data_dma_buf_type)); + GET_DMA_BUFFER_TYPE(areq_ctx->data_dma_buf_type)); return 0; fail_unmap_din: @@ -1584,8 +1614,8 @@ int ssi_buffer_mgr_map_hash_request_update( &curr_buff[*curr_buff_cnt]); areq_ctx->in_nents = ssi_buffer_mgr_get_sgl_nents(src, - nbytes, - &dummy, NULL); + nbytes, + &dummy, NULL); sg_copy_to_buffer(src, areq_ctx->in_nents, &curr_buff[*curr_buff_cnt], nbytes); *curr_buff_cnt += nbytes; @@ -1608,15 +1638,15 @@ int ssi_buffer_mgr_map_hash_request_update( (update_data_len - *curr_buff_cnt), *next_buff_cnt); ssi_buffer_mgr_copy_scatterlist_portion(next_buff, src, - (update_data_len - *curr_buff_cnt), - nbytes, SSI_SG_TO_BUF); + (update_data_len - *curr_buff_cnt), + nbytes, SSI_SG_TO_BUF); /* change the buffer index for next operation */ swap_index = 1; } if (*curr_buff_cnt != 0) { if (ssi_ahash_handle_curr_buf(dev, areq_ctx, curr_buff, - *curr_buff_cnt, &sg_data) != 0) { + *curr_buff_cnt, &sg_data) != 0) { return -ENOMEM; } /* change the buffer index for next operation */ @@ -1625,11 +1655,12 @@ int ssi_buffer_mgr_map_hash_request_update( if (update_data_len > *curr_buff_cnt) { if (unlikely(ssi_buffer_mgr_map_scatterlist(dev, src, - (update_data_len - *curr_buff_cnt), - DMA_TO_DEVICE, - &areq_ctx->in_nents, - LLI_MAX_NUM_OF_DATA_ENTRIES, - &dummy, &mapped_nents))){ + (update_data_len - *curr_buff_cnt), + DMA_TO_DEVICE, + &areq_ctx->in_nents, + LLI_MAX_NUM_OF_DATA_ENTRIES, + &dummy, + &mapped_nents))){ goto unmap_curr_buff; } if ((mapped_nents == 1) @@ -1649,12 +1680,14 @@ int ssi_buffer_mgr_map_hash_request_update( mlli_params->curr_pool = buff_mgr->mlli_buffs_pool; /* add the src data to the sg_data */ ssi_buffer_mgr_add_scatterlist_entry(&sg_data, - areq_ctx->in_nents, - src, - (update_data_len - *curr_buff_cnt), 0, - true, &areq_ctx->mlli_nents); + areq_ctx->in_nents, + src, + (update_data_len - *curr_buff_cnt), + 0, + true, + &areq_ctx->mlli_nents); if (unlikely(ssi_buffer_mgr_generate_mlli(dev, &sg_data, - mlli_params) != 0)) { + mlli_params) != 0)) { goto fail_unmap_din; } } @@ -1684,8 +1717,8 @@ void ssi_buffer_mgr_unmap_hash_request( */ if (areq_ctx->mlli_params.curr_pool) { SSI_LOG_DEBUG("free MLLI buffer: dma=0x%llX virt=%pK\n", - (unsigned long long)areq_ctx->mlli_params.mlli_dma_addr, - areq_ctx->mlli_params.mlli_virt_addr); + (unsigned long long)areq_ctx->mlli_params.mlli_dma_addr, + areq_ctx->mlli_params.mlli_virt_addr); dma_pool_free(areq_ctx->mlli_params.curr_pool, areq_ctx->mlli_params.mlli_virt_addr, areq_ctx->mlli_params.mlli_dma_addr); @@ -1693,9 +1726,9 @@ void ssi_buffer_mgr_unmap_hash_request( if ((src) && likely(areq_ctx->in_nents != 0)) { SSI_LOG_DEBUG("Unmapped sg src: virt=%pK dma=0x%llX len=0x%X\n", - sg_virt(src), - (unsigned long long)sg_dma_address(src), - sg_dma_len(src)); + sg_virt(src), + (unsigned long long)sg_dma_address(src), + sg_dma_len(src)); dma_unmap_sg(dev, src, areq_ctx->in_nents, DMA_TO_DEVICE); } -- cgit v1.2.3 From 22aa4c93eee7da62e9e5048cff975eec51ab2ede Mon Sep 17 00:00:00 2001 From: Simon Sandström Date: Sun, 2 Jul 2017 01:25:48 +0200 Subject: staging: ccree: Fix alignment issues in ssi_cipher.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes checkpatch.pl alignment warnings. Signed-off-by: Simon Sandström Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_cipher.c | 75 +++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_cipher.c b/drivers/staging/ccree/ssi_cipher.c index af16bd02397c..f05ba7070cd3 100644 --- a/drivers/staging/ccree/ssi_cipher.c +++ b/drivers/staging/ccree/ssi_cipher.c @@ -93,8 +93,7 @@ static int validate_keys_sizes(struct ssi_ablkcipher_ctx *ctx_p, u32 size) break; } case S_DIN_to_DES: - if (likely(size == DES3_EDE_KEY_SIZE || - size == DES_KEY_SIZE)) + if (likely(size == DES3_EDE_KEY_SIZE || size == DES_KEY_SIZE)) return 0; break; #if SSI_CC_HAS_MULTI2 @@ -185,8 +184,8 @@ static int ssi_blkcipher_init(struct crypto_tfm *tfm) int rc = 0; unsigned int max_key_buf_size = get_max_keysize(tfm); - SSI_LOG_DEBUG("Initializing context @%p for %s\n", ctx_p, - crypto_tfm_alg_name(tfm)); + SSI_LOG_DEBUG("Initializing context @%p for %s\n", + ctx_p, crypto_tfm_alg_name(tfm)); ctx_p->cipher_mode = ssi_alg->cipher_mode; ctx_p->flow_mode = ssi_alg->flow_mode; @@ -207,12 +206,12 @@ static int ssi_blkcipher_init(struct crypto_tfm *tfm) max_key_buf_size, DMA_TO_DEVICE); if (dma_mapping_error(dev, ctx_p->user.key_dma_addr)) { SSI_LOG_ERR("Mapping Key %u B at va=%pK for DMA failed\n", - max_key_buf_size, ctx_p->user.key); + max_key_buf_size, ctx_p->user.key); return -ENOMEM; } SSI_LOG_DEBUG("Mapped key %u B at va=%pK to dma=0x%llX\n", - max_key_buf_size, ctx_p->user.key, - (unsigned long long)ctx_p->user.key_dma_addr); + max_key_buf_size, ctx_p->user.key, + (unsigned long long)ctx_p->user.key_dma_addr); if (ctx_p->cipher_mode == DRV_CIPHER_ESSIV) { /* Alloc hash tfm for essiv */ @@ -233,7 +232,7 @@ static void ssi_blkcipher_exit(struct crypto_tfm *tfm) unsigned int max_key_buf_size = get_max_keysize(tfm); SSI_LOG_DEBUG("Clearing context @%p for %s\n", - crypto_tfm_ctx(tfm), crypto_tfm_alg_name(tfm)); + crypto_tfm_ctx(tfm), crypto_tfm_alg_name(tfm)); if (ctx_p->cipher_mode == DRV_CIPHER_ESSIV) { /* Free hash tfm for essiv */ @@ -243,9 +242,9 @@ static void ssi_blkcipher_exit(struct crypto_tfm *tfm) /* Unmap key buffer */ dma_unmap_single(dev, ctx_p->user.key_dma_addr, max_key_buf_size, - DMA_TO_DEVICE); + DMA_TO_DEVICE); SSI_LOG_DEBUG("Unmapped key buffer key_dma_addr=0x%llX\n", - (unsigned long long)ctx_p->user.key_dma_addr); + (unsigned long long)ctx_p->user.key_dma_addr); /* Free key buffer in context */ kfree(ctx_p->user.key); @@ -270,7 +269,7 @@ static int ssi_verify_3des_keys(const u8 *key, unsigned int keylen) /* verify key1 != key2 and key3 != key2*/ if (unlikely((memcmp((u8 *)tdes_key->key1, (u8 *)tdes_key->key2, sizeof(tdes_key->key1)) == 0) || - (memcmp((u8 *)tdes_key->key3, (u8 *)tdes_key->key2, sizeof(tdes_key->key3)) == 0))) { + (memcmp((u8 *)tdes_key->key3, (u8 *)tdes_key->key2, sizeof(tdes_key->key3)) == 0))) { return -ENOEXEC; } @@ -302,7 +301,7 @@ static int ssi_blkcipher_setkey(struct crypto_tfm *tfm, unsigned int max_key_buf_size = get_max_keysize(tfm); SSI_LOG_DEBUG("Setting key in context @%p for %s. keylen=%u\n", - ctx_p, crypto_tfm_alg_name(tfm), keylen); + ctx_p, crypto_tfm_alg_name(tfm), keylen); dump_byte_array("key", (u8 *)key, keylen); SSI_LOG_DEBUG("ssi_blkcipher_setkey: after FIPS check"); @@ -379,7 +378,7 @@ static int ssi_blkcipher_setkey(struct crypto_tfm *tfm, /* STAT_PHASE_1: Copy key to ctx */ dma_sync_single_for_cpu(dev, ctx_p->user.key_dma_addr, - max_key_buf_size, DMA_TO_DEVICE); + max_key_buf_size, DMA_TO_DEVICE); if (ctx_p->flow_mode == S_DIN_to_MULTI2) { #if SSI_CC_HAS_MULTI2 @@ -412,7 +411,7 @@ static int ssi_blkcipher_setkey(struct crypto_tfm *tfm, } } dma_sync_single_for_device(dev, ctx_p->user.key_dma_addr, - max_key_buf_size, DMA_TO_DEVICE); + max_key_buf_size, DMA_TO_DEVICE); ctx_p->keylen = keylen; SSI_LOG_DEBUG("ssi_blkcipher_setkey: return safely"); @@ -621,11 +620,9 @@ ssi_blkcipher_create_data_desc( /* Process */ if (likely(req_ctx->dma_buf_type == SSI_DMA_BUF_DLLI)) { SSI_LOG_DEBUG(" data params addr 0x%llX length 0x%X \n", - (unsigned long long)sg_dma_address(src), - nbytes); + (unsigned long long)sg_dma_address(src), nbytes); SSI_LOG_DEBUG(" data params addr 0x%llX length 0x%X \n", - (unsigned long long)sg_dma_address(dst), - nbytes); + (unsigned long long)sg_dma_address(dst), nbytes); hw_desc_init(&desc[*seq_size]); set_din_type(&desc[*seq_size], DMA_DLLI, sg_dma_address(src), nbytes, NS_BIT); @@ -689,13 +686,13 @@ ssi_blkcipher_create_data_desc( } static int ssi_blkcipher_complete(struct device *dev, - struct ssi_ablkcipher_ctx *ctx_p, - struct blkcipher_req_ctx *req_ctx, - struct scatterlist *dst, - struct scatterlist *src, - unsigned int ivsize, - void *areq, - void __iomem *cc_base) + struct ssi_ablkcipher_ctx *ctx_p, + struct blkcipher_req_ctx *req_ctx, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int ivsize, + void *areq, + void __iomem *cc_base) { int completion_error = 0; u32 inflight_counter; @@ -732,8 +729,8 @@ static int ssi_blkcipher_process( int rc, seq_len = 0, cts_restore_flag = 0; SSI_LOG_DEBUG("%s areq=%p info=%p nbytes=%d\n", - ((direction == DRV_CRYPTO_DIRECTION_ENCRYPT) ? "Encrypt" : "Decrypt"), - areq, info, nbytes); + ((direction == DRV_CRYPTO_DIRECTION_ENCRYPT) ? "Encrypt" : "Decrypt"), + areq, info, nbytes); /* STAT_PHASE_0: Init and sanity checks */ @@ -786,12 +783,8 @@ static int ssi_blkcipher_process( ssi_blkcipher_create_setup_desc(tfm, req_ctx, ivsize, nbytes, desc, &seq_len); /* Data processing */ - ssi_blkcipher_create_data_desc(tfm, - req_ctx, - dst, src, - nbytes, - areq, - desc, &seq_len); + ssi_blkcipher_create_data_desc(tfm, req_ctx, dst, src, nbytes, areq, + desc, &seq_len); /* do we need to generate IV? */ if (req_ctx->is_giv) { @@ -851,8 +844,8 @@ static int ssi_ablkcipher_init(struct crypto_tfm *tfm) } static int ssi_ablkcipher_setkey(struct crypto_ablkcipher *tfm, - const u8 *key, - unsigned int keylen) + const u8 *key, + unsigned int keylen) { return ssi_blkcipher_setkey(crypto_ablkcipher_tfm(tfm), key, keylen); } @@ -1266,7 +1259,7 @@ int ssi_ablkcipher_free(struct ssi_drvdata *drvdata) if (blkcipher_handle) { /* Remove registered algs */ list_for_each_entry_safe(t_alg, n, - &blkcipher_handle->blkcipher_alg_list, + &blkcipher_handle->blkcipher_alg_list, entry) { crypto_unregister_alg(&t_alg->crypto_alg); list_del(&t_alg->entry); @@ -1286,7 +1279,7 @@ int ssi_ablkcipher_alloc(struct ssi_drvdata *drvdata) int alg; ablkcipher_handle = kmalloc(sizeof(struct ssi_blkcipher_handle), - GFP_KERNEL); + GFP_KERNEL); if (!ablkcipher_handle) return -ENOMEM; @@ -1302,7 +1295,7 @@ int ssi_ablkcipher_alloc(struct ssi_drvdata *drvdata) if (IS_ERR(t_alg)) { rc = PTR_ERR(t_alg); SSI_LOG_ERR("%s alg allocation failed\n", - blkcipher_algs[alg].driver_name); + blkcipher_algs[alg].driver_name); goto fail0; } t_alg->drvdata = drvdata; @@ -1310,17 +1303,17 @@ int ssi_ablkcipher_alloc(struct ssi_drvdata *drvdata) SSI_LOG_DEBUG("registering %s\n", blkcipher_algs[alg].driver_name); rc = crypto_register_alg(&t_alg->crypto_alg); SSI_LOG_DEBUG("%s alg registration rc = %x\n", - t_alg->crypto_alg.cra_driver_name, rc); + t_alg->crypto_alg.cra_driver_name, rc); if (unlikely(rc != 0)) { SSI_LOG_ERR("%s alg registration failed\n", - t_alg->crypto_alg.cra_driver_name); + t_alg->crypto_alg.cra_driver_name); kfree(t_alg); goto fail0; } else { list_add_tail(&t_alg->entry, &ablkcipher_handle->blkcipher_alg_list); SSI_LOG_DEBUG("Registered %s\n", - t_alg->crypto_alg.cra_driver_name); + t_alg->crypto_alg.cra_driver_name); } } return 0; -- cgit v1.2.3 From 8426423407ad1ffcc943df7a3c1b0d15d07a22ef Mon Sep 17 00:00:00 2001 From: Simon Sandström Date: Sun, 2 Jul 2017 01:25:49 +0200 Subject: staging: ccree: Fix alignment issues in ssi_driver.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes checkpatch.pl alignment warnings. Signed-off-by: Simon Sandström Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_driver.c | 40 +++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_driver.c b/drivers/staging/ccree/ssi_driver.c index d66f5de732a4..afb7c48d2d51 100644 --- a/drivers/staging/ccree/ssi_driver.c +++ b/drivers/staging/ccree/ssi_driver.c @@ -85,8 +85,7 @@ void dump_byte_array(const char *name, const u8 *the_array, unsigned long size) return; } - ret = snprintf(line_buf, sizeof(line_buf), "%s[%lu]: ", - name, size); + ret = snprintf(line_buf, sizeof(line_buf), "%s[%lu]: ", name, size); if (ret < 0) { SSI_LOG_ERR("snprintf returned %d . aborting buffer array dump\n", ret); return; @@ -95,8 +94,8 @@ void dump_byte_array(const char *name, const u8 *the_array, unsigned long size) for (i = 0, cur_byte = the_array; (i < size) && (line_offset < sizeof(line_buf)); i++, cur_byte++) { ret = snprintf(line_buf + line_offset, - sizeof(line_buf) - line_offset, - "0x%02X ", *cur_byte); + sizeof(line_buf) - line_offset, + "0x%02X ", *cur_byte); if (ret < 0) { SSI_LOG_ERR("snprintf returned %d . aborting buffer array dump\n", ret); return; @@ -193,11 +192,11 @@ int init_cc_regs(struct ssi_drvdata *drvdata, bool is_probe) #ifdef DX_IRQ_DELAY /* Set CC IRQ delay */ CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_IRQ_TIMER_INIT_VAL), - DX_IRQ_DELAY); + DX_IRQ_DELAY); #endif if (CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_IRQ_TIMER_INIT_VAL)) > 0) { SSI_LOG_DEBUG("irq_delay=%d CC cycles\n", - CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_IRQ_TIMER_INIT_VAL))); + CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_IRQ_TIMER_INIT_VAL))); } #endif @@ -252,9 +251,9 @@ static int init_cc_resources(struct platform_device *plat_dev) goto init_cc_res_err; } SSI_LOG_DEBUG("Got MEM resource (%s): start=0x%llX end=0x%llX\n", - new_drvdata->res_mem->name, - (unsigned long long)new_drvdata->res_mem->start, - (unsigned long long)new_drvdata->res_mem->end); + new_drvdata->res_mem->name, + (unsigned long long)new_drvdata->res_mem->start, + (unsigned long long)new_drvdata->res_mem->end); /* Map registers space */ req_mem_cc_regs = request_mem_region(new_drvdata->res_mem->start, resource_size(new_drvdata->res_mem), "arm_cc7x_regs"); if (unlikely(!req_mem_cc_regs)) { @@ -266,7 +265,8 @@ static int init_cc_resources(struct platform_device *plat_dev) cc_base = ioremap(new_drvdata->res_mem->start, resource_size(new_drvdata->res_mem)); if (unlikely(!cc_base)) { SSI_LOG_ERR("ioremap[CC](0x%08X,0x%08X) failed\n", - (unsigned int)new_drvdata->res_mem->start, (unsigned int)resource_size(new_drvdata->res_mem)); + (unsigned int)new_drvdata->res_mem->start, + (unsigned int)resource_size(new_drvdata->res_mem)); rc = -ENOMEM; goto init_cc_res_err; } @@ -284,15 +284,15 @@ static int init_cc_resources(struct platform_device *plat_dev) IRQF_SHARED, "arm_cc7x", new_drvdata); if (unlikely(rc != 0)) { SSI_LOG_ERR("Could not register to interrupt %llu\n", - (unsigned long long)new_drvdata->res_irq->start); + (unsigned long long)new_drvdata->res_irq->start); goto init_cc_res_err; } init_completion(&new_drvdata->icache_setup_completion); irq_registered = true; SSI_LOG_DEBUG("Registered to IRQ (%s) %llu\n", - new_drvdata->res_irq->name, - (unsigned long long)new_drvdata->res_irq->start); + new_drvdata->res_irq->name, + (unsigned long long)new_drvdata->res_irq->start); new_drvdata->plat_dev = plat_dev; @@ -310,7 +310,7 @@ static int init_cc_resources(struct platform_device *plat_dev) signature_val = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_SIGNATURE)); if (signature_val != DX_DEV_SIGNATURE) { SSI_LOG_ERR("Invalid CC signature: SIGNATURE=0x%08X != expected=0x%08X\n", - signature_val, (u32)DX_DEV_SIGNATURE); + signature_val, (u32)DX_DEV_SIGNATURE); rc = -EINVAL; goto init_cc_res_err; } @@ -431,7 +431,7 @@ init_cc_res_err: new_drvdata->cc_base = NULL; } release_mem_region(new_drvdata->res_mem->start, - resource_size(new_drvdata->res_mem)); + resource_size(new_drvdata->res_mem)); new_drvdata->res_mem = NULL; } kfree(new_drvdata); @@ -474,7 +474,7 @@ static void cleanup_cc_resources(struct platform_device *plat_dev) if (drvdata->cc_base) { iounmap(drvdata->cc_base); release_mem_region(drvdata->res_mem->start, - resource_size(drvdata->res_mem)); + resource_size(drvdata->res_mem)); drvdata->cc_base = NULL; drvdata->res_mem = NULL; } @@ -519,12 +519,12 @@ static int cc7x_probe(struct platform_device *plat_dev) asm volatile("mrc p15, 0, %0, c0, c0, 1" : "=r" (ctr)); cacheline_size = 4 << ((ctr >> 16) & 0xf); SSI_LOG_DEBUG("CP15(L1_CACHE_BYTES) = %u , Kconfig(L1_CACHE_BYTES) = %u\n", - cacheline_size, L1_CACHE_BYTES); + cacheline_size, L1_CACHE_BYTES); asm volatile("mrc p15, 0, %0, c0, c0, 0" : "=r" (ctr)); - SSI_LOG_DEBUG("Main ID register (MIDR): Implementer 0x%02X, Arch 0x%01X," - " Part 0x%03X, Rev r%dp%d\n", - (ctr >> 24), (ctr >> 16) & 0xF, (ctr >> 4) & 0xFFF, (ctr >> 20) & 0xF, ctr & 0xF); + SSI_LOG_DEBUG("Main ID register (MIDR): Implementer 0x%02X, Arch 0x%01X, Part 0x%03X, Rev r%dp%d\n", + (ctr >> 24), (ctr >> 16) & 0xF, (ctr >> 4) & 0xFFF, + (ctr >> 20) & 0xF, ctr & 0xF); #endif /* Map registers space */ -- cgit v1.2.3 From 9ac8a459de6d6e2b7167657f3e6ae815c5db72c3 Mon Sep 17 00:00:00 2001 From: Simon Sandström Date: Sun, 2 Jul 2017 01:25:52 +0200 Subject: staging: ccree: Fix alignment issues in ssi_ivgen.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes checkpatch.pl alignment warnings. Signed-off-by: Simon Sandström Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_ivgen.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_ivgen.c b/drivers/staging/ccree/ssi_ivgen.c index 5ff3368c04d9..0260fbd08be8 100644 --- a/drivers/staging/ccree/ssi_ivgen.c +++ b/drivers/staging/ccree/ssi_ivgen.c @@ -166,7 +166,8 @@ void ssi_ivgen_fini(struct ssi_drvdata *drvdata) if (ivgen_ctx->pool_meta) { memset(ivgen_ctx->pool_meta, 0, SSI_IVPOOL_META_SIZE); dma_free_coherent(device, SSI_IVPOOL_META_SIZE, - ivgen_ctx->pool_meta, ivgen_ctx->pool_meta_dma); + ivgen_ctx->pool_meta, + ivgen_ctx->pool_meta_dma); } ivgen_ctx->pool = NULL_SRAM_ADDR; -- cgit v1.2.3 From db9cbea44b47129e74a71b2bf1905952950d618a Mon Sep 17 00:00:00 2001 From: Simon Sandström Date: Sun, 2 Jul 2017 01:25:53 +0200 Subject: staging: ccree: Fix alignment issues in ssi_request_mgr.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes checkpatch.pl alignment warnings. Signed-off-by: Simon Sandström Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_request_mgr.c | 42 ++++++++++++++++----------------- 1 file changed, 20 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_request_mgr.c b/drivers/staging/ccree/ssi_request_mgr.c index f40dff2762f9..3d6020a57be1 100644 --- a/drivers/staging/ccree/ssi_request_mgr.c +++ b/drivers/staging/ccree/ssi_request_mgr.c @@ -127,7 +127,7 @@ int request_mgr_init(struct ssi_drvdata *drvdata) SSI_LOG_DEBUG("hw_queue_size=0x%08X\n", req_mgr_h->hw_queue_size); if (req_mgr_h->hw_queue_size < MIN_HW_QUEUE_SIZE) { SSI_LOG_ERR("Invalid HW queue size = %u (Min. required is %u)\n", - req_mgr_h->hw_queue_size, MIN_HW_QUEUE_SIZE); + req_mgr_h->hw_queue_size, MIN_HW_QUEUE_SIZE); rc = -ENOMEM; goto req_mgr_init_err; } @@ -175,7 +175,8 @@ static inline void enqueue_seq( writel_relaxed(seq[i].word[5], (volatile void __iomem *)(cc_base + CC_REG_OFFSET(CRY_KERNEL, DSCRPTR_QUEUE_WORD0))); #ifdef DX_DUMP_DESCS SSI_LOG_DEBUG("desc[%02d]: 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X\n", i, - seq[i].word[0], seq[i].word[1], seq[i].word[2], seq[i].word[3], seq[i].word[4], seq[i].word[5]); + seq[i].word[0], seq[i].word[1], seq[i].word[2], + seq[i].word[3], seq[i].word[4], seq[i].word[5]); #endif } } @@ -209,7 +210,7 @@ static inline int request_mgr_queues_status_check( (MAX_REQUEST_QUEUE_SIZE - 1)) == req_mgr_h->req_queue_tail)) { SSI_LOG_ERR("SW FIFO is full. req_queue_head=%d sw_fifo_len=%d\n", - req_mgr_h->req_queue_head, MAX_REQUEST_QUEUE_SIZE); + req_mgr_h->req_queue_head, MAX_REQUEST_QUEUE_SIZE); return -EBUSY; } @@ -219,9 +220,8 @@ static inline int request_mgr_queues_status_check( /* Wait for space in HW queue. Poll constant num of iterations. */ for (poll_queue = 0; poll_queue < SSI_MAX_POLL_ITER ; poll_queue++) { req_mgr_h->q_free_slots = - CC_HAL_READ_REGISTER( - CC_REG_OFFSET(CRY_KERNEL, - DSCRPTR_QUEUE_CONTENT)); + CC_HAL_READ_REGISTER(CC_REG_OFFSET(CRY_KERNEL, + DSCRPTR_QUEUE_CONTENT)); if (unlikely(req_mgr_h->q_free_slots < req_mgr_h->min_free_hw_slots)) { req_mgr_h->min_free_hw_slots = req_mgr_h->q_free_slots; @@ -233,7 +233,7 @@ static inline int request_mgr_queues_status_check( } SSI_LOG_DEBUG("HW FIFO is full. q_free_slots=%d total_seq_len=%d\n", - req_mgr_h->q_free_slots, total_seq_len); + req_mgr_h->q_free_slots, total_seq_len); } /* No room in the HW queue try again later */ SSI_LOG_DEBUG("HW FIFO full, timeout. req_queue_head=%d " @@ -289,9 +289,8 @@ int send_request( * in case iv gen add the max size and in case of no dout add 1 * for the internal completion descriptor */ - rc = request_mgr_queues_status_check(req_mgr_h, - cc_base, - max_required_seq_len); + rc = request_mgr_queues_status_check(req_mgr_h, cc_base, + max_required_seq_len); if (likely(rc == 0)) /* There is enough place in the queue */ break; @@ -324,15 +323,16 @@ int send_request( if (ssi_req->ivgen_dma_addr_len > 0) { SSI_LOG_DEBUG("Acquire IV from pool into %d DMA addresses 0x%llX, 0x%llX, 0x%llX, IV-size=%u\n", - ssi_req->ivgen_dma_addr_len, - (unsigned long long)ssi_req->ivgen_dma_addr[0], - (unsigned long long)ssi_req->ivgen_dma_addr[1], - (unsigned long long)ssi_req->ivgen_dma_addr[2], - ssi_req->ivgen_size); + ssi_req->ivgen_dma_addr_len, + (unsigned long long)ssi_req->ivgen_dma_addr[0], + (unsigned long long)ssi_req->ivgen_dma_addr[1], + (unsigned long long)ssi_req->ivgen_dma_addr[2], + ssi_req->ivgen_size); /* Acquire IV from pool */ - rc = ssi_ivgen_getiv(drvdata, ssi_req->ivgen_dma_addr, ssi_req->ivgen_dma_addr_len, - ssi_req->ivgen_size, iv_seq, &iv_seq_len); + rc = ssi_ivgen_getiv(drvdata, ssi_req->ivgen_dma_addr, + ssi_req->ivgen_dma_addr_len, + ssi_req->ivgen_size, iv_seq, &iv_seq_len); if (unlikely(rc != 0)) { SSI_LOG_ERR("Failed to generate IV (rc=%d)\n", rc); @@ -416,9 +416,8 @@ int send_request_init( enqueue_seq(cc_base, desc, len); /* Update the free slots in HW queue */ - req_mgr_h->q_free_slots = CC_HAL_READ_REGISTER( - CC_REG_OFFSET(CRY_KERNEL, - DSCRPTR_QUEUE_CONTENT)); + req_mgr_h->q_free_slots = CC_HAL_READ_REGISTER(CC_REG_OFFSET(CRY_KERNEL, + DSCRPTR_QUEUE_CONTENT)); return 0; } @@ -543,8 +542,7 @@ static void comp_handler(unsigned long devarg) } /* after verifing that there is nothing to do, Unmask AXI completion interrupt */ CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_IMR), - CC_HAL_READ_REGISTER( - CC_REG_OFFSET(HOST_RGF, HOST_IMR)) & ~irq); + CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_IMR)) & ~irq); } /* -- cgit v1.2.3 From 5c6ffda0dd2a47c5b3b073b551077a8f1cc86971 Mon Sep 17 00:00:00 2001 From: Simon Sandström Date: Sun, 2 Jul 2017 01:25:54 +0200 Subject: staging: ccree: Fix alignment issues in ssi_sram_mgr.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes checkpatch.pl alignment warnings. Signed-off-by: Simon Sandström Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_sram_mgr.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_sram_mgr.c b/drivers/staging/ccree/ssi_sram_mgr.c index e05c0c13c2eb..f11116afe89a 100644 --- a/drivers/staging/ccree/ssi_sram_mgr.c +++ b/drivers/staging/ccree/ssi_sram_mgr.c @@ -58,7 +58,7 @@ int ssi_sram_mgr_init(struct ssi_drvdata *drvdata) sizeof(struct ssi_sram_mgr_ctx), GFP_KERNEL); if (!drvdata->sram_mgr_handle) { SSI_LOG_ERR("Not enough memory to allocate SRAM_MGR ctx (%zu)\n", - sizeof(struct ssi_sram_mgr_ctx)); + sizeof(struct ssi_sram_mgr_ctx)); rc = -ENOMEM; goto out; } @@ -90,12 +90,12 @@ ssi_sram_addr_t ssi_sram_mgr_alloc(struct ssi_drvdata *drvdata, u32 size) if (unlikely((size & 0x3) != 0)) { SSI_LOG_ERR("Requested buffer size (%u) is not multiple of 4", - size); + size); return NULL_SRAM_ADDR; } if (unlikely(size > (SSI_CC_SRAM_SIZE - smgr_ctx->sram_free_offset))) { SSI_LOG_ERR("Not enough space to allocate %u B (at offset %llu)\n", - size, smgr_ctx->sram_free_offset); + size, smgr_ctx->sram_free_offset); return NULL_SRAM_ADDR; } -- cgit v1.2.3 From 55c0698a2c156fa27f04c6d602b43dca1ce9283e Mon Sep 17 00:00:00 2001 From: Simon Sandström Date: Sun, 2 Jul 2017 01:25:55 +0200 Subject: staging: ccree: Fix alignment issues in ssi_sysfs.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes checkpatch.pl alignment warnings. Signed-off-by: Simon Sandström Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_sysfs.c | 59 ++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_sysfs.c b/drivers/staging/ccree/ssi_sysfs.c index 07b634c84787..28a46c7be41c 100644 --- a/drivers/staging/ccree/ssi_sysfs.c +++ b/drivers/staging/ccree/ssi_sysfs.c @@ -143,8 +143,12 @@ static void display_db(struct stat_item item[MAX_STAT_OP_TYPES][MAX_STAT_PHASES] avg = (u64)item[i][j].sum; do_div(avg, item[i][j].count); SSI_LOG_ERR("%s, %s: min=%d avg=%d max=%d sum=%lld count=%d\n", - stat_name_db[i].op_type_name, stat_name_db[i].stat_phase_name[j], - item[i][j].min, (int)avg, item[i][j].max, (long long)item[i][j].sum, item[i][j].count); + stat_name_db[i].op_type_name, + stat_name_db[i].stat_phase_name[j], + item[i][j].min, (int)avg, + item[i][j].max, + (long long)item[i][j].sum, + item[i][j].count); } } } @@ -155,21 +159,23 @@ static void display_db(struct stat_item item[MAX_STAT_OP_TYPES][MAX_STAT_PHASES] **************************************/ static ssize_t ssi_sys_stats_host_db_clear(struct kobject *kobj, - struct kobj_attribute *attr, const char *buf, size_t count) + struct kobj_attribute *attr, + const char *buf, size_t count) { init_db(stat_host_db); return count; } static ssize_t ssi_sys_stats_cc_db_clear(struct kobject *kobj, - struct kobj_attribute *attr, const char *buf, size_t count) + struct kobj_attribute *attr, + const char *buf, size_t count) { init_db(stat_cc_db); return count; } static ssize_t ssi_sys_stat_host_db_show(struct kobject *kobj, - struct kobj_attribute *attr, char *buf) + struct kobj_attribute *attr, char *buf) { int i, j; char line[512]; @@ -178,7 +184,7 @@ static ssize_t ssi_sys_stat_host_db_show(struct kobject *kobj, ssize_t buf_len, tmp_len = 0; buf_len = scnprintf(buf, PAGE_SIZE, - "phase\t\t\t\t\t\t\tmin[cy]\tavg[cy]\tmax[cy]\t#samples\n"); + "phase\t\t\t\t\t\t\tmin[cy]\tavg[cy]\tmax[cy]\t#samples\n"); if (buf_len < 0)/* scnprintf shouldn't return negative value according to its implementation*/ return buf_len; for (i = STAT_OP_TYPE_ENCODE; i < MAX_STAT_OP_TYPES; i++) { @@ -192,11 +198,11 @@ static ssize_t ssi_sys_stat_host_db_show(struct kobject *kobj, avg = min_cyc = max_cyc = 0; } tmp_len = scnprintf(line, 512, - "%s::%s\t\t\t\t\t%6u\t%6u\t%6u\t%7u\n", - stat_name_db[i].op_type_name, - stat_name_db[i].stat_phase_name[j], - min_cyc, (unsigned int)avg, max_cyc, - stat_host_db[i][j].count); + "%s::%s\t\t\t\t\t%6u\t%6u\t%6u\t%7u\n", + stat_name_db[i].op_type_name, + stat_name_db[i].stat_phase_name[j], + min_cyc, (unsigned int)avg, max_cyc, + stat_host_db[i][j].count); if (tmp_len < 0)/* scnprintf shouldn't return negative value according to its implementation*/ return buf_len; if (buf_len + tmp_len >= PAGE_SIZE) @@ -209,7 +215,7 @@ static ssize_t ssi_sys_stat_host_db_show(struct kobject *kobj, } static ssize_t ssi_sys_stat_cc_db_show(struct kobject *kobj, - struct kobj_attribute *attr, char *buf) + struct kobj_attribute *attr, char *buf) { int i; char line[256]; @@ -218,7 +224,7 @@ static ssize_t ssi_sys_stat_cc_db_show(struct kobject *kobj, ssize_t buf_len, tmp_len = 0; buf_len = scnprintf(buf, PAGE_SIZE, - "phase\tmin[cy]\tavg[cy]\tmax[cy]\t#samples\n"); + "phase\tmin[cy]\tavg[cy]\tmax[cy]\t#samples\n"); if (buf_len < 0)/* scnprintf shouldn't return negative value according to its implementation*/ return buf_len; for (i = STAT_OP_TYPE_ENCODE; i < MAX_STAT_OP_TYPES; i++) { @@ -230,13 +236,10 @@ static ssize_t ssi_sys_stat_cc_db_show(struct kobject *kobj, } else { avg = min_cyc = max_cyc = 0; } - tmp_len = scnprintf(line, 256, - "%s\t%6u\t%6u\t%6u\t%7u\n", - stat_name_db[i].op_type_name, - min_cyc, - (unsigned int)avg, - max_cyc, - stat_cc_db[i][STAT_PHASE_6].count); + tmp_len = scnprintf(line, 256, "%s\t%6u\t%6u\t%6u\t%7u\n", + stat_name_db[i].op_type_name, min_cyc, + (unsigned int)avg, max_cyc, + stat_cc_db[i][STAT_PHASE_6].count); if (tmp_len < 0)/* scnprintf shouldn't return negative value according to its implementation*/ return buf_len; @@ -276,7 +279,7 @@ void display_all_stat_db(void) #endif /*CC_CYCLE_COUNT*/ static ssize_t ssi_sys_regdump_show(struct kobject *kobj, - struct kobj_attribute *attr, char *buf) + struct kobj_attribute *attr, char *buf) { struct ssi_drvdata *drvdata = sys_get_drvdata(); u32 register_value; @@ -297,7 +300,7 @@ static ssize_t ssi_sys_regdump_show(struct kobject *kobj, } static ssize_t ssi_sys_help_show(struct kobject *kobj, - struct kobj_attribute *attr, char *buf) + struct kobj_attribute *attr, char *buf) { char *help_str[] = { "cat reg_dump ", "Print several of CC register values", @@ -356,8 +359,8 @@ static struct ssi_drvdata *sys_get_drvdata(void) } static int sys_init_dir(struct sys_dir *sys_dir, struct ssi_drvdata *drvdata, - struct kobject *parent_dir_kobj, const char *dir_name, - struct kobj_attribute *attrs, u32 num_of_attrs) + struct kobject *parent_dir_kobj, const char *dir_name, + struct kobj_attribute *attrs, u32 num_of_attrs) { int i; @@ -374,7 +377,7 @@ static int sys_init_dir(struct sys_dir *sys_dir, struct ssi_drvdata *drvdata, /* allocate memory for directory's attributes list */ sys_dir->sys_dir_attr_list = kzalloc(sizeof(struct attribute *) * (num_of_attrs + 1), - GFP_KERNEL); + GFP_KERNEL); if (!(sys_dir->sys_dir_attr_list)) { kobject_put(sys_dir->sys_dir_kobj); @@ -420,9 +423,9 @@ int ssi_sysfs_init(struct kobject *sys_dev_obj, struct ssi_drvdata *drvdata) SSI_LOG_ERR("setup sysfs under %s\n", sys_dev_obj->name); /* Initialize top directory */ - retval = sys_init_dir(&sys_top_dir, drvdata, sys_dev_obj, - "cc_info", ssi_sys_top_level_attrs, - ARRAY_SIZE(ssi_sys_top_level_attrs)); + retval = sys_init_dir(&sys_top_dir, drvdata, sys_dev_obj, "cc_info", + ssi_sys_top_level_attrs, + ARRAY_SIZE(ssi_sys_top_level_attrs)); return retval; } -- cgit v1.2.3 From d4e25108bb20e0294f7e8bcd478a8ff20e5b269f Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 29 Jun 2017 08:42:00 -0700 Subject: staging: wilc1000: Neaten refresh_scan - remove always 1 argument All uses of refresh_scan() have a constant 1 as the second argument. Remove it and neaten the function declaration. Miscellanea: o Remove overly deep indentation by using continue; o Remove unnecessary test of the address of a static array as it's always non-zero o Rename and use proper type for the first void * argument as it's always the struct wilc_priv * o Move variables into loop where used Signed-off-by: Joe Perches Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 65 ++++++++++------------- 1 file changed, 28 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 68fd5b3b8b2d..ac5aaafa461c 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -214,48 +214,39 @@ static u32 get_rssi_avg(struct network_info *network_info) return rssi_v; } -static void refresh_scan(void *user_void, u8 all, bool direct_scan) +static void refresh_scan(struct wilc_priv *priv, bool direct_scan) { - struct wilc_priv *priv; - struct wiphy *wiphy; - struct cfg80211_bss *bss = NULL; + struct wiphy *wiphy = priv->dev->ieee80211_ptr->wiphy; int i; - int rssi = 0; - - priv = user_void; - wiphy = priv->dev->ieee80211_ptr->wiphy; for (i = 0; i < last_scanned_cnt; i++) { struct network_info *network_info; + s32 freq; + struct ieee80211_channel *channel; + int rssi; + struct cfg80211_bss *bss; network_info = &last_scanned_shadow[i]; - if (!network_info->found || all) { - s32 freq; - struct ieee80211_channel *channel; - - if (network_info) { - freq = ieee80211_channel_to_frequency((s32)network_info->ch, NL80211_BAND_2GHZ); - channel = ieee80211_get_channel(wiphy, freq); - - rssi = get_rssi_avg(network_info); - if (memcmp("DIRECT-", network_info->ssid, 7) || - direct_scan) { - bss = cfg80211_inform_bss(wiphy, - channel, - CFG80211_BSS_FTYPE_UNKNOWN, - network_info->bssid, - network_info->tsf_hi, - network_info->cap_info, - network_info->beacon_period, - (const u8 *)network_info->ies, - (size_t)network_info->ies_len, - (s32)rssi * 100, - GFP_KERNEL); - cfg80211_put_bss(wiphy, bss); - } - } - } + if (!memcmp("DIRECT-", network_info->ssid, 7) && !direct_scan) + continue; + + freq = ieee80211_channel_to_frequency((s32)network_info->ch, + NL80211_BAND_2GHZ); + channel = ieee80211_get_channel(wiphy, freq); + rssi = get_rssi_avg(network_info); + bss = cfg80211_inform_bss(wiphy, + channel, + CFG80211_BSS_FTYPE_UNKNOWN, + network_info->bssid, + network_info->tsf_hi, + network_info->cap_info, + network_info->beacon_period, + (const u8 *)network_info->ies, + (size_t)network_info->ies_len, + (s32)rssi * 100, + GFP_KERNEL); + cfg80211_put_bss(wiphy, bss); } } @@ -442,7 +433,7 @@ static void CfgScanResult(enum scan_event scan_event, } } } else if (scan_event == SCAN_EVENT_DONE) { - refresh_scan(priv, 1, false); + refresh_scan(priv, false); mutex_lock(&priv->scan_req_lock); @@ -466,7 +457,7 @@ static void CfgScanResult(enum scan_event scan_event, }; update_scan_time(); - refresh_scan(priv, 1, false); + refresh_scan(priv, false); cfg80211_scan_done(priv->pstrScanReq, &info); priv->bCfgScanning = false; @@ -540,7 +531,7 @@ static void CfgConnectResult(enum conn_event enuConnDisconnEvent, } if (bNeedScanRefresh) - refresh_scan(priv, 1, true); + refresh_scan(priv, true); } cfg80211_connect_result(dev, pstrConnectInfo->bssid, -- cgit v1.2.3 From a511a358fd48fc8ce5af750aad41426ca628ef29 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 30 Jun 2017 11:46:40 +0100 Subject: staging: wilc1000: fix a typo: "incative" -> "inactive" Trivial fix to typos in netdev_err error messages. I should have spotted this in a previous round of spelling mistake checks on this driver but this one slipped through. Signed-off-by: Colin Ian King Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 2568dfc15181..7b620658ec38 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -1963,7 +1963,7 @@ static s32 Handle_Get_InActiveTime(struct wilc_vif *vif, wilc_get_vif_idx(vif)); if (result) { - netdev_err(vif->ndev, "Failed to SET incative time\n"); + netdev_err(vif->ndev, "Failed to SET inactive time\n"); return -EFAULT; } @@ -1976,7 +1976,7 @@ static s32 Handle_Get_InActiveTime(struct wilc_vif *vif, wilc_get_vif_idx(vif)); if (result) { - netdev_err(vif->ndev, "Failed to get incative time\n"); + netdev_err(vif->ndev, "Failed to get inactive time\n"); return -EFAULT; } -- cgit v1.2.3 From 4c7be5583ded518a024d3d0ab1f3a423102294b0 Mon Sep 17 00:00:00 2001 From: Dmitriy Cherkasov Date: Sat, 8 Jul 2017 15:44:47 -0700 Subject: staging: wilc1000: add parameter name to function definition Add missing parameter name to fix the following checkpatch.pl warning: WARNING: function definition argument 'struct device *' should also have an identifier name Signed-off-by: Dmitriy Cherkasov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wfi_netdevice.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index c89bf4301096..7a36561a599e 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -227,8 +227,8 @@ int wilc1000_wlan_init(struct net_device *dev, struct wilc_vif *vif); void wilc_frmw_to_linux(struct wilc *wilc, u8 *buff, u32 size, u32 pkt_offset); void wilc_mac_indicate(struct wilc *wilc, int flag); void wilc_netdev_cleanup(struct wilc *wilc); -int wilc_netdev_init(struct wilc **wilc, struct device *, int io_type, int gpio, - const struct wilc_hif_func *ops); +int wilc_netdev_init(struct wilc **wilc, struct device *dev, int io_type, + int gpio, const struct wilc_hif_func *ops); void wilc1000_wlan_deinit(struct net_device *dev); void WILC_WFI_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size); int wilc_wlan_get_firmware(struct net_device *dev); -- cgit v1.2.3 From 8a88dd46c87bef398fce43b8bba581c0ac5146b2 Mon Sep 17 00:00:00 2001 From: Ilia Sergachev Date: Sun, 9 Jul 2017 23:36:35 +0200 Subject: staging: wilc1000: fix variable signedness txq_count receives a value from wilc_wlan_handle_txq() and therefore should be u32 found using sparse: drivers/staging/wilc1000/linux_wlan.c:306:58: warning: incorrect type in argument 2 (different signedness) Signed-off-by: Ilia Sergachev Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index dbb3e24615be..1266dcccad30 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -283,7 +283,8 @@ int wilc_wlan_get_num_conn_ifcs(struct wilc *wilc) static int linux_wlan_txq_task(void *vp) { - int ret, txq_count; + int ret; + u32 txq_count; struct wilc_vif *vif; struct wilc *wl; struct net_device *dev = vp; -- cgit v1.2.3 From ac9735b9934efa5a7146671360663548b5427a75 Mon Sep 17 00:00:00 2001 From: Aleksey Rybalkin Date: Mon, 3 Jul 2017 23:27:15 +0500 Subject: staging: greybus: loopback_test: fix comment style issues According to checkpatch warning, block comments should align the * on each line. Also, preferred style for multi-line comments is starting the comment text after the second *. Signed-off-by: Aleksey Rybalkin Acked-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/tools/loopback_test.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/greybus/tools/loopback_test.c b/drivers/staging/greybus/tools/loopback_test.c index 32a43693181c..d86bcce53e6b 100644 --- a/drivers/staging/greybus/tools/loopback_test.c +++ b/drivers/staging/greybus/tools/loopback_test.c @@ -528,11 +528,11 @@ static int log_results(struct loopback_test *t) tm = *localtime(&local_time); /* - * file name will test_name_size_iteration_max.csv - * every time the same test with the same parameters is run we will then - * append to the same CSV with datestamp - representing each test - * dataset. - */ + * file name will test_name_size_iteration_max.csv + * every time the same test with the same parameters is run we will then + * append to the same CSV with datestamp - representing each test + * dataset. + */ if (t->file_output && !t->porcelain) { snprintf(file_name, sizeof(file_name), "%s_%d_%d.csv", t->test_name, t->size, t->iteration_max); @@ -779,7 +779,8 @@ static void prepare_devices(struct loopback_test *t) { int i; - /* Cancel any running tests on enabled devices. If + /* + * Cancel any running tests on enabled devices. If * stop_all option is given, stop test on all devices. */ for (i = 0; i < t->device_count; i++) -- cgit v1.2.3 From bf766625aed67ce2b97e6e86d49260cc72e688b0 Mon Sep 17 00:00:00 2001 From: Mitchell Tasman Date: Mon, 10 Jul 2017 23:14:44 -0400 Subject: staging: greybus: arche: wrap over-length lines Adjust formatting of several comments to keep line length within the 80 column limit preferred by the Linux kernel coding style. Signed-off-by: Mitchell Tasman Acked-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/arche-platform.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index eced2d26467b..625990400fa9 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -176,7 +176,10 @@ static irqreturn_t arche_platform_wd_irq(int irq, void *devid) arche_platform_set_wake_detect_state(arche_pdata, WD_STATE_IDLE); } else { - /* Check we are not in middle of irq thread already */ + /* + * Check we are not in middle of irq thread + * already + */ if (arche_pdata->wake_detect_state != WD_STATE_COLDBOOT_START) { arche_platform_set_wake_detect_state(arche_pdata, @@ -657,12 +660,14 @@ static SIMPLE_DEV_PM_OPS(arche_platform_pm_ops, arche_platform_resume); static const struct of_device_id arche_platform_of_match[] = { - { .compatible = "google,arche-platform", }, /* Use PID/VID of SVC device */ + /* Use PID/VID of SVC device */ + { .compatible = "google,arche-platform", }, { }, }; static const struct of_device_id arche_combined_id[] = { - { .compatible = "google,arche-platform", }, /* Use PID/VID of SVC device */ + /* Use PID/VID of SVC device */ + { .compatible = "google,arche-platform", }, { .compatible = "usbffff,2", }, { }, }; -- cgit v1.2.3 From 1e1858cb60b22b7f9a1dc67c741c569bae65ec3f Mon Sep 17 00:00:00 2001 From: Arushi Singhal Date: Fri, 7 Jul 2017 11:11:36 +0530 Subject: staging: rtl8712: fix "Alignment match open parenthesis" Fix checkpatch issues: "CHECK: Alignment should match open parenthesis". Signed-off-by: Arushi Singhal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/mlme_linux.c | 4 ++-- drivers/staging/rtl8712/rtl8712_cmd.c | 2 +- drivers/staging/rtl8712/rtl8712_efuse.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8712/mlme_linux.c b/drivers/staging/rtl8712/mlme_linux.c index 20372659d15d..a077069d6227 100644 --- a/drivers/staging/rtl8712/mlme_linux.c +++ b/drivers/staging/rtl8712/mlme_linux.c @@ -111,8 +111,8 @@ void r8712_os_indicate_disconnect(struct _adapter *adapter) */ memcpy(&backupPMKIDList[0], - &adapter->securitypriv.PMKIDList[0], - sizeof(struct RT_PMKID_LIST) * NUM_PMKID_CACHE); + &adapter->securitypriv.PMKIDList[0], + sizeof(struct RT_PMKID_LIST) * NUM_PMKID_CACHE); backupPMKIDIndex = adapter->securitypriv.PMKIDIndex; backupTKIPCountermeasure = adapter->securitypriv.btkip_countermeasure; diff --git a/drivers/staging/rtl8712/rtl8712_cmd.c b/drivers/staging/rtl8712/rtl8712_cmd.c index 5346c657485d..0104aced113e 100644 --- a/drivers/staging/rtl8712/rtl8712_cmd.c +++ b/drivers/staging/rtl8712/rtl8712_cmd.c @@ -385,7 +385,7 @@ _next: if (blnPending) wr_sz += 8; /* Append 8 bytes */ r8712_write_mem(padapter, RTL8712_DMA_H2CCMD, wr_sz, - (u8 *)pdesc); + (u8 *)pdesc); pcmdpriv->cmd_seq++; if (pcmd->cmdcode == GEN_CMD_CODE(_CreateBss)) { pcmd->res = H2C_SUCCESS; diff --git a/drivers/staging/rtl8712/rtl8712_efuse.c b/drivers/staging/rtl8712/rtl8712_efuse.c index 205298e23656..d90213eb5e20 100644 --- a/drivers/staging/rtl8712/rtl8712_efuse.c +++ b/drivers/staging/rtl8712/rtl8712_efuse.c @@ -347,7 +347,7 @@ static u8 fix_header(struct _adapter *padapter, u8 header, u16 header_addr) ret = false; if (value == 0xFF) /* write again */ efuse_one_byte_write(padapter, addr, - pkt.data[i * 2]); + pkt.data[i * 2]); } if (!efuse_one_byte_read(padapter, addr + 1, &value)) { ret = false; -- cgit v1.2.3 From 97c2d79ae014fc5fcfdc867dc309e06c31006fae Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani Date: Fri, 7 Jul 2017 15:40:39 +0530 Subject: staging: rtl8712: Remove explicit NULL comparison Replace the explicit "if (val != NULL)" with if (val). Signed-off-by: Muhammad Falak R Wani Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_xmit.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8712/rtl8712_xmit.c b/drivers/staging/rtl8712/rtl8712_xmit.c index 7fe626583c8a..42d014007764 100644 --- a/drivers/staging/rtl8712/rtl8712_xmit.c +++ b/drivers/staging/rtl8712/rtl8712_xmit.c @@ -640,7 +640,7 @@ int r8712_xmitframe_complete(struct _adapter *padapter, /* 1st frame dequeued */ pxmitframe = dequeue_xframe_ex(pxmitpriv, phwxmits, hwentry); /* need to remember the 1st frame */ - if (pxmitframe != NULL) { + if (pxmitframe) { #ifdef CONFIG_R8712_TX_AGGR /* 1. dequeue 2nd frame @@ -653,13 +653,13 @@ int r8712_xmitframe_complete(struct _adapter *padapter, r8712_free_xmitbuf(pxmitpriv, pxmitbuf); return false; } - if (p2ndxmitframe != NULL) + if (p2ndxmitframe) if (p2ndxmitframe->frame_tag != DATA_FRAMETAG) { r8712_free_xmitbuf(pxmitpriv, pxmitbuf); return false; } r8712_xmitframe_aggr_1st(pxmitbuf, pxmitframe); - if (p2ndxmitframe != NULL) { + if (p2ndxmitframe) { u16 total_length; total_length = r8712_xmitframe_aggr_next( @@ -667,7 +667,7 @@ int r8712_xmitframe_complete(struct _adapter *padapter, do { p2ndxmitframe = dequeue_xframe_ex( pxmitpriv, phwxmits, hwentry); - if (p2ndxmitframe != NULL) + if (p2ndxmitframe) total_length = r8712_xmitframe_aggr_next( pxmitbuf, -- cgit v1.2.3 From 948d704855312ca1c5533a0bc39ac0783f90beb9 Mon Sep 17 00:00:00 2001 From: Shreeya Patel Date: Sun, 9 Jul 2017 01:28:25 +0530 Subject: staging: rtl8723bs: Place constant at the right. Move constant to the right of a relational operator. This coding style is more common for the kernel code. Problem found by checkpatch. Signed-off-by: Shreeya Patel Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/core/rtw_btcoex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8723bs/core/rtw_btcoex.c b/drivers/staging/rtl8723bs/core/rtw_btcoex.c index 3c5cb78b52ea..01f78d1671de 100644 --- a/drivers/staging/rtl8723bs/core/rtw_btcoex.c +++ b/drivers/staging/rtl8723bs/core/rtw_btcoex.c @@ -55,7 +55,7 @@ void rtw_btcoex_ConnectNotify(struct adapter *padapter, u8 action) void rtw_btcoex_MediaStatusNotify(struct adapter *padapter, u8 mediaStatus) { - if ((RT_MEDIA_CONNECT == mediaStatus) + if ((mediaStatus == RT_MEDIA_CONNECT) && (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == true)) { rtw_hal_set_hwreg(padapter, HW_VAR_DL_RSVD_PAGE, NULL); } -- cgit v1.2.3 From cbe5843e7624b6a468d74faccffec57b5c73200b Mon Sep 17 00:00:00 2001 From: Thomas Gardner Date: Fri, 7 Jul 2017 10:24:32 +1000 Subject: staging: typec: Fix endianness warning discovered by sparse The below warning is resolved by removing the cpu_to_le32() call. This call was redundant; vdm_run_state_machine() ensures that SVDM responses have the correct endianness before sending. typec/tcpm.c:1019:49: warning: incorrect type in assignment (different base types) typec/tcpm.c:1019:49: expected unsigned int [unsigned] [usertype] typec/tcpm.c:1019:49: got restricted __le32 [usertype] Signed-off-by: Thomas Gardner Reviewed-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- drivers/staging/typec/tcpm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/typec/tcpm.c b/drivers/staging/typec/tcpm.c index 20eb4ebcf8c3..2195c80235a1 100644 --- a/drivers/staging/typec/tcpm.c +++ b/drivers/staging/typec/tcpm.c @@ -1015,8 +1015,7 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt, if (port->data_role == TYPEC_DEVICE && port->nr_snk_vdo) { for (i = 0; i < port->nr_snk_vdo; i++) - response[i + 1] - = cpu_to_le32(port->snk_vdo[i]); + response[i + 1] = port->snk_vdo[i]; rlen = port->nr_snk_vdo + 1; } break; -- cgit v1.2.3 From 0805a0c0e0cb99db7df2a3099966dae319c8ee29 Mon Sep 17 00:00:00 2001 From: Dmitriy Cherkasov Date: Fri, 7 Jul 2017 16:03:42 -0700 Subject: staging: lustre: lnet: remove dead code and useless wrapper After removing commented out code, ksocknal_csum() becomes a useless wrapper for crc32_le(). Remove it, and instead call crc32_le() directly. Fixes the following checkpatch warning: WARNING: space prohibited before semicolon Signed-off-by: Dmitriy Cherkasov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h | 11 ----------- .../staging/lustre/lnet/klnds/socklnd/socklnd_lib.c | 20 ++++++++++---------- 2 files changed, 10 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h index 5540de65f9a2..9eb169da2c2f 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h @@ -519,17 +519,6 @@ extern struct ksock_proto ksocknal_protocol_v3x; #define CPU_MASK_NONE 0UL #endif -static inline __u32 ksocknal_csum(__u32 crc, unsigned char const *p, size_t len) -{ -#if 1 - return crc32_le(crc, p, len); -#else - while (len-- > 0) - crc = ((crc + 0x100) & ~0xff) | ((crc + *p++) & 0xff) ; - return crc; -#endif -} - static inline int ksocknal_route_mask(void) { diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c index 8a036f4eb8d8..9c328dc6537b 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c @@ -201,9 +201,9 @@ ksocknal_lib_recv_iov(struct ksock_conn *conn) if (fragnob > sum) fragnob = sum; - conn->ksnc_rx_csum = ksocknal_csum(conn->ksnc_rx_csum, - iov[i].iov_base, - fragnob); + conn->ksnc_rx_csum = crc32_le(conn->ksnc_rx_csum, + iov[i].iov_base, + fragnob); } conn->ksnc_msg.ksm_csum = saved_csum; } @@ -243,8 +243,8 @@ ksocknal_lib_recv_kiov(struct ksock_conn *conn) if (fragnob > sum) fragnob = sum; - conn->ksnc_rx_csum = ksocknal_csum(conn->ksnc_rx_csum, - base, fragnob); + conn->ksnc_rx_csum = crc32_le(conn->ksnc_rx_csum, + base, fragnob); kunmap(kiov[i].bv_page); } @@ -265,22 +265,22 @@ ksocknal_lib_csum_tx(struct ksock_tx *tx) tx->tx_msg.ksm_csum = 0; - csum = ksocknal_csum(~0, tx->tx_iov[0].iov_base, - tx->tx_iov[0].iov_len); + csum = crc32_le(~0, tx->tx_iov[0].iov_base, + tx->tx_iov[0].iov_len); if (tx->tx_kiov) { for (i = 0; i < tx->tx_nkiov; i++) { base = kmap(tx->tx_kiov[i].bv_page) + tx->tx_kiov[i].bv_offset; - csum = ksocknal_csum(csum, base, tx->tx_kiov[i].bv_len); + csum = crc32_le(csum, base, tx->tx_kiov[i].bv_len); kunmap(tx->tx_kiov[i].bv_page); } } else { for (i = 1; i < tx->tx_niov; i++) - csum = ksocknal_csum(csum, tx->tx_iov[i].iov_base, - tx->tx_iov[i].iov_len); + csum = crc32_le(csum, tx->tx_iov[i].iov_base, + tx->tx_iov[i].iov_len); } if (*ksocknal_tunables.ksnd_inject_csum_error) { -- cgit v1.2.3 From fd3074867f906aeaa44c9ce22c11ac73718e9089 Mon Sep 17 00:00:00 2001 From: Sameer Wadgaonkar Date: Fri, 30 Jun 2017 15:43:02 -0400 Subject: staging: unisys: visorbus: controlvmchannel.h: fixed comment formatting issues Removed comments from the right side of lines and fixed spacing in comments. Added kernel-doc like comments and cleaned up the inline comments in the structures. Signed-off-by: Sameer Wadgaonkar Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/controlvmchannel.h | 688 +++++++++++++-------- 1 file changed, 414 insertions(+), 274 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/visorbus/controlvmchannel.h b/drivers/staging/unisys/visorbus/controlvmchannel.h index ed045eff0e33..5c67baf73153 100644 --- a/drivers/staging/unisys/visorbus/controlvmchannel.h +++ b/drivers/staging/unisys/visorbus/controlvmchannel.h @@ -1,4 +1,5 @@ -/* Copyright (C) 2010 - 2015 UNISYS CORPORATION +/* + * Copyright (C) 2010 - 2015 UNISYS CORPORATION * All rights reserved. * * This program is free software; you can redistribute it and/or modify it @@ -26,11 +27,12 @@ #define VISOR_CONTROLVM_CHANNEL_SIGNATURE VISOR_CHANNEL_SIGNATURE #define CONTROLVM_MESSAGE_MAX 64 -/* Must increment this whenever you insert or delete fields within - * this channel struct. Also increment whenever you change the meaning - * of fields within this channel struct so as to break pre-existing - * software. Note that you can usually add fields to the END of the - * channel struct withOUT needing to increment this. +/* + * Must increment this whenever you insert or delete fields within this channel + * struct. Also increment whenever you change the meaning of fields within this + * channel struct so as to break pre-existing software. Note that you can + * usually add fields to the END of the channel struct withOUT needing to + * increment this. */ #define VISOR_CONTROLVM_CHANNEL_VERSIONID 1 @@ -51,28 +53,31 @@ /* Max num of messages stored during IOVM creation to be reused after crash */ #define CONTROLVM_CRASHMSG_MAX 2 +/* + * struct visor_segment_state + * @enabled: May enter other states. + * @active: Assigned to active partition. + * @alive: Configure message sent to service/server. + * @revoked: Similar to partition state ShuttingDown. + * @allocated: Memory (device/port number) has been selected by Command. + * @known: Has been introduced to the service/guest partition. + * @ready: Service/Guest partition has responded to introduction. + * @operating: Resource is configured and operating. + * @reserved: Natural alignment. + * + * Note: Don't use high bit unless we need to switch to ushort which is + * non-compliant. + */ struct visor_segment_state { - /* Bit 0: May enter other states */ u16 enabled:1; - /* Bit 1: Assigned to active partition */ u16 active:1; - /* Bit 2: Configure message sent to service/server */ u16 alive:1; - /* Bit 3: similar to partition state ShuttingDown */ u16 revoked:1; - /* Bit 4: memory (device/port number) has been selected by Command */ u16 allocated:1; - /* Bit 5: has been introduced to the service/guest partition */ u16 known:1; - /* Bit 6: service/Guest partition has responded to introduction */ u16 ready:1; - /* Bit 7: resource is configured and operating */ u16 operating:1; - /* Natural alignment*/ u16 reserved:8; -/* Note: don't use high bit unless we need to switch to ushort - * which is non-compliant - */ } __packed; static const struct visor_segment_state segment_state_running = { @@ -87,74 +92,101 @@ static const struct visor_segment_state segment_state_standby = { 1, 1, 0, 0, 1, 1, 1, 0 }; -/* Ids for commands that may appear in either queue of a ControlVm channel. +/* + * enum controlvm_id + * @CONTROLVM_INVALID: + * @CONTROLVM_BUS_CREATE: CP --> SP, GP. + * @CONTROLVM_BUS_DESTROY: CP --> SP, GP. + * @CONTROLVM_BUS_CONFIGURE: CP --> SP. + * @CONTROLVM_BUS_CHANGESTATE: CP --> SP, GP. + * @CONTROLVM_BUS_CHANGESTATE_EVENT: SP, GP --> CP. + * @CONTROLVM_DEVICE_CREATE: CP --> SP, GP. + * @CONTROLVM_DEVICE_DESTROY: CP --> SP, GP. + * @CONTROLVM_DEVICE_CONFIGURE: CP --> SP. + * @CONTROLVM_DEVICE_CHANGESTATE: CP --> SP, GP. + * @CONTROLVM_DEVICE_CHANGESTATE_EVENT: SP, GP --> CP. + * @CONTROLVM_DEVICE_RECONFIGURE: CP --> Boot. + * @CONTROLVM_CHIPSET_INIT: CP --> SP, GP. + * @CONTROLVM_CHIPSET_STOP: CP --> SP, GP. + * @CONTROLVM_CHIPSET_READY: CP --> SP. + * @CONTROLVM_CHIPSET_SELFTEST: CP --> SP. + * + * Ids for commands that may appear in either queue of a ControlVm channel. * - * Commands that are initiated by the command partition (CP), by an IO or - * console service partition (SP), or by a guest partition (GP)are: - * - issued on the RequestQueue queue (q #0) in the ControlVm channel - * - responded to on the ResponseQueue queue (q #1) in the ControlVm channel + * Commands that are initiated by the command partition (CP), by an IO or + * console service partition (SP), or by a guest partition (GP) are: + * - issued on the RequestQueue queue (q #0) in the ControlVm channel + * - responded to on the ResponseQueue queue (q #1) in the ControlVm channel * - * Events that are initiated by an IO or console service partition (SP) or - * by a guest partition (GP) are: - * - issued on the EventQueue queue (q #2) in the ControlVm channel - * - responded to on the EventAckQueue queue (q #3) in the ControlVm channel + * Events that are initiated by an IO or console service partition (SP) or + * by a guest partition (GP) are: + * - issued on the EventQueue queue (q #2) in the ControlVm channel + * - responded to on the EventAckQueue queue (q #3) in the ControlVm channel */ enum controlvm_id { CONTROLVM_INVALID = 0, - /* SWITCH commands required Parameter: SwitchNumber */ - /* BUS commands required Parameter: BusNumber */ - CONTROLVM_BUS_CREATE = 0x101, /* CP --> SP, GP */ - CONTROLVM_BUS_DESTROY = 0x102, /* CP --> SP, GP */ - CONTROLVM_BUS_CONFIGURE = 0x104, /* CP --> SP */ - CONTROLVM_BUS_CHANGESTATE = 0x105, /* CP --> SP, GP */ - CONTROLVM_BUS_CHANGESTATE_EVENT = 0x106, /* SP, GP --> CP */ -/* DEVICE commands required Parameter: BusNumber, DeviceNumber */ - - CONTROLVM_DEVICE_CREATE = 0x201, /* CP --> SP, GP */ - CONTROLVM_DEVICE_DESTROY = 0x202, /* CP --> SP, GP */ - CONTROLVM_DEVICE_CONFIGURE = 0x203, /* CP --> SP */ - CONTROLVM_DEVICE_CHANGESTATE = 0x204, /* CP --> SP, GP */ - CONTROLVM_DEVICE_CHANGESTATE_EVENT = 0x205, /* SP, GP --> CP */ - CONTROLVM_DEVICE_RECONFIGURE = 0x206, /* CP --> Boot */ -/* CHIPSET commands */ - CONTROLVM_CHIPSET_INIT = 0x301, /* CP --> SP, GP */ - CONTROLVM_CHIPSET_STOP = 0x302, /* CP --> SP, GP */ - CONTROLVM_CHIPSET_READY = 0x304, /* CP --> SP */ - CONTROLVM_CHIPSET_SELFTEST = 0x305, /* CP --> SP */ - + /* + * SWITCH commands required Parameter: SwitchNumber. + * BUS commands required Parameter: BusNumber + */ + CONTROLVM_BUS_CREATE = 0x101, + CONTROLVM_BUS_DESTROY = 0x102, + CONTROLVM_BUS_CONFIGURE = 0x104, + CONTROLVM_BUS_CHANGESTATE = 0x105, + CONTROLVM_BUS_CHANGESTATE_EVENT = 0x106, + /* DEVICE commands required Parameter: BusNumber, DeviceNumber */ + CONTROLVM_DEVICE_CREATE = 0x201, + CONTROLVM_DEVICE_DESTROY = 0x202, + CONTROLVM_DEVICE_CONFIGURE = 0x203, + CONTROLVM_DEVICE_CHANGESTATE = 0x204, + CONTROLVM_DEVICE_CHANGESTATE_EVENT = 0x205, + CONTROLVM_DEVICE_RECONFIGURE = 0x206, + /* CHIPSET commands */ + CONTROLVM_CHIPSET_INIT = 0x301, + CONTROLVM_CHIPSET_STOP = 0x302, + CONTROLVM_CHIPSET_READY = 0x304, + CONTROLVM_CHIPSET_SELFTEST = 0x305, }; +/* + * struct irq_info + * @reserved1: Natural alignment purposes + * @recv_irq_handle: Specifies interrupt handle. It is used to retrieve the + * corresponding interrupt pin from Monitor; and the interrupt + * pin is used to connect to the corresponding interrupt. + * Used by IOPart-GP only. + * @recv_irq_vector: Specifies interrupt vector. It, interrupt pin, and shared + * are used to connect to the corresponding interrupt. + * Used by IOPart-GP only. + * @recv_irq_shared: Specifies if the recvInterrupt is shared. It, interrupt + * pin and vector are used to connect to 0 = not shared; + * 1 = shared the corresponding interrupt. + * Used by IOPart-GP only. + * @reserved: Natural alignment purposes + */ struct irq_info { u64 reserved1; - - /* specifies interrupt handle. It is used to retrieve the - * corresponding interrupt pin from Monitor; and the - * interrupt pin is used to connect to the corresponding - * interrupt. Used by IOPart-GP only. - */ u64 recv_irq_handle; - - /* specifies interrupt vector. It, interrupt pin, and shared are - * used to connect to the corresponding interrupt. Used by - * IOPart-GP only. - */ u32 recv_irq_vector; - - /* specifies if the recvInterrupt is shared. It, interrupt pin - * and vector are used to connect to 0 = not shared; 1 = shared. - * the corresponding interrupt. Used by IOPart-GP only. - */ u8 recv_irq_shared; - u8 reserved[3]; /* Natural alignment purposes */ + u8 reserved[3]; } __packed; +/* + * struct efi_visor_indication + * @boot_to_fw_ui: Stop in UEFI UI + * @clear_nvram: Clear NVRAM + * @clear_cmos: Clear CMOS + * @boot_to_tool: Run install tool + * @reserved: Natural alignment + */ struct efi_visor_indication { - u64 boot_to_fw_ui:1; /* Bit 0: Stop in uefi ui */ - u64 clear_nvram:1; /* Bit 1: Clear NVRAM */ - u64 clear_cmos:1; /* Bit 2: Clear CMOS */ - u64 boot_to_tool:1; /* Bit 3: Run install tool */ - /* remaining bits are available */ - u64 reserved:60; /* Natural alignment */ + u64 boot_to_fw_ui:1; + u64 clear_nvram:1; + u64 clear_cmos:1; + u64 boot_to_tool:1; + /* Remaining bits are available */ + u64 reserved:60; } __packed; enum visor_chipset_feature { @@ -162,182 +194,249 @@ enum visor_chipset_feature { VISOR_CHIPSET_FEATURE_PARA_HOTPLUG = 0x00000002, }; -/* This is the common structure that is at the beginning of every - * ControlVm message (both commands and responses) in any ControlVm - * queue. Commands are easily distinguished from responses by - * looking at the flags.response field. +/* + * struct controlvm_message_header + * @id: See CONTROLVM_ID. + * @message_size: Includes size of this struct + size of message. + * @segment_index: Index of segment containing Vm message/information. + * @completion_status: Error status code or result of message completion. + * @struct flags: + * @failed: =1 in a response to signify failure. + * @response_expected: =1 in all messages that expect a response. + * @server: =1 in all bus & device-related messages where the + * message receiver is to act as the bus or device + * server. + * @test_message: =1 for testing use only (Control and Command + * ignore this). + * @partial_completion: =1 if there are forthcoming responses/acks + * associated with this message. + * @preserve: =1 this is to let us know to preserve channel + * contents. + * @writer_in_diag: =1 the DiagWriter is active in the Diagnostic + * Partition. + * @reserve: Natural alignment. + * @reserved: Natural alignment. + * @message_handle: Identifies the particular message instance. + * @payload_vm_offset: Offset of payload area from start of this instance. + * @payload_max_bytes: Maximum bytes allocated in payload area of ControlVm + * segment. + * @payload_bytes: Actual number of bytes of payload area to copy between + * IO/Command. If non-zero, there is a payload to copy. + * + * This is the common structure that is at the beginning of every + * ControlVm message (both commands and responses) in any ControlVm + * queue. Commands are easily distinguished from responses by + * looking at the flags.response field. */ struct controlvm_message_header { - u32 id; /* See CONTROLVM_ID. */ - /* For requests, indicates the message type. */ - /* For responses, indicates the type of message we are responding to. */ - - /* Includes size of this struct + size of message */ + u32 id; + /* + * For requests, indicates the message type. For responses, indicates + * the type of message we are responding to. + */ u32 message_size; - /* Index of segment containing Vm message/information */ u32 segment_index; - /* Error status code or result of message completion */ u32 completion_status; struct { - /* =1 in a response to signify failure */ u32 failed:1; - /* =1 in all messages that expect a response */ u32 response_expected:1; - /* =1 in all bus & device-related messages where the message - * receiver is to act as the bus or device server - */ u32 server:1; - /* =1 for testing use only (Control and Command ignore this */ u32 test_message:1; - /* =1 if there are forthcoming responses/acks associated - * with this message - */ u32 partial_completion:1; - /* =1 this is to let us know to preserve channel contents */ u32 preserve:1; - /* =1 the DiagWriter is active in the Diagnostic Partition */ u32 writer_in_diag:1; - /* Natural alignment */ u32 reserve:25; } __packed flags; - /* Natural alignment */ u32 reserved; - /* Identifies the particular message instance */ u64 message_handle; - /* request instances with the corresponding response instance. */ - /* Offset of payload area from start of this instance */ u64 payload_vm_offset; - /* Maximum bytes allocated in payload area of ControlVm segment */ u32 payload_max_bytes; - /* Actual number of bytes of payload area to copy between IO/Command */ u32 payload_bytes; - /* if non-zero, there is a payload to copy. */ } __packed; +/* + * struct controlvm_packet_device_create - For CONTROLVM_DEVICE_CREATE + * @bus_no: Bus # (0..n-1) from the msg receiver's end. + * @dev_no: Bus-relative (0..n-1) device number. + * @channel_addr: Guest physical address of the channel, which can be + * dereferenced by the receiver of this ControlVm command. + * @channel_bytes: Specifies size of the channel in bytes. + * @data_type_uuid: Specifies format of data in channel. + * @dev_inst_uuid: Instance guid for the device. + * @irq_info intr: Specifies interrupt information. + */ struct controlvm_packet_device_create { - u32 bus_no; /* bus # (0..n-1) from the msg receiver's end */ - u32 dev_no; /* bus-relative (0..n-1) device number */ - /* Guest physical address of the channel, which can be dereferenced by - * the receiver of this ControlVm command - */ + u32 bus_no; + u32 dev_no; u64 channel_addr; - u64 channel_bytes; /* specifies size of the channel in bytes */ - uuid_le data_type_uuid; /* specifies format of data in channel */ - uuid_le dev_inst_uuid; /* instance guid for the device */ - struct irq_info intr; /* specifies interrupt information */ -} __packed; /* for CONTROLVM_DEVICE_CREATE */ + u64 channel_bytes; + uuid_le data_type_uuid; + uuid_le dev_inst_uuid; + struct irq_info intr; +} __packed; +/* + * struct controlvm_packet_device_configure - For CONTROLVM_DEVICE_CONFIGURE + * @bus_no: Bus number (0..n-1) from the msg receiver's perspective. + * @dev_no: Bus-relative (0..n-1) device number. + */ struct controlvm_packet_device_configure { - /* bus # (0..n-1) from the msg receiver's perspective */ u32 bus_no; - /* Control uses header SegmentIndex field to access bus number... */ - u32 dev_no; /* bus-relative (0..n-1) device number */ -} __packed; /* for CONTROLVM_DEVICE_CONFIGURE */ + /* Control uses header SegmentIndex field to access bus number. */ + u32 dev_no; +} __packed; +/* Total 128 bytes */ struct controlvm_message_device_create { struct controlvm_message_header header; struct controlvm_packet_device_create packet; -} __packed; /* total 128 bytes */ +} __packed; +/* Total 56 bytes */ struct controlvm_message_device_configure { struct controlvm_message_header header; struct controlvm_packet_device_configure packet; -} __packed; /* total 56 bytes */ +} __packed; -/* This is the format for a message in any ControlVm queue. */ +/* + * struct controlvm_message_packet - This is the format for a message in any + * ControlVm queue. + * @struct create_bus: For CONTROLVM_BUS_CREATE. + * @bus_no: Bus # (0..n-1) from the msg receiver's perspective. + * @dev_count: Indicates the max number of devices on this bus. + * @channel_addr: Guest physical address of the channel, which can be + * dereferenced by the receiver of this ControlVM + * command. + * @channel_bytes: Size of the channel. + * @bus_data_type_uuid: Indicates format of data in bus channel. + * @bus_inst_uuid: Instance uuid for the bus. + * + * @struct destroy_bus: For CONTROLVM_BUS_DESTROY. + * @bus_no: Bus # (0..n-1) from the msg receiver's perspective. + * @reserved: Natural alignment purposes. + * + * @struct configure_bus: For CONTROLVM_BUS_CONFIGURE. + * @bus_no: Bus # (0..n-1) from the receiver's perspective. + * @reserved1: For alignment purposes. + * @guest_handle: This is used to convert guest physical address to + * physical address. + * @recv_bus_irq_handle: Specifies interrupt info. It is used by SP to + * register to receive interrupts from the CP. This + * interrupt is used for bus level notifications. + * The corresponding sendBusInterruptHandle is kept + * in CP. + * + * @struct create_device: For CONTROLVM_DEVICE_CREATE. + * + * @struct destroy_device: For CONTROLVM_DEVICE_DESTROY. + * @bus_no: Bus # (0..n-1) from the msg receiver's perspective. + * @dev_no: Bus-relative (0..n-1) device number. + * + * @struct configure_device: For CONTROLVM_DEVICE_CONFIGURE. + * + * @struct reconfigure_device: For CONTROLVM_DEVICE_RECONFIGURE. + * @bus_no: Bus # (0..n-1) from the msg receiver's perspective. + * @dev_no: Bus-relative (0..n-1) device number. + * + * @struct bus_change_state: For CONTROLVM_BUS_CHANGESTATE. + * @bus_no: + * @struct state: + * @reserved: Natural alignment purposes. + * + * @struct device_change_state: For CONTROLVM_DEVICE_CHANGESTATE. + * @bus_no: + * @dev_no: + * @struct state: + * @struct flags: + * @phys_device: =1 if message is for a physical device. + * @reserved: Natural alignment. + * @reserved1: Natural alignment. + * @reserved: Natural alignment purposes. + * + * @struct device_change_state_event: For CONTROLVM_DEVICE_CHANGESTATE_EVENT. + * @bus_no: + * @dev_no: + * @struct state: + * @reserved: Natural alignment purposes. + * + * @struct init_chipset: For CONTROLVM_CHIPSET_INIT. + * @bus_count: Indicates the max number of busses. + * @switch_count: Indicates the max number of switches. + * @enum features: + * @platform_number: + * + * @struct chipset_selftest: For CONTROLVM_CHIPSET_SELFTEST. + * @options: Reserved. + * @test: Bit 0 set to run embedded selftest. + * + * @addr: A physical address of something, that can be dereferenced by the + * receiver of this ControlVm command. + * + * @handle: A handle of something (depends on command id). + */ struct controlvm_message_packet { union { struct { - /* bus # (0..n-1) from the msg receiver's perspective */ u32 bus_no; - /* indicates the max number of devices on this bus */ u32 dev_count; - /* Guest physical address of the channel, which can be - * dereferenced by the receiver of this ControlVm command - */ u64 channel_addr; - u64 channel_bytes; /* size of the channel */ - /* indicates format of data in bus channel*/ + u64 channel_bytes; uuid_le bus_data_type_uuid; - uuid_le bus_inst_uuid; /* instance uuid for the bus */ - } __packed create_bus; /* for CONTROLVM_BUS_CREATE */ + uuid_le bus_inst_uuid; + } __packed create_bus; struct { - /* bus # (0..n-1) from the msg receiver's perspective */ u32 bus_no; - u32 reserved; /* Natural alignment purposes */ - } __packed destroy_bus; /* for CONTROLVM_BUS_DESTROY */ + u32 reserved; + } __packed destroy_bus; struct { - /* bus # (0..n-1) from the receiver's perspective */ u32 bus_no; - u32 reserved1; /* for alignment purposes */ - /* This is used to convert guest physical address to physical address */ + u32 reserved1; u64 guest_handle; u64 recv_bus_irq_handle; - /* specifies interrupt info. It is used by SP - * to register to receive interrupts from the - * CP. This interrupt is used for bus level - * notifications. The corresponding - * sendBusInterruptHandle is kept in CP. - */ - } __packed configure_bus; /* for CONTROLVM_BUS_CONFIGURE */ - /* for CONTROLVM_DEVICE_CREATE */ + } __packed configure_bus; struct controlvm_packet_device_create create_device; struct { - /* bus # (0..n-1) from the msg receiver's perspective */ u32 bus_no; - u32 dev_no; /* bus-relative (0..n-1) device # */ - } __packed destroy_device; /* for CONTROLVM_DEVICE_DESTROY */ - /* for CONTROLVM_DEVICE_CONFIGURE */ + u32 dev_no; + } __packed destroy_device; struct controlvm_packet_device_configure configure_device; struct { - /* bus # (0..n-1) from the msg receiver's perspective */ u32 bus_no; - u32 dev_no; /* bus-relative (0..n-1) device # */ + u32 dev_no; } __packed reconfigure_device; - /* for CONTROLVM_DEVICE_RECONFIGURE */ struct { u32 bus_no; struct visor_segment_state state; - u8 reserved[2]; /* Natural alignment purposes */ - } __packed bus_change_state; /* for CONTROLVM_BUS_CHANGESTATE */ + u8 reserved[2]; + } __packed bus_change_state; struct { u32 bus_no; u32 dev_no; struct visor_segment_state state; struct { - /* =1 if message is for a physical device */ u32 phys_device:1; - u32 reserved:31; /* Natural alignment */ - u32 reserved1; /* Natural alignment */ + u32 reserved:31; + u32 reserved1; } __packed flags; - u8 reserved[2]; /* Natural alignment purposes */ + u8 reserved[2]; } __packed device_change_state; - /* for CONTROLVM_DEVICE_CHANGESTATE */ struct { u32 bus_no; u32 dev_no; struct visor_segment_state state; - u8 reserved[6]; /* Natural alignment purposes */ + u8 reserved[6]; } __packed device_change_state_event; - /* for CONTROLVM_DEVICE_CHANGESTATE_EVENT */ struct { - /* indicates the max number of busses */ u32 bus_count; - /* indicates the max number of switches */ u32 switch_count; enum visor_chipset_feature features; - u32 platform_number; /* Platform Number */ - } __packed init_chipset; /* for CONTROLVM_CHIPSET_INIT */ + u32 platform_number; + } __packed init_chipset; struct { - u32 options; /* reserved */ - u32 test; /* bit 0 set to run embedded selftest */ + u32 options; + u32 test; } __packed chipset_selftest; - /* for CONTROLVM_CHIPSET_SELFTEST */ - /* a physical address of something, that can be dereferenced - * by the receiver of this ControlVm command - */ u64 addr; - /* a handle of something (depends on command id) */ u64 handle; }; } __packed; @@ -348,93 +447,139 @@ struct controlvm_message { struct controlvm_message_packet cmd; } __packed; +/* + * struct visor_controlvm_channel + * @struct header: + * @gp_controlvm: Guest phys addr of this channel. + * @gp_partition_tables: Guest phys addr of partition tables. + * @gp_diag_guest: Guest phys addr of diagnostic channel. + * @gp_boot_romdisk: Guest phys addr of (read* only) Boot + * ROM disk. + * @gp_boot_ramdisk: Guest phys addr of writable Boot RAM + * disk. + * @gp_acpi_table: Guest phys addr of acpi table. + * @gp_control_channel: Guest phys addr of control channel. + * @gp_diag_romdisk: Guest phys addr of diagnostic ROM disk. + * @gp_nvram: Guest phys addr of NVRAM channel. + * @request_payload_offset: Offset to request payload area. + * @event_payload_offset: Offset to event payload area. + * @request_payload_bytes: Bytes available in request payload area. + * @event_payload_bytes: Bytes available in event payload area. + * @control_channel_bytes: + * @nvram_channel_bytes: Bytes in PartitionNvram segment. + * @message_bytes: sizeof(CONTROLVM_MESSAGE). + * @message_count: CONTROLVM_MESSAGE_MAX. + * @gp_smbios_table: Guest phys addr of SMBIOS tables. + * @gp_physical_smbios_table: Guest phys addr of SMBIOS table. + * @gp_reserved: VISOR_MAX_GUESTS_PER_SERVICE. + * @virtual_guest_firmware_image_base: Guest physical address of EFI firmware + * image base. + * @virtual_guest_firmware_entry_point: Guest physical address of EFI firmware + * entry point. + * @virtual_guest_firmware_image_size: Guest EFI firmware image size. + * @virtual_guest_firmware_boot_base: GPA = 1MB where EFI firmware image is + * copied to. + * @virtual_guest_image_base: + * @virtual_guest_image_size: + * @prototype_control_channel_offset: + * @virtual_guest_partition_handle: + * @restore_action: Restore Action field to restore the + * guest partition. + * @dump_action: For Windows guests it shows if the + * visordisk is in dump mode. + * @nvram_fail_count: + * @saved_crash_message_count: = CONTROLVM_CRASHMSG_MAX. + * @saved_crash_message_offset: Offset to request payload area needed + * for crash dump. + * @installation_error: Type of error encountered during + * installation. + * @installation_text_id: Id of string to display. + * @installation_remaining_steps: Number of remaining installation steps + * (for progress bars). + * @tool_action: VISOR_TOOL_ACTIONS Installation Action + * field. + * @reserved: Alignment. + * @struct efi_visor_ind: + * @sp_reserved: + * @reserved2: Force signals to begin on 128-byte + * cache line. + * @struct request_queue: Guest partition uses this queue to send + * requests to Control. + * @struct response_queue: Control uses this queue to respond to + * service or guest partition request. + * @struct event_queue: Control uses this queue to send events + * to guest partition. + * @struct event_ack_queue: Service or guest partition uses this + * queue to ack Control events. + * @struct request_msg: Request fixed-size message pool - + * does not include payload. + * @struct response_msg: Response fixed-size message pool - + * does not include payload. + * @struct event_msg: Event fixed-size message pool - + * does not include payload. + * @struct event_ack_msg: Ack fixed-size message pool - + * does not include payload. + * @struct saved_crash_msg: Message stored during IOVM creation to + * be reused after crash. + */ struct visor_controlvm_channel { struct channel_header header; - u64 gp_controlvm; /* guest phys addr of this channel */ - u64 gp_partition_tables;/* guest phys addr of partition tables */ - u64 gp_diag_guest; /* guest phys addr of diagnostic channel */ - u64 gp_boot_romdisk;/* guest phys addr of (read* only) Boot ROM disk */ - u64 gp_boot_ramdisk;/* guest phys addr of writable Boot RAM disk */ - u64 gp_acpi_table; /* guest phys addr of acpi table */ - u64 gp_control_channel;/* guest phys addr of control channel */ - u64 gp_diag_romdisk;/* guest phys addr of diagnostic ROM disk */ - u64 gp_nvram; /* guest phys addr of NVRAM channel */ - u64 request_payload_offset; /* Offset to request payload area */ - u64 event_payload_offset; /* Offset to event payload area */ - /* Bytes available in request payload area */ + u64 gp_controlvm; + u64 gp_partition_tables; + u64 gp_diag_guest; + u64 gp_boot_romdisk; + u64 gp_boot_ramdisk; + u64 gp_acpi_table; + u64 gp_control_channel; + u64 gp_diag_romdisk; + u64 gp_nvram; + u64 request_payload_offset; + u64 event_payload_offset; u32 request_payload_bytes; - u32 event_payload_bytes;/* Bytes available in event payload area */ + u32 event_payload_bytes; u32 control_channel_bytes; - u32 nvram_channel_bytes; /* Bytes in PartitionNvram segment */ - u32 message_bytes; /* sizeof(CONTROLVM_MESSAGE) */ - u32 message_count; /* CONTROLVM_MESSAGE_MAX */ - u64 gp_smbios_table; /* guest phys addr of SMBIOS tables */ - u64 gp_physical_smbios_table; /* guest phys addr of SMBIOS table */ - /* VISOR_MAX_GUESTS_PER_SERVICE */ + u32 nvram_channel_bytes; + u32 message_bytes; + u32 message_count; + u64 gp_smbios_table; + u64 gp_physical_smbios_table; char gp_reserved[2688]; - - /* guest physical address of EFI firmware image base */ u64 virtual_guest_firmware_image_base; - - /* guest physical address of EFI firmware entry point */ u64 virtual_guest_firmware_entry_point; - - /* guest EFI firmware image size */ u64 virtual_guest_firmware_image_size; - - /* GPA = 1MB where EFI firmware image is copied to */ u64 virtual_guest_firmware_boot_base; u64 virtual_guest_image_base; u64 virtual_guest_image_size; u64 prototype_control_channel_offset; u64 virtual_guest_partition_handle; - /* Restore Action field to restore the guest partition */ u16 restore_action; - /* For Windows guests it shows if the visordisk is in dump mode */ u16 dump_action; u16 nvram_fail_count; - u16 saved_crash_message_count; /* = CONTROLVM_CRASHMSG_MAX */ - /* Offset to request payload area needed for crash dump */ + u16 saved_crash_message_count; u32 saved_crash_message_offset; - /* Type of error encountered during installation */ u32 installation_error; - u32 installation_text_id; /* Id of string to display */ - /* Number of remaining installation steps (for progress bars) */ + u32 installation_text_id; u16 installation_remaining_steps; - /* VISOR_TOOL_ACTIONS Installation Action field */ u8 tool_action; - u8 reserved; /* alignment */ + u8 reserved; struct efi_visor_indication efi_visor_ind; u32 sp_reserved; - /* Force signals to begin on 128-byte cache line */ u8 reserved2[28]; - /* guest partition uses this queue to send requests to Control */ struct signal_queue_header request_queue; - /* Control uses this queue to respond to service or guest - * partition requests - */ struct signal_queue_header response_queue; - /* Control uses this queue to send events to guest partition */ struct signal_queue_header event_queue; - /* Service or guest partition uses this queue to ack Control events */ struct signal_queue_header event_ack_queue; - /* Request fixed-size message pool - does not include payload */ - struct controlvm_message request_msg[CONTROLVM_MESSAGE_MAX]; - - /* Response fixed-size message pool - does not include payload */ - struct controlvm_message response_msg[CONTROLVM_MESSAGE_MAX]; - - /* Event fixed-size message pool - does not include payload */ - struct controlvm_message event_msg[CONTROLVM_MESSAGE_MAX]; - - /* Ack fixed-size message pool - does not include payload */ - struct controlvm_message event_ack_msg[CONTROLVM_MESSAGE_MAX]; - - /* Message stored during IOVM creation to be reused after crash */ - struct controlvm_message saved_crash_msg[CONTROLVM_CRASHMSG_MAX]; + struct controlvm_message request_msg[CONTROLVM_MESSAGE_MAX]; + struct controlvm_message response_msg[CONTROLVM_MESSAGE_MAX]; + struct controlvm_message event_msg[CONTROLVM_MESSAGE_MAX]; + struct controlvm_message event_ack_msg[CONTROLVM_MESSAGE_MAX]; + struct controlvm_message saved_crash_msg[CONTROLVM_CRASHMSG_MAX]; } __packed; -/* The following header will be located at the beginning of PayloadVmOffset for +/* + * struct visor_controlvm_parameters_header + * + * The following header will be located at the beginning of PayloadVmOffset for * various ControlVm commands. The receiver of a ControlVm command with a * PayloadVmOffset will dereference this address and then use connection_offset, * initiator_offset, and target_offset to get the location of UTF-8 formatted @@ -457,7 +602,8 @@ struct visor_controlvm_parameters_header { u32 name_length; uuid_le id; u32 revision; - u32 reserved; /* Natural alignment */ + /* Natural alignment */ + u32 reserved; } __packed; /* General Errors------------------------------------------------------[0-99] */ @@ -473,57 +619,50 @@ struct visor_controlvm_parameters_header { #define CONTROLVM_RESP_EXPECTED_CHIPSET_INIT 101 /* Maximum Limit----------------------------------------------------[200-299] */ -#define CONTROLVM_RESP_ERROR_MAX_BUSES 201 /* BUS_CREATE */ -#define CONTROLVM_RESP_ERROR_MAX_DEVICES 202 /* DEVICE_CREATE */ +/* BUS_CREATE */ +#define CONTROLVM_RESP_ERROR_MAX_BUSES 201 +/* DEVICE_CREATE */ +#define CONTROLVM_RESP_ERROR_MAX_DEVICES 202 + /* Payload and Parameter Related------------------------------------[400-499] */ -#define CONTROLVM_RESP_PAYLOAD_INVALID 400 /* SWITCH_ATTACHEXTPORT, - * DEVICE_CONFIGURE - */ -#define CONTROLVM_RESP_INITIATOR_PARAMETER_INVALID 401 /* Multiple */ -#define CONTROLVM_RESP_TARGET_PARAMETER_INVALID 402 /* DEVICE_CONFIGURE */ -#define CONTROLVM_RESP_CLIENT_PARAMETER_INVALID 403 /* DEVICE_CONFIGURE */ -/* Specified[Packet Structure] Value-------------------------------[500-599] */ -#define CONTROLVM_RESP_BUS_INVALID 500 /* SWITCH_ATTACHINTPORT, - * BUS_CONFIGURE, - * DEVICE_CREATE, - * DEVICE_CONFIG - * DEVICE_DESTROY - */ -#define CONTROLVM_RESP_DEVICE_INVALID 501 /* SWITCH_ATTACHINTPORT*/ - /* DEVICE_CREATE, - * DEVICE_CONFIGURE, - * DEVICE_DESTROY - */ -#define CONTROLVM_RESP_CHANNEL_INVALID 502 /* DEVICE_CREATE, - * DEVICE_CONFIGURE - */ -/* Partition Driver Callback Interface----------------------[600-699] */ -#define CONTROLVM_RESP_VIRTPCI_DRIVER_FAILURE 604 /* BUS_CREATE, - * BUS_DESTROY, - * DEVICE_CREATE, - * DEVICE_DESTROY - */ -/* Unable to invoke VIRTPCI callback */ -#define CONTROLVM_RESP_VIRTPCI_DRIVER_CALLBACK_ERROR 605 /* BUS_CREATE, - * BUS_DESTROY, - * DEVICE_CREATE, - * DEVICE_DESTROY - */ -/* VIRTPCI Callback returned error */ +/* SWITCH_ATTACHEXTPORT, DEVICE_CONFIGURE */ +#define CONTROLVM_RESP_PAYLOAD_INVALID 400 +/* Multiple */ +#define CONTROLVM_RESP_INITIATOR_PARAMETER_INVALID 401 +/* DEVICE_CONFIGURE */ +#define CONTROLVM_RESP_TARGET_PARAMETER_INVALID 402 +/* DEVICE_CONFIGURE */ +#define CONTROLVM_RESP_CLIENT_PARAMETER_INVALID 403 + +/* Specified[Packet Structure] Value--------------------------------[500-599] */ +/* SWITCH_ATTACHINTPORT */ +/* BUS_CONFIGURE, DEVICE_CREATE, DEVICE_CONFIG, DEVICE_DESTROY */ +#define CONTROLVM_RESP_BUS_INVALID 500 +/* SWITCH_ATTACHINTPORT*/ +/* DEVICE_CREATE, DEVICE_CONFIGURE, DEVICE_DESTROY */ +#define CONTROLVM_RESP_DEVICE_INVALID 501 +/* DEVICE_CREATE, DEVICE_CONFIGURE */ +#define CONTROLVM_RESP_CHANNEL_INVALID 502 +/* Partition Driver Callback Interface------------------------------[600-699] */ +/* BUS_CREATE, BUS_DESTROY, DEVICE_CREATE, DEVICE_DESTROY */ +#define CONTROLVM_RESP_VIRTPCI_DRIVER_FAILURE 604 +/* Unable to invoke VIRTPCI callback. VIRTPCI Callback returned error. */ +/* BUS_CREATE, BUS_DESTROY, DEVICE_CREATE, DEVICE_DESTROY */ +#define CONTROLVM_RESP_VIRTPCI_DRIVER_CALLBACK_ERROR 605 +/* Generic device callback returned error. */ +/* SWITCH_ATTACHEXTPORT, SWITCH_DETACHEXTPORT, DEVICE_CONFIGURE */ #define CONTROLVM_RESP_GENERIC_DRIVER_CALLBACK_ERROR 606 - /* SWITCH_ATTACHEXTPORT, - * SWITCH_DETACHEXTPORT - * DEVICE_CONFIGURE - */ -/* generic device callback returned error */ /* Bus Related------------------------------------------------------[700-799] */ -#define CONTROLVM_RESP_ERROR_BUS_DEVICE_ATTACHED 700 /* BUS_DESTROY */ +/* BUS_DESTROY */ +#define CONTROLVM_RESP_ERROR_BUS_DEVICE_ATTACHED 700 + /* Channel Related--------------------------------------------------[800-899] */ -#define CONTROLVM_RESP_CHANNEL_TYPE_UNKNOWN 800 /* GET_CHANNELINFO, - * DEVICE_DESTROY - */ -#define CONTROLVM_RESP_CHANNEL_SIZE_TOO_SMALL 801 /* DEVICE_CREATE */ +/* GET_CHANNELINFO, DEVICE_DESTROY */ +#define CONTROLVM_RESP_CHANNEL_TYPE_UNKNOWN 800 +/* DEVICE_CREATE */ +#define CONTROLVM_RESP_CHANNEL_SIZE_TOO_SMALL 801 + /* Chipset Shutdown Related---------------------------------------[1000-1099] */ #define CONTROLVM_RESP_CHIPSET_SHUTDOWN_FAILED 1000 #define CONTROLVM_RESP_CHIPSET_SHUTDOWN_ALREADY_ACTIVE 1001 @@ -535,4 +674,5 @@ struct visor_controlvm_parameters_header { /* Device Related-------------------------------------------------[1400-1499] */ #define CONTROLVM_RESP_DEVICE_UDEV_TIMEOUT 1400 -#endif /* __CONTROLVMCHANNEL_H__ */ +/* __CONTROLVMCHANNEL_H__ */ +#endif -- cgit v1.2.3 From 19528057c0f958e6270f4681c51e1bb925d2f8ec Mon Sep 17 00:00:00 2001 From: Sameer Wadgaonkar Date: Fri, 30 Jun 2017 15:43:03 -0400 Subject: staging: unisys: visorbus: vbuschannel.h: fixed comment formatting issues Removed comments from the right side of the lines. Added kernel-doc like comments and cleaned up the inline comments in the structures. Signed-off-by: Sameer Wadgaonkar Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/vbuschannel.h | 91 +++++++++++++++++---------- 1 file changed, 58 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/visorbus/vbuschannel.h b/drivers/staging/unisys/visorbus/vbuschannel.h index 01d7d517dba7..56114f566cfa 100644 --- a/drivers/staging/unisys/visorbus/vbuschannel.h +++ b/drivers/staging/unisys/visorbus/vbuschannel.h @@ -1,4 +1,5 @@ -/* Copyright (C) 2010 - 2015 UNISYS CORPORATION +/* + * Copyright (C) 2010 - 2015 UNISYS CORPORATION * All rights reserved. * * This program is free software; you can redistribute it and/or modify it @@ -15,13 +16,15 @@ #ifndef __VBUSCHANNEL_H__ #define __VBUSCHANNEL_H__ -/* The vbus channel is the channel area provided via the BUS_CREATE controlvm - * message for each virtual bus. This channel area is provided to both server - * and client ends of the bus. The channel header area is initialized by - * the server, and the remaining information is filled in by the client. - * We currently use this for the client to provide various information about - * the client devices and client drivers for the server end to see. +/* + * The vbus channel is the channel area provided via the BUS_CREATE controlvm + * message for each virtual bus. This channel area is provided to both server + * and client ends of the bus. The channel header area is initialized by + * the server, and the remaining information is filled in by the client. + * We currently use this for the client to provide various information about + * the client devices and client drivers for the server end to see. */ + #include #include #include "channel.h" @@ -30,11 +33,11 @@ #define VISOR_VBUS_CHANNEL_UUID \ UUID_LE(0x193b331b, 0xc58f, 0x11da, \ 0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f) -static const uuid_le visor_vbus_channel_uuid = VISOR_VBUS_CHANNEL_UUID; #define VISOR_VBUS_CHANNEL_SIGNATURE VISOR_CHANNEL_SIGNATURE -/* Must increment this whenever you insert or delete fields within this channel +/* + * Must increment this whenever you insert or delete fields within this channel * struct. Also increment whenever you change the meaning of fields within this * channel struct so as to break pre-existing software. Note that you can * usually add fields to the END of the channel struct withOUT needing to @@ -42,43 +45,65 @@ static const uuid_le visor_vbus_channel_uuid = VISOR_VBUS_CHANNEL_UUID; */ #define VISOR_VBUS_CHANNEL_VERSIONID 1 -/* +static const uuid_le visor_vbus_channel_uuid = VISOR_VBUS_CHANNEL_UUID; + +/* struct visor_vbus_deviceinfo + * @devtype: Short string identifying the device type. + * @drvname: Driver .sys file name. + * @infostrs: Kernel vversion. + * @reserved: Pad size to 256 bytes. + * * An array of this struct is present in the channel area for each vbus. - * (See vbuschannel.h.) - * It is filled in by the client side to provide info about the device - * and driver from the client's perspective. + * (See vbuschannel.h.). It is filled in by the client side to provide info + * about the device and driver from the client's perspective. */ struct visor_vbus_deviceinfo { - u8 devtype[16]; /* short string identifying the device type */ - u8 drvname[16]; /* driver .sys file name */ - u8 infostrs[96]; /* kernel version */ - u8 reserved[128]; /* pad size to 256 bytes */ + u8 devtype[16]; + u8 drvname[16]; + u8 infostrs[96]; + u8 reserved[128]; } __packed; +/* + * struct visor_vbus_headerinfo + * @struct_bytes: Size of this struct in bytes. + * @device_info_struct_bytes: Size of VISOR_VBUS_DEVICEINFO. + * @dev_info_count: Num of items in DevInfo member. This is the + * allocated size. + * @chp_info_offset: Byte offset from beginning of this struct to the + * ChpInfo struct. + * @bus_info_offset: Byte offset from beginning of this struct to the + * BusInfo struct. + * @dev_info_offset: Byte offset from beginning of this struct to the + * DevInfo array. + * @reserved: Natural Alignment + */ struct visor_vbus_headerinfo { - u32 struct_bytes; /* size of this struct in bytes */ - u32 device_info_struct_bytes; /* sizeof(VISOR_VBUS_DEVICEINFO) */ - u32 dev_info_count; /* num of items in DevInfo member */ - /* (this is the allocated size) */ - u32 chp_info_offset; /* byte offset from beginning of this struct */ - /* to the ChpInfo struct (below) */ - u32 bus_info_offset; /* byte offset from beginning of this struct */ - /* to the BusInfo struct (below) */ - u32 dev_info_offset; /* byte offset from beginning of this struct */ - /* to the DevInfo array (below) */ + u32 struct_bytes; + u32 device_info_struct_bytes; + u32 dev_info_count; + u32 chp_info_offset; + u32 bus_info_offset; + u32 dev_info_offset; u8 reserved[104]; } __packed; +/* + * struct visor_vbus_channel + * @channel_header: Initialized by server. + * @hdr_info: Initialized by server. + * @chp_info: Describes client chipset device and driver. + * @bus_info: Describes client bus device and driver. + * @dev_info: Describes client device and driver for each device on the + * bus. + */ struct visor_vbus_channel { - struct channel_header channel_header; /* initialized by server */ - struct visor_vbus_headerinfo hdr_info; /* initialized by server */ - /* the remainder of this channel is filled in by the client */ + struct channel_header channel_header; + struct visor_vbus_headerinfo hdr_info; + /* The remainder of this channel is filled in by the client */ struct visor_vbus_deviceinfo chp_info; - /* describes client chipset device and driver */ struct visor_vbus_deviceinfo bus_info; - /* describes client bus device and driver */ struct visor_vbus_deviceinfo dev_info[0]; - /* describes client device and driver for each device on the bus */ } __packed; #endif -- cgit v1.2.3 From 5787a8a76207fd6a102a92649c2e905f1a4d4af3 Mon Sep 17 00:00:00 2001 From: Sameer Wadgaonkar Date: Fri, 30 Jun 2017 15:43:04 -0400 Subject: staging: unisys: visorbus: vmcallinterface.h: fixed comment formatting issues Removed comments from the right side of the lines. Added kernel-doc like comments and cleaned up the inline comments in the structures. Signed-off-by: Sameer Wadgaonkar Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/vmcallinterface.h | 56 +++++++++++++---------- 1 file changed, 33 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/visorbus/vmcallinterface.h b/drivers/staging/unisys/visorbus/vmcallinterface.h index cc70e1b16bda..de6693f83c6b 100644 --- a/drivers/staging/unisys/visorbus/vmcallinterface.h +++ b/drivers/staging/unisys/visorbus/vmcallinterface.h @@ -1,4 +1,5 @@ -/* Copyright (C) 2010 - 2015 UNISYS CORPORATION +/* + * Copyright (C) 2010 - 2015 UNISYS CORPORATION * All rights reserved. * * This program is free software; you can redistribute it and/or modify it @@ -15,18 +16,20 @@ #ifndef __VMCALLINTERFACE_H__ #define __VMCALLINTERFACE_H__ -enum vmcall_monitor_interface_method_tuple { /* VMCALL identification tuples */ - /* Note: when a new VMCALL is added: - * - the 1st 2 hex digits correspond to one of the - * VMCALL_MONITOR_INTERFACE types and - * - the next 2 hex digits are the nth relative instance of within a - * type - * E.G. for VMCALL_VIRTPART_RECYCLE_PART, - * - the 0x02 identifies it as a VMCALL_VIRTPART type and - * - the 0x01 identifies it as the 1st instance of a VMCALL_VIRTPART - * type of VMCALL - */ - /* used by all Guests, not just IO */ +/* + * enum vmcall_monitor_interface_method_tuple - VMCALL identification tuples. + * @VMCALL_CONTROLVM_ADDR: Used by all guests, not just IO. + * + * Note: When a new VMCALL is added: + * - The 1st 2 hex digits correspond to one of the VMCALL_MONITOR_INTERFACE + * types. + * - The next 2 hex digits are the nth relative instance of within a type. + * E.G. for VMCALL_VIRTPART_RECYCLE_PART, + * - The 0x02 identifies it as a VMCALL_VIRTPART type. + * - The 0x01 identifies it as the 1st instance of a VMCALL_VIRTPART type of + * VMCALL. + */ +enum vmcall_monitor_interface_method_tuple { VMCALL_CONTROLVM_ADDR = 0x0501, }; @@ -39,16 +42,23 @@ enum vmcall_result { VMCALL_RESULT_DEVICE_NOT_READY = 5 }; -/* Structures for IO VMCALLs */ -/* Parameters to VMCALL_CONTROLVM_ADDR interface */ +/* + * struct vmcall_io_controlvm_addr_params - Structure for IO VMCALLS. Has + * parameters to VMCALL_CONTROLVM_ADDR + * interface. + * @address: The Guest-relative physical address of the ControlVm channel. + * This VMCall fills this in with the appropriate address. + * Contents provided by this VMCALL (OUT). + * @channel_bytes: The size of the ControlVm channel in bytes This VMCall fills + * this in with the appropriate address. Contents provided by + * this VMCALL (OUT). + * @unused: Unused Bytes in the 64-Bit Aligned Struct. + */ struct vmcall_io_controlvm_addr_params { - /* The Guest-relative physical address of the ControlVm channel. */ - /* This VMCall fills this in with the appropriate address. */ - u64 address; /* contents provided by this VMCALL (OUT) */ - /* the size of the ControlVm channel in bytes This VMCall fills this */ - /* in with the appropriate address. */ - u32 channel_bytes; /* contents provided by this VMCALL (OUT) */ - u8 unused[4]; /* Unused Bytes in the 64-Bit Aligned Struct */ + u64 address; + u32 channel_bytes; + u8 unused[4]; } __packed; -#endif /* __VMCALLINTERFACE_H__ */ +/* __VMCALLINTERFACE_H__ */ +#endif -- cgit v1.2.3 From 060b293b9b5901afebff9e85ae9d5e11519bb295 Mon Sep 17 00:00:00 2001 From: Sameer Wadgaonkar Date: Fri, 30 Jun 2017 15:43:05 -0400 Subject: staging: unisys: visorbus: visorbus_main.c: fixed comment formatting issues Removed comments from the right side of the lines. Signed-off-by: Sameer Wadgaonkar Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorbus_main.c | 40 ++++++++++++++----------- 1 file changed, 23 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index 1c785dd19ddd..e271de664976 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -1,4 +1,5 @@ -/* visorbus_main.c +/* + * visorbus_main.c * * Copyright � 2010 - 2015 UNISYS CORPORATION * All rights reserved. @@ -22,13 +23,14 @@ #define MYDRVNAME "visorbus" -/* Display string that is guaranteed to be no longer the 99 characters*/ +/* Display string that is guaranteed to be no longer the 99 characters */ #define LINESIZE 99 #define CURRENT_FILE_PC VISOR_BUS_PC_visorbus_main_c #define POLLJIFFIES_NORMALCHANNEL 10 -static bool initialized; /* stores whether bus_registration was successful */ +/* stores whether bus_registration was successful */ +static bool initialized; static struct dentry *visorbus_debugfs_dir; /* @@ -122,7 +124,7 @@ visorbus_match(struct device *xdev, struct device_driver *xdrv) /* * This describes the TYPE of bus. - * (Don't confuse this with an INSTANCE of the bus.) + * (Don't confuse this with an INSTANCE of the bus.) */ struct bus_type visorbus_type = { .name = "visorbus", @@ -369,8 +371,9 @@ static void vbuschannel_print_devinfo(struct visor_vbus_deviceinfo *devinfo, struct seq_file *seq, int devix) { + /* uninitialized vbus device entry */ if (!isprint(devinfo->devtype[0])) - return; /* uninitialized vbus device entry */ + return; if (devix >= 0) seq_printf(seq, "[%d]", devix); @@ -503,7 +506,7 @@ visordriver_remove_device(struct device *xdev) return 0; } -/** +/* * visorbus_unregister_visor_driver() - unregisters the provided driver * @drv: the driver to unregister * @@ -517,7 +520,7 @@ visorbus_unregister_visor_driver(struct visor_driver *drv) } EXPORT_SYMBOL_GPL(visorbus_unregister_visor_driver); -/** +/* * visorbus_read_channel() - reads from the designated channel into * the provided buffer * @dev: the device whose channel is read from @@ -538,7 +541,7 @@ visorbus_read_channel(struct visor_device *dev, unsigned long offset, } EXPORT_SYMBOL_GPL(visorbus_read_channel); -/** +/* * visorbus_write_channel() - writes the provided buffer into the designated * channel * @dev: the device whose channel is written to @@ -559,7 +562,7 @@ visorbus_write_channel(struct visor_device *dev, unsigned long offset, } EXPORT_SYMBOL_GPL(visorbus_write_channel); -/** +/* * visorbus_enable_channel_interrupts() - enables interrupts on the * designated device * @dev: the device on which to enable interrupts @@ -581,7 +584,7 @@ visorbus_enable_channel_interrupts(struct visor_device *dev) } EXPORT_SYMBOL_GPL(visorbus_enable_channel_interrupts); -/** +/* * visorbus_disable_channel_interrupts() - disables interrupts on the * designated device * @dev: the device on which to disable interrupts @@ -664,7 +667,8 @@ create_visor_device(struct visor_device *dev) goto err_put; list_add_tail(&dev->list_all, &list_all_device_instances); - return 0; /* success: reference kept via unmatched get_device() */ + /* success: reference kept via unmatched get_device() */ + return 0; err_put: put_device(&dev->device); @@ -901,7 +905,7 @@ visordriver_probe_device(struct device *xdev) return res; } -/** +/* * visorbus_register_visor_driver() - registers the provided visor driver * for handling one or more visor device * types (channel_types) @@ -952,8 +956,9 @@ visordriver_probe_device(struct device *xdev) */ int visorbus_register_visor_driver(struct visor_driver *drv) { + /* can't register on a nonexistent bus */ if (!initialized) - return -ENODEV; /* can't register on a nonexistent bus */ + return -ENODEV; drv->driver.name = drv->name; drv->driver.bus = &visorbus_type; @@ -1195,8 +1200,9 @@ visorchipset_initiate_device_pause_resume(struct visor_device *dev, dev->pausing = true; err = drv->pause(dev, pause_state_change_complete); } else { - /* The vbus_dev_info structure in the channel was been - * cleared, make sure it is valid. + /* + * The vbus_dev_info structure in the channel was been cleared, + * make sure it is valid. */ fix_vbus_dev_info(dev); if (!drv->resume) @@ -1209,7 +1215,7 @@ visorchipset_initiate_device_pause_resume(struct visor_device *dev, return err; } -/** +/* * visorchipset_device_pause() - start a pause operation for a visor device * @dev_info: struct visor_device identifying the device being paused * @@ -1232,7 +1238,7 @@ visorchipset_device_pause(struct visor_device *dev_info) return 0; } -/** +/* * visorchipset_device_resume() - start a resume operation for a visor device * @dev_info: struct visor_device identifying the device being resumed * -- cgit v1.2.3 From d82effd7c0f5d4fd228897d32a6b118851cb309e Mon Sep 17 00:00:00 2001 From: David Kershner Date: Fri, 30 Jun 2017 15:43:06 -0400 Subject: staging: unisys: include: remove unused macros in channel.h Several MACROS were not in use by the code, get rid of them. Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/include/channel.h | 21 --------------------- 1 file changed, 21 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/include/channel.h b/drivers/staging/unisys/include/channel.h index 692efcb38245..7f7542c36eea 100644 --- a/drivers/staging/unisys/include/channel.h +++ b/drivers/staging/unisys/include/channel.h @@ -59,27 +59,6 @@ enum channel_clientstate { /* access channel anytime */ }; -#define VISOR_CHANNEL_SERVER_READY(ch) \ - (readl(&(ch)->srv_state) == CHANNELSRV_READY) - -#define VISOR_VALID_CHANNELCLI_TRANSITION(o, n) \ - (((((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_DISABLED)) || \ - (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_DISABLED)) || \ - (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_DISABLED)) || \ - (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_DETACHED)) || \ - (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_DETACHED)) || \ - (((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_ATTACHING)) || \ - (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_ATTACHED)) || \ - (((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_ATTACHED)) || \ - (((o) == CHANNELCLI_BUSY) && ((n) == CHANNELCLI_ATTACHED)) || \ - (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_BUSY)) || \ - (((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_OWNED)) || \ - (((o) == CHANNELCLI_DISABLED) && ((n) == CHANNELCLI_OWNED)) || \ - (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_OWNED)) || \ - (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_OWNED)) || \ - (((o) == CHANNELCLI_BUSY) && ((n) == CHANNELCLI_OWNED)) || (0)) \ - ? (1) : (0)) - /* Values for VISORA_CHANNEL_PROTOCOL.CliErrorBoot: */ /* throttling invalid boot channel statetransition error due to client * disabled -- cgit v1.2.3 From 0496bedf0ecf12ff992722abf598e834a64d9ed7 Mon Sep 17 00:00:00 2001 From: Sameer Wadgaonkar Date: Fri, 30 Jun 2017 15:43:07 -0400 Subject: staging: unisys: visorbus: visorchannel.c: fixed comment formatting issues Removed comments from the right side of the lines. Signed-off-by: Sameer Wadgaonkar Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorchannel.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/visorbus/visorchannel.c b/drivers/staging/unisys/visorbus/visorchannel.c index 6885c2cb7135..0f0250902625 100644 --- a/drivers/staging/unisys/visorbus/visorchannel.c +++ b/drivers/staging/unisys/visorbus/visorchannel.c @@ -41,11 +41,15 @@ struct visorchannel { bool requested; struct channel_header chan_hdr; uuid_le guid; - bool needs_lock; /* channel creator knows if more than one */ - /* thread will be inserting or removing */ - spinlock_t insert_lock; /* protect head writes in chan_hdr */ - spinlock_t remove_lock; /* protect tail writes in chan_hdr */ - + /* + * channel creator knows if more than one + * thread will be inserting or removing + */ + bool needs_lock; + /* protect head writes in chan_hdr */ + spinlock_t insert_lock; + /* protect tail writes in chan_hdr */ + spinlock_t remove_lock; uuid_le type; uuid_le inst; }; @@ -246,9 +250,9 @@ signalremove_inner(struct visorchannel *channel, u32 queue, void *msg) /* * For each data field in SIGNAL_QUEUE_HEADER that was modified, - * update host memory. + * update host memory. Required for channel sync. */ - mb(); /* required for channel synch */ + mb(); error = SIG_WRITE_FIELD(channel, queue, &sig_hdr, tail); if (error) @@ -351,9 +355,9 @@ signalinsert_inner(struct visorchannel *channel, u32 queue, void *msg) /* * For each data field in SIGNAL_QUEUE_HEADER that was modified, - * update host memory. + * update host memory. Required for channel sync. */ - mb(); /* required for channel synch */ + mb(); err = SIG_WRITE_FIELD(channel, queue, &sig_hdr, head); if (err) -- cgit v1.2.3 From ac0aba6720edc7edf5bee42d242ea87a98039e51 Mon Sep 17 00:00:00 2001 From: Sameer Wadgaonkar Date: Fri, 30 Jun 2017 15:43:08 -0400 Subject: staging: unisys: visorbus: visorchipset.c: fixed comment formatting issues Removed comments from the right side of the lines. Signed-off-by: Sameer Wadgaonkar Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorchipset.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 22150564b4fb..bf6f79ea4988 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -312,7 +312,8 @@ parser_string_get(struct parser_context *ctx) value_length = i; break; } - if (value_length < 0) /* '\0' was not included in the length */ + /* '\0' was not included in the length */ + if (value_length < 0) value_length = nscan; value = kmalloc(value_length + 1, GFP_KERNEL); if (!value) @@ -1023,7 +1024,8 @@ parahotplug_request_destroy(struct parahotplug_request *req) } static LIST_HEAD(parahotplug_request_list); -static DEFINE_SPINLOCK(parahotplug_request_list_lock); /* lock for above */ +/* lock for above */ +static DEFINE_SPINLOCK(parahotplug_request_list_lock); /* * parahotplug_request_complete() - mark request as complete @@ -1326,8 +1328,8 @@ static int unisys_vmcall(unsigned long tuple, unsigned long param) goto error; return 0; - -error: /* Need to convert from VMCALL error codes to Linux */ +/* Need to convert from VMCALL error codes to Linux */ +error: switch (result) { case VMCALL_RESULT_INVALID_PARAM: return -EINVAL; -- cgit v1.2.3 From 5bf74b4443948f163c335a188e7038b3eb54e3ac Mon Sep 17 00:00:00 2001 From: Sameer Wadgaonkar Date: Fri, 30 Jun 2017 15:43:09 -0400 Subject: staging: unisys: include: channel.h: fixed comment formatting issues Removed comments from the right side of the lines. Added kernel-doc like comments and cleaned up the inline comments in the structures. Signed-off-by: Sameer Wadgaonkar Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/include/channel.h | 263 ++++++++++++++++++------------- 1 file changed, 150 insertions(+), 113 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/include/channel.h b/drivers/staging/unisys/include/channel.h index 7f7542c36eea..8affc53e061b 100644 --- a/drivers/staging/unisys/include/channel.h +++ b/drivers/staging/unisys/include/channel.h @@ -1,4 +1,5 @@ -/* Copyright (C) 2010 - 2013 UNISYS CORPORATION +/* + * Copyright (C) 2010 - 2013 UNISYS CORPORATION * All rights reserved. * * This program is free software; you can redistribute it and/or modify @@ -34,52 +35,61 @@ #define VISOR_CHANNEL_SIGNATURE SIGNATURE_32('E', 'C', 'N', 'L') +/* + * enum channel_serverstate + * @CHANNELSRV_UNINITIALIZED: Channel is in an undefined state. + * @CHANNELSRV_READY: Channel has been initialized by server. + */ enum channel_serverstate { - CHANNELSRV_UNINITIALIZED = 0, /* channel is in an undefined state */ - CHANNELSRV_READY = 1 /* channel has been initialized by server */ + CHANNELSRV_UNINITIALIZED = 0, + CHANNELSRV_READY = 1 }; +/* + * enum channel_clientstate + * @CHANNELCLI_DETACHED: + * @CHANNELCLI_DISABLED: Client can see channel but is NOT allowed to use it + * unless given TBD* explicit request + * (should actually be < DETACHED). + * @CHANNELCLI_ATTACHING: Legacy EFI client request for EFI server to attach. + * @CHANNELCLI_ATTACHED: Idle, but client may want to use channel any time. + * @CHANNELCLI_BUSY: Client either wants to use or is using channel. + * @CHANNELCLI_OWNED: "No worries" state - client can access channel + * anytime. + */ enum channel_clientstate { CHANNELCLI_DETACHED = 0, - CHANNELCLI_DISABLED = 1, /* client can see channel but is NOT - * allowed to use it unless given TBD - * explicit request (should actually be - * < DETACHED) - */ - CHANNELCLI_ATTACHING = 2, /* legacy EFI client request - * for EFI server to attach - */ - CHANNELCLI_ATTACHED = 3, /* idle, but client may want - * to use channel any time - */ - CHANNELCLI_BUSY = 4, /* client either wants to use or is - * using channel - */ - CHANNELCLI_OWNED = 5 /* "no worries" state - client can */ - /* access channel anytime */ + CHANNELCLI_DISABLED = 1, + CHANNELCLI_ATTACHING = 2, + CHANNELCLI_ATTACHED = 3, + CHANNELCLI_BUSY = 4, + CHANNELCLI_OWNED = 5 }; /* Values for VISORA_CHANNEL_PROTOCOL.CliErrorBoot: */ -/* throttling invalid boot channel statetransition error due to client - * disabled + +/* + * Throttling invalid boot channel statetransition error due to client + * disabled. */ #define VISOR_CLIERRORBOOT_THROTTLEMSG_DISABLED 0x01 -/* throttling invalid boot channel statetransition error due to client - * not attached +/* + * Throttling invalid boot channel statetransition error due to client + * not attached. */ #define VISOR_CLIERRORBOOT_THROTTLEMSG_NOTATTACHED 0x02 -/* throttling invalid boot channel statetransition error due to busy channel */ +/* Throttling invalid boot channel statetransition error due to busy channel */ #define VISOR_CLIERRORBOOT_THROTTLEMSG_BUSY 0x04 -/* Values for VISOR_CHANNEL_PROTOCOL.Features: This define exists so - * that windows guest can look at the FeatureFlags in the io channel, - * and configure the windows driver to use interrupts or not based on - * this setting. This flag is set in uislib after the - * VISOR_VHBA_init_channel is called. All feature bits for all - * channels should be defined here. The io channel feature bits are - * defined right here +/* + * Values for VISOR_CHANNEL_PROTOCOL.Features: This define exists so that + * windows guest can look at the FeatureFlags in the io channel, and configure + * the windows driver to use interrupts or not based on this setting. This flag + * is set in uislib after the VISOR_VHBA_init_channel is called. All feature + * bits for all channels should be defined here. The io channel feature bits + * are defined right here */ #define VISOR_DRIVER_ENABLES_INTS (0x1ULL << 1) #define VISOR_CHANNEL_IS_POLLING (0x1ULL << 3) @@ -87,97 +97,121 @@ enum channel_clientstate { #define VISOR_DRIVER_DISABLES_INTS (0x1ULL << 5) #define VISOR_DRIVER_ENHANCED_RCVBUF_CHECKING (0x1ULL << 6) -/* Common Channel Header */ +/* + * struct channel_header - Common Channel Header + * @signature: Signature. + * @legacy_state: DEPRECATED - being replaced by. + * @header_size: sizeof(struct channel_header). + * @size: Total size of this channel in bytes. + * @features: Flags to modify behavior. + * @chtype: Channel type: data, bus, control, etc.. + * @partition_handle: ID of guest partition. + * @handle: Device number of this channel in client. + * @ch_space_offset: Offset in bytes to channel specific area. + * @version_id: Struct channel_header Version ID. + * @partition_index: Index of guest partition. + * @zone_uuid: Guid of Channel's zone. + * @cli_str_offset: Offset from channel header to null-terminated + * ClientString (0 if ClientString not present). + * @cli_state_boot: CHANNEL_CLIENTSTATE of pre-boot EFI client of this + * channel. + * @cmd_state_cli: CHANNEL_COMMANDSTATE (overloaded in Windows drivers, see + * ServerStateUp, ServerStateDown, etc). + * @cli_state_os: CHANNEL_CLIENTSTATE of Guest OS client of this channel. + * @ch_characteristic: CHANNEL_CHARACTERISTIC_. + * @cmd_state_srv: CHANNEL_COMMANDSTATE (overloaded in Windows drivers, see + * ServerStateUp, ServerStateDown, etc). + * @srv_state: CHANNEL_SERVERSTATE. + * @cli_error_boot: Bits to indicate err states for boot clients, so err + * messages can be throttled. + * @cli_error_os: Bits to indicate err states for OS clients, so err + * messages can be throttled. + * @filler: Pad out to 128 byte cacheline. + * @recover_channel: Please add all new single-byte values below here. + */ struct channel_header { - u64 signature; /* Signature */ - u32 legacy_state; /* DEPRECATED - being replaced by */ - /* SrvState, CliStateBoot, and CliStateOS below */ - u32 header_size; /* sizeof(struct channel_header) */ - u64 size; /* Total size of this channel in bytes */ - u64 features; /* Flags to modify behavior */ - uuid_le chtype; /* Channel type: data, bus, control, etc. */ - u64 partition_handle; /* ID of guest partition */ - u64 handle; /* Device number of this channel in client */ - u64 ch_space_offset; /* Offset in bytes to channel specific area */ - u32 version_id; /* struct channel_header Version ID */ - u32 partition_index; /* Index of guest partition */ - uuid_le zone_uuid; /* Guid of Channel's zone */ - u32 cli_str_offset; /* offset from channel header to - * nul-terminated ClientString (0 if - * ClientString not present) - */ - u32 cli_state_boot; /* CHANNEL_CLIENTSTATE of pre-boot - * EFI client of this channel - */ - u32 cmd_state_cli; /* CHANNEL_COMMANDSTATE (overloaded in - * Windows drivers, see ServerStateUp, - * ServerStateDown, etc) - */ - u32 cli_state_os; /* CHANNEL_CLIENTSTATE of Guest OS - * client of this channel - */ - u32 ch_characteristic; /* CHANNEL_CHARACTERISTIC_ */ - u32 cmd_state_srv; /* CHANNEL_COMMANDSTATE (overloaded in - * Windows drivers, see ServerStateUp, - * ServerStateDown, etc) - */ - u32 srv_state; /* CHANNEL_SERVERSTATE */ - u8 cli_error_boot; /* bits to indicate err states for - * boot clients, so err messages can - * be throttled - */ - u8 cli_error_os; /* bits to indicate err states for OS - * clients, so err messages can be - * throttled - */ - u8 filler[1]; /* Pad out to 128 byte cacheline */ - /* Please add all new single-byte values below here */ + u64 signature; + u32 legacy_state; + /* SrvState, CliStateBoot, and CliStateOS below */ + u32 header_size; + u64 size; + u64 features; + uuid_le chtype; + u64 partition_handle; + u64 handle; + u64 ch_space_offset; + u32 version_id; + u32 partition_index; + uuid_le zone_uuid; + u32 cli_str_offset; + u32 cli_state_boot; + u32 cmd_state_cli; + u32 cli_state_os; + u32 ch_characteristic; + u32 cmd_state_srv; + u32 srv_state; + u8 cli_error_boot; + u8 cli_error_os; + u8 filler[1]; u8 recover_channel; } __packed; #define VISOR_CHANNEL_ENABLE_INTS (0x1ULL << 0) -/* Subheader for the Signal Type variation of the Common Channel */ +/* + * struct signal_queue_header - Subheader for the Signal Type variation of the + * Common Channel. + * @version: SIGNAL_QUEUE_HEADER Version ID. + * @chtype: Queue type: storage, network. + * @size: Total size of this queue in bytes. + * @sig_base_offset: Offset to signal queue area. + * @features: Flags to modify behavior. + * @num_sent: Total # of signals placed in this queue. + * @num_overflows: Total # of inserts failed due to full queue. + * @signal_size: Total size of a signal for this queue. + * @max_slots: Max # of slots in queue, 1 slot is always empty. + * @max_signals: Max # of signals in queue (MaxSignalSlots-1). + * @head: Queue head signal #. + * @num_received: Total # of signals removed from this queue. + * @tail: Queue tail signal. + * @reserved1: Reserved field. + * @reserved2: Reserved field. + * @client_queue: + * @num_irq_received: Total # of Interrupts received. This is incremented by the + * ISR in the guest windows driver. + * @num_empty: Number of times that visor_signal_remove is called and + * returned Empty Status. + * @errorflags: Error bits set during SignalReinit to denote trouble with + * client's fields. + * @filler: Pad out to 64 byte cacheline. + */ struct signal_queue_header { /* 1st cache line */ - u32 version; /* SIGNAL_QUEUE_HEADER Version ID */ - u32 chtype; /* Queue type: storage, network */ - u64 size; /* Total size of this queue in bytes */ - u64 sig_base_offset; /* Offset to signal queue area */ - u64 features; /* Flags to modify behavior */ - u64 num_sent; /* Total # of signals placed in this queue */ - u64 num_overflows; /* Total # of inserts failed due to - * full queue - */ - u32 signal_size; /* Total size of a signal for this queue */ - u32 max_slots; /* Max # of slots in queue, 1 slot is - * always empty - */ - u32 max_signals; /* Max # of signals in queue - * (MaxSignalSlots-1) - */ - u32 head; /* Queue head signal # */ + u32 version; + u32 chtype; + u64 size; + u64 sig_base_offset; + u64 features; + u64 num_sent; + u64 num_overflows; + u32 signal_size; + u32 max_slots; + u32 max_signals; + u32 head; /* 2nd cache line */ - u64 num_received; /* Total # of signals removed from this queue */ - u32 tail; /* Queue tail signal */ - u32 reserved1; /* Reserved field */ - u64 reserved2; /* Reserved field */ + u64 num_received; + u32 tail; + u32 reserved1; + u64 reserved2; u64 client_queue; - u64 num_irq_received; /* Total # of Interrupts received. This - * is incremented by the ISR in the - * guest windows driver - */ - u64 num_empty; /* Number of times that visor_signal_remove - * is called and returned Empty Status. - */ - u32 errorflags; /* Error bits set during SignalReinit - * to denote trouble with client's - * fields - */ - u8 filler[12]; /* Pad out to 64 byte cacheline */ + u64 num_irq_received; + u64 num_empty; + u32 errorflags; + u8 filler[12]; } __packed; -/* Generic function useful for validating any type of channel when it is +/* + * Generic function useful for validating any type of channel when it is * received by the client that will be accessing the channel. * Note that is only needed for callers in the EFI environment, and * is used to pass the EFI_DIAG_CAPTURE_PROTOCOL needed to log messages. @@ -199,7 +233,8 @@ visor_check_channel(struct channel_header *ch, return 0; } } - if (expected_min_bytes > 0) { /* verify channel size */ + /* verify channel size */ + if (expected_min_bytes > 0) { if (ch->size < expected_min_bytes) { pr_err("Channel mismatch on channel=%s(%pUL) field=size expected=0x%-8.8Lx actual=0x%-8.8Lx\n", chname, &expected_uuid, @@ -208,7 +243,8 @@ visor_check_channel(struct channel_header *ch, return 0; } } - if (expected_version > 0) { /* verify channel version */ + /* verify channel version */ + if (expected_version > 0) { if (ch->version_id != expected_version) { pr_err("Channel mismatch on channel=%s(%pUL) field=version expected=0x%-8.8lx actual=0x%-8.8x\n", chname, &expected_uuid, @@ -217,7 +253,8 @@ visor_check_channel(struct channel_header *ch, return 0; } } - if (expected_signature > 0) { /* verify channel signature */ + /* verify channel signature */ + if (expected_signature > 0) { if (ch->signature != expected_signature) { pr_err("Channel mismatch on channel=%s(%pUL) field=signature expected=0x%-8.8Lx actual=0x%-8.8Lx\n", chname, &expected_uuid, -- cgit v1.2.3 From 6cf6e5e64532b2c6e4c77ffa235e295c4f35b0f7 Mon Sep 17 00:00:00 2001 From: Sameer Wadgaonkar Date: Fri, 30 Jun 2017 15:43:10 -0400 Subject: staging: unisys: include: iochannel.h: fixed comment formatting issues Removed comments from the right side of the lines. Added kernel-doc like comments and cleaned up the inline comments in the structures. Signed-off-by: Sameer Wadgaonkar Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/include/iochannel.h | 492 ++++++++++++++++------------- 1 file changed, 280 insertions(+), 212 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/include/iochannel.h b/drivers/staging/unisys/include/iochannel.h index c7cb3fbde7b2..d79261047c30 100644 --- a/drivers/staging/unisys/include/iochannel.h +++ b/drivers/staging/unisys/include/iochannel.h @@ -71,8 +71,10 @@ #define MAXNUM(a, b) (((a) > (b)) ? (a) : (b)) /* Define the two queues per data channel between iopart and ioguestparts. */ + /* Used by ioguestpart to 'insert' signals to iopart. */ #define IOCHAN_TO_IOPART 0 + /* Used by ioguestpart to 'remove' signals from iopart, same previous queue. */ #define IOCHAN_FROM_IOPART 1 @@ -83,46 +85,45 @@ #define MAX_PHYS_INFO 64 -/* Various types of network packets that can be sent in cmdrsp. */ +/* + * enum net_types - Various types of network packets that can be sent in cmdrsp. + * @NET_RCV_POST: Submit buffer to hold receiving incoming packet. + * @NET_RCV: visornic -> uisnic. Incoming packet received. + * @NET_XMIT: uisnic -> visornic. For outgoing packet. + * @NET_XMIT_DONE: visornic -> uisnic. Outgoing packet xmitted. + * @NET_RCV_ENBDIS: uisnic -> visornic. Enable/Disable packet reception. + * @NET_RCV_ENBDIS_ACK: visornic -> uisnic. Acknowledge enable/disable packet. + * @NET_RCV_PROMISC: uisnic -> visornic. Enable/Disable promiscuous mode. + * @NET_CONNECT_STATUS: visornic -> uisnic. Indicate the loss or restoration of + * a network connection. + * @NET_MACADDR: uisnic -> visornic. Indicates the client has requested + * to update it's MAC address. + * @NET_MACADDR_ACK: MAC address acknowledge. + */ enum net_types { - NET_RCV_POST = 0, /* - * Submit buffer to hold receiving - * incoming packet - */ - /* visornic -> uisnic */ - NET_RCV, /* incoming packet received */ - /* uisnic -> visornic */ - NET_XMIT, /* for outgoing net packets */ - /* visornic -> uisnic */ - NET_XMIT_DONE, /* outgoing packet xmitted */ - /* uisnic -> visornic */ - NET_RCV_ENBDIS, /* enable/disable packet reception */ - /* visornic -> uisnic */ - NET_RCV_ENBDIS_ACK, /* acknowledge enable/disable packet */ - /* reception */ - /* uisnic -> visornic */ - NET_RCV_PROMISC, /* enable/disable promiscuous mode */ - /* visornic -> uisnic */ - NET_CONNECT_STATUS, /* - * indicate the loss or restoration of a network - * connection - */ - /* uisnic -> visornic */ - NET_MACADDR, /* - * Indicates the client has requested to update - * it's MAC address - */ - NET_MACADDR_ACK, /* MAC address acknowledge */ - + NET_RCV_POST = 0, + NET_RCV, + NET_XMIT, + NET_XMIT_DONE, + NET_RCV_ENBDIS, + NET_RCV_ENBDIS_ACK, + /* Reception */ + NET_RCV_PROMISC, + NET_CONNECT_STATUS, + NET_MACADDR, + NET_MACADDR_ACK, }; -#define ETH_MIN_DATA_SIZE 46 /* minimum eth data size */ +/* Minimum eth data size */ +#define ETH_MIN_DATA_SIZE 46 #define ETH_MIN_PACKET_SIZE (ETH_HLEN + ETH_MIN_DATA_SIZE) -#define VISOR_ETH_MAX_MTU 16384 /* maximum data size */ +/* Maximum data size */ +#define VISOR_ETH_MAX_MTU 16384 #ifndef MAX_MACADDR_LEN -#define MAX_MACADDR_LEN 6 /* number of bytes in MAC address */ +/* Number of bytes in MAC address */ +#define MAX_MACADDR_LEN 6 #endif /* Various types of scsi task mgmt commands. */ @@ -156,10 +157,16 @@ struct guest_phys_info { #define GPI_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof(struct guest_phys_info)) +/* + * struct uisscsi_dest + * @channel: Bus number. + * @id: Target number. + * @lun: Logical unit number. + */ struct uisscsi_dest { - u32 channel; /* channel == bus number */ - u32 id; /* id == target number */ - u32 lun; /* lun == logical unit number */ + u32 channel; + u32 id; + u32 lun; } __packed; struct vhba_wwnn { @@ -168,53 +175,71 @@ struct vhba_wwnn { } __packed; /* + * struct vhba_config_max + * @max_channel: Maximum channel for devices attached to this bus. + * @max_id: Maximum SCSI ID for devices attached to bus. + * @max_lun: Maximum SCSI LUN for devices attached to bus. + * @cmd_per_lun: Maximum number of outstanding commands per LUN. + * @max_io_size: Maximum io size for devices attached to this bus. Max io size + * is often determined by the resource of the hba. + * e.g Max scatter gather list length * page size / sector size. + * * WARNING: Values stired in this structure must contain maximum counts (not * maximum values). + * + * 20 bytes */ -struct vhba_config_max {/* 20 bytes */ - u32 max_channel;/* maximum channel for devices attached to this bus */ - u32 max_id; /* maximum SCSI ID for devices attached to bus */ - u32 max_lun; /* maximum SCSI LUN for devices attached to bus */ - u32 cmd_per_lun;/* maximum number of outstanding commands per LUN */ - u32 max_io_size;/* maximum io size for devices attached to this bus */ - /* max io size is often determined by the resource of the hba. e.g */ - /* max scatter gather list length * page size / sector size */ +struct vhba_config_max { + u32 max_channel; + u32 max_id; + u32 max_lun; + u32 cmd_per_lun; + u32 max_io_size; } __packed; +/* + * struct uiscmdrsp_scsi + * + * @handle: The handle to the cmd that was received. Send it back as + * is in the rsp packet. + * @cmnd: The cdb for the command. + * @bufflen: Length of data to be transferred out or in. + * @guest_phys_entries: Number of entries in scatter-gather list. + * @struct gpi_list: Physical address information for each fragment. + * @enum data_dir: Direction of the data, if any. + * @struct vdest: Identifies the virtual hba, id, channel, lun to which + * cmd was sent. + * @linuxstat: Original Linux status used by Linux vdisk. + * @scsistat: The scsi status. + * @addlstat: Non-scsi status. + * @sensebuf: Sense info in case cmd failed. sensebuf holds the + * sense_data struct. See sense_data struct for more + * details. + * @*vdisk: Pointer to the vdisk to clean up when IO completes. + * @no_disk_result: Used to return no disk inquiry result when + * no_disk_result is set to 1 + * scsi.scsistat is SAM_STAT_GOOD + * scsi.addlstat is 0 + * scsi.linuxstat is SAM_STAT_GOOD + * That is, there is NO error. + */ struct uiscmdrsp_scsi { - u64 handle; /* the handle to the cmd that was received */ - /* send it back as is in the rsp packet. */ - u8 cmnd[MAX_CMND_SIZE]; /* the cdb for the command */ - u32 bufflen; /* length of data to be transferred out or in */ - u16 guest_phys_entries; /* Number of entries in scatter-gather list */ - struct guest_phys_info gpi_list[MAX_PHYS_INFO]; /* physical address - * information for each - * fragment - */ - enum dma_data_direction data_dir; /* direction of the data, if any */ - struct uisscsi_dest vdest; /* identifies the virtual hba, id, */ - /* channel, lun to which cmd was sent */ - + u64 handle; + u8 cmnd[MAX_CMND_SIZE]; + u32 bufflen; + u16 guest_phys_entries; + struct guest_phys_info gpi_list[MAX_PHYS_INFO]; + enum dma_data_direction data_dir; + struct uisscsi_dest vdest; /* Needed to queue the rsp back to cmd originator. */ - int linuxstat; /* original Linux status used by Linux vdisk */ - u8 scsistat; /* the scsi status */ - u8 addlstat; /* non-scsi status */ + int linuxstat; + u8 scsistat; + u8 addlstat; #define ADDL_SEL_TIMEOUT 4 - /* The following fields are need to determine the result of command. */ - u8 sensebuf[MAX_SENSE_SIZE]; /* sense info in case cmd failed; */ - /* sensebuf holds the sense_data struct; */ - /* See sense_data struct for more details. */ - void *vdisk; /* Pointer to the vdisk to clean up when IO completes. */ + u8 sensebuf[MAX_SENSE_SIZE]; + void *vdisk; int no_disk_result; - /* - * Used to return no disk inquiry result - * when no_disk_result is set to 1, - * scsi.scsistat is SAM_STAT_GOOD - * scsi.addlstat is 0 - * scsi.linuxstat is SAM_STAT_GOOD - * That is, there is NO error. - */ } __packed; /* @@ -234,22 +259,35 @@ struct uiscmdrsp_scsi { * connected to this logical unit. */ -#define DEV_NOT_CAPABLE 0x7f /* - * peripheral qualifier of 0x3 - * peripheral type of 0x1f - * specifies no device but target present - */ - -#define DEV_DISK_CAPABLE_NOT_PRESENT 0x20 /* peripheral qualifier of 0x1 - * peripheral type of 0 - disk - * Specifies device capable, but - * not present - */ +/* + * Peripheral qualifier of 0x3 + * Peripheral type of 0x1f + * Specifies no device but target present + */ +#define DEV_NOT_CAPABLE 0x7f +/* + * Peripheral qualifier of 0x1 + * Peripheral type of 0 - disk + * Specifies device capable, but not present + */ +#define DEV_DISK_CAPABLE_NOT_PRESENT 0x20 +/* HiSup = 1; shows support for report luns must be returned for lun 0. */ +#define DEV_HISUPPORT 0x10 -#define DEV_HISUPPORT 0x10 /* - * HiSup = 1; shows support for report luns - * must be returned for lun 0. - */ +/* + * Peripheral qualifier of 0x3 + * Peripheral type of 0x1f + * Specifies no device but target present + */ +#define DEV_NOT_CAPABLE 0x7f +/* + * Peripheral qualifier of 0x1 + * Peripheral type of 0 - disk + * Specifies device capable, but not present + */ +#define DEV_DISK_CAPABLE_NOT_PRESENT 0x20 +/* HiSup = 1; shows support for report luns must be returned for lun 0. */ +#define DEV_HISUPPORT 0x10 /* * NOTE: Linux code assumes inquiry contains 36 bytes. Without checking length @@ -258,11 +296,12 @@ struct uiscmdrsp_scsi { * inquiry result. */ #define NO_DISK_INQUIRY_RESULT_LEN 36 - -#define MIN_INQUIRY_RESULT_LEN 5 /* 5 bytes minimum for inquiry result */ +/* 5 bytes minimum for inquiry result */ +#define MIN_INQUIRY_RESULT_LEN 5 /* SCSI device version for no disk inquiry result */ -#define SCSI_SPC2_VER 4 /* indicates SCSI SPC2 (SPC3 is 5) */ +/* indicates SCSI SPC2 (SPC3 is 5) */ +#define SCSI_SPC2_VER 4 /* Struct and Defines to support sense information. */ @@ -297,35 +336,48 @@ struct sense_data { u8 sense_key_specific[3]; } __packed; +/* + * struct net_pkt_xmt + * @len: Full length of data in the packet. + * @num_frags: Number of fragments in frags containing data. + * @struct phys_info frags: Physical page information. + * @ethhdr: The ethernet header. + * @struct lincsum: These are needed for csum at uisnic end. + * @valid: 1 = struct is valid - else ignore. + * @hrawoffv: 1 = hwrafoff is valid. + * @nhrawoffv: 1 = nhwrafoff is valid. + * @protocol: Specifies packet protocol. + * @csum: Value used to set skb->csum at IOPart. + * @hrawoff: Value used to set skb->h.raw at IOPart. hrawoff points to + * the start of the TRANSPORT LAYER HEADER. + * @nhrawoff: Value used to set skb->nh.raw at IOPart. nhrawoff points to + * the start of the NETWORK LAYER HEADER. + * + * NOTE: + * The full packet is described in frags but the ethernet header is + * separately kept in ethhdr so that uisnic doesn't have "MAP" the + * guest memory to get to the header. uisnic needs ethhdr to + * determine how to route the packet. + */ struct net_pkt_xmt { - int len; /* full length of data in the packet */ - int num_frags; /* number of fragments in frags containing data */ - struct phys_info frags[MAX_PHYS_INFO]; /* physical page information */ - char ethhdr[ETH_HLEN]; /* the ethernet header */ + int len; + int num_frags; + struct phys_info frags[MAX_PHYS_INFO]; + char ethhdr[ETH_HLEN]; struct { - /* These are needed for csum at uisnic end */ - u8 valid; /* 1 = struct is valid - else ignore */ - u8 hrawoffv; /* 1 = hwrafoff is valid */ - u8 nhrawoffv; /* 1 = nhwrafoff is valid */ - __be16 protocol; /* specifies packet protocol */ - __wsum csum; /* value used to set skb->csum at IOPart */ - u32 hrawoff; /* value used to set skb->h.raw at IOPart */ - /* hrawoff points to the start of the TRANSPORT LAYER HEADER */ - u32 nhrawoff; /* value used to set skb->nh.raw at IOPart */ - /* nhrawoff points to the start of the NETWORK LAYER HEADER */ + u8 valid; + u8 hrawoffv; + u8 nhrawoffv; + __be16 protocol; + __wsum csum; + u32 hrawoff; + u32 nhrawoff; } lincsum; - - /* - * NOTE: - * The full packet is described in frags but the ethernet header is - * separately kept in ethhdr so that uisnic doesn't have "MAP" the - * guest memory to get to the header. uisnic needs ethhdr to - * determine how to route the packet. - */ } __packed; struct net_pkt_xmtdone { - u32 xmt_done_result; /* result of NET_XMIT */ + /* Result of NET_XMIT */ + u32 xmt_done_result; } __packed; /* @@ -341,14 +393,12 @@ struct net_pkt_xmtdone { ((VISOR_ETH_MAX_MTU + ETH_HLEN + RCVPOST_BUF_SIZE - 1) \ / RCVPOST_BUF_SIZE) -/* - * rcv buf size must be large enough to include ethernet data len + ethernet +/* rcv buf size must be large enough to include ethernet data len + ethernet * header len - we are choosing 2K because it is guaranteed to be describable. */ struct net_pkt_rcvpost { /* Physical page information for the single fragment 2K rcv buf */ struct phys_info frag; - /* * Ensures that receive posts are returned to the adapter which we sent * them from originally. @@ -358,143 +408,148 @@ struct net_pkt_rcvpost { } __packed; /* + * struct net_pkt_rcv + * @rcv_done_len: Length of the received data. + * @numrcvbufs: Contains the incoming data. Guest side MUST chain these + * together. + * @*rcvbuf: List of chained rcvbufa. Each entry is a receive buffer + * provided by NET_RCV_POST. NOTE: First rcvbuf in the + * chain will also be provided in net.buf. + * @unique_num: + * @rcvs_dropped_delta: + * * The number of rcvbuf that can be chained is based on max mtu and size of each * rcvbuf. */ struct net_pkt_rcv { - u32 rcv_done_len; /* length of received data */ - - /* - * numrcvbufs: contain the incoming data; guest side MUST chain these - * together. - */ + u32 rcv_done_len; u8 numrcvbufs; - - void *rcvbuf[MAX_NET_RCV_CHAIN]; /* list of chained rcvbufs */ - - /* Each entry is a receive buffer provided by NET_RCV_POST. */ - /* NOTE: first rcvbuf in the chain will also be provided in net.buf. */ + void *rcvbuf[MAX_NET_RCV_CHAIN]; u64 unique_num; u32 rcvs_dropped_delta; } __packed; struct net_pkt_enbdis { void *context; - u16 enable; /* 1 = enable, 0 = disable */ + /* 1 = enable, 0 = disable */ + u16 enable; } __packed; struct net_pkt_macaddr { void *context; - u8 macaddr[MAX_MACADDR_LEN]; /* 6 bytes */ + /* 6 bytes */ + u8 macaddr[MAX_MACADDR_LEN]; } __packed; -/* cmd rsp packet used for VNIC network traffic */ +/* + * struct uiscmdrsp_net - cmd rsp packet used for VNIC network traffic. + * @enum type: + * @*buf: + * @union: + * @struct xmt: Used for NET_XMIT. + * @struct xmtdone: Used for NET_XMIT_DONE. + * @struct rcvpost: Used for NET_RCV_POST. + * @struct rcv: Used for NET_RCV. + * @struct enbdis: Used for NET_RCV_ENBDIS, NET_RCV_ENBDIS_ACK, + * NET_RCV_PROMSIC, and NET_CONNECT_STATUS. + * @struct macaddr: + */ struct uiscmdrsp_net { enum net_types type; void *buf; union { - struct net_pkt_xmt xmt; /* used for NET_XMIT */ - struct net_pkt_xmtdone xmtdone; /* used for NET_XMIT_DONE */ - struct net_pkt_rcvpost rcvpost; /* used for NET_RCV_POST */ - struct net_pkt_rcv rcv; /* used for NET_RCV */ - struct net_pkt_enbdis enbdis; /* used for NET_RCV_ENBDIS, */ - /* NET_RCV_ENBDIS_ACK, */ - /* NET_RCV_PROMSIC, */ - /* and NET_CONNECT_STATUS */ + struct net_pkt_xmt xmt; + struct net_pkt_xmtdone xmtdone; + struct net_pkt_rcvpost rcvpost; + struct net_pkt_rcv rcv; + struct net_pkt_enbdis enbdis; struct net_pkt_macaddr macaddr; }; } __packed; +/* + * struct uiscmdrsp_scsitaskmgmt + * @enum tasktype: The type of task. + * @struct vdest: The vdisk for which this task mgmt is generated. + * @handle: This is a handle that the guest has saved off for its + * own use. The handle value is preserved by iopart and + * returned as in task mgmt rsp. + * @notify_handle: For Linux guests, this is a pointer to wait_queue_head + * that a thread is waiting on to see if the taskmgmt + * command has completed. When the rsp is received by + * guest, the thread receiving the response uses this to + * notify the thread waiting for taskmgmt command + * completion. It's value is preserved by iopart and + * returned as in the task mgmt rsp. + * @notifyresult_handle: This is a handle to the location in the guest where + * the result of the taskmgmt command (result field) is + * saved to when the response is handled. It's value is + * preserved by iopart and returned as is in the task mgmt + * rsp. + * @result: Result of taskmgmt command - set by IOPart. + */ struct uiscmdrsp_scsitaskmgmt { - /* The type of task. */ enum task_mgmt_types tasktype; - - /* The vdisk for which this task mgmt is generated. */ struct uisscsi_dest vdest; - - /* - * This is a handle that the guest has saved off for its own use. - * The handle value is preserved by iopart and returned as in task - * mgmt rsp. - */ u64 handle; - - /* - * For Linux guests, this is a pointer to wait_queue_head that a - * thread is waiting on to see if the taskmgmt command has completed. - * When the rsp is received by guest, the thread receiving the - * response uses this to notify the thread waiting for taskmgmt - * command completion. It's value is preserved by iopart and returned - * as in the task mgmt rsp. - */ u64 notify_handle; - - /* - * This is a handle to the location in the guest where the result of - * the taskmgmt command (result field) is saved to when the response - * is handled. It's value is preserved by iopart and returned as in - * the task mgmt rsp. - */ u64 notifyresult_handle; - - /* Result of taskmgmt command - set by IOPart - values are: */ char result; #define TASK_MGMT_FAILED 0 } __packed; -/* Used by uissd to send disk add/remove notifications to Guest. */ -/* Note that the vHba pointer is not used by the Client/Guest side. */ +/* + * struct uiscmdrsp_disknotify - Used by uissd to send disk add/remove + * notifications to Guest. + * @add: 0-remove, 1-add. + * @*v_hba: Channel info to route msg. + * @channel: SCSI Path of Disk to added or removed. + * @id: SCSI Path of Disk to added or removed. + * @lun: SCSI Path of Disk to added or removed. + * + * Note that the vHba pointer is not used by the Client/Guest side. + */ struct uiscmdrsp_disknotify { - u8 add; /* 0-remove, 1-add */ - void *v_hba; /* channel info to route msg */ - u32 channel, id, lun; /* SCSI Path of Disk to added or removed */ + u8 add; + void *v_hba; + u32 channel, id, lun; } __packed; /* - * The following is used by virthba/vSCSI to send the Acquire/Release commands - * to the IOVM. + * struct uiscmdrsp_vdiskmgmt - The following is used by virthba/vSCSI to send + * the Acquire/Release commands to the IOVM. + * @enum vdisktype: The type of task. + * @struct vdest: The vdisk for which this task mgmt is generated. + * @handle: This is a handle that the guest has saved off for its + * own use. It's value is preserved by iopart and returned + * as in the task mgmt rsp. + * @notify_handle: For Linux guests, this is a pointer to wait_queue_head + * that a thread is waiting on to see if the tskmgmt + * command has completed. When the rsp is received by + * guest, the thread receiving the response uses this to + * notify the thread waiting for taskmgmt command + * completion. It's value is preserved by iopart and + * returned as in the task mgmt rsp. + * @notifyresult_handle: Handle to the location in guest where the result of the + * taskmgmt command (result field) is saved to when the + * response is handled. It's value is preserved by iopart + * and returned as in the task mgmt rsp. + * @result: Result of taskmgmt command - set by IOPart. */ struct uiscmdrsp_vdiskmgmt { - /* The type of task */ enum vdisk_mgmt_types vdisktype; - - /* The vdisk for which this task mgmt is generated */ struct uisscsi_dest vdest; - - /* - * This is a handle that the guest has saved off for its own use. It's - * value is preserved by iopart and returned as in the task mgmt rsp. - */ u64 handle; - - /* - * For Linux guests, this is a pointer to wait_queue_head that a - * thread is waiting on to see if the tskmgmt command has completed. - * When the rsp is received by guest, the thread receiving the - * response uses this to notify the thread waiting for taskmgmt - * command completion. It's value is preserved by iopart and returned - * as in the task mgmt rsp. - */ u64 notify_handle; - - /* - * Handle to the location in guest where the result of the - * taskmgmt command (result field) is saved to when the response - * is handled. It's value is preserved by iopart and returned as in - * the task mgmt rsp. - */ u64 notifyresult_handle; - - /* Result of taskmgmt command - set by IOPart - values are: */ char result; } __packed; /* Keeping cmd and rsp info in one structure for now cmd rsp packet for SCSI */ struct uiscmdrsp { char cmdtype; - -/* Describes what type of information is in the struct */ + /* Describes what type of information is in the struct */ #define CMD_SCSI_TYPE 1 #define CMD_NET_TYPE 2 #define CMD_SCSITASKMGMT_TYPE 3 @@ -509,21 +564,33 @@ struct uiscmdrsp { }; /* Send the response when the cmd is done (scsi and scsittaskmgmt). */ void *private_data; - struct uiscmdrsp *next; /* General Purpose Queue Link */ - struct uiscmdrsp *activeQ_next; /* Pointer to the nextactive commands */ - struct uiscmdrsp *activeQ_prev; /* Pointer to the prevactive commands */ + /* General Purpose Queue Link */ + struct uiscmdrsp *next; + /* Pointer to the nextactive commands */ + struct uiscmdrsp *activeQ_next; + /* Pointer to the prevactive commands */ + struct uiscmdrsp *activeQ_prev; } __packed; +/* total = 28 bytes */ struct iochannel_vhba { - struct vhba_wwnn wwnn; /* 8 bytes */ - struct vhba_config_max max; /* 20 bytes */ -} __packed; /* total = 28 bytes */ + /* 8 bytes */ + struct vhba_wwnn wwnn; + /* 20 bytes */ + struct vhba_config_max max; +} __packed; + struct iochannel_vnic { - u8 macaddr[6]; /* 6 bytes */ - u32 num_rcv_bufs; /* 4 bytes */ - u32 mtu; /* 4 bytes */ - uuid_le zone_uuid; /* 16 bytes */ + /* 6 bytes */ + u8 macaddr[6]; + /* 4 bytes */ + u32 num_rcv_bufs; + /* 4 bytes */ + u32 mtu; + /* 16 bytes */ + uuid_le zone_uuid; } __packed; + /* * This is just the header of the IO channel. It is assumed that directly after * this header there is a large region of memory which contains the command and @@ -550,4 +617,5 @@ struct visor_io_channel { #define PI_PAGE_SIZE 0x1000 #define PI_PAGE_MASK 0x0FFF -#endif /* __IOCHANNEL_H__ */ +/* __IOCHANNEL_H__ */ +#endif -- cgit v1.2.3 From 921557cbc46dd7c9c0654402cb21cc76dc8d373a Mon Sep 17 00:00:00 2001 From: Sameer Wadgaonkar Date: Fri, 30 Jun 2017 15:43:11 -0400 Subject: staging: unisys: visornic: visornic_main.c: fixed comment formatting issues Removed comments from the right side of the lines. Signed-off-by: Sameer Wadgaonkar Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visornic/visornic_main.c | 98 +++++++++++++++---------- 1 file changed, 61 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c index 2891622eef18..5c2614bebe26 100644 --- a/drivers/staging/unisys/visornic/visornic_main.c +++ b/drivers/staging/unisys/visornic/visornic_main.c @@ -84,7 +84,8 @@ struct visornic_devdata { u64 incarnation_id; /* flags as they were prior to set_multicast_list */ unsigned short old_flags; - atomic_t usage; /* count of users */ + /* count of users */ + atomic_t usage; /* number of rcv buffers the vnic will post */ int num_rcv_bufs; @@ -108,31 +109,43 @@ struct visornic_devdata { struct uiscmdrsp *cmdrsp_rcv; /* xmit_cmdrsp - issues NET_XMIT - only one active xmit at a time */ struct uiscmdrsp *xmit_cmdrsp; - - bool server_down; /* IOPART is down */ - bool server_change_state; /* Processing SERVER_CHANGESTATE msg */ - bool going_away; /* device is being torn down */ + /* IOPART is down */ + bool server_down; + /* Processing SERVER_CHANGESTATE msg */ + bool server_change_state; + /* device is being torn down */ + bool going_away; struct dentry *eth_debugfs_dir; u64 interrupts_rcvd; u64 interrupts_notme; u64 interrupts_disabled; u64 busy_cnt; - spinlock_t priv_lock; /* spinlock to access devdata structures */ + /* spinlock to access devdata structures */ + spinlock_t priv_lock; /* flow control counter */ u64 flow_control_upper_hits; u64 flow_control_lower_hits; /* debug counters */ - unsigned long n_rcv0; /* # rcvs of 0 buffers */ - unsigned long n_rcv1; /* # rcvs of 1 buffers */ - unsigned long n_rcv2; /* # rcvs of 2 buffers */ - unsigned long n_rcvx; /* # rcvs of >2 buffers */ - unsigned long found_repost_rcvbuf_cnt; /* # repost_rcvbuf_cnt */ - unsigned long repost_found_skb_cnt; /* # of found the skb */ - unsigned long n_repost_deficit; /* # of lost rcv buffers */ - unsigned long bad_rcv_buf; /* # of unknown rcv skb not freed */ - unsigned long n_rcv_packets_not_accepted;/* # bogs rcv packets */ + /* # rcvs of 0 buffers */ + unsigned long n_rcv0; + /* # rcvs of 1 buffers */ + unsigned long n_rcv1; + /* # rcvs of 2 buffers */ + unsigned long n_rcv2; + /* # rcvs of >2 buffers */ + unsigned long n_rcvx; + /* # repost_rcvbuf_cnt */ + unsigned long found_repost_rcvbuf_cnt; + /* # of found the skb */ + unsigned long repost_found_skb_cnt; + /* # of lost rcv buffers */ + unsigned long n_repost_deficit; + /* # of unknown rcv skb not freed */ + unsigned long bad_rcv_buf; + /* # bogs rcv packets */ + unsigned long n_rcv_packets_not_accepted; int queuefullmsg_logged; struct chanstat chstat; @@ -493,7 +506,8 @@ visornic_disable_with_timeout(struct net_device *netdev, const int timeout) /* send a msg telling the other end we are stopping incoming pkts */ spin_lock_irqsave(&devdata->priv_lock, flags); devdata->enabled = 0; - devdata->enab_dis_acked = 0; /* must wait for ack */ + /* must wait for ack */ + devdata->enab_dis_acked = 0; spin_unlock_irqrestore(&devdata->priv_lock, flags); /* send disable and wait for ack -- don't hold lock when sending @@ -578,10 +592,12 @@ init_rcv_bufs(struct net_device *netdev, struct visornic_devdata *devdata) */ for (i = 0; i < devdata->num_rcv_bufs; i++) { devdata->rcvbuf[i] = alloc_rcv_buf(netdev); + /* if we failed to allocate one let us stop */ if (!devdata->rcvbuf[i]) - break; /* if we failed to allocate one let us stop */ + break; } - if (i == 0) /* couldn't even allocate one -- bail out */ + /* couldn't even allocate one -- bail out */ + if (i == 0) return -ENOMEM; count = i; @@ -1236,7 +1252,8 @@ visornic_rx(struct uiscmdrsp *cmdrsp) * firstfrag & set data_len to show rest see if we have to chain * frag_list. */ - if (skb->len > RCVPOST_BUF_SIZE) { /* do PRECAUTIONARY check */ + /* do PRECAUTIONARY check */ + if (skb->len > RCVPOST_BUF_SIZE) { if (cmdrsp->net.rcv.numrcvbufs < 2) { if (repost_return(cmdrsp, devdata, skb, netdev) < 0) dev_err(&devdata->netdev->dev, @@ -1244,23 +1261,24 @@ visornic_rx(struct uiscmdrsp *cmdrsp) return 0; } /* length rcvd is greater than firstfrag in this skb rcv buf */ - skb->tail += RCVPOST_BUF_SIZE; /* amount in skb->data */ - skb->data_len = skb->len - RCVPOST_BUF_SIZE; /* amount that - * will be in - * frag_list - */ + /* amount in skb->data */ + skb->tail += RCVPOST_BUF_SIZE; + /* amount that will be in frag_list */ + skb->data_len = skb->len - RCVPOST_BUF_SIZE; } else { /* data fits in this skb - no chaining - do * PRECAUTIONARY check */ - if (cmdrsp->net.rcv.numrcvbufs != 1) { /* should be 1 */ + /* should be 1 */ + if (cmdrsp->net.rcv.numrcvbufs != 1) { if (repost_return(cmdrsp, devdata, skb, netdev) < 0) dev_err(&devdata->netdev->dev, "repost_return failed"); return 0; } skb->tail += skb->len; - skb->data_len = 0; /* nothing rcvd in frag_list */ + /* nothing rcvd in frag_list */ + skb->data_len = 0; } off = skb_tail_pointer(skb) - skb->data; @@ -1286,7 +1304,8 @@ visornic_rx(struct uiscmdrsp *cmdrsp) cc < cmdrsp->net.rcv.numrcvbufs; cc++) { curr = (struct sk_buff *)cmdrsp->net.rcv.rcvbuf[cc]; curr->next = NULL; - if (!prev) /* start of list- set head */ + /* start of list- set head */ + if (!prev) skb_shinfo(skb)->frag_list = curr; else prev->next = curr; @@ -1321,11 +1340,13 @@ visornic_rx(struct uiscmdrsp *cmdrsp) skb->ip_summed = CHECKSUM_NONE; do { + /* accept all packets */ if (netdev->flags & IFF_PROMISC) - break; /* accept all packets */ + break; if (skb->pkt_type == PACKET_BROADCAST) { + /* accept all broadcast packets */ if (netdev->flags & IFF_BROADCAST) - break; /* accept all broadcast packets */ + break; } else if (skb->pkt_type == PACKET_MULTICAST) { if ((netdev->flags & IFF_MULTICAST) && (netdev_mc_count(netdev))) { @@ -1651,13 +1672,14 @@ service_resp_queue(struct uiscmdrsp *cmdrsp, struct visornic_devdata *devdata, struct net_device *netdev; while (*rx_work_done < budget) { - /* TODO: CLIENT ACQUIRE -- Don't really need this at the - * moment - */ + /* TODO: CLIENT ACQUIRE -- Don't really need this at the + * moment + */ + /* queue empty */ if (visorchannel_signalremove(devdata->dev->visorchannel, IOCHAN_FROM_IOPART, cmdrsp)) - break; /* queue empty */ + break; switch (cmdrsp->net.type) { case NET_RCV: @@ -1831,7 +1853,8 @@ static int visornic_probe(struct visor_device *dev) dev_set_drvdata(&dev->device, devdata); init_waitqueue_head(&devdata->rsp_queue); spin_lock_init(&devdata->priv_lock); - devdata->enabled = 0; /* not yet */ + /* not yet */ + devdata->enabled = 0; atomic_set(&devdata->usage, 1); /* Setup rcv bufs */ @@ -1984,7 +2007,8 @@ static void host_side_disappeared(struct visornic_devdata *devdata) unsigned long flags; spin_lock_irqsave(&devdata->priv_lock, flags); - devdata->dev = NULL; /* indicate device destroyed */ + /* indicate device destroyed */ + devdata->dev = NULL; spin_unlock_irqrestore(&devdata->priv_lock, flags); } @@ -2023,8 +2047,8 @@ static void visornic_remove(struct visor_device *dev) cancel_work_sync(&devdata->timeout_reset); debugfs_remove_recursive(devdata->eth_debugfs_dir); - - unregister_netdev(netdev); /* this will call visornic_close() */ + /* this will call visornic_close() */ + unregister_netdev(netdev); del_timer_sync(&devdata->irq_poll_timer); netif_napi_del(&devdata->napi); -- cgit v1.2.3 From 781facd05eb9641bf49a0e0342c13102404a9fed Mon Sep 17 00:00:00 2001 From: Sameer Wadgaonkar Date: Fri, 30 Jun 2017 15:43:12 -0400 Subject: staging: unisys: visorhba: visorhba_main.c: fixed comment formatting issues Removed comments from the right side of the lines. Signed-off-by: Sameer Wadgaonkar Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorhba/visorhba_main.c | 33 ++++++++++++++++--------- 1 file changed, 22 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/visorhba/visorhba_main.c b/drivers/staging/unisys/visorhba/visorhba_main.c index a6e7a6bbc428..1ab4b8568ee6 100644 --- a/drivers/staging/unisys/visorhba/visorhba_main.c +++ b/drivers/staging/unisys/visorhba/visorhba_main.c @@ -48,7 +48,8 @@ MODULE_ALIAS("visorbus:" VISOR_VHBA_CHANNEL_UUID_STR); struct visordisk_info { u32 valid; - u32 channel, id, lun; /* Disk Path */ + /* Disk Path */ + u32 channel, id, lun; atomic_t ios_threshold; atomic_t error_count; struct visordisk_info *next; @@ -56,8 +57,10 @@ struct visordisk_info { struct scsipending { struct uiscmdrsp cmdrsp; - void *sent; /* The Data being tracked */ - char cmdtype; /* Type of pointer that is being stored */ + /* The Data being tracked */ + void *sent; + /* Type of pointer that is being stored */ + char cmdtype; }; /* Each scsi_host has a host_data area that contains this struct. */ @@ -71,7 +74,8 @@ struct visorhba_devdata { struct scsipending pending[MAX_PENDING_REQUESTS]; /* Start search for next pending free slot here */ unsigned int nextinsert; - spinlock_t privlock; /* lock to protect data in devdata */ + /* lock to protect data in devdata */ + spinlock_t privlock; bool serverdown; bool serverchangingstate; unsigned long long acquire_failed_cnt; @@ -136,8 +140,9 @@ static struct task_struct *visor_thread_start */ static void visor_thread_stop(struct task_struct *task) { + /* no thread running */ if (!task) - return; /* no thread running */ + return; kthread_stop(task); } @@ -176,7 +181,8 @@ static int add_scsipending_entry(struct visorhba_devdata *devdata, entry->cmdtype = cmdtype; if (new) entry->sent = new; - else /* wants to send cmdrsp */ + /* wants to send cmdrsp */ + else entry->sent = &entry->cmdrsp; devdata->nextinsert = (insert_location + 1) % MAX_PENDING_REQUESTS; spin_unlock_irqrestore(&devdata->privlock, flags); @@ -249,9 +255,11 @@ static unsigned int simple_idr_get(struct idr *idrtable, void *p, id = idr_alloc(idrtable, p, 1, INT_MAX, GFP_NOWAIT); spin_unlock_irqrestore(lock, flags); idr_preload_end(); + /* failure */ if (id < 0) - return 0; /* failure */ - return (unsigned int)(id); /* idr_alloc() guarantees > 0 */ + return 0; + /* idr_alloc() guarantees > 0 */ + return (unsigned int)(id); } /* @@ -573,12 +581,14 @@ static int visorhba_slave_alloc(struct scsi_device *scsidev) struct visorhba_devdata *devdata; struct Scsi_Host *scsihost = (struct Scsi_Host *)scsidev->host; + /* even though we errored, treat as success */ devdata = (struct visorhba_devdata *)scsihost->hostdata; if (!devdata) - return 0; /* even though we errored, treat as success */ + return 0; + /* already allocated return success */ for_each_vdisk_match(vdisk, devdata, scsidev) - return 0; /* already allocated return success */ + return 0; tmpvdisk = kzalloc(sizeof(*tmpvdisk), GFP_ATOMIC); if (!tmpvdisk) @@ -930,10 +940,11 @@ drain_queue(struct uiscmdrsp *cmdrsp, struct visorhba_devdata *devdata) struct scsi_cmnd *scsicmd; while (1) { + /* queue empty */ if (visorchannel_signalremove(devdata->dev->visorchannel, IOCHAN_FROM_IOPART, cmdrsp)) - break; /* queue empty */ + break; if (cmdrsp->cmdtype == CMD_SCSI_TYPE) { /* scsicmd location is returned by the -- cgit v1.2.3 From 0c58bc0d3d3a752fd16cfca5429f1d7c49cb52e8 Mon Sep 17 00:00:00 2001 From: Sameer Wadgaonkar Date: Fri, 30 Jun 2017 15:43:13 -0400 Subject: staging: unisys: visorinput: visorinput.c: fixed comment formatting issues Removed comments from the right side of the lines. Signed-off-by: Sameer Wadgaonkar Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorinput/visorinput.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/visorinput/visorinput.c b/drivers/staging/unisys/visorinput/visorinput.c index 45bc340d4e9d..c15f28fccdbe 100644 --- a/drivers/staging/unisys/visorinput/visorinput.c +++ b/drivers/staging/unisys/visorinput/visorinput.c @@ -60,11 +60,13 @@ enum visorinput_device_type { */ struct visorinput_devdata { struct visor_device *dev; - struct mutex lock_visor_dev; /* lock for dev */ + /* lock for dev */ + struct mutex lock_visor_dev; struct input_dev *visorinput_dev; bool paused; bool interrupts_enabled; - unsigned int keycode_table_bytes; /* size of following array */ + /* size of following array */ + unsigned int keycode_table_bytes; /* for keyboard devices: visorkbd_keycode[] + visorkbd_ext_keycode[] */ unsigned char keycode_table[0]; }; @@ -162,9 +164,8 @@ static const unsigned char visorkbd_keycode[KEYCODE_TABLE_BYTES] = { [81] = KEY_KP3, [82] = KEY_KP0, [83] = KEY_KPDOT, - [86] = KEY_102ND, /* enables UK backslash+pipe key, - * and FR lessthan+greaterthan key - */ + /* enables UK backslash+pipe key and FR lessthan+greaterthan key */ + [86] = KEY_102ND, [87] = KEY_F11, [88] = KEY_F12, [90] = KEY_KPLEFTPAREN, @@ -302,7 +303,8 @@ setup_client_keyboard(void *devdata, /* opaque on purpose */ BIT_MASK(LED_SCROLLL) | BIT_MASK(LED_NUML); visorinput_dev->keycode = keycode_table; - visorinput_dev->keycodesize = 1; /* sizeof(unsigned char) */ + /* sizeof(unsigned char) */ + visorinput_dev->keycodesize = 1; visorinput_dev->keycodemax = KEYCODE_TABLE_BYTES; for (i = 1; i < visorinput_dev->keycodemax; i++) @@ -313,7 +315,8 @@ setup_client_keyboard(void *devdata, /* opaque on purpose */ visorinput_dev->open = visorinput_open; visorinput_dev->close = visorinput_close; - input_set_drvdata(visorinput_dev, devdata); /* pre input_register! */ + /* pre input_register! */ + input_set_drvdata(visorinput_dev, devdata); return visorinput_dev; } @@ -354,7 +357,8 @@ setup_client_mouse(void *devdata /* opaque on purpose */) visorinput_dev->open = visorinput_open; visorinput_dev->close = visorinput_close; - input_set_drvdata(visorinput_dev, devdata); /* pre input_register! */ + /* pre input_register! */ + input_set_drvdata(visorinput_dev, devdata); input_set_capability(visorinput_dev, EV_REL, REL_WHEEL); return visorinput_dev; -- cgit v1.2.3 From aa93321cefa77def2e16f0ec1a3d8f77365ccc6e Mon Sep 17 00:00:00 2001 From: Sameer Wadgaonkar Date: Fri, 30 Jun 2017 15:43:14 -0400 Subject: staging: unisys: visorinput: ultrainputreport.h: fixed comment formatting issues Removed comments from the right side of the lines. Signed-off-by: Sameer Wadgaonkar Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- .../staging/unisys/visorinput/ultrainputreport.h | 65 ++++++++++------------ 1 file changed, 28 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/visorinput/ultrainputreport.h b/drivers/staging/unisys/visorinput/ultrainputreport.h index a4baea53c518..3ffad83100c4 100644 --- a/drivers/staging/unisys/visorinput/ultrainputreport.h +++ b/drivers/staging/unisys/visorinput/ultrainputreport.h @@ -20,44 +20,35 @@ /* These defines identify mouse and keyboard activity which is specified by the * firmware to the host using the cmsimpleinput protocol. @ingroup coretypes */ -#define INPUTACTION_XY_MOTION 1 /* only motion; arg1=x, arg2=y */ -#define INPUTACTION_MOUSE_BUTTON_DOWN 2 /* arg1: 1=left,2=center,3=right */ -#define INPUTACTION_MOUSE_BUTTON_UP 3 /* arg1: 1=left,2=center,3=right */ -#define INPUTACTION_MOUSE_BUTTON_CLICK 4 /* arg1: 1=left,2=center,3=right */ -#define INPUTACTION_MOUSE_BUTTON_DCLICK 5 /* arg1: 1=left,2=center, - * 3=right - */ -#define INPUTACTION_WHEEL_ROTATE_AWAY 6 /* arg1: wheel rotation away from - * user - */ -#define INPUTACTION_WHEEL_ROTATE_TOWARD 7 /* arg1: wheel rotation toward - * user - */ -#define INPUTACTION_KEY_DOWN 64 /* arg1: scancode, as follows: - * If arg1 <= 0xff, it's a 1-byte - * scancode and arg1 is that scancode. - * If arg1 > 0xff, it's a 2-byte - * scanecode, with the 1st byte in the - * low 8 bits, and the 2nd byte in the - * high 8 bits. E.g., the right ALT key - * would appear as x'38e0'. - */ -#define INPUTACTION_KEY_UP 65 /* arg1: scancode (in same format as - * inputaction_keyDown) - */ + /* only motion; arg1=x, arg2=y */ +#define INPUTACTION_XY_MOTION 1 +/* arg1: 1=left,2=center,3=right */ +#define INPUTACTION_MOUSE_BUTTON_DOWN 2 +/* arg1: 1=left,2=center,3=right */ +#define INPUTACTION_MOUSE_BUTTON_UP 3 +/* arg1: 1=left,2=center,3=right */ +#define INPUTACTION_MOUSE_BUTTON_CLICK 4 +/* arg1: 1=left,2=center 3=right */ +#define INPUTACTION_MOUSE_BUTTON_DCLICK 5 +/* arg1: wheel rotation away from user */ +#define INPUTACTION_WHEEL_ROTATE_AWAY 6 +/* arg1: wheel rotation toward user */ +#define INPUTACTION_WHEEL_ROTATE_TOWARD 7 +/* arg1: scancode, as follows: If arg1 <= 0xff, it's a 1-byte scancode and arg1 + * is that scancode. If arg1 > 0xff, it's a 2-byte scanecode, with the 1st + * byte in the low 8 bits, and the 2nd byte in the high 8 bits. + * E.g., the right ALT key would appear as x'38e0'. + */ +#define INPUTACTION_KEY_DOWN 64 +/* arg1: scancode (in same format as inputaction_keyDown) */ +#define INPUTACTION_KEY_UP 65 +/* arg1: scancode (in same format as inputaction_keyDown); MUST refer to one of + * the locking keys, like capslock, numlock, or scrolllock. + * arg2: 1 iff locking key should be in the LOCKED position (e.g., light is ON) + */ #define INPUTACTION_SET_LOCKING_KEY_STATE 66 - /* arg1: scancode (in same format - * as inputaction_keyDown); - * MUST refer to one of the - * locking keys, like capslock, - * numlock, or scrolllock - * arg2: 1 iff locking key should be - * in the LOCKED position - * (e.g., light is ON) - */ -#define INPUTACTION_KEY_DOWN_UP 67 /* arg1: scancode (in same format - * as inputaction_keyDown) - */ +/* arg1: scancode (in same format as inputaction_keyDown */ +#define INPUTACTION_KEY_DOWN_UP 67 struct visor_inputactivity { u16 action; -- cgit v1.2.3 From 946726ef0a6b68cb087c1259e890bd0c18e39397 Mon Sep 17 00:00:00 2001 From: David Binder Date: Fri, 30 Jun 2017 15:43:15 -0400 Subject: staging: unisys: include: Fix spelling mistake Fixes minor spelling mistake: stired -> stored. Signed-off-by: David Binder Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/include/iochannel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/include/iochannel.h b/drivers/staging/unisys/include/iochannel.h index d79261047c30..5212c191df25 100644 --- a/drivers/staging/unisys/include/iochannel.h +++ b/drivers/staging/unisys/include/iochannel.h @@ -184,7 +184,7 @@ struct vhba_wwnn { * is often determined by the resource of the hba. * e.g Max scatter gather list length * page size / sector size. * - * WARNING: Values stired in this structure must contain maximum counts (not + * WARNING: Values stored in this structure must contain maximum counts (not * maximum values). * * 20 bytes -- cgit v1.2.3 From 2e670eef551f56e1404eafa9ba68cdd4dbd9cad4 Mon Sep 17 00:00:00 2001 From: David Binder Date: Fri, 30 Jun 2017 15:43:16 -0400 Subject: staging: unisys: visorbus: Remove unused #define Removes unused MYDRVNAME define. Signed-off-by: David Binder Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorbus_main.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index e271de664976..075e817526e7 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -21,8 +21,6 @@ #include "visorbus.h" #include "visorbus_private.h" -#define MYDRVNAME "visorbus" - /* Display string that is guaranteed to be no longer the 99 characters */ #define LINESIZE 99 -- cgit v1.2.3 From b35fae7e2c3301805f26aa017a52eb4772c8aa57 Mon Sep 17 00:00:00 2001 From: David Binder Date: Fri, 30 Jun 2017 15:43:17 -0400 Subject: staging: unisys: visorbus: Rename #define to fit surrounding namespace Renames MYDRVNAME to better fit with the surrounding driver namespace. Signed-off-by: David Binder Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorchannel.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/visorbus/visorchannel.c b/drivers/staging/unisys/visorbus/visorchannel.c index 0f0250902625..fcff2319ebb8 100644 --- a/drivers/staging/unisys/visorbus/visorchannel.c +++ b/drivers/staging/unisys/visorbus/visorchannel.c @@ -26,7 +26,7 @@ #include "visorbus_private.h" #include "controlvmchannel.h" -#define MYDRVNAME "visorchannel" +#define VISOR_DRV_NAME "visorchannel" #define VISOR_CONSOLEVIDEO_CHANNEL_GUID \ UUID_LE(0x3cd6e705, 0xd6a2, 0x4aa5, \ @@ -418,7 +418,7 @@ visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes, * this. Remember that we haven't requested it so we don't try to * release later on. */ - channel->requested = request_mem_region(physaddr, size, MYDRVNAME); + channel->requested = request_mem_region(physaddr, size, VISOR_DRV_NAME); if (!channel->requested && uuid_le_cmp(guid, visor_video_guid)) /* we only care about errors if this is not the video channel */ goto err_destroy_channel; @@ -448,7 +448,7 @@ visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes, release_mem_region(channel->physaddr, channel->nbytes); channel->mapped = NULL; channel->requested = request_mem_region(channel->physaddr, - channel_bytes, MYDRVNAME); + channel_bytes, VISOR_DRV_NAME); if (!channel->requested && uuid_le_cmp(guid, visor_video_guid)) /* we only care about errors if this is not the video channel */ goto err_destroy_channel; -- cgit v1.2.3 From 75f92fcda2923c6350a17fa2cc535d0c0eba86cb Mon Sep 17 00:00:00 2001 From: David Binder Date: Fri, 30 Jun 2017 15:43:18 -0400 Subject: staging: unisys: visorhba: Fix up existing function comments Refactors existing static function comments to increase code readability. Signed-off-by: David Binder Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorhba/visorhba_main.c | 325 +++++++++++++----------- 1 file changed, 170 insertions(+), 155 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/visorhba/visorhba_main.c b/drivers/staging/unisys/visorhba/visorhba_main.c index 1ab4b8568ee6..b48a221616e9 100644 --- a/drivers/staging/unisys/visorhba/visorhba_main.c +++ b/drivers/staging/unisys/visorhba/visorhba_main.c @@ -112,15 +112,15 @@ struct visorhba_devices_open { (iter->lun == match->lun)) /* - * visor_thread_start - starts a thread for the device - * @threadfn: Function the thread starts - * @thrcontext: Context to pass to the thread, i.e. devdata - * @name: string describing name of thread + * visor_thread_start - Starts a thread for the device + * @threadfn: Function the thread starts + * @thrcontext: Context to pass to the thread, i.e. devdata + * @name: String describing name of thread * - * Starts a thread for the device. + * Starts a thread for the device. * - * Return the task_struct * denoting the thread on success, - * or NULL on failure + * Return: The task_struct * denoting the thread on success, + * or NULL on failure */ static struct task_struct *visor_thread_start (int (*threadfn)(void *), void *thrcontext, char *name) @@ -136,7 +136,8 @@ static struct task_struct *visor_thread_start } /* - * visor_thread_stop - stops the thread if it is running + * visor_thread_stop - Stops the thread if it is running + * @task: Description of process to stop */ static void visor_thread_stop(struct task_struct *task) { @@ -147,17 +148,18 @@ static void visor_thread_stop(struct task_struct *task) } /* - * add_scsipending_entry - save off io command that is pending in - * Service Partition - * @devdata: Pointer to devdata - * @cmdtype: Specifies the type of command pending - * @new: The command to be saved + * add_scsipending_entry - Save off io command that is pending in + * Service Partition + * @devdata: Pointer to devdata + * @cmdtype: Specifies the type of command pending + * @new: The command to be saved * - * Saves off the io command that is being handled by the Service - * Partition so that it can be handled when it completes. If new is - * NULL it is assumed the entry refers only to the cmdrsp. - * Returns insert_location where entry was added, - * -EBUSY if it can't + * Saves off the io command that is being handled by the Service + * Partition so that it can be handled when it completes. If new is + * NULL it is assumed the entry refers only to the cmdrsp. + * + * Return: Insert_location where entry was added on success, + * -EBUSY if it can't */ static int add_scsipending_entry(struct visorhba_devdata *devdata, char cmdtype, void *new) @@ -191,12 +193,13 @@ static int add_scsipending_entry(struct visorhba_devdata *devdata, } /* - * del_scsipending_ent - removes an entry from the pending array - * @devdata: Device holding the pending array - * @del: Entry to remove + * del_scsipending_ent - Removes an entry from the pending array + * @devdata: Device holding the pending array + * @del: Entry to remove + * + * Removes the entry pointed at by del and returns it. * - * Removes the entry pointed at by del and returns it. - * Returns the scsipending entry pointed at + * Return: The scsipending entry pointed to on success, NULL on failure */ static void *del_scsipending_ent(struct visorhba_devdata *devdata, int del) @@ -218,13 +221,14 @@ static void *del_scsipending_ent(struct visorhba_devdata *devdata, } /* - * get_scsipending_cmdrsp - return the cmdrsp stored in a pending entry - * @ddata: Device holding the pending array - * @ent: Entry that stores the cmdrsp + * get_scsipending_cmdrsp - Return the cmdrsp stored in a pending entry + * @ddata: Device holding the pending array + * @ent: Entry that stores the cmdrsp * - * Each scsipending entry has a cmdrsp in it. The cmdrsp is only valid - * if the "sent" field is not NULL - * Returns a pointer to the cmdrsp. + * Each scsipending entry has a cmdrsp in it. The cmdrsp is only valid + * if the "sent" field is not NULL. + * + * Return: A pointer to the cmdrsp, NULL on failure */ static struct uiscmdrsp *get_scsipending_cmdrsp(struct visorhba_devdata *ddata, int ent) @@ -236,13 +240,15 @@ static struct uiscmdrsp *get_scsipending_cmdrsp(struct visorhba_devdata *ddata, } /* - * simple_idr_get - associate a provided pointer with an int value - * 1 <= value <= INT_MAX, and return this int value; - * the pointer value can be obtained later by passing - * this int value to idr_find() - * @idrtable: the data object maintaining the pointer<-->int mappings - * @p: the pointer value to be remembered - * @lock: a spinlock used when exclusive access to idrtable is needed + * simple_idr_get - Associate a provided pointer with an int value + * 1 <= value <= INT_MAX, and return this int value; + * the pointer value can be obtained later by passing + * this int value to idr_find() + * @idrtable: The data object maintaining the pointer<-->int mappings + * @p: The pointer value to be remembered + * @lock: A spinlock used when exclusive access to idrtable is needed + * + * Return: The id number mapped to pointer 'p', 0 on failure */ static unsigned int simple_idr_get(struct idr *idrtable, void *p, spinlock_t *lock) @@ -263,10 +269,15 @@ static unsigned int simple_idr_get(struct idr *idrtable, void *p, } /* - * setup_scsitaskmgmt_handles - stash the necessary handles so that the - * completion processing logic for a taskmgmt - * cmd will be able to find who to wake up - * and where to stash the result + * setup_scsitaskmgmt_handles - Stash the necessary handles so that the + * completion processing logic for a taskmgmt + * cmd will be able to find who to wake up + * and where to stash the result + * @idrtable: The data object maintaining the pointer<-->int mappings + * @lock: A spinlock used when exclusive access to idrtable is needed + * @cmdrsp: Response from the IOVM + * @event: The event handle to associate with an id + * @result: The location to place the result of the event handle into */ static void setup_scsitaskmgmt_handles(struct idr *idrtable, spinlock_t *lock, struct uiscmdrsp *cmdrsp, @@ -281,8 +292,10 @@ static void setup_scsitaskmgmt_handles(struct idr *idrtable, spinlock_t *lock, } /* - * cleanup_scsitaskmgmt_handles - forget handles created by - * setup_scsitaskmgmt_handles() + * cleanup_scsitaskmgmt_handles - Forget handles created by + * setup_scsitaskmgmt_handles() + * @idrtable: The data object maintaining the pointer<-->int mappings + * @cmdrsp: Response from the IOVM */ static void cleanup_scsitaskmgmt_handles(struct idr *idrtable, struct uiscmdrsp *cmdrsp) @@ -294,14 +307,15 @@ static void cleanup_scsitaskmgmt_handles(struct idr *idrtable, } /* - * forward_taskmgmt_command - send taskmegmt command to the Service - * Partition - * @tasktype: Type of taskmgmt command - * @scsidev: Scsidev that issued command + * forward_taskmgmt_command - Send taskmegmt command to the Service + * Partition + * @tasktype: Type of taskmgmt command + * @scsidev: Scsidev that issued command * - * Create a cmdrsp packet and send it to the Serivce Partition - * that will service this request. - * Returns whether the command was queued successfully or not. + * Create a cmdrsp packet and send it to the Serivce Partition + * that will service this request. + * + * Return: Int representing whether command was queued successfully or not */ static int forward_taskmgmt_command(enum task_mgmt_types tasktype, struct scsi_cmnd *scsicmd) @@ -373,11 +387,10 @@ err_del_scsipending_ent: } /* - * visorhba_abort_handler - Send TASK_MGMT_ABORT_TASK - * @scsicmd: The scsicmd that needs aborted - * - * Returns SUCCESS if inserted, failure otherwise + * visorhba_abort_handler - Send TASK_MGMT_ABORT_TASK + * @scsicmd: The scsicmd that needs aborted * + * Return: SUCCESS if inserted, FAILED otherwise */ static int visorhba_abort_handler(struct scsi_cmnd *scsicmd) { @@ -398,10 +411,10 @@ static int visorhba_abort_handler(struct scsi_cmnd *scsicmd) } /* - * visorhba_device_reset_handler - Send TASK_MGMT_LUN_RESET - * @scsicmd: The scsicmd that needs aborted + * visorhba_device_reset_handler - Send TASK_MGMT_LUN_RESET + * @scsicmd: The scsicmd that needs aborted * - * Returns SUCCESS if inserted, failure otherwise + * Return: SUCCESS if inserted, FAILED otherwise */ static int visorhba_device_reset_handler(struct scsi_cmnd *scsicmd) { @@ -422,11 +435,11 @@ static int visorhba_device_reset_handler(struct scsi_cmnd *scsicmd) } /* - * visorhba_bus_reset_handler - Send TASK_MGMT_TARGET_RESET for each - * target on the bus - * @scsicmd: The scsicmd that needs aborted + * visorhba_bus_reset_handler - Send TASK_MGMT_TARGET_RESET for each + * target on the bus + * @scsicmd: The scsicmd that needs aborted * - * Returns SUCCESS + * Return: SUCCESS if inserted, FAILED otherwise */ static int visorhba_bus_reset_handler(struct scsi_cmnd *scsicmd) { @@ -446,11 +459,10 @@ static int visorhba_bus_reset_handler(struct scsi_cmnd *scsicmd) } /* - * visorhba_host_reset_handler - Not supported - * @scsicmd: The scsicmd that needs aborted + * visorhba_host_reset_handler - Not supported + * @scsicmd: The scsicmd that needs to be aborted * - * Not supported, return SUCCESS - * Returns SUCCESS + * Return: Not supported, return SUCCESS */ static int visorhba_host_reset_handler(struct scsi_cmnd *scsicmd) @@ -460,10 +472,10 @@ visorhba_host_reset_handler(struct scsi_cmnd *scsicmd) } /* - * visorhba_get_info - * @shp: Scsi host that is requesting information + * visorhba_get_info - Get information about SCSI device + * @shp: Scsi host that is requesting information * - * Returns string with info + * Return: String with visorhba information */ static const char *visorhba_get_info(struct Scsi_Host *shp) { @@ -472,15 +484,15 @@ static const char *visorhba_get_info(struct Scsi_Host *shp) } /* - * visorhba_queue_command_lck -- queues command to the Service Partition - * @scsicmd: Command to be queued - * @vsiorhba_cmnd_done: Done command to call when scsicmd is returned + * visorhba_queue_command_lck - Queues command to the Service Partition + * @scsicmd: Command to be queued + * @vsiorhba_cmnd_done: Done command to call when scsicmd is returned * - * Queues to scsicmd to the ServicePartition after converting it to a - * uiscmdrsp structure. + * Queues to scsicmd to the ServicePartition after converting it to a + * uiscmdrsp structure. * - * Returns success if queued to the Service Partition, otherwise - * failure. + * Return: 0 if successfully queued to the Service Partition, otherwise + * error code */ static int visorhba_queue_command_lck(struct scsi_cmnd *scsicmd, @@ -563,13 +575,13 @@ static DEF_SCSI_QCMD(visorhba_queue_command) #endif /* - * visorhba_slave_alloc - called when new disk is discovered - * @scsidev: New disk + * visorhba_slave_alloc - Called when new disk is discovered + * @scsidev: New disk * - * Create a new visordisk_info structure and add it to our - * list of vdisks. + * Create a new visordisk_info structure and add it to our + * list of vdisks. * - * Returns success when created, otherwise error. + * Return: 0 on success, -ENOMEM on failure. */ static int visorhba_slave_alloc(struct scsi_device *scsidev) { @@ -602,11 +614,8 @@ static int visorhba_slave_alloc(struct scsi_device *scsidev) } /* - * visorhba_slave_destroy - disk is going away - * @scsidev: scsi device going away - * - * Disk is going away, clean up resources. - * Returns void. + * visorhba_slave_destroy - Disk is going away, clean up resources. + * @scsidev: Scsi device to destroy */ static void visorhba_slave_destroy(struct scsi_device *scsidev) { @@ -645,10 +654,13 @@ static struct scsi_host_template visorhba_driver_template = { }; /* - * info_debugfs_show - debugfs interface to dump visorhba states + * info_debugfs_show - Debugfs interface to dump visorhba states + * @seq: The sequence file to write information to + * @v: Unused, but needed for use with seq file single_open invocation * - * This presents a file in the debugfs tree named: - * /visorhba/vbus:dev/info + * Presents a file in the debugfs tree named: /visorhba/vbus:dev/info. + * + * Return: SUCCESS */ static int info_debugfs_show(struct seq_file *seq, void *v) { @@ -689,12 +701,13 @@ static const struct file_operations info_debugfs_fops = { }; /* - * complete_taskmgmt_command - complete task management - * @cmdrsp: Response from the IOVM + * complete_taskmgmt_command - Complete task management + * @idrtable: The data object maintaining the pointer<-->int mappings + * @cmdrsp: Response from the IOVM + * @result: The result of the task management command * - * Service Partition returned the result of the task management - * command. Wake up anyone waiting for it. - * Returns void + * Service Partition returned the result of the task management + * command. Wake up anyone waiting for it. */ static void complete_taskmgmt_command(struct idr *idrtable, struct uiscmdrsp *cmdrsp, int result) @@ -718,13 +731,12 @@ static void complete_taskmgmt_command(struct idr *idrtable, } /* - * visorhba_serverdown_complete - Called when we are done cleaning up - * from serverdown - * @work: work structure for this serverdown request + * visorhba_serverdown_complete - Called when we are done cleaning up + * from serverdown + * @devdata: Visorhba instance on which to complete serverdown * - * Called when we are done cleanning up from serverdown, stop processing - * queue, fail pending IOs. - * Returns void when finished cleaning up + * Called when we are done cleanning up from serverdown, stop processing + * queue, fail pending IOs. */ static void visorhba_serverdown_complete(struct visorhba_devdata *devdata) { @@ -768,12 +780,13 @@ static void visorhba_serverdown_complete(struct visorhba_devdata *devdata) } /* - * visorhba_serverdown - Got notified that the IOVM is down - * @devdata: visorhba that is being serviced by downed IOVM. + * visorhba_serverdown - Got notified that the IOVM is down + * @devdata: Visorhba that is being serviced by downed IOVM + * + * Something happened to the IOVM, return immediately and + * schedule cleanup work. * - * Something happened to the IOVM, return immediately and - * schedule work cleanup work. - * Return SUCCESS or EINVAL + * Return: 0 on success, -EINVAL on failure */ static int visorhba_serverdown(struct visorhba_devdata *devdata) { @@ -787,12 +800,11 @@ static int visorhba_serverdown(struct visorhba_devdata *devdata) } /* - * do_scsi_linuxstat - scsi command returned linuxstat - * @cmdrsp: response from IOVM - * @scsicmd: Command issued. + * do_scsi_linuxstat - Scsi command returned linuxstat + * @cmdrsp: Response from IOVM + * @scsicmd: Command issued * - * Don't log errors for disk-not-present inquiries - * Returns void + * Don't log errors for disk-not-present inquiries. */ static void do_scsi_linuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd) @@ -838,12 +850,11 @@ static int set_no_disk_inquiry_result(unsigned char *buf, } /* - * do_scsi_nolinuxstat - scsi command didn't have linuxstat - * @cmdrsp: response from IOVM - * @scsicmd: Command issued. + * do_scsi_nolinuxstat - Scsi command didn't have linuxstat + * @cmdrsp: Response from IOVM + * @scsicmd: Command issued * - * Handle response when no linuxstat was returned - * Returns void + * Handle response when no linuxstat was returned. */ static void do_scsi_nolinuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd) @@ -905,13 +916,12 @@ do_scsi_nolinuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd) } /* - * complete_scsi_command - complete a scsi command - * @uiscmdrsp: Response from Service Partition - * @scsicmd: The scsi command + * complete_scsi_command - Complete a scsi command + * @uiscmdrsp: Response from Service Partition + * @scsicmd: The scsi command * - * Response returned by the Service Partition, finish it and send - * completion to the scsi midlayer. - * Returns void. + * Response was returned by the Service Partition. Finish it and send + * completion to the scsi midlayer. */ static void complete_scsi_command(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd) @@ -927,12 +937,11 @@ complete_scsi_command(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd) } /* - * drain_queue - pull responses out of iochannel - * @cmdrsp: Response from the IOSP - * @devdata: device that owns this iochannel + * drain_queue - Pull responses out of iochannel + * @cmdrsp: Response from the IOSP + * @devdata: Device that owns this iochannel * - * Pulls responses out of the iochannel and process the responses. - * Restuns void + * Pulls responses out of the iochannel and process the responses. */ static void drain_queue(struct uiscmdrsp *cmdrsp, struct visorhba_devdata *devdata) @@ -970,12 +979,14 @@ drain_queue(struct uiscmdrsp *cmdrsp, struct visorhba_devdata *devdata) } /* - * process_incoming_rsps - Process responses from IOSP - * @v: void pointer to visorhba_devdata + * process_incoming_rsps - Process responses from IOSP + * @v: Void pointer to visorhba_devdata * - * Main function for the thread that processes the responses - * from the IO Service Partition. When the queue is empty, wait - * to check to see if it is full again. + * Main function for the thread that processes the responses + * from the IO Service Partition. When the queue is empty, wait + * to check to see if it is full again. + * + * Return: 0 on success, -ENOMEM on failure */ static int process_incoming_rsps(void *v) { @@ -1002,14 +1013,15 @@ static int process_incoming_rsps(void *v) } /* - * visorhba_pause - function to handle visorbus pause messages - * @dev: device that is pausing. - * @complete_func: function to call when finished + * visorhba_pause - Function to handle visorbus pause messages + * @dev: Device that is pausing + * @complete_func: Function to call when finished + * + * Something has happened to the IO Service Partition that is + * handling this device. Quiet this device and reset commands + * so that the Service Partition can be corrected. * - * Something has happened to the IO Service Partition that is - * handling this device. Quiet this device and reset commands - * so that the Service Partition can be corrected. - * Returns SUCCESS + * Return: SUCCESS */ static int visorhba_pause(struct visor_device *dev, visorbus_state_complete_func complete_func) @@ -1022,13 +1034,14 @@ static int visorhba_pause(struct visor_device *dev, } /* - * visorhba_resume - function called when the IO Service Partition is back - * @dev: device that is pausing. - * @complete_func: function to call when finished + * visorhba_resume - Function called when the IO Service Partition is back + * @dev: Device that is pausing + * @complete_func: Function to call when finished * - * Yay! The IO Service Partition is back, the channel has been wiped - * so lets re-establish connection and start processing responses. - * Returns 0 on success, error on failure. + * Yay! The IO Service Partition is back, the channel has been wiped + * so lets re-establish connection and start processing responses. + * + * Return: 0 on success, -EINVAL on failure */ static int visorhba_resume(struct visor_device *dev, visorbus_state_complete_func complete_func) @@ -1052,11 +1065,12 @@ static int visorhba_resume(struct visor_device *dev, } /* - * visorhba_probe - device has been discovered, do acquire - * @dev: visor_device that was discovered + * visorhba_probe - Device has been discovered; do acquire + * @dev: visor_device that was discovered + * + * A new HBA was discovered; do the initial connections of it. * - * A new HBA was discovered, do the initial connections of it. - * Return 0 on success, otherwise error. + * Return: 0 on success, otherwise error code */ static int visorhba_probe(struct visor_device *dev) { @@ -1150,11 +1164,10 @@ err_scsi_host_put: } /* - * visorhba_remove - remove a visorhba device - * @dev: Device to remove + * visorhba_remove - Remove a visorhba device + * @dev: Device to remove * - * Removes the visorhba device. - * Returns void. + * Removes the visorhba device. */ static void visorhba_remove(struct visor_device *dev) { @@ -1192,10 +1205,12 @@ static struct visor_driver visorhba_driver = { }; /* - * visorhba_init - driver init routine + * visorhba_init - Driver init routine + * + * Initialize the visorhba driver and register it with visorbus + * to handle s-Par virtual host bus adapter. * - * Initialize the visorhba driver and register it with visorbus - * to handle s-Par virtual host bus adapter. + * Return: 0 on success, error code otherwise */ static int visorhba_init(void) { @@ -1218,9 +1233,9 @@ cleanup_debugfs: } /* - * visorhba_exit - driver exit routine + * visorhba_exit - Driver exit routine * - * Unregister driver from the bus and free up memory. + * Unregister driver from the bus and free up memory. */ static void visorhba_exit(void) { -- cgit v1.2.3 From 19fb5eaa64b3e2c1608098df5cf210f6a8a18d24 Mon Sep 17 00:00:00 2001 From: David Binder Date: Fri, 30 Jun 2017 15:43:19 -0400 Subject: staging: unisys: include: channel.h: Adjust whitespace usage Adjusts spacing and removes unnecessary blank lines to create a more uniform coding style. Signed-off-by: David Binder Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/include/channel.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/include/channel.h b/drivers/staging/unisys/include/channel.h index 8affc53e061b..fef1b0dfaef6 100644 --- a/drivers/staging/unisys/include/channel.h +++ b/drivers/staging/unisys/include/channel.h @@ -265,10 +265,7 @@ visor_check_channel(struct channel_header *ch, return 1; } -/* - * CHANNEL Guids - */ - +/* CHANNEL Guids */ /* {414815ed-c58c-11da-95a9-00e08161165f} */ #define VISOR_VHBA_CHANNEL_UUID \ UUID_LE(0x414815ed, 0xc58c, 0x11da, \ @@ -276,7 +273,6 @@ visor_check_channel(struct channel_header *ch, static const uuid_le visor_vhba_channel_uuid = VISOR_VHBA_CHANNEL_UUID; #define VISOR_VHBA_CHANNEL_UUID_STR \ "414815ed-c58c-11da-95a9-00e08161165f" - /* {8cd5994d-c58e-11da-95a9-00e08161165f} */ #define VISOR_VNIC_CHANNEL_UUID \ UUID_LE(0x8cd5994d, 0xc58e, 0x11da, \ @@ -284,7 +280,6 @@ static const uuid_le visor_vhba_channel_uuid = VISOR_VHBA_CHANNEL_UUID; static const uuid_le visor_vnic_channel_uuid = VISOR_VNIC_CHANNEL_UUID; #define VISOR_VNIC_CHANNEL_UUID_STR \ "8cd5994d-c58e-11da-95a9-00e08161165f" - /* {72120008-4AAB-11DC-8530-444553544200} */ #define VISOR_SIOVM_UUID \ UUID_LE(0x72120008, 0x4AAB, 0x11DC, \ -- cgit v1.2.3 From 2d15800d4b8e115047e059bb6e546aa3559f75c1 Mon Sep 17 00:00:00 2001 From: David Binder Date: Fri, 30 Jun 2017 15:43:20 -0400 Subject: staging: unisys: include: iochannel.h: Adjust whitespace usage Adjusts spacing and removes unnecessary blank lines to create a more uniform coding style. Signed-off-by: David Binder Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/include/iochannel.h | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/include/iochannel.h b/drivers/staging/unisys/include/iochannel.h index 5212c191df25..12849bbc4525 100644 --- a/drivers/staging/unisys/include/iochannel.h +++ b/drivers/staging/unisys/include/iochannel.h @@ -7,9 +7,7 @@ * Everything needed for IOPart-GuestPart communication is define in * this file. Note: Everything is OS-independent because this file is * used by Windows, Linux and possible EFI drivers. - */ - -/* + * * Communication flow between the IOPart and GuestPart uses the channel headers * channel state. The following states are currently being used: * UNINIT(All Zeroes), CHANNEL_ATTACHING, CHANNEL_ATTACHED, CHANNEL_OPENED @@ -30,7 +28,6 @@ */ #include - #include #include "channel.h" @@ -80,9 +77,7 @@ /* Size of cdb - i.e., SCSI cmnd */ #define MAX_CMND_SIZE 16 - #define MAX_SENSE_SIZE 64 - #define MAX_PHYS_INFO 64 /* @@ -245,9 +240,7 @@ struct uiscmdrsp_scsi { /* * Defines to support sending correct inquiry result when no disk is * configured. - */ - -/* + * * From SCSI SPC2 - * * If the target is not capable of supporting a device on this logical unit, the -- cgit v1.2.3 From 8a92ef71160a59865dfbf522a3b1d8389c223e0c Mon Sep 17 00:00:00 2001 From: David Binder Date: Fri, 30 Jun 2017 15:43:21 -0400 Subject: staging: unisys: include: visorbus.h: Adjust whitespace usage Adjusts presence of blank lines to create a more uniform coding style. Signed-off-by: David Binder Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/include/visorbus.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/include/visorbus.h b/drivers/staging/unisys/include/visorbus.h index de0635542fbd..b727dee9e94c 100644 --- a/drivers/staging/unisys/include/visorbus.h +++ b/drivers/staging/unisys/include/visorbus.h @@ -23,7 +23,6 @@ * * There should be nothing in this file that is private to the visorbus * bus implementation itself. - * */ #ifndef __VISORBUS_H__ @@ -45,6 +44,7 @@ extern struct bus_type visorbus_type; typedef void (*visorbus_state_complete_func) (struct visor_device *dev, int status); + struct visorchipset_state { u32 created:1; u32 attached:1; -- cgit v1.2.3 From 1a2d11ff2b900674a37849c79c0cf3688c6b35f2 Mon Sep 17 00:00:00 2001 From: David Binder Date: Fri, 30 Jun 2017 15:43:22 -0400 Subject: staging: unisys: visorbus: controlvmchannel.h: Adjust whitespace usage Removes unnecessary blank lines to create a more uniform coding style. Signed-off-by: David Binder Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/controlvmchannel.h | 9 --------- 1 file changed, 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/visorbus/controlvmchannel.h b/drivers/staging/unisys/visorbus/controlvmchannel.h index 5c67baf73153..dd3aff0d0162 100644 --- a/drivers/staging/unisys/visorbus/controlvmchannel.h +++ b/drivers/staging/unisys/visorbus/controlvmchannel.h @@ -613,17 +613,14 @@ struct visor_controlvm_parameters_header { #define CONTROLVM_RESP_KMALLOC_FAILED 3 #define CONTROLVM_RESP_ID_UNKNOWN 4 #define CONTROLVM_RESP_ID_INVALID_FOR_CLIENT 5 - /* CONTROLVM_INIT_CHIPSET-------------------------------------------[100-199] */ #define CONTROLVM_RESP_CLIENT_SWITCHCOUNT_NONZERO 100 #define CONTROLVM_RESP_EXPECTED_CHIPSET_INIT 101 - /* Maximum Limit----------------------------------------------------[200-299] */ /* BUS_CREATE */ #define CONTROLVM_RESP_ERROR_MAX_BUSES 201 /* DEVICE_CREATE */ #define CONTROLVM_RESP_ERROR_MAX_DEVICES 202 - /* Payload and Parameter Related------------------------------------[400-499] */ /* SWITCH_ATTACHEXTPORT, DEVICE_CONFIGURE */ #define CONTROLVM_RESP_PAYLOAD_INVALID 400 @@ -633,7 +630,6 @@ struct visor_controlvm_parameters_header { #define CONTROLVM_RESP_TARGET_PARAMETER_INVALID 402 /* DEVICE_CONFIGURE */ #define CONTROLVM_RESP_CLIENT_PARAMETER_INVALID 403 - /* Specified[Packet Structure] Value--------------------------------[500-599] */ /* SWITCH_ATTACHINTPORT */ /* BUS_CONFIGURE, DEVICE_CREATE, DEVICE_CONFIG, DEVICE_DESTROY */ @@ -652,25 +648,20 @@ struct visor_controlvm_parameters_header { /* Generic device callback returned error. */ /* SWITCH_ATTACHEXTPORT, SWITCH_DETACHEXTPORT, DEVICE_CONFIGURE */ #define CONTROLVM_RESP_GENERIC_DRIVER_CALLBACK_ERROR 606 - /* Bus Related------------------------------------------------------[700-799] */ /* BUS_DESTROY */ #define CONTROLVM_RESP_ERROR_BUS_DEVICE_ATTACHED 700 - /* Channel Related--------------------------------------------------[800-899] */ /* GET_CHANNELINFO, DEVICE_DESTROY */ #define CONTROLVM_RESP_CHANNEL_TYPE_UNKNOWN 800 /* DEVICE_CREATE */ #define CONTROLVM_RESP_CHANNEL_SIZE_TOO_SMALL 801 - /* Chipset Shutdown Related---------------------------------------[1000-1099] */ #define CONTROLVM_RESP_CHIPSET_SHUTDOWN_FAILED 1000 #define CONTROLVM_RESP_CHIPSET_SHUTDOWN_ALREADY_ACTIVE 1001 - /* Chipset Stop Related-------------------------------------------[1100-1199] */ #define CONTROLVM_RESP_CHIPSET_STOP_FAILED_BUS 1100 #define CONTROLVM_RESP_CHIPSET_STOP_FAILED_SWITCH 1101 - /* Device Related-------------------------------------------------[1400-1499] */ #define CONTROLVM_RESP_DEVICE_UDEV_TIMEOUT 1400 -- cgit v1.2.3 From 35709e0f900fd574092329521b5723fb6262b07f Mon Sep 17 00:00:00 2001 From: Steve Wilson Date: Fri, 30 Jun 2017 15:43:23 -0400 Subject: staging: unisys: visorbus: adjust tabs in function Removed extra tabs in visorbus_get_device_by_id function. Signed-off-by: Steve Wilson Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorchipset.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index bf6f79ea4988..973ed61703e2 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -365,9 +365,9 @@ struct visor_device *visorbus_get_device_by_id(u32 bus_no, u32 dev_no, struct device *dev_start = NULL; struct visor_device *vdev = NULL; struct visor_busdev id = { - .bus_no = bus_no, - .dev_no = dev_no - }; + .bus_no = bus_no, + .dev_no = dev_no + }; if (from) dev_start = &from->device; -- cgit v1.2.3 From b372fee1d60fb44996d833f69a6146e8717ab44d Mon Sep 17 00:00:00 2001 From: Zachary Dremann Date: Fri, 30 Jun 2017 15:43:24 -0400 Subject: staging: unisys: visorbus: Indent struct assignment correctly Several structure initializations all had their members indented with 2 tabs instead of one. Remove the extra tabs. Signed-off-by: Zachary Dremann Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorbus_main.c | 42 ++++++++++++------------- 1 file changed, 21 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index 075e817526e7..d29f9ae8ede1 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -240,23 +240,23 @@ static ssize_t typename_show(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR_RO(typename); static struct attribute *channel_attrs[] = { - &dev_attr_physaddr.attr, - &dev_attr_nbytes.attr, - &dev_attr_clientpartition.attr, - &dev_attr_typeguid.attr, - &dev_attr_zoneguid.attr, - &dev_attr_typename.attr, - NULL + &dev_attr_physaddr.attr, + &dev_attr_nbytes.attr, + &dev_attr_clientpartition.attr, + &dev_attr_typeguid.attr, + &dev_attr_zoneguid.attr, + &dev_attr_typename.attr, + NULL }; static struct attribute_group channel_attr_grp = { - .name = "channel", - .attrs = channel_attrs, + .name = "channel", + .attrs = channel_attrs, }; static const struct attribute_group *visorbus_channel_groups[] = { - &channel_attr_grp, - NULL + &channel_attr_grp, + NULL }; /* end implementation of specific channel attributes */ @@ -331,22 +331,22 @@ static ssize_t channel_id_show(struct device *dev, static DEVICE_ATTR_RO(channel_id); static struct attribute *dev_attrs[] = { - &dev_attr_partition_handle.attr, - &dev_attr_partition_guid.attr, - &dev_attr_partition_name.attr, - &dev_attr_channel_addr.attr, - &dev_attr_channel_bytes.attr, - &dev_attr_channel_id.attr, - NULL + &dev_attr_partition_handle.attr, + &dev_attr_partition_guid.attr, + &dev_attr_partition_name.attr, + &dev_attr_channel_addr.attr, + &dev_attr_channel_bytes.attr, + &dev_attr_channel_id.attr, + NULL }; static struct attribute_group dev_attr_grp = { - .attrs = dev_attrs, + .attrs = dev_attrs, }; static const struct attribute_group *visorbus_groups[] = { - &dev_attr_grp, - NULL + &dev_attr_grp, + NULL }; /* -- cgit v1.2.3 From 87408fe0d8ae56997e3ca3a13dcf8b53a38c2405 Mon Sep 17 00:00:00 2001 From: Zachary Dremann Date: Fri, 30 Jun 2017 15:43:25 -0400 Subject: staging: unisys: visorbus: use __func__ over hardcoded name As reported by checkpatch.pl, replace hardcoded uses of the current function's name in format strings with uses of __func__. Signed-off-by: Zachary Dremann Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorchipset.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 973ed61703e2..7d37a002b3b5 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -581,7 +581,7 @@ visorbus_create(struct controlvm_message *inmsg) bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL); if (bus_info && (bus_info->state.created == 1)) { dev_err(&chipset_dev->acpi_device->dev, - "failed visorbus_create: already exists\n"); + "failed %s: already exists\n", __func__); err = -EEXIST; goto err_respond; } -- cgit v1.2.3 From 7b9de71bd5d53e1f20166d7a182f277ff7bbc1f3 Mon Sep 17 00:00:00 2001 From: Erik Arfvidson Date: Fri, 30 Jun 2017 15:43:26 -0400 Subject: staging: unisys: visorbus: fix improper bracket blocks This patch fixes visorbus_main.c improper function brackets. for the following functions: partition_handle_show partition_guid_show partition_name_show channel_addr_show channel_bytes_show channel_id_show Signed-off-by: Erik Arfvidson Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorbus_main.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index d29f9ae8ede1..f884b59efe37 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -270,7 +270,8 @@ static const struct attribute_group *visorbus_channel_groups[] = { static ssize_t partition_handle_show(struct device *dev, struct device_attribute *attr, - char *buf) { + char *buf) +{ struct visor_device *vdev = to_visor_device(dev); u64 handle = visorchannel_get_clientpartition(vdev->visorchannel); @@ -280,7 +281,8 @@ static DEVICE_ATTR_RO(partition_handle); static ssize_t partition_guid_show(struct device *dev, struct device_attribute *attr, - char *buf) { + char *buf) +{ struct visor_device *vdev = to_visor_device(dev); return sprintf(buf, "{%pUb}\n", &vdev->partition_uuid); @@ -289,7 +291,8 @@ static DEVICE_ATTR_RO(partition_guid); static ssize_t partition_name_show(struct device *dev, struct device_attribute *attr, - char *buf) { + char *buf) +{ struct visor_device *vdev = to_visor_device(dev); return sprintf(buf, "%s\n", vdev->name); @@ -298,7 +301,8 @@ static DEVICE_ATTR_RO(partition_name); static ssize_t channel_addr_show(struct device *dev, struct device_attribute *attr, - char *buf) { + char *buf) +{ struct visor_device *vdev = to_visor_device(dev); u64 addr = visorchannel_get_physaddr(vdev->visorchannel); @@ -308,7 +312,8 @@ static DEVICE_ATTR_RO(channel_addr); static ssize_t channel_bytes_show(struct device *dev, struct device_attribute *attr, - char *buf) { + char *buf) +{ struct visor_device *vdev = to_visor_device(dev); u64 nbytes = visorchannel_get_nbytes(vdev->visorchannel); @@ -318,7 +323,8 @@ static DEVICE_ATTR_RO(channel_bytes); static ssize_t channel_id_show(struct device *dev, struct device_attribute *attr, - char *buf) { + char *buf) +{ struct visor_device *vdev = to_visor_device(dev); int len = 0; -- cgit v1.2.3 From 0a24e42969b8eab55dfa78b299310094adca9734 Mon Sep 17 00:00:00 2001 From: Ioana Radulescu Date: Thu, 29 Jun 2017 11:25:46 -0500 Subject: staging: fsl-dpaa2/eth: Remove dead code All possible values of the switch statement are explicitly handled, so there's no need to have a default branch. Signed-off-by: Ioana Radulescu Acked-by: Bogdan Purcareata Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c index 5312edc26f01..031179ab3a22 100644 --- a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c +++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c @@ -217,8 +217,6 @@ static void dpaa2_eth_get_ethtool_stats(struct net_device *net_dev, case 2: num_cnt = sizeof(dpni_stats.page_2) / sizeof(u64); break; - default: - break; } for (k = 0; k < num_cnt; k++) *(data + i++) = dpni_stats.raw.counter[k]; -- cgit v1.2.3 From 85bcd624399cd4feebd1f41be0079489c9cfec7f Mon Sep 17 00:00:00 2001 From: Kamal Heib Date: Fri, 30 Jun 2017 21:34:43 +0300 Subject: staging: android: ion: statify __ion_add_cma_heaps Fix the following sparse warning: symbol '__ion_add_cma_heaps' was not declared. Should it be static? Cc: Greg Kroah-Hartman Signed-off-by: Kamal Heib Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_cma_heap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c index a0949bc0dcf4..c6db9b726002 100644 --- a/drivers/staging/android/ion/ion_cma_heap.c +++ b/drivers/staging/android/ion/ion_cma_heap.c @@ -106,7 +106,7 @@ static struct ion_heap *__ion_cma_heap_create(struct cma *cma) return &cma_heap->heap; } -int __ion_add_cma_heaps(struct cma *cma, void *data) +static int __ion_add_cma_heaps(struct cma *cma, void *data) { struct ion_heap *heap; -- cgit v1.2.3 From da1fe271c665a1f598432f688119bff7c2b5e7dd Mon Sep 17 00:00:00 2001 From: Mateusz Nowotyński Date: Sun, 9 Jul 2017 18:14:38 +0200 Subject: Staging: android: remove unnecessary blank lines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removes unnecessary blank lines in android/ion/ion_cma_heap.c Signed-off-by: Mateusz Nowotyński Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_cma_heap.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c index c6db9b726002..368a592c5c7e 100644 --- a/drivers/staging/android/ion/ion_cma_heap.c +++ b/drivers/staging/android/ion/ion_cma_heap.c @@ -31,7 +31,6 @@ struct ion_cma_heap { #define to_cma_heap(x) container_of(x, struct ion_cma_heap, heap) - /* ION CMA heap operations functions */ static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer, unsigned long len, -- cgit v1.2.3 From c1116da9a2b12d1fb8b93ef2874acb3835f1d918 Mon Sep 17 00:00:00 2001 From: Mateusz Nowotyński Date: Sun, 9 Jul 2017 18:14:39 +0200 Subject: Staging: android: fix sizeof style issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Converts sizeof(type) to sizeof(variable) in android/ion/ion_cma_heap.c Signed-off-by: Mateusz Nowotyński Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_cma_heap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c index 368a592c5c7e..dd5545d9990a 100644 --- a/drivers/staging/android/ion/ion_cma_heap.c +++ b/drivers/staging/android/ion/ion_cma_heap.c @@ -45,7 +45,7 @@ static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer, if (!pages) return -ENOMEM; - table = kmalloc(sizeof(struct sg_table), GFP_KERNEL); + table = kmalloc(sizeof(*table), GFP_KERNEL); if (!table) goto err; -- cgit v1.2.3 From f0d6bd7a204fd95af1e4518503764135ba014e99 Mon Sep 17 00:00:00 2001 From: Mateusz Nowotyński Date: Sun, 9 Jul 2017 18:14:40 +0200 Subject: Staging: android: Remove unnecessary blank lines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removes unnecessary blank lines in android/ion/ion_system_heap.c Signed-off-by: Mateusz Nowotyński Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_system_heap.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 5964bf21fd80..4dc5d7a589c2 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -98,7 +98,6 @@ static void free_buffer_page(struct ion_system_heap *heap, ion_page_pool_free(pool, page); } - static struct page *alloc_largest_available(struct ion_system_heap *heap, struct ion_buffer *buffer, unsigned long size, @@ -256,7 +255,6 @@ static struct ion_heap_ops system_heap_ops = { static int ion_system_heap_debug_show(struct ion_heap *heap, struct seq_file *s, void *unused) { - struct ion_system_heap *sys_heap = container_of(heap, struct ion_system_heap, heap); -- cgit v1.2.3 From feb9828b1eb1da9c1b7caa40aaa86e4fc65c0cbd Mon Sep 17 00:00:00 2001 From: Mateusz Nowotyński Date: Sun, 9 Jul 2017 18:14:41 +0200 Subject: Staging: android: Fix code alignment issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes code alignment issue in ion/ion.h Signed-off-by: Mateusz Nowotyński Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index fa9ed81ab972..b91328a51b77 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -226,8 +226,8 @@ int ion_heap_buffer_zero(struct ion_buffer *buffer); int ion_heap_pages_zero(struct page *page, size_t size, pgprot_t pgprot); int ion_alloc(size_t len, - unsigned int heap_id_mask, - unsigned int flags); + unsigned int heap_id_mask, + unsigned int flags); /** * ion_heap_init_shrinker @@ -291,7 +291,7 @@ size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size); * flag. */ size_t ion_heap_freelist_shrink(struct ion_heap *heap, - size_t size); + size_t size); /** * ion_heap_freelist_size - returns the size of the freelist in bytes @@ -352,7 +352,7 @@ void ion_page_pool_free(struct ion_page_pool *pool, struct page *page); * returns the number of items freed in pages */ int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, - int nr_to_scan); + int nr_to_scan); long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); -- cgit v1.2.3 From 2fcd74b7c2a60bcbcdb84fce92fed2f83b247a61 Mon Sep 17 00:00:00 2001 From: Mateusz Nowotyński Date: Sun, 9 Jul 2017 18:14:42 +0200 Subject: Staging: android: use BIT macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use BIT macro instead of left shifting in android/ion/ion.h Signed-off-by: Mateusz Nowotyński Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index b91328a51b77..621e5f7ceacb 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -135,7 +135,7 @@ struct ion_heap_ops { /** * heap flags - flags between the heaps and core ion code */ -#define ION_HEAP_FLAG_DEFER_FREE (1 << 0) +#define ION_HEAP_FLAG_DEFER_FREE BIT(0) /** * private flags - flags internal to ion @@ -146,7 +146,7 @@ struct ion_heap_ops { * any buffer storage that came from the system allocator will be * returned to the system allocator. */ -#define ION_PRIV_FLAG_SHRINKER_FREE (1 << 0) +#define ION_PRIV_FLAG_SHRINKER_FREE BIT(0) /** * struct ion_heap - represents a heap in the system -- cgit v1.2.3 From f47d8b11eeaf32fa124cf006ef9f4ef6d63c9d50 Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Mon, 3 Jul 2017 19:13:34 -0400 Subject: staging: comedi: Use offset_in_page macro Use offset_in_page macro instead of (var & ~PAGE_MASK) The Coccinelle semantic patch used to make this change is as follows: // @@ unsigned long p; @@ - p & ~PAGE_MASK + offset_in_page(p) // Signed-off-by: Amitoj Kaur Chawla Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_buf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedi_buf.c b/drivers/staging/comedi/comedi_buf.c index 8e9b30b26810..b455ff6714eb 100644 --- a/drivers/staging/comedi/comedi_buf.c +++ b/drivers/staging/comedi/comedi_buf.c @@ -165,7 +165,7 @@ int comedi_buf_map_put(struct comedi_buf_map *bm) int comedi_buf_map_access(struct comedi_buf_map *bm, unsigned long offset, void *buf, int len, int write) { - unsigned int pgoff = offset & ~PAGE_MASK; + unsigned int pgoff = offset_in_page(offset); unsigned long pg = offset >> PAGE_SHIFT; int done = 0; -- cgit v1.2.3 From cb9c79a8d63ff24649eea4747487a150fc3d6ff3 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Thu, 13 Jul 2017 11:19:51 +0300 Subject: staging: ccree remove unnecessary parentheses Remove unnecessary parentheses from ccree driver code. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_aead.c | 4 ++-- drivers/staging/ccree/ssi_buffer_mgr.c | 8 ++++---- drivers/staging/ccree/ssi_driver.c | 2 +- drivers/staging/ccree/ssi_ivgen.c | 2 +- drivers/staging/ccree/ssi_request_mgr.c | 2 +- drivers/staging/ccree/ssi_sysfs.c | 8 ++++---- 6 files changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_aead.c b/drivers/staging/ccree/ssi_aead.c index 3a10c31e73ec..99eeedac5ee4 100644 --- a/drivers/staging/ccree/ssi_aead.c +++ b/drivers/staging/ccree/ssi_aead.c @@ -92,7 +92,7 @@ static void ssi_aead_exit(struct crypto_aead *tfm) struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); SSI_LOG_DEBUG("Clearing context @%p for %s\n", - crypto_aead_ctx(tfm), crypto_tfm_alg_name(&(tfm->base))); + crypto_aead_ctx(tfm), crypto_tfm_alg_name(&tfm->base)); dev = &ctx->drvdata->plat_dev->dev; /* Unmap enckey buffer */ @@ -143,7 +143,7 @@ static int ssi_aead_init(struct crypto_aead *tfm) struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); struct ssi_crypto_alg *ssi_alg = container_of(alg, struct ssi_crypto_alg, aead_alg); - SSI_LOG_DEBUG("Initializing context @%p for %s\n", ctx, crypto_tfm_alg_name(&(tfm->base))); + SSI_LOG_DEBUG("Initializing context @%p for %s\n", ctx, crypto_tfm_alg_name(&tfm->base)); /* Initialize modes in instance */ ctx->cipher_mode = ssi_alg->cipher_mode; diff --git a/drivers/staging/ccree/ssi_buffer_mgr.c b/drivers/staging/ccree/ssi_buffer_mgr.c index feeaf8db4b58..4127f9ff3b28 100644 --- a/drivers/staging/ccree/ssi_buffer_mgr.c +++ b/drivers/staging/ccree/ssi_buffer_mgr.c @@ -221,7 +221,7 @@ static int ssi_buffer_mgr_generate_mlli( /* Allocate memory from the pointed pool */ mlli_params->mlli_virt_addr = dma_pool_alloc( mlli_params->curr_pool, GFP_KERNEL, - &(mlli_params->mlli_dma_addr)); + &mlli_params->mlli_dma_addr); if (unlikely(!mlli_params->mlli_virt_addr)) { SSI_LOG_ERR("dma_pool_alloc() failed\n"); rc = -ENOMEM; @@ -249,7 +249,7 @@ static int ssi_buffer_mgr_generate_mlli( /*Calculate the current MLLI table length for the *length field in the descriptor */ - *(sg_data->mlli_nents[i]) += + *sg_data->mlli_nents[i] += (total_nents - prev_total_nents); prev_total_nents = total_nents; } @@ -1176,7 +1176,7 @@ static inline int ssi_buffer_mgr_aead_chain_data( rc = ssi_buffer_mgr_map_scatterlist(dev, req->dst, size_for_map, DMA_BIDIRECTIONAL, - &(areq_ctx->dst.nents), + &areq_ctx->dst.nents, LLI_MAX_NUM_OF_DATA_ENTRIES, &dst_last_bytes, &dst_mapped_nents); @@ -1407,7 +1407,7 @@ int ssi_buffer_mgr_map_aead_request( if (is_gcm4543) size_to_map += crypto_aead_ivsize(tfm); rc = ssi_buffer_mgr_map_scatterlist(dev, req->src, - size_to_map, DMA_BIDIRECTIONAL, &(areq_ctx->src.nents), + size_to_map, DMA_BIDIRECTIONAL, &areq_ctx->src.nents, LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES + LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy, &mapped_nents); if (unlikely(rc != 0)) { rc = -ENOMEM; diff --git a/drivers/staging/ccree/ssi_driver.c b/drivers/staging/ccree/ssi_driver.c index afb7c48d2d51..4246c9b1d05d 100644 --- a/drivers/staging/ccree/ssi_driver.c +++ b/drivers/staging/ccree/ssi_driver.c @@ -327,7 +327,7 @@ static int init_cc_resources(struct platform_device *plat_dev) } #ifdef ENABLE_CC_SYSFS - rc = ssi_sysfs_init(&(plat_dev->dev.kobj), new_drvdata); + rc = ssi_sysfs_init(&plat_dev->dev.kobj, new_drvdata); if (unlikely(rc != 0)) { SSI_LOG_ERR("init_stat_db failed\n"); goto init_cc_res_err; diff --git a/drivers/staging/ccree/ssi_ivgen.c b/drivers/staging/ccree/ssi_ivgen.c index 0260fbd08be8..f140dbc5195c 100644 --- a/drivers/staging/ccree/ssi_ivgen.c +++ b/drivers/staging/ccree/ssi_ivgen.c @@ -158,7 +158,7 @@ int ssi_ivgen_init_sram_pool(struct ssi_drvdata *drvdata) void ssi_ivgen_fini(struct ssi_drvdata *drvdata) { struct ssi_ivgen_ctx *ivgen_ctx = drvdata->ivgen_handle; - struct device *device = &(drvdata->plat_dev->dev); + struct device *device = &drvdata->plat_dev->dev; if (!ivgen_ctx) return; diff --git a/drivers/staging/ccree/ssi_request_mgr.c b/drivers/staging/ccree/ssi_request_mgr.c index 3d6020a57be1..0c8988cd22a4 100644 --- a/drivers/staging/ccree/ssi_request_mgr.c +++ b/drivers/staging/ccree/ssi_request_mgr.c @@ -317,7 +317,7 @@ int send_request( if (!is_dout) { init_completion(&ssi_req->seq_compl); ssi_req->user_cb = request_mgr_complete; - ssi_req->user_arg = &(ssi_req->seq_compl); + ssi_req->user_arg = &ssi_req->seq_compl; total_seq_len++; } diff --git a/drivers/staging/ccree/ssi_sysfs.c b/drivers/staging/ccree/ssi_sysfs.c index 28a46c7be41c..802fd498a4f5 100644 --- a/drivers/staging/ccree/ssi_sysfs.c +++ b/drivers/staging/ccree/ssi_sysfs.c @@ -257,7 +257,7 @@ void update_host_stat(unsigned int op_type, unsigned int phase, cycles_t result) unsigned long flags; spin_lock_irqsave(&stat_lock, flags); - update_db(&(stat_host_db[op_type][phase]), (unsigned int)result); + update_db(&stat_host_db[op_type][phase], (unsigned int)result); spin_unlock_irqrestore(&stat_lock, flags); } @@ -266,7 +266,7 @@ void update_cc_stat( unsigned int phase, unsigned int elapsed_cycles) { - update_db(&(stat_cc_db[op_type][phase]), elapsed_cycles); + update_db(&stat_cc_db[op_type][phase], elapsed_cycles); } void display_all_stat_db(void) @@ -388,7 +388,7 @@ static int sys_init_dir(struct sys_dir *sys_dir, struct ssi_drvdata *drvdata, /* initialize attributes list */ for (i = 0; i < num_of_attrs; ++i) - sys_dir->sys_dir_attr_list[i] = &(attrs[i].attr); + sys_dir->sys_dir_attr_list[i] = &attrs[i].attr; /* last list entry should be NULL */ sys_dir->sys_dir_attr_list[num_of_attrs] = NULL; @@ -396,7 +396,7 @@ static int sys_init_dir(struct sys_dir *sys_dir, struct ssi_drvdata *drvdata, sys_dir->sys_dir_attr_group.attrs = sys_dir->sys_dir_attr_list; return sysfs_create_group(sys_dir->sys_dir_kobj, - &(sys_dir->sys_dir_attr_group)); + &sys_dir->sys_dir_attr_group); } static void sys_free_dir(struct sys_dir *sys_dir) -- cgit v1.2.3 From 9006ec2fa4fed48f64f113f69159bcc80b7ebd1d Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Thu, 13 Jul 2017 11:19:52 +0300 Subject: staging: ccree: clean up struct ssi_aead_ctx struct ssi_aead_ctx has some nested structure defined, resulting in code accessing them to be very unreadable. Move out the nested structure definitions out of the struct and use the change to make the code accessing it more readable and better coding style compliant by shortening lines and properly matching alignment, Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_aead.c | 108 +++++++++++++++++++++++---------------- 1 file changed, 64 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_aead.c b/drivers/staging/ccree/ssi_aead.c index 99eeedac5ee4..fd37dde8188a 100644 --- a/drivers/staging/ccree/ssi_aead.c +++ b/drivers/staging/ccree/ssi_aead.c @@ -56,22 +56,26 @@ struct ssi_aead_handle { struct list_head aead_list; }; +struct cc_hmac_s { + u8 *padded_authkey; + u8 *ipad_opad; /* IPAD, OPAD*/ + dma_addr_t padded_authkey_dma_addr; + dma_addr_t ipad_opad_dma_addr; +}; + +struct cc_xcbc_s { + u8 *xcbc_keys; /* K1,K2,K3 */ + dma_addr_t xcbc_keys_dma_addr; +}; + struct ssi_aead_ctx { struct ssi_drvdata *drvdata; u8 ctr_nonce[MAX_NONCE_SIZE]; /* used for ctr3686 iv and aes ccm */ u8 *enckey; dma_addr_t enckey_dma_addr; union { - struct { - u8 *padded_authkey; - u8 *ipad_opad; /* IPAD, OPAD*/ - dma_addr_t padded_authkey_dma_addr; - dma_addr_t ipad_opad_dma_addr; - } hmac; - struct { - u8 *xcbc_keys; /* K1,K2,K3 */ - dma_addr_t xcbc_keys_dma_addr; - } xcbc; + struct cc_hmac_s hmac; + struct cc_xcbc_s xcbc; } auth_state; unsigned int enc_keylen; unsigned int auth_keylen; @@ -105,33 +109,37 @@ static void ssi_aead_exit(struct crypto_aead *tfm) } if (ctx->auth_mode == DRV_HASH_XCBC_MAC) { /* XCBC authetication */ - if (ctx->auth_state.xcbc.xcbc_keys) { + struct cc_xcbc_s *xcbc = &ctx->auth_state.xcbc; + + if (xcbc->xcbc_keys) { dma_free_coherent(dev, CC_AES_128_BIT_KEY_SIZE * 3, - ctx->auth_state.xcbc.xcbc_keys, - ctx->auth_state.xcbc.xcbc_keys_dma_addr); + xcbc->xcbc_keys, + xcbc->xcbc_keys_dma_addr); } SSI_LOG_DEBUG("Freed xcbc_keys DMA buffer xcbc_keys_dma_addr=0x%llX\n", - (unsigned long long)ctx->auth_state.xcbc.xcbc_keys_dma_addr); - ctx->auth_state.xcbc.xcbc_keys_dma_addr = 0; - ctx->auth_state.xcbc.xcbc_keys = NULL; + (unsigned long long)xcbc->xcbc_keys_dma_addr); + xcbc->xcbc_keys_dma_addr = 0; + xcbc->xcbc_keys = NULL; } else if (ctx->auth_mode != DRV_HASH_NULL) { /* HMAC auth. */ - if (ctx->auth_state.hmac.ipad_opad) { + struct cc_hmac_s *hmac = &ctx->auth_state.hmac; + + if (hmac->ipad_opad) { dma_free_coherent(dev, 2 * MAX_HMAC_DIGEST_SIZE, - ctx->auth_state.hmac.ipad_opad, - ctx->auth_state.hmac.ipad_opad_dma_addr); + hmac->ipad_opad, + hmac->ipad_opad_dma_addr); SSI_LOG_DEBUG("Freed ipad_opad DMA buffer ipad_opad_dma_addr=0x%llX\n", - (unsigned long long)ctx->auth_state.hmac.ipad_opad_dma_addr); - ctx->auth_state.hmac.ipad_opad_dma_addr = 0; - ctx->auth_state.hmac.ipad_opad = NULL; + (unsigned long long)hmac->ipad_opad_dma_addr); + hmac->ipad_opad_dma_addr = 0; + hmac->ipad_opad = NULL; } - if (ctx->auth_state.hmac.padded_authkey) { + if (hmac->padded_authkey) { dma_free_coherent(dev, MAX_HMAC_BLOCK_SIZE, - ctx->auth_state.hmac.padded_authkey, - ctx->auth_state.hmac.padded_authkey_dma_addr); + hmac->padded_authkey, + hmac->padded_authkey_dma_addr); SSI_LOG_DEBUG("Freed padded_authkey DMA buffer padded_authkey_dma_addr=0x%llX\n", - (unsigned long long)ctx->auth_state.hmac.padded_authkey_dma_addr); - ctx->auth_state.hmac.padded_authkey_dma_addr = 0; - ctx->auth_state.hmac.padded_authkey = NULL; + (unsigned long long)hmac->padded_authkey_dma_addr); + hmac->padded_authkey_dma_addr = 0; + hmac->padded_authkey = NULL; } } } @@ -165,31 +173,42 @@ static int ssi_aead_init(struct crypto_aead *tfm) /* Set default authlen value */ if (ctx->auth_mode == DRV_HASH_XCBC_MAC) { /* XCBC authetication */ + struct cc_xcbc_s *xcbc = &ctx->auth_state.xcbc; + const unsigned int key_size = CC_AES_128_BIT_KEY_SIZE * 3; + /* Allocate dma-coherent buffer for XCBC's K1+K2+K3 */ /* (and temporary for user key - up to 256b) */ - ctx->auth_state.xcbc.xcbc_keys = dma_alloc_coherent(dev, - CC_AES_128_BIT_KEY_SIZE * 3, - &ctx->auth_state.xcbc.xcbc_keys_dma_addr, GFP_KERNEL); - if (!ctx->auth_state.xcbc.xcbc_keys) { + xcbc->xcbc_keys = dma_alloc_coherent(dev, key_size, + &xcbc->xcbc_keys_dma_addr, + GFP_KERNEL); + if (!xcbc->xcbc_keys) { SSI_LOG_ERR("Failed allocating buffer for XCBC keys\n"); goto init_failed; } } else if (ctx->auth_mode != DRV_HASH_NULL) { /* HMAC authentication */ + struct cc_hmac_s *hmac = &ctx->auth_state.hmac; + const unsigned int digest_size = 2 * MAX_HMAC_DIGEST_SIZE; + dma_addr_t *pkey_dma = &hmac->padded_authkey_dma_addr; + /* Allocate dma-coherent buffer for IPAD + OPAD */ - ctx->auth_state.hmac.ipad_opad = dma_alloc_coherent(dev, - 2 * MAX_HMAC_DIGEST_SIZE, - &ctx->auth_state.hmac.ipad_opad_dma_addr, GFP_KERNEL); - if (!ctx->auth_state.hmac.ipad_opad) { + hmac->ipad_opad = dma_alloc_coherent(dev, digest_size, + &hmac->ipad_opad_dma_addr, + GFP_KERNEL); + + if (!hmac->ipad_opad) { SSI_LOG_ERR("Failed allocating IPAD/OPAD buffer\n"); goto init_failed; } + SSI_LOG_DEBUG("Allocated authkey buffer in context ctx->authkey=@%p\n", - ctx->auth_state.hmac.ipad_opad); + hmac->ipad_opad); + + hmac->padded_authkey = dma_alloc_coherent(dev, + MAX_HMAC_BLOCK_SIZE, + pkey_dma, + GFP_KERNEL); - ctx->auth_state.hmac.padded_authkey = dma_alloc_coherent(dev, - MAX_HMAC_BLOCK_SIZE, - &ctx->auth_state.hmac.padded_authkey_dma_addr, GFP_KERNEL); - if (!ctx->auth_state.hmac.padded_authkey) { + if (!hmac->padded_authkey) { SSI_LOG_ERR("failed to allocate padded_authkey\n"); goto init_failed; } @@ -295,6 +314,7 @@ static int hmac_setkey(struct cc_hw_desc *desc, struct ssi_aead_ctx *ctx) DRV_HASH_HW_SHA1 : DRV_HASH_HW_SHA256; unsigned int digest_size = (ctx->auth_mode == DRV_HASH_SHA1) ? CC_SHA1_DIGEST_SIZE : CC_SHA256_DIGEST_SIZE; + struct cc_hmac_s *hmac = &ctx->auth_state.hmac; int idx = 0; int i; @@ -331,7 +351,7 @@ static int hmac_setkey(struct cc_hw_desc *desc, struct ssi_aead_ctx *ctx) /* Perform HASH update */ hw_desc_init(&desc[idx]); set_din_type(&desc[idx], DMA_DLLI, - ctx->auth_state.hmac.padded_authkey_dma_addr, + hmac->padded_authkey_dma_addr, SHA256_BLOCK_SIZE, NS_BIT); set_cipher_mode(&desc[idx], hash_mode); set_xor_active(&desc[idx]); @@ -342,8 +362,8 @@ static int hmac_setkey(struct cc_hw_desc *desc, struct ssi_aead_ctx *ctx) hw_desc_init(&desc[idx]); set_cipher_mode(&desc[idx], hash_mode); set_dout_dlli(&desc[idx], - (ctx->auth_state.hmac.ipad_opad_dma_addr + - digest_ofs), digest_size, NS_BIT, 0); + (hmac->ipad_opad_dma_addr + digest_ofs), + digest_size, NS_BIT, 0); set_flow_mode(&desc[idx], S_HASH_to_DOUT); set_setup_mode(&desc[idx], SETUP_WRITE_STATE0); set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED); -- cgit v1.2.3 From 0fca74fbcc6cf9738bb73a88de8d5775a04f88b8 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Thu, 13 Jul 2017 11:19:53 +0300 Subject: staging: ccree: use proper printk format for dma_addr_t Fix needless casting to unsigned long long in printk for DMA addresses by using proper %pad format. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_aead.c | 16 ++++---- drivers/staging/ccree/ssi_buffer_mgr.c | 48 ++++++++++++------------ drivers/staging/ccree/ssi_cipher.c | 20 +++++----- drivers/staging/ccree/ssi_driver.c | 6 +-- drivers/staging/ccree/ssi_hash.c | 65 ++++++++++++++++----------------- drivers/staging/ccree/ssi_request_mgr.c | 8 ++-- 6 files changed, 81 insertions(+), 82 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_aead.c b/drivers/staging/ccree/ssi_aead.c index fd37dde8188a..43455b930a1e 100644 --- a/drivers/staging/ccree/ssi_aead.c +++ b/drivers/staging/ccree/ssi_aead.c @@ -102,8 +102,8 @@ static void ssi_aead_exit(struct crypto_aead *tfm) /* Unmap enckey buffer */ if (ctx->enckey) { dma_free_coherent(dev, AES_MAX_KEY_SIZE, ctx->enckey, ctx->enckey_dma_addr); - SSI_LOG_DEBUG("Freed enckey DMA buffer enckey_dma_addr=0x%llX\n", - (unsigned long long)ctx->enckey_dma_addr); + SSI_LOG_DEBUG("Freed enckey DMA buffer enckey_dma_addr=%pad\n", + ctx->enckey_dma_addr); ctx->enckey_dma_addr = 0; ctx->enckey = NULL; } @@ -116,8 +116,8 @@ static void ssi_aead_exit(struct crypto_aead *tfm) xcbc->xcbc_keys, xcbc->xcbc_keys_dma_addr); } - SSI_LOG_DEBUG("Freed xcbc_keys DMA buffer xcbc_keys_dma_addr=0x%llX\n", - (unsigned long long)xcbc->xcbc_keys_dma_addr); + SSI_LOG_DEBUG("Freed xcbc_keys DMA buffer xcbc_keys_dma_addr=%pad\n", + xcbc->xcbc_keys_dma_addr); xcbc->xcbc_keys_dma_addr = 0; xcbc->xcbc_keys = NULL; } else if (ctx->auth_mode != DRV_HASH_NULL) { /* HMAC auth. */ @@ -127,8 +127,8 @@ static void ssi_aead_exit(struct crypto_aead *tfm) dma_free_coherent(dev, 2 * MAX_HMAC_DIGEST_SIZE, hmac->ipad_opad, hmac->ipad_opad_dma_addr); - SSI_LOG_DEBUG("Freed ipad_opad DMA buffer ipad_opad_dma_addr=0x%llX\n", - (unsigned long long)hmac->ipad_opad_dma_addr); + SSI_LOG_DEBUG("Freed ipad_opad DMA buffer ipad_opad_dma_addr=%pad\n", + hmac->ipad_opad_dma_addr); hmac->ipad_opad_dma_addr = 0; hmac->ipad_opad = NULL; } @@ -136,8 +136,8 @@ static void ssi_aead_exit(struct crypto_aead *tfm) dma_free_coherent(dev, MAX_HMAC_BLOCK_SIZE, hmac->padded_authkey, hmac->padded_authkey_dma_addr); - SSI_LOG_DEBUG("Freed padded_authkey DMA buffer padded_authkey_dma_addr=0x%llX\n", - (unsigned long long)hmac->padded_authkey_dma_addr); + SSI_LOG_DEBUG("Freed padded_authkey DMA buffer padded_authkey_dma_addr=%pad\n", + hmac->padded_authkey_dma_addr); hmac->padded_authkey_dma_addr = 0; hmac->padded_authkey = NULL; } diff --git a/drivers/staging/ccree/ssi_buffer_mgr.c b/drivers/staging/ccree/ssi_buffer_mgr.c index 4127f9ff3b28..dcd78f6d4d0b 100644 --- a/drivers/staging/ccree/ssi_buffer_mgr.c +++ b/drivers/staging/ccree/ssi_buffer_mgr.c @@ -259,9 +259,9 @@ static int ssi_buffer_mgr_generate_mlli( mlli_params->mlli_len = (total_nents * LLI_ENTRY_BYTE_SIZE); SSI_LOG_DEBUG("MLLI params: " - "virt_addr=%pK dma_addr=0x%llX mlli_len=0x%X\n", + "virt_addr=%pK dma_addr=%pad mlli_len=0x%X\n", mlli_params->mlli_virt_addr, - (unsigned long long)mlli_params->mlli_dma_addr, + mlli_params->mlli_dma_addr, mlli_params->mlli_len); build_mlli_exit: @@ -275,9 +275,9 @@ static inline void ssi_buffer_mgr_add_buffer_entry( { unsigned int index = sgl_data->num_of_buffers; - SSI_LOG_DEBUG("index=%u single_buff=0x%llX " + SSI_LOG_DEBUG("index=%u single_buff=%pad " "buffer_len=0x%08X is_last=%d\n", - index, (unsigned long long)buffer_dma, buffer_len, is_last_entry); + index, buffer_dma, buffer_len, is_last_entry); sgl_data->nents[index] = 1; sgl_data->entry[index].buffer_dma = buffer_dma; sgl_data->offset[index] = 0; @@ -358,10 +358,10 @@ static int ssi_buffer_mgr_map_scatterlist( SSI_LOG_ERR("dma_map_sg() single buffer failed\n"); return -ENOMEM; } - SSI_LOG_DEBUG("Mapped sg: dma_address=0x%llX " + SSI_LOG_DEBUG("Mapped sg: dma_address=%pad " "page=%p addr=%pK offset=%u " "length=%u\n", - (unsigned long long)sg_dma_address(sg), + sg_dma_address(sg), sg_page(sg), sg_virt(sg), sg->offset, sg->length); @@ -422,10 +422,10 @@ ssi_aead_handle_config_buf(struct device *dev, "config buffer failed\n"); return -ENOMEM; } - SSI_LOG_DEBUG("Mapped curr_buff: dma_address=0x%llX " + SSI_LOG_DEBUG("Mapped curr_buff: dma_address=%pad " "page=%p addr=%pK " "offset=%u length=%u\n", - (unsigned long long)sg_dma_address(&areq_ctx->ccm_adata_sg), + sg_dma_address(&areq_ctx->ccm_adata_sg), sg_page(&areq_ctx->ccm_adata_sg), sg_virt(&areq_ctx->ccm_adata_sg), areq_ctx->ccm_adata_sg.offset, @@ -455,10 +455,10 @@ static inline int ssi_ahash_handle_curr_buf(struct device *dev, "src buffer failed\n"); return -ENOMEM; } - SSI_LOG_DEBUG("Mapped curr_buff: dma_address=0x%llX " + SSI_LOG_DEBUG("Mapped curr_buff: dma_address=%pad " "page=%p addr=%pK " "offset=%u length=%u\n", - (unsigned long long)sg_dma_address(areq_ctx->buff_sg), + sg_dma_address(areq_ctx->buff_sg), sg_page(areq_ctx->buff_sg), sg_virt(areq_ctx->buff_sg), areq_ctx->buff_sg->offset, @@ -482,8 +482,8 @@ void ssi_buffer_mgr_unmap_blkcipher_request( struct blkcipher_req_ctx *req_ctx = (struct blkcipher_req_ctx *)ctx; if (likely(req_ctx->gen_ctx.iv_dma_addr != 0)) { - SSI_LOG_DEBUG("Unmapped iv: iv_dma_addr=0x%llX iv_size=%u\n", - (unsigned long long)req_ctx->gen_ctx.iv_dma_addr, + SSI_LOG_DEBUG("Unmapped iv: iv_dma_addr=%pad iv_size=%u\n", + req_ctx->gen_ctx.iv_dma_addr, ivsize); dma_unmap_single(dev, req_ctx->gen_ctx.iv_dma_addr, ivsize, @@ -542,9 +542,9 @@ int ssi_buffer_mgr_map_blkcipher_request( "for DMA failed\n", ivsize, info); return -ENOMEM; } - SSI_LOG_DEBUG("Mapped iv %u B at va=%pK to dma=0x%llX\n", + SSI_LOG_DEBUG("Mapped iv %u B at va=%pK to dma=%pad\n", ivsize, info, - (unsigned long long)req_ctx->gen_ctx.iv_dma_addr); + req_ctx->gen_ctx.iv_dma_addr); } else { req_ctx->gen_ctx.iv_dma_addr = 0; } @@ -673,8 +673,8 @@ void ssi_buffer_mgr_unmap_aead_request( *allocated and should be released */ if (areq_ctx->mlli_params.curr_pool) { - SSI_LOG_DEBUG("free MLLI buffer: dma=0x%08llX virt=%pK\n", - (unsigned long long)areq_ctx->mlli_params.mlli_dma_addr, + SSI_LOG_DEBUG("free MLLI buffer: dma=%pad virt=%pK\n", + areq_ctx->mlli_params.mlli_dma_addr, areq_ctx->mlli_params.mlli_virt_addr); dma_pool_free(areq_ctx->mlli_params.curr_pool, areq_ctx->mlli_params.mlli_virt_addr, @@ -791,9 +791,9 @@ static inline int ssi_buffer_mgr_aead_chain_iv( goto chain_iv_exit; } - SSI_LOG_DEBUG("Mapped iv %u B at va=%pK to dma=0x%llX\n", + SSI_LOG_DEBUG("Mapped iv %u B at va=%pK to dma=%pad\n", hw_iv_size, req->iv, - (unsigned long long)areq_ctx->gen_ctx.iv_dma_addr); + areq_ctx->gen_ctx.iv_dma_addr); if (do_chain && areq_ctx->plaintext_authenticate_only) { // TODO: what about CTR?? ask Ron struct crypto_aead *tfm = crypto_aead_reqtfm(req); unsigned int iv_size_to_authenc = crypto_aead_ivsize(tfm); @@ -1716,8 +1716,8 @@ void ssi_buffer_mgr_unmap_hash_request( *allocated and should be released */ if (areq_ctx->mlli_params.curr_pool) { - SSI_LOG_DEBUG("free MLLI buffer: dma=0x%llX virt=%pK\n", - (unsigned long long)areq_ctx->mlli_params.mlli_dma_addr, + SSI_LOG_DEBUG("free MLLI buffer: dma=%pad virt=%pK\n", + areq_ctx->mlli_params.mlli_dma_addr, areq_ctx->mlli_params.mlli_virt_addr); dma_pool_free(areq_ctx->mlli_params.curr_pool, areq_ctx->mlli_params.mlli_virt_addr, @@ -1725,9 +1725,9 @@ void ssi_buffer_mgr_unmap_hash_request( } if ((src) && likely(areq_ctx->in_nents != 0)) { - SSI_LOG_DEBUG("Unmapped sg src: virt=%pK dma=0x%llX len=0x%X\n", + SSI_LOG_DEBUG("Unmapped sg src: virt=%pK dma=%pad len=0x%X\n", sg_virt(src), - (unsigned long long)sg_dma_address(src), + sg_dma_address(src), sg_dma_len(src)); dma_unmap_sg(dev, src, areq_ctx->in_nents, DMA_TO_DEVICE); @@ -1735,9 +1735,9 @@ void ssi_buffer_mgr_unmap_hash_request( if (*prev_len != 0) { SSI_LOG_DEBUG("Unmapped buffer: areq_ctx->buff_sg=%pK" - " dma=0x%llX len 0x%X\n", + " dma=%pad len 0x%X\n", sg_virt(areq_ctx->buff_sg), - (unsigned long long)sg_dma_address(areq_ctx->buff_sg), + sg_dma_address(areq_ctx->buff_sg), sg_dma_len(areq_ctx->buff_sg)); dma_unmap_sg(dev, areq_ctx->buff_sg, 1, DMA_TO_DEVICE); if (!do_revert) { diff --git a/drivers/staging/ccree/ssi_cipher.c b/drivers/staging/ccree/ssi_cipher.c index f05ba7070cd3..10be9270d749 100644 --- a/drivers/staging/ccree/ssi_cipher.c +++ b/drivers/staging/ccree/ssi_cipher.c @@ -209,9 +209,9 @@ static int ssi_blkcipher_init(struct crypto_tfm *tfm) max_key_buf_size, ctx_p->user.key); return -ENOMEM; } - SSI_LOG_DEBUG("Mapped key %u B at va=%pK to dma=0x%llX\n", + SSI_LOG_DEBUG("Mapped key %u B at va=%pK to dma=%pad\n", max_key_buf_size, ctx_p->user.key, - (unsigned long long)ctx_p->user.key_dma_addr); + ctx_p->user.key_dma_addr); if (ctx_p->cipher_mode == DRV_CIPHER_ESSIV) { /* Alloc hash tfm for essiv */ @@ -243,8 +243,8 @@ static void ssi_blkcipher_exit(struct crypto_tfm *tfm) /* Unmap key buffer */ dma_unmap_single(dev, ctx_p->user.key_dma_addr, max_key_buf_size, DMA_TO_DEVICE); - SSI_LOG_DEBUG("Unmapped key buffer key_dma_addr=0x%llX\n", - (unsigned long long)ctx_p->user.key_dma_addr); + SSI_LOG_DEBUG("Unmapped key buffer key_dma_addr=%pad\n", + ctx_p->user.key_dma_addr); /* Free key buffer in context */ kfree(ctx_p->user.key); @@ -619,10 +619,10 @@ ssi_blkcipher_create_data_desc( } /* Process */ if (likely(req_ctx->dma_buf_type == SSI_DMA_BUF_DLLI)) { - SSI_LOG_DEBUG(" data params addr 0x%llX length 0x%X \n", - (unsigned long long)sg_dma_address(src), nbytes); - SSI_LOG_DEBUG(" data params addr 0x%llX length 0x%X \n", - (unsigned long long)sg_dma_address(dst), nbytes); + SSI_LOG_DEBUG(" data params addr %pad length 0x%X \n", + sg_dma_address(src), nbytes); + SSI_LOG_DEBUG(" data params addr %pad length 0x%X \n", + sg_dma_address(dst), nbytes); hw_desc_init(&desc[*seq_size]); set_din_type(&desc[*seq_size], DMA_DLLI, sg_dma_address(src), nbytes, NS_BIT); @@ -635,9 +635,9 @@ ssi_blkcipher_create_data_desc( (*seq_size)++; } else { /* bypass */ - SSI_LOG_DEBUG(" bypass params addr 0x%llX " + SSI_LOG_DEBUG(" bypass params addr %pad " "length 0x%X addr 0x%08X\n", - (unsigned long long)req_ctx->mlli_params.mlli_dma_addr, + req_ctx->mlli_params.mlli_dma_addr, req_ctx->mlli_params.mlli_len, (unsigned int)ctx_p->drvdata->mlli_sram_addr); hw_desc_init(&desc[*seq_size]); diff --git a/drivers/staging/ccree/ssi_driver.c b/drivers/staging/ccree/ssi_driver.c index 4246c9b1d05d..d7b9a636d907 100644 --- a/drivers/staging/ccree/ssi_driver.c +++ b/drivers/staging/ccree/ssi_driver.c @@ -250,10 +250,10 @@ static int init_cc_resources(struct platform_device *plat_dev) rc = -ENODEV; goto init_cc_res_err; } - SSI_LOG_DEBUG("Got MEM resource (%s): start=0x%llX end=0x%llX\n", + SSI_LOG_DEBUG("Got MEM resource (%s): start=%pad end=%pad\n", new_drvdata->res_mem->name, - (unsigned long long)new_drvdata->res_mem->start, - (unsigned long long)new_drvdata->res_mem->end); + new_drvdata->res_mem->start, + new_drvdata->res_mem->end); /* Map registers space */ req_mem_cc_regs = request_mem_region(new_drvdata->res_mem->start, resource_size(new_drvdata->res_mem), "arm_cc7x_regs"); if (unlikely(!req_mem_cc_regs)) { diff --git a/drivers/staging/ccree/ssi_hash.c b/drivers/staging/ccree/ssi_hash.c index ffd1f984fba5..658e1988016d 100644 --- a/drivers/staging/ccree/ssi_hash.c +++ b/drivers/staging/ccree/ssi_hash.c @@ -139,9 +139,9 @@ static int ssi_hash_map_result(struct device *dev, return -ENOMEM; } SSI_LOG_DEBUG("Mapped digest result buffer %u B " - "at va=%pK to dma=0x%llX\n", + "at va=%pK to dma=%pad\n", digestsize, state->digest_result_buff, - (unsigned long long)state->digest_result_dma_addr); + state->digest_result_dma_addr); return 0; } @@ -203,9 +203,9 @@ static int ssi_hash_map_request(struct device *dev, ctx->inter_digestsize, state->digest_buff); goto fail3; } - SSI_LOG_DEBUG("Mapped digest %d B at va=%pK to dma=0x%llX\n", + SSI_LOG_DEBUG("Mapped digest %d B at va=%pK to dma=%pad\n", ctx->inter_digestsize, state->digest_buff, - (unsigned long long)state->digest_buff_dma_addr); + state->digest_buff_dma_addr); if (is_hmac) { dma_sync_single_for_cpu(dev, ctx->digest_buff_dma_addr, ctx->inter_digestsize, DMA_BIDIRECTIONAL); @@ -252,9 +252,9 @@ static int ssi_hash_map_request(struct device *dev, HASH_LEN_SIZE, state->digest_bytes_len); goto fail4; } - SSI_LOG_DEBUG("Mapped digest len %u B at va=%pK to dma=0x%llX\n", + SSI_LOG_DEBUG("Mapped digest len %u B at va=%pK to dma=%pad\n", HASH_LEN_SIZE, state->digest_bytes_len, - (unsigned long long)state->digest_bytes_len_dma_addr); + state->digest_bytes_len_dma_addr); } else { state->digest_bytes_len_dma_addr = 0; } @@ -266,9 +266,9 @@ static int ssi_hash_map_request(struct device *dev, ctx->inter_digestsize, state->opad_digest_buff); goto fail5; } - SSI_LOG_DEBUG("Mapped opad digest %d B at va=%pK to dma=0x%llX\n", + SSI_LOG_DEBUG("Mapped opad digest %d B at va=%pK to dma=%pad\n", ctx->inter_digestsize, state->opad_digest_buff, - (unsigned long long)state->opad_digest_dma_addr); + state->opad_digest_dma_addr); } else { state->opad_digest_dma_addr = 0; } @@ -321,22 +321,22 @@ static void ssi_hash_unmap_request(struct device *dev, if (state->digest_buff_dma_addr != 0) { dma_unmap_single(dev, state->digest_buff_dma_addr, ctx->inter_digestsize, DMA_BIDIRECTIONAL); - SSI_LOG_DEBUG("Unmapped digest-buffer: digest_buff_dma_addr=0x%llX\n", - (unsigned long long)state->digest_buff_dma_addr); + SSI_LOG_DEBUG("Unmapped digest-buffer: digest_buff_dma_addr=%pad\n", + state->digest_buff_dma_addr); state->digest_buff_dma_addr = 0; } if (state->digest_bytes_len_dma_addr != 0) { dma_unmap_single(dev, state->digest_bytes_len_dma_addr, HASH_LEN_SIZE, DMA_BIDIRECTIONAL); - SSI_LOG_DEBUG("Unmapped digest-bytes-len buffer: digest_bytes_len_dma_addr=0x%llX\n", - (unsigned long long)state->digest_bytes_len_dma_addr); + SSI_LOG_DEBUG("Unmapped digest-bytes-len buffer: digest_bytes_len_dma_addr=%pad\n", + state->digest_bytes_len_dma_addr); state->digest_bytes_len_dma_addr = 0; } if (state->opad_digest_dma_addr != 0) { dma_unmap_single(dev, state->opad_digest_dma_addr, ctx->inter_digestsize, DMA_BIDIRECTIONAL); - SSI_LOG_DEBUG("Unmapped opad-digest: opad_digest_dma_addr=0x%llX\n", - (unsigned long long)state->opad_digest_dma_addr); + SSI_LOG_DEBUG("Unmapped opad-digest: opad_digest_dma_addr=%pad\n", + state->opad_digest_dma_addr); state->opad_digest_dma_addr = 0; } @@ -358,9 +358,9 @@ static void ssi_hash_unmap_result(struct device *dev, digestsize, DMA_BIDIRECTIONAL); SSI_LOG_DEBUG("unmpa digest result buffer " - "va (%pK) pa (%llx) len %u\n", + "va (%pK) pa (%pad) len %u\n", state->digest_result_buff, - (unsigned long long)state->digest_result_dma_addr, + state->digest_result_dma_addr, digestsize); memcpy(result, state->digest_result_buff, @@ -1003,9 +1003,8 @@ static int ssi_hash_setkey(void *hash, " DMA failed\n", key, keylen); return -ENOMEM; } - SSI_LOG_DEBUG("mapping key-buffer: key_dma_addr=0x%llX " - "keylen=%u\n", - (unsigned long long)ctx->key_params.key_dma_addr, + SSI_LOG_DEBUG("mapping key-buffer: key_dma_addr=%pad " + "keylen=%u\n", ctx->key_params.key_dma_addr, ctx->key_params.keylen); if (keylen > blocksize) { @@ -1148,8 +1147,8 @@ out: dma_unmap_single(&ctx->drvdata->plat_dev->dev, ctx->key_params.key_dma_addr, ctx->key_params.keylen, DMA_TO_DEVICE); - SSI_LOG_DEBUG("Unmapped key-buffer: key_dma_addr=0x%llX keylen=%u\n", - (unsigned long long)ctx->key_params.key_dma_addr, + SSI_LOG_DEBUG("Unmapped key-buffer: key_dma_addr=%pad keylen=%u\n", + ctx->key_params.key_dma_addr, ctx->key_params.keylen); } return rc; @@ -1186,9 +1185,9 @@ static int ssi_xcbc_setkey(struct crypto_ahash *ahash, " DMA failed\n", key, keylen); return -ENOMEM; } - SSI_LOG_DEBUG("mapping key-buffer: key_dma_addr=0x%llX " + SSI_LOG_DEBUG("mapping key-buffer: key_dma_addr=%pad " "keylen=%u\n", - (unsigned long long)ctx->key_params.key_dma_addr, + ctx->key_params.key_dma_addr, ctx->key_params.keylen); ctx->is_hmac = true; @@ -1235,8 +1234,8 @@ static int ssi_xcbc_setkey(struct crypto_ahash *ahash, dma_unmap_single(&ctx->drvdata->plat_dev->dev, ctx->key_params.key_dma_addr, ctx->key_params.keylen, DMA_TO_DEVICE); - SSI_LOG_DEBUG("Unmapped key-buffer: key_dma_addr=0x%llX keylen=%u\n", - (unsigned long long)ctx->key_params.key_dma_addr, + SSI_LOG_DEBUG("Unmapped key-buffer: key_dma_addr=%pad keylen=%u\n", + ctx->key_params.key_dma_addr, ctx->key_params.keylen); return rc; @@ -1291,8 +1290,8 @@ static void ssi_hash_free_ctx(struct ssi_hash_ctx *ctx) dma_unmap_single(dev, ctx->digest_buff_dma_addr, sizeof(ctx->digest_buff), DMA_BIDIRECTIONAL); SSI_LOG_DEBUG("Unmapped digest-buffer: " - "digest_buff_dma_addr=0x%llX\n", - (unsigned long long)ctx->digest_buff_dma_addr); + "digest_buff_dma_addr=%pad\n", + ctx->digest_buff_dma_addr); ctx->digest_buff_dma_addr = 0; } if (ctx->opad_tmp_keys_dma_addr != 0) { @@ -1300,8 +1299,8 @@ static void ssi_hash_free_ctx(struct ssi_hash_ctx *ctx) sizeof(ctx->opad_tmp_keys_buff), DMA_BIDIRECTIONAL); SSI_LOG_DEBUG("Unmapped opad-digest: " - "opad_tmp_keys_dma_addr=0x%llX\n", - (unsigned long long)ctx->opad_tmp_keys_dma_addr); + "opad_tmp_keys_dma_addr=%pad\n", + ctx->opad_tmp_keys_dma_addr); ctx->opad_tmp_keys_dma_addr = 0; } @@ -1320,9 +1319,9 @@ static int ssi_hash_alloc_ctx(struct ssi_hash_ctx *ctx) sizeof(ctx->digest_buff), ctx->digest_buff); goto fail; } - SSI_LOG_DEBUG("Mapped digest %zu B at va=%pK to dma=0x%llX\n", + SSI_LOG_DEBUG("Mapped digest %zu B at va=%pK to dma=%pad\n", sizeof(ctx->digest_buff), ctx->digest_buff, - (unsigned long long)ctx->digest_buff_dma_addr); + ctx->digest_buff_dma_addr); ctx->opad_tmp_keys_dma_addr = dma_map_single(dev, (void *)ctx->opad_tmp_keys_buff, sizeof(ctx->opad_tmp_keys_buff), DMA_BIDIRECTIONAL); if (dma_mapping_error(dev, ctx->opad_tmp_keys_dma_addr)) { @@ -1331,9 +1330,9 @@ static int ssi_hash_alloc_ctx(struct ssi_hash_ctx *ctx) ctx->opad_tmp_keys_buff); goto fail; } - SSI_LOG_DEBUG("Mapped opad_tmp_keys %zu B at va=%pK to dma=0x%llX\n", + SSI_LOG_DEBUG("Mapped opad_tmp_keys %zu B at va=%pK to dma=%pad\n", sizeof(ctx->opad_tmp_keys_buff), ctx->opad_tmp_keys_buff, - (unsigned long long)ctx->opad_tmp_keys_dma_addr); + ctx->opad_tmp_keys_dma_addr); ctx->is_hmac = false; return 0; diff --git a/drivers/staging/ccree/ssi_request_mgr.c b/drivers/staging/ccree/ssi_request_mgr.c index 0c8988cd22a4..3f39150cda4f 100644 --- a/drivers/staging/ccree/ssi_request_mgr.c +++ b/drivers/staging/ccree/ssi_request_mgr.c @@ -322,11 +322,11 @@ int send_request( } if (ssi_req->ivgen_dma_addr_len > 0) { - SSI_LOG_DEBUG("Acquire IV from pool into %d DMA addresses 0x%llX, 0x%llX, 0x%llX, IV-size=%u\n", + SSI_LOG_DEBUG("Acquire IV from pool into %d DMA addresses %pad, %pad, %pad, IV-size=%u\n", ssi_req->ivgen_dma_addr_len, - (unsigned long long)ssi_req->ivgen_dma_addr[0], - (unsigned long long)ssi_req->ivgen_dma_addr[1], - (unsigned long long)ssi_req->ivgen_dma_addr[2], + ssi_req->ivgen_dma_addr[0], + ssi_req->ivgen_dma_addr[1], + ssi_req->ivgen_dma_addr[2], ssi_req->ivgen_size); /* Acquire IV from pool */ -- cgit v1.2.3 From 42886fab0d0265b6b00cdab1af85cfe7f533fb84 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Thu, 13 Jul 2017 11:19:56 +0300 Subject: staging: ccree: CamelCase to snake_case in func vars Turn local vars and function parameters names in CamelCase to snake_case. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_aead.c | 26 +++++++++++++------------- drivers/staging/ccree/ssi_buffer_mgr.c | 15 ++++++++------- drivers/staging/ccree/ssi_hash.c | 29 +++++++++++++++-------------- 3 files changed, 36 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_aead.c b/drivers/staging/ccree/ssi_aead.c index 43455b930a1e..84ae173d4994 100644 --- a/drivers/staging/ccree/ssi_aead.c +++ b/drivers/staging/ccree/ssi_aead.c @@ -308,7 +308,7 @@ static int xcbc_setkey(struct cc_hw_desc *desc, struct ssi_aead_ctx *ctx) static int hmac_setkey(struct cc_hw_desc *desc, struct ssi_aead_ctx *ctx) { - unsigned int hmacPadConst[2] = { HMAC_IPAD_CONST, HMAC_OPAD_CONST }; + unsigned int hmac_pad_const[2] = { HMAC_IPAD_CONST, HMAC_OPAD_CONST }; unsigned int digest_ofs = 0; unsigned int hash_mode = (ctx->auth_mode == DRV_HASH_SHA1) ? DRV_HASH_HW_SHA1 : DRV_HASH_HW_SHA256; @@ -342,7 +342,7 @@ static int hmac_setkey(struct cc_hw_desc *desc, struct ssi_aead_ctx *ctx) /* Prepare ipad key */ hw_desc_init(&desc[idx]); - set_xor_val(&desc[idx], hmacPadConst[i]); + set_xor_val(&desc[idx], hmac_pad_const[i]); set_cipher_mode(&desc[idx], hash_mode); set_flow_mode(&desc[idx], S_DIN_to_HASH); set_setup_mode(&desc[idx], SETUP_LOAD_STATE1); @@ -1380,27 +1380,27 @@ data_size_err: } #if SSI_CC_HAS_AES_CCM -static unsigned int format_ccm_a0(u8 *pA0Buff, u32 headerSize) +static unsigned int format_ccm_a0(u8 *pa0_buff, u32 header_size) { unsigned int len = 0; - if (headerSize == 0) + if (header_size == 0) return 0; - if (headerSize < ((1UL << 16) - (1UL << 8))) { + if (header_size < ((1UL << 16) - (1UL << 8))) { len = 2; - pA0Buff[0] = (headerSize >> 8) & 0xFF; - pA0Buff[1] = headerSize & 0xFF; + pa0_buff[0] = (header_size >> 8) & 0xFF; + pa0_buff[1] = header_size & 0xFF; } else { len = 6; - pA0Buff[0] = 0xFF; - pA0Buff[1] = 0xFE; - pA0Buff[2] = (headerSize >> 24) & 0xFF; - pA0Buff[3] = (headerSize >> 16) & 0xFF; - pA0Buff[4] = (headerSize >> 8) & 0xFF; - pA0Buff[5] = headerSize & 0xFF; + pa0_buff[0] = 0xFF; + pa0_buff[1] = 0xFE; + pa0_buff[2] = (header_size >> 24) & 0xFF; + pa0_buff[3] = (header_size >> 16) & 0xFF; + pa0_buff[4] = (header_size >> 8) & 0xFF; + pa0_buff[5] = header_size & 0xFF; } return len; diff --git a/drivers/staging/ccree/ssi_buffer_mgr.c b/drivers/staging/ccree/ssi_buffer_mgr.c index dcd78f6d4d0b..b451144cbc75 100644 --- a/drivers/staging/ccree/ssi_buffer_mgr.c +++ b/drivers/staging/ccree/ssi_buffer_mgr.c @@ -182,8 +182,8 @@ static inline int ssi_buffer_mgr_render_buff_to_mlli( } static inline int ssi_buffer_mgr_render_scatterlist_to_mlli( - struct scatterlist *sgl, u32 sgl_data_len, u32 sglOffset, u32 *curr_nents, - u32 **mlli_entry_pp) + struct scatterlist *sgl, u32 sgl_data_len, u32 sgl_offset, + u32 *curr_nents, u32 **mlli_entry_pp) { struct scatterlist *curr_sgl = sgl; u32 *mlli_entry_p = *mlli_entry_pp; @@ -192,16 +192,17 @@ static inline int ssi_buffer_mgr_render_scatterlist_to_mlli( for ( ; (curr_sgl) && (sgl_data_len != 0); curr_sgl = sg_next(curr_sgl)) { u32 entry_data_len = - (sgl_data_len > sg_dma_len(curr_sgl) - sglOffset) ? - sg_dma_len(curr_sgl) - sglOffset : sgl_data_len; + (sgl_data_len > sg_dma_len(curr_sgl) - sgl_offset) ? + sg_dma_len(curr_sgl) - sgl_offset : + sgl_data_len; sgl_data_len -= entry_data_len; rc = ssi_buffer_mgr_render_buff_to_mlli( - sg_dma_address(curr_sgl) + sglOffset, entry_data_len, curr_nents, - &mlli_entry_p); + sg_dma_address(curr_sgl) + sgl_offset, entry_data_len, + curr_nents, &mlli_entry_p); if (rc != 0) return rc; - sglOffset = 0; + sgl_offset = 0; } *mlli_entry_pp = mlli_entry_p; return 0; diff --git a/drivers/staging/ccree/ssi_hash.c b/drivers/staging/ccree/ssi_hash.c index 658e1988016d..748dd2133686 100644 --- a/drivers/staging/ccree/ssi_hash.c +++ b/drivers/staging/ccree/ssi_hash.c @@ -967,7 +967,7 @@ static int ssi_hash_setkey(void *hash, unsigned int keylen, bool synchronize) { - unsigned int hmacPadConst[2] = { HMAC_IPAD_CONST, HMAC_OPAD_CONST }; + unsigned int hmac_pad_const[2] = { HMAC_IPAD_CONST, HMAC_OPAD_CONST }; struct ssi_crypto_req ssi_req = {}; struct ssi_hash_ctx *ctx = NULL; int blocksize = 0; @@ -1108,7 +1108,7 @@ static int ssi_hash_setkey(void *hash, /* Prepare ipad key */ hw_desc_init(&desc[idx]); - set_xor_val(&desc[idx], hmacPadConst[i]); + set_xor_val(&desc[idx], hmac_pad_const[i]); set_cipher_mode(&desc[idx], ctx->hw_mode); set_flow_mode(&desc[idx], S_DIN_to_HASH); set_setup_mode(&desc[idx], SETUP_LOAD_STATE1); @@ -1441,18 +1441,19 @@ static int ssi_mac_final(struct ahash_request *req) struct cc_hw_desc desc[SSI_MAX_AHASH_SEQ_LEN]; int idx = 0; int rc = 0; - u32 keySize, keyLen; + u32 key_size, key_len; u32 digestsize = crypto_ahash_digestsize(tfm); u32 rem_cnt = state->buff_index ? state->buff1_cnt : state->buff0_cnt; if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC) { - keySize = CC_AES_128_BIT_KEY_SIZE; - keyLen = CC_AES_128_BIT_KEY_SIZE; + key_size = CC_AES_128_BIT_KEY_SIZE; + key_len = CC_AES_128_BIT_KEY_SIZE; } else { - keySize = (ctx->key_params.keylen == 24) ? AES_MAX_KEY_SIZE : ctx->key_params.keylen; - keyLen = ctx->key_params.keylen; + key_size = (ctx->key_params.keylen == 24) ? AES_MAX_KEY_SIZE : + ctx->key_params.keylen; + key_len = ctx->key_params.keylen; } SSI_LOG_DEBUG("===== final xcbc reminder (%d) ====\n", rem_cnt); @@ -1478,8 +1479,8 @@ static int ssi_mac_final(struct ahash_request *req) set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_DECRYPT); set_din_type(&desc[idx], DMA_DLLI, (ctx->opad_tmp_keys_dma_addr + - XCBC_MAC_K1_OFFSET), keySize, NS_BIT); - set_key_size_aes(&desc[idx], keyLen); + XCBC_MAC_K1_OFFSET), key_size, NS_BIT); + set_key_size_aes(&desc[idx], key_len); set_flow_mode(&desc[idx], S_DIN_to_AES); set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); idx++; @@ -1508,7 +1509,7 @@ static int ssi_mac_final(struct ahash_request *req) if (state->xcbc_count == 0) { hw_desc_init(&desc[idx]); set_cipher_mode(&desc[idx], ctx->hw_mode); - set_key_size_aes(&desc[idx], keyLen); + set_key_size_aes(&desc[idx], key_len); set_cmac_size0_mode(&desc[idx]); set_flow_mode(&desc[idx], S_DIN_to_AES); idx++; @@ -1621,7 +1622,7 @@ static int ssi_mac_digest(struct ahash_request *req) u32 digestsize = crypto_ahash_digestsize(tfm); struct ssi_crypto_req ssi_req = {}; struct cc_hw_desc desc[SSI_MAX_AHASH_SEQ_LEN]; - u32 keyLen; + u32 key_len; int idx = 0; int rc; @@ -1646,17 +1647,17 @@ static int ssi_mac_digest(struct ahash_request *req) ssi_req.user_arg = (void *)req; if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC) { - keyLen = CC_AES_128_BIT_KEY_SIZE; + key_len = CC_AES_128_BIT_KEY_SIZE; ssi_hash_create_xcbc_setup(req, desc, &idx); } else { - keyLen = ctx->key_params.keylen; + key_len = ctx->key_params.keylen; ssi_hash_create_cmac_setup(req, desc, &idx); } if (req->nbytes == 0) { hw_desc_init(&desc[idx]); set_cipher_mode(&desc[idx], ctx->hw_mode); - set_key_size_aes(&desc[idx], keyLen); + set_key_size_aes(&desc[idx], key_len); set_cmac_size0_mode(&desc[idx]); set_flow_mode(&desc[idx], S_DIN_to_AES); idx++; -- cgit v1.2.3 From 698592e23e1bf3eae4c02b4169ac8c81310cfa0e Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Thu, 13 Jul 2017 11:19:57 +0300 Subject: staging: ccree: CamelCase to snake_case in aead struct Rename aead_req_struct fields from CamelCase to snake_case. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_aead.c | 26 ++++++------ drivers/staging/ccree/ssi_aead.h | 12 +++--- drivers/staging/ccree/ssi_buffer_mgr.c | 78 +++++++++++++++++----------------- 3 files changed, 58 insertions(+), 58 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_aead.c b/drivers/staging/ccree/ssi_aead.c index 84ae173d4994..d9e342fa7e9f 100644 --- a/drivers/staging/ccree/ssi_aead.c +++ b/drivers/staging/ccree/ssi_aead.c @@ -252,8 +252,8 @@ static void ssi_aead_complete(struct device *dev, void *ssi_req, void __iomem *c } else { /*ENCRYPT*/ if (unlikely(areq_ctx->is_icv_fragmented)) ssi_buffer_mgr_copy_scatterlist_portion( - areq_ctx->mac_buf, areq_ctx->dstSgl, areq->cryptlen + areq_ctx->dstOffset, - areq->cryptlen + areq_ctx->dstOffset + ctx->authsize, SSI_SG_FROM_BUF); + areq_ctx->mac_buf, areq_ctx->dst_sgl, areq->cryptlen + areq_ctx->dst_offset, + areq->cryptlen + areq_ctx->dst_offset + ctx->authsize, SSI_SG_FROM_BUF); /* If an IV was generated, copy it back to the user provided buffer. */ if (areq_ctx->backup_giv) { @@ -777,11 +777,11 @@ ssi_aead_process_authenc_data_desc( { struct scatterlist *cipher = (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ? - areq_ctx->dstSgl : areq_ctx->srcSgl; + areq_ctx->dst_sgl : areq_ctx->src_sgl; unsigned int offset = (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ? - areq_ctx->dstOffset : areq_ctx->srcOffset; + areq_ctx->dst_offset : areq_ctx->src_offset; SSI_LOG_DEBUG("AUTHENC: SRC/DST buffer type DLLI\n"); hw_desc_init(&desc[idx]); set_din_type(&desc[idx], DMA_DLLI, @@ -843,11 +843,11 @@ ssi_aead_process_cipher_data_desc( SSI_LOG_DEBUG("CIPHER: SRC/DST buffer type DLLI\n"); hw_desc_init(&desc[idx]); set_din_type(&desc[idx], DMA_DLLI, - (sg_dma_address(areq_ctx->srcSgl) + - areq_ctx->srcOffset), areq_ctx->cryptlen, NS_BIT); + (sg_dma_address(areq_ctx->src_sgl) + + areq_ctx->src_offset), areq_ctx->cryptlen, NS_BIT); set_dout_dlli(&desc[idx], - (sg_dma_address(areq_ctx->dstSgl) + - areq_ctx->dstOffset), + (sg_dma_address(areq_ctx->dst_sgl) + + areq_ctx->dst_offset), areq_ctx->cryptlen, NS_BIT, 0); set_flow_mode(&desc[idx], flow_mode); break; @@ -1879,7 +1879,7 @@ static inline void ssi_aead_dump_gcm( dump_byte_array("mac_buf", req_ctx->mac_buf, AES_BLOCK_SIZE); - dump_byte_array("gcm_len_block", req_ctx->gcm_len_block.lenA, AES_BLOCK_SIZE); + dump_byte_array("gcm_len_block", req_ctx->gcm_len_block.len_a, AES_BLOCK_SIZE); if (req->src && req->cryptlen) dump_byte_array("req->src", sg_virt(req->src), req->cryptlen + req->assoclen); @@ -1918,16 +1918,16 @@ static int config_gcm_context(struct aead_request *req) __be64 temp64; temp64 = cpu_to_be64(req->assoclen * 8); - memcpy(&req_ctx->gcm_len_block.lenA, &temp64, sizeof(temp64)); + memcpy(&req_ctx->gcm_len_block.len_a, &temp64, sizeof(temp64)); temp64 = cpu_to_be64(cryptlen * 8); - memcpy(&req_ctx->gcm_len_block.lenC, &temp64, 8); + memcpy(&req_ctx->gcm_len_block.len_c, &temp64, 8); } else { //rfc4543=> all data(AAD,IV,Plain) are considered additional data that is nothing is encrypted. __be64 temp64; temp64 = cpu_to_be64((req->assoclen + GCM_BLOCK_RFC4_IV_SIZE + cryptlen) * 8); - memcpy(&req_ctx->gcm_len_block.lenA, &temp64, sizeof(temp64)); + memcpy(&req_ctx->gcm_len_block.len_a, &temp64, sizeof(temp64)); temp64 = 0; - memcpy(&req_ctx->gcm_len_block.lenC, &temp64, 8); + memcpy(&req_ctx->gcm_len_block.len_c, &temp64, 8); } return 0; diff --git a/drivers/staging/ccree/ssi_aead.h b/drivers/staging/ccree/ssi_aead.h index 39cc633a3ffa..e85bcd917e7b 100644 --- a/drivers/staging/ccree/ssi_aead.h +++ b/drivers/staging/ccree/ssi_aead.h @@ -69,8 +69,8 @@ struct aead_req_ctx { u8 gcm_iv_inc2[AES_BLOCK_SIZE] ____cacheline_aligned; u8 hkey[AES_BLOCK_SIZE] ____cacheline_aligned; struct { - u8 lenA[GCM_BLOCK_LEN_SIZE] ____cacheline_aligned; - u8 lenC[GCM_BLOCK_LEN_SIZE]; + u8 len_a[GCM_BLOCK_LEN_SIZE] ____cacheline_aligned; + u8 len_c[GCM_BLOCK_LEN_SIZE]; } gcm_len_block; u8 ccm_config[CCM_CONFIG_BUF_SIZE] ____cacheline_aligned; @@ -94,10 +94,10 @@ struct aead_req_ctx { struct ssi_mlli assoc; struct ssi_mlli src; struct ssi_mlli dst; - struct scatterlist *srcSgl; - struct scatterlist *dstSgl; - unsigned int srcOffset; - unsigned int dstOffset; + struct scatterlist *src_sgl; + struct scatterlist *dst_sgl; + unsigned int src_offset; + unsigned int dst_offset; enum ssi_req_dma_buf_type assoc_buff_type; enum ssi_req_dma_buf_type data_buff_type; struct mlli_params mlli_params; diff --git a/drivers/staging/ccree/ssi_buffer_mgr.c b/drivers/staging/ccree/ssi_buffer_mgr.c index b451144cbc75..6579a54f9dc4 100644 --- a/drivers/staging/ccree/ssi_buffer_mgr.c +++ b/drivers/staging/ccree/ssi_buffer_mgr.c @@ -915,26 +915,26 @@ static inline void ssi_buffer_mgr_prepare_aead_data_dlli( if (likely(req->src == req->dst)) { /*INPLACE*/ areq_ctx->icv_dma_addr = sg_dma_address( - areq_ctx->srcSgl) + + areq_ctx->src_sgl) + (*src_last_bytes - authsize); areq_ctx->icv_virt_addr = sg_virt( - areq_ctx->srcSgl) + + areq_ctx->src_sgl) + (*src_last_bytes - authsize); } else if (direct == DRV_CRYPTO_DIRECTION_DECRYPT) { /*NON-INPLACE and DECRYPT*/ areq_ctx->icv_dma_addr = sg_dma_address( - areq_ctx->srcSgl) + + areq_ctx->src_sgl) + (*src_last_bytes - authsize); areq_ctx->icv_virt_addr = sg_virt( - areq_ctx->srcSgl) + + areq_ctx->src_sgl) + (*src_last_bytes - authsize); } else { /*NON-INPLACE and ENCRYPT*/ areq_ctx->icv_dma_addr = sg_dma_address( - areq_ctx->dstSgl) + + areq_ctx->dst_sgl) + (*dst_last_bytes - authsize); areq_ctx->icv_virt_addr = sg_virt( - areq_ctx->dstSgl) + + areq_ctx->dst_sgl) + (*dst_last_bytes - authsize); } } @@ -956,13 +956,13 @@ static inline int ssi_buffer_mgr_prepare_aead_data_mlli( /*INPLACE*/ ssi_buffer_mgr_add_scatterlist_entry(sg_data, areq_ctx->src.nents, - areq_ctx->srcSgl, + areq_ctx->src_sgl, areq_ctx->cryptlen, - areq_ctx->srcOffset, + areq_ctx->src_offset, is_last_table, &areq_ctx->src.mlli_nents); - icv_nents = ssi_buffer_mgr_get_aead_icv_nents(areq_ctx->srcSgl, + icv_nents = ssi_buffer_mgr_get_aead_icv_nents(areq_ctx->src_sgl, areq_ctx->src.nents, authsize, *src_last_bytes, @@ -1004,10 +1004,10 @@ static inline int ssi_buffer_mgr_prepare_aead_data_mlli( } else { /* Contig. ICV */ /*Should hanlde if the sg is not contig.*/ areq_ctx->icv_dma_addr = sg_dma_address( - &areq_ctx->srcSgl[areq_ctx->src.nents - 1]) + + &areq_ctx->src_sgl[areq_ctx->src.nents - 1]) + (*src_last_bytes - authsize); areq_ctx->icv_virt_addr = sg_virt( - &areq_ctx->srcSgl[areq_ctx->src.nents - 1]) + + &areq_ctx->src_sgl[areq_ctx->src.nents - 1]) + (*src_last_bytes - authsize); } @@ -1015,20 +1015,20 @@ static inline int ssi_buffer_mgr_prepare_aead_data_mlli( /*NON-INPLACE and DECRYPT*/ ssi_buffer_mgr_add_scatterlist_entry(sg_data, areq_ctx->src.nents, - areq_ctx->srcSgl, + areq_ctx->src_sgl, areq_ctx->cryptlen, - areq_ctx->srcOffset, + areq_ctx->src_offset, is_last_table, &areq_ctx->src.mlli_nents); ssi_buffer_mgr_add_scatterlist_entry(sg_data, areq_ctx->dst.nents, - areq_ctx->dstSgl, + areq_ctx->dst_sgl, areq_ctx->cryptlen, - areq_ctx->dstOffset, + areq_ctx->dst_offset, is_last_table, &areq_ctx->dst.mlli_nents); - icv_nents = ssi_buffer_mgr_get_aead_icv_nents(areq_ctx->srcSgl, + icv_nents = ssi_buffer_mgr_get_aead_icv_nents(areq_ctx->src_sgl, areq_ctx->src.nents, authsize, *src_last_bytes, @@ -1056,10 +1056,10 @@ static inline int ssi_buffer_mgr_prepare_aead_data_mlli( } else { /* Contig. ICV */ /*Should hanlde if the sg is not contig.*/ areq_ctx->icv_dma_addr = sg_dma_address( - &areq_ctx->srcSgl[areq_ctx->src.nents - 1]) + + &areq_ctx->src_sgl[areq_ctx->src.nents - 1]) + (*src_last_bytes - authsize); areq_ctx->icv_virt_addr = sg_virt( - &areq_ctx->srcSgl[areq_ctx->src.nents - 1]) + + &areq_ctx->src_sgl[areq_ctx->src.nents - 1]) + (*src_last_bytes - authsize); } @@ -1067,20 +1067,20 @@ static inline int ssi_buffer_mgr_prepare_aead_data_mlli( /*NON-INPLACE and ENCRYPT*/ ssi_buffer_mgr_add_scatterlist_entry(sg_data, areq_ctx->dst.nents, - areq_ctx->dstSgl, + areq_ctx->dst_sgl, areq_ctx->cryptlen, - areq_ctx->dstOffset, + areq_ctx->dst_offset, is_last_table, &areq_ctx->dst.mlli_nents); ssi_buffer_mgr_add_scatterlist_entry(sg_data, areq_ctx->src.nents, - areq_ctx->srcSgl, + areq_ctx->src_sgl, areq_ctx->cryptlen, - areq_ctx->srcOffset, + areq_ctx->src_offset, is_last_table, &areq_ctx->src.mlli_nents); - icv_nents = ssi_buffer_mgr_get_aead_icv_nents(areq_ctx->dstSgl, + icv_nents = ssi_buffer_mgr_get_aead_icv_nents(areq_ctx->dst_sgl, areq_ctx->dst.nents, authsize, *dst_last_bytes, @@ -1093,10 +1093,10 @@ static inline int ssi_buffer_mgr_prepare_aead_data_mlli( if (likely(!areq_ctx->is_icv_fragmented)) { /* Contig. ICV */ areq_ctx->icv_dma_addr = sg_dma_address( - &areq_ctx->dstSgl[areq_ctx->dst.nents - 1]) + + &areq_ctx->dst_sgl[areq_ctx->dst.nents - 1]) + (*dst_last_bytes - authsize); areq_ctx->icv_virt_addr = sg_virt( - &areq_ctx->dstSgl[areq_ctx->dst.nents - 1]) + + &areq_ctx->dst_sgl[areq_ctx->dst.nents - 1]) + (*dst_last_bytes - authsize); } else { areq_ctx->icv_dma_addr = areq_ctx->mac_buf_dma_addr; @@ -1138,25 +1138,25 @@ static inline int ssi_buffer_mgr_aead_chain_data( rc = -EINVAL; goto chain_data_exit; } - areq_ctx->srcSgl = req->src; - areq_ctx->dstSgl = req->dst; + areq_ctx->src_sgl = req->src; + areq_ctx->dst_sgl = req->dst; if (is_gcm4543) size_for_map += crypto_aead_ivsize(tfm); size_for_map += (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ? authsize : 0; src_mapped_nents = ssi_buffer_mgr_get_sgl_nents(req->src, size_for_map, &src_last_bytes, &chained); - sg_index = areq_ctx->srcSgl->length; + sg_index = areq_ctx->src_sgl->length; //check where the data starts while (sg_index <= size_to_skip) { - offset -= areq_ctx->srcSgl->length; - areq_ctx->srcSgl = sg_next(areq_ctx->srcSgl); + offset -= areq_ctx->src_sgl->length; + areq_ctx->src_sgl = sg_next(areq_ctx->src_sgl); //if have reached the end of the sgl, then this is unexpected - if (!areq_ctx->srcSgl) { + if (!areq_ctx->src_sgl) { SSI_LOG_ERR("reached end of sg list. unexpected\n"); BUG(); } - sg_index += areq_ctx->srcSgl->length; + sg_index += areq_ctx->src_sgl->length; src_mapped_nents--; } if (unlikely(src_mapped_nents > LLI_MAX_NUM_OF_DATA_ENTRIES)) { @@ -1167,7 +1167,7 @@ static inline int ssi_buffer_mgr_aead_chain_data( areq_ctx->src.nents = src_mapped_nents; - areq_ctx->srcOffset = offset; + areq_ctx->src_offset = offset; if (req->src != req->dst) { size_for_map = req->assoclen + req->cryptlen; @@ -1188,19 +1188,19 @@ static inline int ssi_buffer_mgr_aead_chain_data( } dst_mapped_nents = ssi_buffer_mgr_get_sgl_nents(req->dst, size_for_map, &dst_last_bytes, &chained); - sg_index = areq_ctx->dstSgl->length; + sg_index = areq_ctx->dst_sgl->length; offset = size_to_skip; //check where the data starts while (sg_index <= size_to_skip) { - offset -= areq_ctx->dstSgl->length; - areq_ctx->dstSgl = sg_next(areq_ctx->dstSgl); + offset -= areq_ctx->dst_sgl->length; + areq_ctx->dst_sgl = sg_next(areq_ctx->dst_sgl); //if have reached the end of the sgl, then this is unexpected - if (!areq_ctx->dstSgl) { + if (!areq_ctx->dst_sgl) { SSI_LOG_ERR("reached end of sg list. unexpected\n"); BUG(); } - sg_index += areq_ctx->dstSgl->length; + sg_index += areq_ctx->dst_sgl->length; dst_mapped_nents--; } if (unlikely(dst_mapped_nents > LLI_MAX_NUM_OF_DATA_ENTRIES)) { @@ -1209,7 +1209,7 @@ static inline int ssi_buffer_mgr_aead_chain_data( return -ENOMEM; } areq_ctx->dst.nents = dst_mapped_nents; - areq_ctx->dstOffset = offset; + areq_ctx->dst_offset = offset; if ((src_mapped_nents > 1) || (dst_mapped_nents > 1) || do_chain) { -- cgit v1.2.3 From 079a7174ae7d24ae93e7fb26fcafdbe0218e08da Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Thu, 13 Jul 2017 11:19:58 +0300 Subject: staging: ccree: avoid constant comparison Re-write predicate to avoid constant comparison. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_aead.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_aead.c b/drivers/staging/ccree/ssi_aead.c index d9e342fa7e9f..46dd70872d57 100644 --- a/drivers/staging/ccree/ssi_aead.c +++ b/drivers/staging/ccree/ssi_aead.c @@ -1572,7 +1572,7 @@ static int config_ccm_adata(struct aead_request *req) /* taken from crypto/ccm.c */ /* 2 <= L <= 8, so 1 <= L' <= 7. */ - if (2 > l || l > 8) { + if (l < 2 || l > 8) { SSI_LOG_ERR("illegal iv value %X\n", req->iv[0]); return -EINVAL; } -- cgit v1.2.3 From b71ad22dffe1090888cabfed94ad3655299665a0 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Thu, 13 Jul 2017 11:19:59 +0300 Subject: staging: ccree: avoid unnecessary line continuation Avoid unnecessary line continuation in log function call. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_aead.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_aead.c b/drivers/staging/ccree/ssi_aead.c index 46dd70872d57..ea29b8a1a71d 100644 --- a/drivers/staging/ccree/ssi_aead.c +++ b/drivers/staging/ccree/ssi_aead.c @@ -1863,8 +1863,9 @@ static inline void ssi_aead_dump_gcm( SSI_LOG_DEBUG("%s\n", title); } - SSI_LOG_DEBUG("cipher_mode %d, authsize %d, enc_keylen %d, assoclen %d, cryptlen %d\n", \ - ctx->cipher_mode, ctx->authsize, ctx->enc_keylen, req->assoclen, req_ctx->cryptlen); + SSI_LOG_DEBUG("cipher_mode %d, authsize %d, enc_keylen %d, assoclen %d, cryptlen %d\n", + ctx->cipher_mode, ctx->authsize, ctx->enc_keylen, + req->assoclen, req_ctx->cryptlen); if (ctx->enckey) dump_byte_array("mac key", ctx->enckey, 16); -- cgit v1.2.3 From 04f682b936a497588ae85fca8630bcbf68dd2f61 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Thu, 13 Jul 2017 11:20:02 +0300 Subject: staging: ccree: remove whitespace before a quoted newline Remove unnecessary whitespace before a quoted newline in strings. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_cipher.c | 6 +++--- drivers/staging/ccree/ssi_hash.c | 2 +- drivers/staging/ccree/ssi_sysfs.c | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_cipher.c b/drivers/staging/ccree/ssi_cipher.c index 10be9270d749..bfe9b1ccbf37 100644 --- a/drivers/staging/ccree/ssi_cipher.c +++ b/drivers/staging/ccree/ssi_cipher.c @@ -614,14 +614,14 @@ ssi_blkcipher_create_data_desc( break; #endif /*SSI_CC_HAS_MULTI2*/ default: - SSI_LOG_ERR("invalid flow mode, flow_mode = %d \n", flow_mode); + SSI_LOG_ERR("invalid flow mode, flow_mode = %d\n", flow_mode); return; } /* Process */ if (likely(req_ctx->dma_buf_type == SSI_DMA_BUF_DLLI)) { - SSI_LOG_DEBUG(" data params addr %pad length 0x%X \n", + SSI_LOG_DEBUG(" data params addr %pad length 0x%X\n", sg_dma_address(src), nbytes); - SSI_LOG_DEBUG(" data params addr %pad length 0x%X \n", + SSI_LOG_DEBUG(" data params addr %pad length 0x%X\n", sg_dma_address(dst), nbytes); hw_desc_init(&desc[*seq_size]); set_din_type(&desc[*seq_size], DMA_DLLI, sg_dma_address(src), diff --git a/drivers/staging/ccree/ssi_hash.c b/drivers/staging/ccree/ssi_hash.c index 748dd2133686..fba0643e78fa 100644 --- a/drivers/staging/ccree/ssi_hash.c +++ b/drivers/staging/ccree/ssi_hash.c @@ -1557,7 +1557,7 @@ static int ssi_mac_finup(struct ahash_request *req) SSI_LOG_DEBUG("===== finup xcbc(%d) ====\n", req->nbytes); if (state->xcbc_count > 0 && req->nbytes == 0) { - SSI_LOG_DEBUG("No data to update. Call to fdx_mac_final \n"); + SSI_LOG_DEBUG("No data to update. Call to fdx_mac_final\n"); return ssi_mac_final(req); } diff --git a/drivers/staging/ccree/ssi_sysfs.c b/drivers/staging/ccree/ssi_sysfs.c index 802fd498a4f5..0655658bba4d 100644 --- a/drivers/staging/ccree/ssi_sysfs.c +++ b/drivers/staging/ccree/ssi_sysfs.c @@ -287,15 +287,15 @@ static ssize_t ssi_sys_regdump_show(struct kobject *kobj, int offset = 0; register_value = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_SIGNATURE)); - offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s \t(0x%lX)\t 0x%08X \n", "HOST_SIGNATURE ", DX_HOST_SIGNATURE_REG_OFFSET, register_value); + offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s \t(0x%lX)\t 0x%08X\n", "HOST_SIGNATURE ", DX_HOST_SIGNATURE_REG_OFFSET, register_value); register_value = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_IRR)); - offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s \t(0x%lX)\t 0x%08X \n", "HOST_IRR ", DX_HOST_IRR_REG_OFFSET, register_value); + offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s \t(0x%lX)\t 0x%08X\n", "HOST_IRR ", DX_HOST_IRR_REG_OFFSET, register_value); register_value = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_POWER_DOWN_EN)); - offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s \t(0x%lX)\t 0x%08X \n", "HOST_POWER_DOWN_EN ", DX_HOST_POWER_DOWN_EN_REG_OFFSET, register_value); + offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s \t(0x%lX)\t 0x%08X\n", "HOST_POWER_DOWN_EN ", DX_HOST_POWER_DOWN_EN_REG_OFFSET, register_value); register_value = CC_HAL_READ_REGISTER(CC_REG_OFFSET(CRY_KERNEL, AXIM_MON_ERR)); - offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s \t(0x%lX)\t 0x%08X \n", "AXIM_MON_ERR ", DX_AXIM_MON_ERR_REG_OFFSET, register_value); + offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s \t(0x%lX)\t 0x%08X\n", "AXIM_MON_ERR ", DX_AXIM_MON_ERR_REG_OFFSET, register_value); register_value = CC_HAL_READ_REGISTER(CC_REG_OFFSET(CRY_KERNEL, DSCRPTR_QUEUE_CONTENT)); - offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s \t(0x%lX)\t 0x%08X \n", "DSCRPTR_QUEUE_CONTENT", DX_DSCRPTR_QUEUE_CONTENT_REG_OFFSET, register_value); + offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s \t(0x%lX)\t 0x%08X\n", "DSCRPTR_QUEUE_CONTENT", DX_DSCRPTR_QUEUE_CONTENT_REG_OFFSET, register_value); return offset; } -- cgit v1.2.3 From 187645ef1f666d6a1d316598cea006513bb8dbed Mon Sep 17 00:00:00 2001 From: Bincy K Philip Date: Wed, 12 Jul 2017 13:01:12 +0530 Subject: staging: ccree: move comment to fit coding style Trivial fix for Line over 80 characters Moved the comment to top of the definition Signed-off-by: Bincy K Philip Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/cc_hw_queue_defs.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/cc_hw_queue_defs.h b/drivers/staging/ccree/cc_hw_queue_defs.h index e6b8cea3f88d..2ae0f655e7a0 100644 --- a/drivers/staging/ccree/cc_hw_queue_defs.h +++ b/drivers/staging/ccree/cc_hw_queue_defs.h @@ -27,7 +27,8 @@ ******************************************************************************/ #define HW_DESC_SIZE_WORDS 6 -#define HW_QUEUE_SLOTS_MAX 15 /* Max. available slots in HW queue */ +/* Define max. available slots in HW queue */ +#define HW_QUEUE_SLOTS_MAX 15 #define CC_REG_NAME(word, name) DX_DSCRPTR_QUEUE_WORD ## word ## _ ## name -- cgit v1.2.3 From 186882700fa266cd379295bae289097443fa230b Mon Sep 17 00:00:00 2001 From: Rui Teng Date: Thu, 13 Jul 2017 10:10:17 +0800 Subject: staging: lustre: fix sparse error: incompatible types in comparison expression Comparing two user space addresses to avoid sparse error: drivers/staging//lustre/lnet/selftest/conrpc.c:490:30: error: incompatible types in comparison expression (different address spaces) Signed-off-by: Rui Teng Acked-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/selftest/conrpc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.c b/drivers/staging/lustre/lnet/selftest/conrpc.c index da36c55b86d3..ae7c2772825e 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.c +++ b/drivers/staging/lustre/lnet/selftest/conrpc.c @@ -487,10 +487,9 @@ lstcon_rpc_trans_interpreter(struct lstcon_rpc_trans *trans, sizeof(struct list_head))) return -EFAULT; - if (tmp.next == head_up) - return 0; - next = tmp.next; + if (next == head_up) + return 0; ent = list_entry(next, struct lstcon_rpc_ent, rpe_link); -- cgit v1.2.3 From 023eba274911c17ef7a29c133f792af6b1e1e073 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 11 Jul 2017 18:49:27 +0100 Subject: staging: fbtft: make const array gamma_par_mask static Don't populate array gamma_par_mask on the stack but instead make it static. Makes the object code smaller by 148 bytes: Before: text data bss dec hex filename 2993 1104 0 4097 1001 drivers/staging/fbtft/fb_st7789v.o After: text data bss dec hex filename 2757 1192 0 3949 f6d drivers/staging/fbtft/fb_st7789v.o Signed-off-by: Colin Ian King Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fbtft/fb_st7789v.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/fbtft/fb_st7789v.c b/drivers/staging/fbtft/fb_st7789v.c index 8935a97ec048..a5d7c87557f8 100644 --- a/drivers/staging/fbtft/fb_st7789v.c +++ b/drivers/staging/fbtft/fb_st7789v.c @@ -189,7 +189,7 @@ static int set_gamma(struct fbtft_par *par, u32 *curves) * The masks are the same for both positive and negative voltage * gamma curves. */ - const u8 gamma_par_mask[] = { + static const u8 gamma_par_mask[] = { 0xFF, /* V63[3:0], V0[3:0]*/ 0x3F, /* V1[5:0] */ 0x3F, /* V2[5:0] */ -- cgit v1.2.3 From 4596351d80b44842d3a57f54ba50511394fa7666 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 10 Jul 2017 16:05:28 +0200 Subject: staging: rtl8192u: reduce stack frame size in ieee80211_rx_mgt_rsl I ran into a stack frame size warning in code that hasn't changed much recently, no idea why I didn't spot this earlier despite build many thousand randconfigs. drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c: In function 'ieee80211_rx_mgt_rsl': drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c:2563:1: error: the frame size of 1676 bytes is larger than 1024 bytes [-Werror=frame-larger-than=] We have a couple of other copies of the same function in the kernel, and they simply don't put a gigantic structure on the stack, so I'm changing this copy to do the same as the others, replacing the stack variable with a GFP_ATOMIC allocation. Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c | 78 ++++++++++++----------- 1 file changed, 42 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c index a4aedb489e92..cbf8eb4a049d 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c @@ -2385,7 +2385,7 @@ static inline void ieee80211_process_probe_response( struct ieee80211_probe_response *beacon, struct ieee80211_rx_stats *stats) { - struct ieee80211_network network; + struct ieee80211_network *network; struct ieee80211_network *target; struct ieee80211_network *oldest = NULL; #ifdef CONFIG_IEEE80211_DEBUG @@ -2397,7 +2397,10 @@ static inline void ieee80211_process_probe_response( u16 capability; //u8 wmm_info; - memset(&network, 0, sizeof(struct ieee80211_network)); + network = kzalloc(sizeof(*network), GFP_ATOMIC); + if (!network) + goto out; + capability = le16_to_cpu(beacon->capability); IEEE80211_DEBUG_SCAN( "'%s' (%pM): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n", @@ -2420,14 +2423,14 @@ static inline void ieee80211_process_probe_response( (capability & (1 << 0x1)) ? '1' : '0', (capability & (1 << 0x0)) ? '1' : '0'); - if (ieee80211_network_init(ieee, beacon, &network, stats)) { + if (ieee80211_network_init(ieee, beacon, network, stats)) { IEEE80211_DEBUG_SCAN("Dropped '%s' (%pM) via %s.\n", escape_essid(info_element->data, info_element->len), beacon->header.addr3, fc == IEEE80211_STYPE_PROBE_RESP ? "PROBE RESPONSE" : "BEACON"); - return; + goto out; } // For Asus EeePc request, @@ -2437,8 +2440,8 @@ static inline void ieee80211_process_probe_response( // then wireless adapter should do active scan from ch1~11 and // passive scan from ch12~14 - if (!IsLegalChannel(ieee, network.channel)) - return; + if (!IsLegalChannel(ieee, network->channel)) + goto out; if (ieee->bGlobalDomain) { if (fc == IEEE80211_STYPE_PROBE_RESP) @@ -2446,19 +2449,19 @@ static inline void ieee80211_process_probe_response( // Case 1: Country code if(IS_COUNTRY_IE_VALID(ieee) ) { - if (!IsLegalChannel(ieee, network.channel)) { - printk("GetScanInfo(): For Country code, filter probe response at channel(%d).\n", network.channel); - return; + if (!IsLegalChannel(ieee, network->channel)) { + printk("GetScanInfo(): For Country code, filter probe response at channel(%d).\n", network->channel); + goto out; } } // Case 2: No any country code. else { // Filter over channel ch12~14 - if (network.channel > 11) + if (network->channel > 11) { - printk("GetScanInfo(): For Global Domain, filter probe response at channel(%d).\n", network.channel); - return; + printk("GetScanInfo(): For Global Domain, filter probe response at channel(%d).\n", network->channel); + goto out; } } } @@ -2467,19 +2470,19 @@ static inline void ieee80211_process_probe_response( // Case 1: Country code if(IS_COUNTRY_IE_VALID(ieee) ) { - if (!IsLegalChannel(ieee, network.channel)) { - printk("GetScanInfo(): For Country code, filter beacon at channel(%d).\n",network.channel); - return; + if (!IsLegalChannel(ieee, network->channel)) { + printk("GetScanInfo(): For Country code, filter beacon at channel(%d).\n",network->channel); + goto out; } } // Case 2: No any country code. else { // Filter over channel ch12~14 - if (network.channel > 14) + if (network->channel > 14) { - printk("GetScanInfo(): For Global Domain, filter beacon at channel(%d).\n",network.channel); - return; + printk("GetScanInfo(): For Global Domain, filter beacon at channel(%d).\n",network->channel); + goto out; } } } @@ -2497,8 +2500,8 @@ static inline void ieee80211_process_probe_response( spin_lock_irqsave(&ieee->lock, flags); - if (is_same_network(&ieee->current_network, &network, ieee)) { - update_network(&ieee->current_network, &network); + if (is_same_network(&ieee->current_network, network, ieee)) { + update_network(&ieee->current_network, network); if ((ieee->current_network.mode == IEEE_N_24G || ieee->current_network.mode == IEEE_G) && ieee->current_network.berp_info_valid){ if(ieee->current_network.erp_value& ERP_UseProtection) @@ -2512,11 +2515,11 @@ static inline void ieee80211_process_probe_response( ieee->LinkDetectInfo.NumRecvBcnInPeriod++; } else //hidden AP - network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & ieee->current_network.flags); + network->flags = (~NETWORK_EMPTY_ESSID & network->flags)|(NETWORK_EMPTY_ESSID & ieee->current_network.flags); } list_for_each_entry(target, &ieee->network_list, list) { - if (is_same_network(target, &network, ieee)) + if (is_same_network(target, network, ieee)) break; if ((oldest == NULL) || (target->last_scanned < oldest->last_scanned)) @@ -2545,16 +2548,16 @@ static inline void ieee80211_process_probe_response( #ifdef CONFIG_IEEE80211_DEBUG IEEE80211_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n", - escape_essid(network.ssid, - network.ssid_len), - network.bssid, + escape_essid(network->ssid, + network->ssid_len), + network->bssid, fc == IEEE80211_STYPE_PROBE_RESP ? "PROBE RESPONSE" : "BEACON"); #endif - memcpy(target, &network, sizeof(*target)); + memcpy(target, network, sizeof(*target)); list_add_tail(&target->list, &ieee->network_list); if(ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) - ieee80211_softmac_new_net(ieee,&network); + ieee80211_softmac_new_net(ieee,network); } else { IEEE80211_DEBUG_SCAN("Updating '%s' (%pM) via %s.\n", escape_essid(target->ssid, @@ -2570,27 +2573,30 @@ static inline void ieee80211_process_probe_response( renew = !time_after(target->last_scanned + ieee->scan_age, jiffies); //YJ,add,080819,for hidden ap if(is_beacon(beacon->header.frame_ctl) == 0) - network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & target->flags); - //if(strncmp(network.ssid, "linksys-c",9) == 0) - // printk("====>2 network.ssid=%s FLAG=%d target.ssid=%s FLAG=%d\n", network.ssid, network.flags, target->ssid, target->flags); - if(((network.flags & NETWORK_EMPTY_ESSID) == NETWORK_EMPTY_ESSID) \ - && (((network.ssid_len > 0) && (strncmp(target->ssid, network.ssid, network.ssid_len)))\ - ||((ieee->current_network.ssid_len == network.ssid_len)&&(strncmp(ieee->current_network.ssid, network.ssid, network.ssid_len) == 0)&&(ieee->state == IEEE80211_NOLINK)))) + network->flags = (~NETWORK_EMPTY_ESSID & network->flags)|(NETWORK_EMPTY_ESSID & target->flags); + //if(strncmp(network->ssid, "linksys-c",9) == 0) + // printk("====>2 network->ssid=%s FLAG=%d target.ssid=%s FLAG=%d\n", network->ssid, network->flags, target->ssid, target->flags); + if(((network->flags & NETWORK_EMPTY_ESSID) == NETWORK_EMPTY_ESSID) \ + && (((network->ssid_len > 0) && (strncmp(target->ssid, network->ssid, network->ssid_len)))\ + ||((ieee->current_network.ssid_len == network->ssid_len)&&(strncmp(ieee->current_network.ssid, network->ssid, network->ssid_len) == 0)&&(ieee->state == IEEE80211_NOLINK)))) renew = 1; //YJ,add,080819,for hidden ap,end - update_network(target, &network); + update_network(target, network); if(renew && (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE)) - ieee80211_softmac_new_net(ieee,&network); + ieee80211_softmac_new_net(ieee,network); } spin_unlock_irqrestore(&ieee->lock, flags); - if (is_beacon(beacon->header.frame_ctl)&&is_same_network(&ieee->current_network, &network, ieee)&&\ + if (is_beacon(beacon->header.frame_ctl)&&is_same_network(&ieee->current_network, network, ieee)&&\ (ieee->state == IEEE80211_LINKED)) { if (ieee->handle_beacon != NULL) { ieee->handle_beacon(ieee->dev,beacon,&ieee->current_network); } } + +out: + kfree(network); } void ieee80211_rx_mgt(struct ieee80211_device *ieee, -- cgit v1.2.3 From 0c2310217b40af190b4a8ff79320088856c2f25c Mon Sep 17 00:00:00 2001 From: Lukasz Faber Date: Wed, 5 Jul 2017 11:45:09 +0200 Subject: staging: rtl8192u: Fix braces placement and spacing Fixes the following checkpatch errors: - open brace '{' following enum go on the same line - space required after that close brace '}' Signed-off-by: Lukasz Faber Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/r8192U_hw.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192u/r8192U_hw.h b/drivers/staging/rtl8192u/r8192U_hw.h index 174ccf618d3e..00a123d44207 100644 --- a/drivers/staging/rtl8192u/r8192U_hw.h +++ b/drivers/staging/rtl8192u/r8192U_hw.h @@ -20,25 +20,24 @@ #ifndef R8192_HW #define R8192_HW -typedef enum _VERSION_819xU{ +typedef enum _VERSION_819xU { VERSION_819xU_A, // A-cut VERSION_819xU_B, // B-cut VERSION_819xU_C,// C-cut } VERSION_819xU, *PVERSION_819xU; //added for different RF type -typedef enum _RT_RF_TYPE_DEF -{ +typedef enum _RT_RF_TYPE_DEF { RF_1T2R = 0, RF_2T4R, RF_819X_MAX_TYPE -}RT_RF_TYPE_DEF; +} RT_RF_TYPE_DEF; -typedef enum _BaseBand_Config_Type{ +typedef enum _BaseBand_Config_Type { BaseBand_Config_PHY_REG = 0, //Radio Path A BaseBand_Config_AGC_TAB = 1, //Radio Path B -}BaseBand_Config_Type, *PBaseBand_Config_Type; +} BaseBand_Config_Type, *PBaseBand_Config_Type; #define RTL8187_REQT_READ 0xc0 #define RTL8187_REQT_WRITE 0x40 #define RTL8187_REQ_GET_REGS 0x05 -- cgit v1.2.3 From 7b379dba14f8039fac06db0fced2e68b86570ddf Mon Sep 17 00:00:00 2001 From: Janusz Lisiecki Date: Mon, 3 Jul 2017 06:41:39 +0200 Subject: staging: ks7010: Fix cast to restricted __le16 in ks_wlan_net.c This patch fixes the following Sparse warnings in ks_wlan_net.c: drivers/staging/ks7010/ks_wlan_net.c:1359:24: warning: cast to restricted __le16 link_ap_info_t structure field 'capability' has native order and is used everywhere in the code in such way (i.e get_ap_information, get_current_ap). Both sides of assignment are u16 (native order) so 'le16_to_cpu' is not needed and wrong. Signed-off-by: Janusz Lisiecki Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/ks_wlan_net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/ks7010/ks_wlan_net.c b/drivers/staging/ks7010/ks_wlan_net.c index 8aa12e813bd7..0f9348ba5d84 100644 --- a/drivers/staging/ks7010/ks_wlan_net.c +++ b/drivers/staging/ks7010/ks_wlan_net.c @@ -1356,7 +1356,7 @@ static inline char *ks_wlan_translate_scan(struct net_device *dev, /* Add mode */ iwe.cmd = SIOCGIWMODE; - capabilities = le16_to_cpu(ap->capability); + capabilities = ap->capability; if (capabilities & (BSS_CAP_ESS | BSS_CAP_IBSS)) { if (capabilities & BSS_CAP_ESS) iwe.u.mode = IW_MODE_INFRA; -- cgit v1.2.3 From f21997572ceda94b2b2c2f33c840af4ad7d4988a Mon Sep 17 00:00:00 2001 From: Simon Sandström Date: Fri, 30 Jun 2017 23:38:51 +0200 Subject: staging: vt6656: Add spaces between operators MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes checkpatch.pl warnings "spaces preferred around that ". Signed-off-by: Simon Sandström Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/device.h | 2 +- drivers/staging/vt6656/firmware.c | 2 +- drivers/staging/vt6656/rf.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h index 4832666cc580..74715c854856 100644 --- a/drivers/staging/vt6656/device.h +++ b/drivers/staging/vt6656/device.h @@ -83,7 +83,7 @@ #define CONFIG_PATH "/etc/vntconfiguration.dat" #define MAX_UINTS 8 -#define OPTION_DEFAULT { [0 ... MAX_UINTS-1] = -1} +#define OPTION_DEFAULT { [0 ... MAX_UINTS - 1] = -1} #define DUPLICATE_RX_CACHE_LENGTH 5 diff --git a/drivers/staging/vt6656/firmware.c b/drivers/staging/vt6656/firmware.c index 282f665aacfa..093a6048bd22 100644 --- a/drivers/staging/vt6656/firmware.c +++ b/drivers/staging/vt6656/firmware.c @@ -65,7 +65,7 @@ int vnt_download_firmware(struct vnt_private *priv) status = vnt_control_out(priv, 0, - 0x1200+ii, + 0x1200 + ii, 0x0000, length, buffer); diff --git a/drivers/staging/vt6656/rf.c b/drivers/staging/vt6656/rf.c index 23581afb4211..42ac86747b30 100644 --- a/drivers/staging/vt6656/rf.c +++ b/drivers/staging/vt6656/rf.c @@ -643,9 +643,9 @@ int vnt_rf_setpower(struct vnt_private *priv, u32 rate, u32 channel) case RATE_48M: case RATE_54M: if (channel > CB_MAX_CHANNEL_24G) - power = priv->ofdm_a_pwr_tbl[channel-15]; + power = priv->ofdm_a_pwr_tbl[channel - 15]; else - power = priv->ofdm_pwr_tbl[channel-1]; + power = priv->ofdm_pwr_tbl[channel - 1]; break; } -- cgit v1.2.3 From 9e6519bbca286a316a9c2a63e5ad95d895419907 Mon Sep 17 00:00:00 2001 From: Simon Sandström Date: Fri, 30 Jun 2017 23:38:52 +0200 Subject: staging: vt6656: Remove unnecessary blank lines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes checkpatch.pl warning "Blank lines aren't necessary after an open brace". Also adds braces to balance if-else statement. Signed-off-by: Simon Sandström Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/power.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/power.c b/drivers/staging/vt6656/power.c index e322b7d8c617..c466e0614bc4 100644 --- a/drivers/staging/vt6656/power.c +++ b/drivers/staging/vt6656/power.c @@ -74,16 +74,15 @@ void vnt_enable_power_saving(struct vnt_private *priv, u16 listen_interval) vnt_mac_reg_bits_on(priv, MAC_REG_PSCTL, PSCTL_GO2DOZE); if (listen_interval >= 2) { - /* clear always listen beacon */ vnt_mac_reg_bits_off(priv, MAC_REG_PSCTL, PSCTL_ALBCN); /* first time set listen next beacon */ vnt_mac_reg_bits_on(priv, MAC_REG_PSCTL, PSCTL_LNBCN); - } else - + } else { /* always listen beacon */ vnt_mac_reg_bits_on(priv, MAC_REG_PSCTL, PSCTL_ALBCN); + } dev_dbg(&priv->usb->dev, "PS:Power Saving Mode Enable...\n"); } @@ -100,7 +99,6 @@ void vnt_enable_power_saving(struct vnt_private *priv, u16 listen_interval) void vnt_disable_power_saving(struct vnt_private *priv) { - /* disable power saving hw function */ vnt_control_out(priv, MESSAGE_TYPE_DISABLE_PS, 0, 0, 0, NULL); -- cgit v1.2.3 From 3781f887860ebaf4a8ba237a18501e03722321e1 Mon Sep 17 00:00:00 2001 From: Simon Sandström Date: Fri, 30 Jun 2017 23:38:53 +0200 Subject: staging: vt6656: Align function parameters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes checkpatch.pl warnings "Alignment should match open parenthesis". Signed-off-by: Simon Sandström Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/key.h | 2 +- drivers/staging/vt6656/rf.c | 2 +- drivers/staging/vt6656/usbpipe.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/key.h b/drivers/staging/vt6656/key.h index 906d3454591d..cfc6c2131536 100644 --- a/drivers/staging/vt6656/key.h +++ b/drivers/staging/vt6656/key.h @@ -46,6 +46,6 @@ int vnt_key_init_table(struct vnt_private *priv); int vnt_set_keys(struct ieee80211_hw *hw, struct ieee80211_sta *sta, - struct ieee80211_vif *vif, struct ieee80211_key_conf *key); + struct ieee80211_vif *vif, struct ieee80211_key_conf *key); #endif /* __KEY_H__ */ diff --git a/drivers/staging/vt6656/rf.c b/drivers/staging/vt6656/rf.c index 42ac86747b30..3a9d19a0b842 100644 --- a/drivers/staging/vt6656/rf.c +++ b/drivers/staging/vt6656/rf.c @@ -611,7 +611,7 @@ int vnt_rf_write_embedded(struct vnt_private *priv, u32 data) reg_data[3] = (u8)(data >> 24); vnt_control_out(priv, MESSAGE_TYPE_WRITE_IFRF, - 0, 0, ARRAY_SIZE(reg_data), reg_data); + 0, 0, ARRAY_SIZE(reg_data), reg_data); return true; } diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c index dc11a05be8c4..23eaef458556 100644 --- a/drivers/staging/vt6656/usbpipe.c +++ b/drivers/staging/vt6656/usbpipe.c @@ -44,7 +44,7 @@ #define USB_CTL_WAIT 500 /* ms */ int vnt_control_out(struct vnt_private *priv, u8 request, u16 value, - u16 index, u16 length, u8 *buffer) + u16 index, u16 length, u8 *buffer) { int status = 0; u8 *usb_buffer; @@ -82,7 +82,7 @@ void vnt_control_out_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 data) } int vnt_control_in(struct vnt_private *priv, u8 request, u16 value, - u16 index, u16 length, u8 *buffer) + u16 index, u16 length, u8 *buffer) { int status; u8 *usb_buffer; -- cgit v1.2.3 From f124a478575b2d12134c97c7e29d782cebb1d049 Mon Sep 17 00:00:00 2001 From: Simon Sandström Date: Fri, 30 Jun 2017 23:38:54 +0200 Subject: staging: vt6656: Use variable instead of its type in sizeof(...) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use sizeof(variable) instead of sizeof(type) in memory allocations to prevent problems if the variable type changes in the future. Signed-off-by: Simon Sandström Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/main_usb.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index 095b85567306..cc6d8778fe5b 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -419,8 +419,7 @@ static bool vnt_alloc_bufs(struct vnt_private *priv) int ii; for (ii = 0; ii < priv->num_tx_context; ii++) { - tx_context = kmalloc(sizeof(struct vnt_usb_send_context), - GFP_KERNEL); + tx_context = kmalloc(sizeof(*tx_context), GFP_KERNEL); if (!tx_context) goto free_tx; @@ -437,7 +436,7 @@ static bool vnt_alloc_bufs(struct vnt_private *priv) } for (ii = 0; ii < priv->num_rcb; ii++) { - priv->rcb[ii] = kzalloc(sizeof(struct vnt_rcb), GFP_KERNEL); + priv->rcb[ii] = kzalloc(sizeof(*priv->rcb[ii]), GFP_KERNEL); if (!priv->rcb[ii]) { dev_err(&priv->usb->dev, "failed to allocate rcb no %d\n", ii); -- cgit v1.2.3 From 358fc9771e1d85e18aa95a2673655715b058d484 Mon Sep 17 00:00:00 2001 From: Craig Inches Date: Wed, 12 Jul 2017 09:02:40 +0000 Subject: Staging: Lustre Clean up line over 80Char in lib-lnet.h This patch fixes a warning generated by checkpatch for a line over 80 characters. Signed-off-by: Craig Inches Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/lnet/lib-lnet.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h index 8ae7423b4543..f534115d402a 100644 --- a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h +++ b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h @@ -453,7 +453,8 @@ extern int portal_rotor; int lnet_lib_init(void); void lnet_lib_exit(void); -int lnet_notify(struct lnet_ni *ni, lnet_nid_t peer, int alive, unsigned long when); +int lnet_notify(struct lnet_ni *ni, lnet_nid_t peer, int alive, + unsigned long when); void lnet_notify_locked(struct lnet_peer *lp, int notifylnd, int alive, unsigned long when); int lnet_add_route(__u32 net, __u32 hops, lnet_nid_t gateway_nid, -- cgit v1.2.3 From e066348300f7360fd81d1373187b04765315b392 Mon Sep 17 00:00:00 2001 From: Craig Inches Date: Wed, 12 Jul 2017 09:02:53 +0000 Subject: Staging: Lustre Fix up multiple Block Comments in lib-types.h This patch fixes some multiline comment blocks which didnt conform to the style guide, found by checkpatch. Signed-off-by: Craig Inches Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/include/linux/lnet/lib-types.h | 46 ++++++++++++++-------- 1 file changed, 30 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/lnet/lib-types.h b/drivers/staging/lustre/include/linux/lnet/lib-types.h index 321752dfe58b..ddb808ed5d0b 100644 --- a/drivers/staging/lustre/include/linux/lnet/lib-types.h +++ b/drivers/staging/lustre/include/linux/lnet/lib-types.h @@ -308,9 +308,11 @@ struct lnet_rc_data { struct lnet_peer { struct list_head lp_hashlist; /* chain on peer hash */ struct list_head lp_txq; /* messages blocking for - tx credits */ + * tx credits + */ struct list_head lp_rtrq; /* messages blocking for - router credits */ + * router credits + */ struct list_head lp_rtr_list; /* chain on router list */ int lp_txcredits; /* # tx credits available */ int lp_mintxcredits; /* low water mark */ @@ -319,23 +321,31 @@ struct lnet_peer { unsigned int lp_alive:1; /* alive/dead? */ unsigned int lp_notify:1; /* notification outstanding? */ unsigned int lp_notifylnd:1;/* outstanding notification - for LND? */ + * for LND? + */ unsigned int lp_notifying:1; /* some thread is handling - notification */ + * notification + */ unsigned int lp_ping_notsent;/* SEND event outstanding - from ping */ + * from ping + */ int lp_alive_count; /* # times router went - dead<->alive */ - long lp_txqnob; /* bytes queued for sending */ + * dead<->alive + */ + long lp_txqnob; /* ytes queued for sending */ unsigned long lp_timestamp; /* time of last aliveness - news */ + * news + */ unsigned long lp_ping_timestamp;/* time of last ping - attempt */ + * attempt + */ unsigned long lp_ping_deadline; /* != 0 if ping reply - expected */ + * expected + */ unsigned long lp_last_alive; /* when I was last alive */ unsigned long lp_last_query; /* when lp_ni was queried - last time */ + * last time + */ struct lnet_ni *lp_ni; /* interface peer is on */ lnet_nid_t lp_nid; /* peer's NID */ int lp_refcount; /* # refs */ @@ -386,7 +396,8 @@ struct lnet_route { struct lnet_remotenet { struct list_head lrn_list; /* chain on - ln_remote_nets_hash */ + * ln_remote_nets_hash + */ struct list_head lrn_routes; /* routes to me */ __u32 lrn_net; /* my net number */ }; @@ -399,14 +410,16 @@ struct lnet_remotenet { struct lnet_rtrbufpool { struct list_head rbp_bufs; /* my free buffer pool */ struct list_head rbp_msgs; /* messages blocking - for a buffer */ + * for a buffer + */ int rbp_npages; /* # pages in each buffer */ /* requested number of buffers */ int rbp_req_nbuffers; /* # buffers actually allocated */ int rbp_nbuffers; - int rbp_credits; /* # free buffers / - blocked messages */ + int rbp_credits; /* # free buffers + * blocked messages + */ int rbp_mincredits; /* low water mark */ }; @@ -442,7 +455,8 @@ enum lnet_match_flags { #define LNET_PTL_LAZY (1 << 0) #define LNET_PTL_MATCH_UNIQUE (1 << 1) /* unique match, for RDMA */ #define LNET_PTL_MATCH_WILDCARD (1 << 2) /* wildcard match, - request portal */ + * request portal + */ /* parameter for matching operations (GET, PUT) */ struct lnet_match_info { -- cgit v1.2.3 From 081cb7dbaa18c0979f9807cb79826fb11f9a0dbe Mon Sep 17 00:00:00 2001 From: Craig Inches Date: Wed, 12 Jul 2017 09:03:04 +0000 Subject: Staging: Lustre Fixing multiline block comments in lnetst.h This fixes multiple block statements found not to match style as per checkpatch Signed-off-by: Craig Inches Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/lnet/lnetst.h | 129 +++++++++++++-------- 1 file changed, 81 insertions(+), 48 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/lnet/lnetst.h b/drivers/staging/lustre/include/linux/lnet/lnetst.h index ea736f8d5231..a4f9ff01d458 100644 --- a/drivers/staging/lustre/include/linux/lnet/lnetst.h +++ b/drivers/staging/lustre/include/linux/lnet/lnetst.h @@ -54,7 +54,8 @@ #define LSTIO_GROUP_ADD 0xC10 /* add group */ #define LSTIO_GROUP_LIST 0xC11 /* list all groups in session */ #define LSTIO_GROUP_INFO 0xC12 /* query default information of - * specified group */ + * specified group + */ #define LSTIO_GROUP_DEL 0xC13 /* delete group */ #define LSTIO_NODES_ADD 0xC14 /* add nodes to specified group */ #define LSTIO_GROUP_UPDATE 0xC15 /* update group */ @@ -102,27 +103,32 @@ struct lstcon_test_ent { int tse_type; /* test type */ int tse_loop; /* loop count */ int tse_concur; /* concurrency of test */ -}; /*** test summary entry, for - *** list_batch command */ +}; /* test summary entry, for + * list_batch command + */ struct lstcon_batch_ent { int bae_state; /* batch status */ int bae_timeout; /* batch timeout */ int bae_ntest; /* # of tests in the batch */ -}; /*** batch summary entry, for - *** list_batch command */ +}; /* batch summary entry, for + * list_batch command + */ struct lstcon_test_batch_ent { struct lstcon_ndlist_ent tbe_cli_nle; /* client (group) node_list - * entry */ + * entry + */ struct lstcon_ndlist_ent tbe_srv_nle; /* server (group) node_list - * entry */ + * entry + */ union { struct lstcon_test_ent tbe_test; /* test entry */ struct lstcon_batch_ent tbe_batch;/* batch entry */ } u; -}; /*** test/batch verbose information entry, - *** for list_batch command */ +}; /* test/batch verbose information entry, + * for list_batch command + */ struct lstcon_rpc_ent { struct list_head rpe_link; /* link chain */ @@ -138,10 +144,10 @@ struct lstcon_rpc_ent { }; struct lstcon_trans_stat { - int trs_rpc_stat[4]; /* RPCs stat (0: total - 1: failed - 2: finished - 4: reserved */ + int trs_rpc_stat[4]; /* RPCs stat (0: total 1: failed + * 2: finished + * 4: reserved + */ int trs_rpc_errno; /* RPC errno */ int trs_fwk_stat[8]; /* framework stat */ int trs_fwk_errno; /* errno of the first remote error */ @@ -275,22 +281,28 @@ struct lstio_session_end_args { struct lstio_debug_args { int lstio_dbg_key; /* IN: session key */ int lstio_dbg_type; /* IN: debug - session|batch| - group|nodes - list */ + * session|batch| + * group|nodes list + */ int lstio_dbg_flags; /* IN: reserved debug - flags */ + * flags + */ int lstio_dbg_timeout; /* IN: timeout of - debug */ + * debug + */ int lstio_dbg_nmlen; /* IN: len of name */ char __user *lstio_dbg_namep; /* IN: name of - group|batch */ + * group|batch + */ int lstio_dbg_count; /* IN: # of test nodes - to debug */ + * to debug + */ struct lnet_process_id __user *lstio_dbg_idsp; /* IN: id of test - nodes */ + * nodes + */ struct list_head __user *lstio_dbg_resultp; /* OUT: list head of - result buffer */ + * result buffer + */ }; struct lstio_group_add_args { @@ -307,7 +319,8 @@ struct lstio_group_del_args { #define LST_GROUP_CLEAN 1 /* remove inactive nodes in the group */ #define LST_GROUP_REFRESH 2 /* refresh inactive nodes - * in the group */ + * in the group + */ #define LST_GROUP_RMND 3 /* delete nodes from the group */ struct lstio_group_update_args { @@ -319,7 +332,8 @@ struct lstio_group_update_args { int lstio_grp_count; /* IN: # of nodes id */ struct lnet_process_id __user *lstio_grp_idsp; /* IN: array of nodes */ struct list_head __user *lstio_grp_resultp; /* OUT: list head of - result buffer */ + * result buffer + */ }; struct lstio_group_nodes_args { @@ -331,7 +345,8 @@ struct lstio_group_nodes_args { unsigned int __user *lstio_grp_featp; struct lnet_process_id __user *lstio_grp_idsp; /* IN: nodes */ struct list_head __user *lstio_grp_resultp; /* OUT: list head of - result buffer */ + * result buffer + */ }; struct lstio_group_list_args { @@ -345,8 +360,9 @@ struct lstio_group_info_args { int lstio_grp_key; /* IN: session key */ int lstio_grp_nmlen; /* IN: name len */ char __user *lstio_grp_namep; /* IN: name */ - struct lstcon_ndlist_ent __user *lstio_grp_entp;/* OUT: description of - group */ + struct lstcon_ndlist_ent __user *lstio_grp_entp;/* OUT: description + * of group + */ int __user *lstio_grp_idxp; /* IN/OUT: node index */ int __user *lstio_grp_ndentp; /* IN/OUT: # of nodent */ struct lstcon_node_ent __user *lstio_grp_dentsp;/* OUT: nodent array */ @@ -369,34 +385,41 @@ struct lstio_batch_del_args { struct lstio_batch_run_args { int lstio_bat_key; /* IN: session key */ int lstio_bat_timeout; /* IN: timeout for - the batch */ + * the batch + */ int lstio_bat_nmlen; /* IN: name length */ char __user *lstio_bat_namep; /* IN: batch name */ struct list_head __user *lstio_bat_resultp; /* OUT: list head of - result buffer */ + * result buffer + */ }; struct lstio_batch_stop_args { int lstio_bat_key; /* IN: session key */ int lstio_bat_force; /* IN: abort unfinished - test RPC */ + * test RPC + */ int lstio_bat_nmlen; /* IN: name length */ char __user *lstio_bat_namep; /* IN: batch name */ struct list_head __user *lstio_bat_resultp; /* OUT: list head of - result buffer */ + * result buffer + */ }; struct lstio_batch_query_args { int lstio_bat_key; /* IN: session key */ int lstio_bat_testidx; /* IN: test index */ int lstio_bat_client; /* IN: we testing - client? */ + * client? + */ int lstio_bat_timeout; /* IN: timeout for - waiting */ + * waiting + */ int lstio_bat_nmlen; /* IN: name length */ char __user *lstio_bat_namep; /* IN: batch name */ struct list_head __user *lstio_bat_resultp; /* OUT: list head of - result buffer */ + * result buffer + */ }; struct lstio_batch_list_args { @@ -411,7 +434,8 @@ struct lstio_batch_info_args { int lstio_bat_nmlen; /* IN: name length */ char __user *lstio_bat_namep; /* IN: name */ int lstio_bat_server; /* IN: query server - or not */ + * or not + */ int lstio_bat_testidx; /* IN: test index */ struct lstcon_test_batch_ent __user *lstio_bat_entp;/* OUT: batch ent */ @@ -424,14 +448,17 @@ struct lstio_batch_info_args { struct lstio_stat_args { int lstio_sta_key; /* IN: session key */ int lstio_sta_timeout; /* IN: timeout for - stat request */ + * stat request + */ int lstio_sta_nmlen; /* IN: group name - length */ + * length + */ char __user *lstio_sta_namep; /* IN: group name */ int lstio_sta_count; /* IN: # of pid */ struct lnet_process_id __user *lstio_sta_idsp; /* IN: pid */ struct list_head __user *lstio_sta_resultp; /* OUT: list head of - result buffer */ + * result buffer + */ }; enum lst_test_type { @@ -452,26 +479,32 @@ struct lstio_test_args { int lstio_tes_concur; /* IN: concurrency */ int lstio_tes_dist; /* IN: node distribution in - destination groups */ + * destination groups + */ int lstio_tes_span; /* IN: node span in - destination groups */ + * destination groups + */ int lstio_tes_sgrp_nmlen; /* IN: source group - name length */ + * name length + */ char __user *lstio_tes_sgrp_name; /* IN: group name */ int lstio_tes_dgrp_nmlen; /* IN: destination group - name length */ + * name length + */ char __user *lstio_tes_dgrp_name; /* IN: group name */ int lstio_tes_param_len; /* IN: param buffer len */ void __user *lstio_tes_param; /* IN: parameter for specified - test: - lstio_bulk_param_t, - lstio_ping_param_t, - ... more */ + * test: lstio_bulk_param_t, + * lstio_ping_param_t, + * ... more + */ int __user *lstio_tes_retp; /* OUT: private returned - value */ + * value + */ struct list_head __user *lstio_tes_resultp;/* OUT: list head of - result buffer */ + * result buffer + */ }; enum lst_brw_type { -- cgit v1.2.3 From 07119e257309a41e5ec4a896fd8c8e588388269e Mon Sep 17 00:00:00 2001 From: Craig Inches Date: Wed, 12 Jul 2017 09:03:28 +0000 Subject: Staging: Lustre Fix block statement style issue This fixes a block statement which didnt end with */ Signed-off-by: Craig Inches Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/lnet/socklnd.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/lnet/socklnd.h b/drivers/staging/lustre/include/linux/lnet/socklnd.h index dd5bc0e46560..a1ae66ede7a8 100644 --- a/drivers/staging/lustre/include/linux/lnet/socklnd.h +++ b/drivers/staging/lustre/include/linux/lnet/socklnd.h @@ -76,7 +76,8 @@ struct ksock_msg { __u64 ksm_zc_cookies[2]; /* Zero-Copy request/ACK cookie */ union { struct ksock_lnet_msg lnetmsg; /* lnet message, it's empty if - * it's NOOP */ + * it's NOOP + */ } WIRE_ATTR ksm_u; } WIRE_ATTR; -- cgit v1.2.3 From 9d5b86ac13c573795525ecac6ed2db39ab23e2a8 Mon Sep 17 00:00:00 2001 From: Benjamin Coddington Date: Sun, 16 Jul 2017 10:28:22 -0400 Subject: fs/locks: Remove fl_nspid and use fs-specific l_pid for remote locks Since commit c69899a17ca4 "NFSv4: Update of VFS byte range lock must be atomic with the stateid update", NFSv4 has been inserting locks in rpciod worker context. The result is that the file_lock's fl_nspid is the kworker's pid instead of the original userspace pid. The fl_nspid is only used to represent the namespaced virtual pid number when displaying locks or returning from F_GETLK. There's no reason to set it for every inserted lock, since we can usually just look it up from fl_pid. So, instead of looking up and holding struct pid for every lock, let's just look up the virtual pid number from fl_pid when it is needed. That means we can remove fl_nspid entirely. The translaton and presentation of fl_pid should handle the following four cases: 1 - F_GETLK on a remote file with a remote lock: In this case, the filesystem should determine the l_pid to return here. Filesystems should indicate that the fl_pid represents a non-local pid value that should not be translated by returning an fl_pid <= 0. 2 - F_GETLK on a local file with a remote lock: This should be the l_pid of the lock manager process, and translated. 3 - F_GETLK on a remote file with a local lock, and 4 - F_GETLK on a local file with a local lock: These should be the translated l_pid of the local locking process. Fuse was already doing the correct thing by translating the pid into the caller's namespace. With this change we must update fuse to translate to init's pid namespace, so that the locks API can then translate from init's pid namespace into the pid namespace of the caller. With this change, the locks API will expect that if a filesystem returns a remote pid as opposed to a local pid for F_GETLK, that remote pid will be <= 0. This signifies that the pid is remote, and the locks API will forego translating that pid into the pid namespace of the local calling process. Finally, we convert remote filesystems to present remote pids using negative numbers. Have lustre, 9p, ceph, cifs, and dlm negate the remote pid returned for F_GETLK lock requests. Since local pids will never be larger than PID_MAX_LIMIT (which is currently defined as <= 4 million), but pid_t is an unsigned int, we should have plenty of room to represent remote pids with negative numbers if we assume that remote pid numbers are similarly limited. If this is not the case, then we run the risk of having a remote pid returned for which there is also a corresponding local pid. This is a problem we have now, but this patch should reduce the chances of that occurring, while also returning those remote pid numbers, for whatever that may be worth. Signed-off-by: Benjamin Coddington Signed-off-by: Jeff Layton --- drivers/staging/lustre/lustre/ldlm/ldlm_flock.c | 2 +- fs/9p/vfs_file.c | 2 +- fs/ceph/locks.c | 2 +- fs/cifs/cifssmb.c | 2 +- fs/dlm/plock.c | 2 +- fs/fuse/file.c | 6 +-- fs/locks.c | 62 +++++++++++++++---------- include/linux/fs.h | 1 - 8 files changed, 45 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c index b7f28b39c7b3..abcbf075acc0 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c @@ -596,7 +596,7 @@ granted: default: getlk->fl_type = F_UNLCK; } - getlk->fl_pid = (pid_t)lock->l_policy_data.l_flock.pid; + getlk->fl_pid = -(pid_t)lock->l_policy_data.l_flock.pid; getlk->fl_start = (loff_t)lock->l_policy_data.l_flock.start; getlk->fl_end = (loff_t)lock->l_policy_data.l_flock.end; } else { diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index 3de3b4a89d89..43c242e17132 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c @@ -288,7 +288,7 @@ static int v9fs_file_getlock(struct file *filp, struct file_lock *fl) fl->fl_end = OFFSET_MAX; else fl->fl_end = glock.start + glock.length - 1; - fl->fl_pid = glock.proc_id; + fl->fl_pid = -glock.proc_id; } kfree(glock.client_id); return res; diff --git a/fs/ceph/locks.c b/fs/ceph/locks.c index 64ae74472046..8cd63e8123d8 100644 --- a/fs/ceph/locks.c +++ b/fs/ceph/locks.c @@ -79,7 +79,7 @@ static int ceph_lock_message(u8 lock_type, u16 operation, struct file *file, err = ceph_mdsc_do_request(mdsc, inode, req); if (operation == CEPH_MDS_OP_GETFILELOCK) { - fl->fl_pid = le64_to_cpu(req->r_reply_info.filelock_reply->pid); + fl->fl_pid = -le64_to_cpu(req->r_reply_info.filelock_reply->pid); if (CEPH_LOCK_SHARED == req->r_reply_info.filelock_reply->type) fl->fl_type = F_RDLCK; else if (CEPH_LOCK_EXCL == req->r_reply_info.filelock_reply->type) diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 72a53bd19865..118a63e7e221 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -2522,7 +2522,7 @@ CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon, pLockData->fl_start = le64_to_cpu(parm_data->start); pLockData->fl_end = pLockData->fl_start + le64_to_cpu(parm_data->length) - 1; - pLockData->fl_pid = le32_to_cpu(parm_data->pid); + pLockData->fl_pid = -le32_to_cpu(parm_data->pid); } } diff --git a/fs/dlm/plock.c b/fs/dlm/plock.c index d401425f602a..e631b1689228 100644 --- a/fs/dlm/plock.c +++ b/fs/dlm/plock.c @@ -367,7 +367,7 @@ int dlm_posix_get(dlm_lockspace_t *lockspace, u64 number, struct file *file, locks_init_lock(fl); fl->fl_type = (op->info.ex) ? F_WRLCK : F_RDLCK; fl->fl_flags = FL_POSIX; - fl->fl_pid = op->info.pid; + fl->fl_pid = -op->info.pid; fl->fl_start = op->info.start; fl->fl_end = op->info.end; rv = 0; diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 3ee4fdc3da9e..7cd692f51d1d 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -2101,11 +2101,11 @@ static int convert_fuse_file_lock(struct fuse_conn *fc, fl->fl_end = ffl->end; /* - * Convert pid into the caller's pid namespace. If the pid - * does not map into the namespace fl_pid will get set to 0. + * Convert pid into init's pid namespace. The locks API will + * translate it into the caller's pid namespace. */ rcu_read_lock(); - fl->fl_pid = pid_vnr(find_pid_ns(ffl->pid, fc->pid_ns)); + fl->fl_pid = pid_nr_ns(find_pid_ns(ffl->pid, fc->pid_ns), &init_pid_ns); rcu_read_unlock(); break; diff --git a/fs/locks.c b/fs/locks.c index d7daa6c8932f..6d0949880ebd 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -137,6 +137,7 @@ #define IS_FLOCK(fl) (fl->fl_flags & FL_FLOCK) #define IS_LEASE(fl) (fl->fl_flags & (FL_LEASE|FL_DELEG|FL_LAYOUT)) #define IS_OFDLCK(fl) (fl->fl_flags & FL_OFDLCK) +#define IS_REMOTELCK(fl) (fl->fl_pid <= 0) static inline bool is_remote_lock(struct file *filp) { @@ -733,7 +734,6 @@ static void locks_wake_up_blocks(struct file_lock *blocker) static void locks_insert_lock_ctx(struct file_lock *fl, struct list_head *before) { - fl->fl_nspid = get_pid(task_tgid(current)); list_add_tail(&fl->fl_list, before); locks_insert_global_locks(fl); } @@ -743,10 +743,6 @@ locks_unlink_lock_ctx(struct file_lock *fl) { locks_delete_global_locks(fl); list_del_init(&fl->fl_list); - if (fl->fl_nspid) { - put_pid(fl->fl_nspid); - fl->fl_nspid = NULL; - } locks_wake_up_blocks(fl); } @@ -823,8 +819,6 @@ posix_test_lock(struct file *filp, struct file_lock *fl) list_for_each_entry(cfl, &ctx->flc_posix, fl_list) { if (posix_locks_conflict(fl, cfl)) { locks_copy_conflock(fl, cfl); - if (cfl->fl_nspid) - fl->fl_pid = pid_vnr(cfl->fl_nspid); goto out; } } @@ -2048,9 +2042,33 @@ int vfs_test_lock(struct file *filp, struct file_lock *fl) } EXPORT_SYMBOL_GPL(vfs_test_lock); +/** + * locks_translate_pid - translate a file_lock's fl_pid number into a namespace + * @fl: The file_lock who's fl_pid should be translated + * @ns: The namespace into which the pid should be translated + * + * Used to tranlate a fl_pid into a namespace virtual pid number + */ +static pid_t locks_translate_pid(struct file_lock *fl, struct pid_namespace *ns) +{ + pid_t vnr; + struct pid *pid; + + if (IS_OFDLCK(fl)) + return -1; + if (IS_REMOTELCK(fl)) + return fl->fl_pid; + + rcu_read_lock(); + pid = find_pid_ns(fl->fl_pid, &init_pid_ns); + vnr = pid_nr_ns(pid, ns); + rcu_read_unlock(); + return vnr; +} + static int posix_lock_to_flock(struct flock *flock, struct file_lock *fl) { - flock->l_pid = IS_OFDLCK(fl) ? -1 : fl->fl_pid; + flock->l_pid = locks_translate_pid(fl, task_active_pid_ns(current)); #if BITS_PER_LONG == 32 /* * Make sure we can represent the posix lock via @@ -2072,7 +2090,7 @@ static int posix_lock_to_flock(struct flock *flock, struct file_lock *fl) #if BITS_PER_LONG == 32 static void posix_lock_to_flock64(struct flock64 *flock, struct file_lock *fl) { - flock->l_pid = IS_OFDLCK(fl) ? -1 : fl->fl_pid; + flock->l_pid = locks_translate_pid(fl, task_active_pid_ns(current)); flock->l_start = fl->fl_start; flock->l_len = fl->fl_end == OFFSET_MAX ? 0 : fl->fl_end - fl->fl_start + 1; @@ -2584,22 +2602,16 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl, { struct inode *inode = NULL; unsigned int fl_pid; + struct pid_namespace *proc_pidns = file_inode(f->file)->i_sb->s_fs_info; - if (fl->fl_nspid) { - struct pid_namespace *proc_pidns = file_inode(f->file)->i_sb->s_fs_info; - - /* Don't let fl_pid change based on who is reading the file */ - fl_pid = pid_nr_ns(fl->fl_nspid, proc_pidns); - - /* - * If there isn't a fl_pid don't display who is waiting on - * the lock if we are called from locks_show, or if we are - * called from __show_fd_info - skip lock entirely - */ - if (fl_pid == 0) - return; - } else - fl_pid = fl->fl_pid; + fl_pid = locks_translate_pid(fl, proc_pidns); + /* + * If there isn't a fl_pid don't display who is waiting on + * the lock if we are called from locks_show, or if we are + * called from __show_fd_info - skip lock entirely + */ + if (fl_pid == 0) + return; if (fl->fl_file != NULL) inode = locks_inode(fl->fl_file); @@ -2674,7 +2686,7 @@ static int locks_show(struct seq_file *f, void *v) fl = hlist_entry(v, struct file_lock, fl_link); - if (fl->fl_nspid && !pid_nr_ns(fl->fl_nspid, proc_pidns)) + if (locks_translate_pid(fl, proc_pidns) == 0) return 0; lock_get_status(f, fl, iter->li_pos, ""); diff --git a/include/linux/fs.h b/include/linux/fs.h index 7b5d6816542b..f0b108af9b02 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -999,7 +999,6 @@ struct file_lock { unsigned char fl_type; unsigned int fl_pid; int fl_link_cpu; /* what cpu's list is this on? */ - struct pid *fl_nspid; wait_queue_head_t fl_wait; struct file *fl_file; loff_t fl_start; -- cgit v1.2.3 From 874bcba65f9a3a2a304b5f520529c046887c3cdc Mon Sep 17 00:00:00 2001 From: Marcus Wolf Date: Sun, 16 Jul 2017 11:52:06 +0100 Subject: staging: pi433: New driver Added a driver for the pi433 radio module (see https://www.pi433.de/en.html for details). Signed-off-by: Marcus Wolf Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Kconfig | 2 + drivers/staging/Makefile | 1 + .../Documentation/devicetree/pi433-overlay.dts | 53 + .../pi433/Documentation/devicetree/pi433.txt | 62 + drivers/staging/pi433/Documentation/pi433.txt | 274 ++++ drivers/staging/pi433/Kconfig | 16 + drivers/staging/pi433/Makefile | 3 + drivers/staging/pi433/TODO | 5 + drivers/staging/pi433/pi433_if.c | 1314 ++++++++++++++++++++ drivers/staging/pi433/pi433_if.h | 152 +++ drivers/staging/pi433/rf69.c | 982 +++++++++++++++ drivers/staging/pi433/rf69.h | 82 ++ drivers/staging/pi433/rf69_enum.h | 201 +++ drivers/staging/pi433/rf69_registers.h | 489 ++++++++ 14 files changed, 3636 insertions(+) create mode 100644 drivers/staging/pi433/Documentation/devicetree/pi433-overlay.dts create mode 100644 drivers/staging/pi433/Documentation/devicetree/pi433.txt create mode 100644 drivers/staging/pi433/Documentation/pi433.txt create mode 100644 drivers/staging/pi433/Kconfig create mode 100644 drivers/staging/pi433/Makefile create mode 100644 drivers/staging/pi433/TODO create mode 100644 drivers/staging/pi433/pi433_if.c create mode 100644 drivers/staging/pi433/pi433_if.h create mode 100644 drivers/staging/pi433/rf69.c create mode 100644 drivers/staging/pi433/rf69.h create mode 100644 drivers/staging/pi433/rf69_enum.h create mode 100644 drivers/staging/pi433/rf69_registers.h (limited to 'drivers') diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 268d4e6ef48a..fdf060c4c494 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -110,4 +110,6 @@ source "drivers/staging/ccree/Kconfig" source "drivers/staging/typec/Kconfig" +source "drivers/staging/pi433/Kconfig" + endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index b93e6f5f0f6e..998f6441e3aa 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -44,3 +44,4 @@ obj-$(CONFIG_KS7010) += ks7010/ obj-$(CONFIG_GREYBUS) += greybus/ obj-$(CONFIG_BCM2835_VCHIQ) += vc04_services/ obj-$(CONFIG_CRYPTO_DEV_CCREE) += ccree/ +obj-$(CONFIG_PI433) += pi433/ diff --git a/drivers/staging/pi433/Documentation/devicetree/pi433-overlay.dts b/drivers/staging/pi433/Documentation/devicetree/pi433-overlay.dts new file mode 100644 index 000000000000..004b5027a934 --- /dev/null +++ b/drivers/staging/pi433/Documentation/devicetree/pi433-overlay.dts @@ -0,0 +1,53 @@ +// Definitions for Pi433 +/dts-v1/; +/plugin/; + +/ { + compatible = "bcm,bcm2835", "bcm,bcm2708", "bcm,bcm2709"; + + fragment@0 { + target = <&spi0>; + __overlay__ { + status = "okay"; + + spidev@0{ + status = "disabled"; + }; + + spidev@1{ + status = "disabled"; + }; + }; + }; + + fragment@1 { + target = <&gpio>; + __overlay__ { + pi433_pins: pi433_pins { + brcm,pins = <7 25 24>; + brcm,function = <0 0 0>; // in in in + }; + }; + }; + + fragment@2 { + target = <&spi0>; + __overlay__ { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + pi433: pi433@0 { + compatible = "Smarthome-Wolf,pi433"; + reg = <0>; + spi-max-frequency = <10000000>; + status = "okay"; + + pinctrl-0 = <&pi433_pins>; + DIO0-gpio = <&gpio 24 0>; + DIO1-gpio = <&gpio 25 0>; + DIO2-gpio = <&gpio 7 0>; + }; + }; + }; +}; diff --git a/drivers/staging/pi433/Documentation/devicetree/pi433.txt b/drivers/staging/pi433/Documentation/devicetree/pi433.txt new file mode 100644 index 000000000000..9ff217fbcbbd --- /dev/null +++ b/drivers/staging/pi433/Documentation/devicetree/pi433.txt @@ -0,0 +1,62 @@ +* Smarthome-Wolf Pi433 - a 433MHz radio module/shield for Raspberry Pi (see www.pi433.de) + +Required properties: +- compatible: must be "Smarthome-Wolf,pi433" +- reg: chip select of SPI Interface +- DIOx-gpio must be dedicated to the GPIO, connected with DIOx of the RFM69 module + + +Example: + +With the following lines in gpio-section, the gpio pins, connected with pi433 are +reserved/declared. + +&gpio{ + [...] + + pi433_pins: pi433_pins { + brcm,pins = <7 25 24>; + brcm,function = <0 0 0>; // in in in + }; + + [...] +} + +With the following lines in spi section, the device pi433 is declared. +It consists of the three gpio pins and an spi interface (here chip select 0) + +&spi0{ + [...] + + pi433: pi433@0 { + compatible = "Smarthome-Wolf,pi433"; + reg = <0>; /* CE 0 */ + #address-cells = <1>; + #size-cells = <0>; + spi-max-frequency = <10000000>; + + pinctrl-0 = <&pi433_pins>; + DIO0-gpio = <&gpio 24 0>; + DIO1-gpio = <&gpio 25 0>; + DIO2-gpio = <&gpio 7 0>; + }; +} + + + +For Raspbian users only +======================= +Since Raspbian supports device tree overlays, you may use and overlay, instead +of editing your boards device tree. +For using the overlay, you need to compile the file pi433-overlay.dts you can +find aside to this documentation. +The file needs to be compiled - either manually or by integration in your kernel +source tree. For a manual compile, you may use a command line like the following: +'linux/scripts/dtc/dtc -@ -I dts -O dtb -o pi433.dtbo pi433-overlay.dts' + +For compiling inside of the kernel tree, you need to copy pi433-overlay.dts to +arch/arm/boot/dts/overlays and you need to add the file to the list of files +in the Makefile over there. Execute 'make dtbs' in kernel tree root to make the +kernel make files compile the device tree overlay for you. + + diff --git a/drivers/staging/pi433/Documentation/pi433.txt b/drivers/staging/pi433/Documentation/pi433.txt new file mode 100644 index 000000000000..38b83b86c334 --- /dev/null +++ b/drivers/staging/pi433/Documentation/pi433.txt @@ -0,0 +1,274 @@ +===== +Pi433 +===== + + +Introduction +============ +This driver is for controlling pi433, a radio module for the Raspberry Pi +(www.pi433.de). It supports transmission and reception. It can be opened +by multiple applications for transmission and reception. While transmit +jobs were queued and process automatically in the background, the first +application asking for reception will block out all other applications +until something gets received terminates the read request. +The driver supports on the fly reloading of the hardware fifo of the rf +chip, thus enabling for much longer telegrams then hardware fifo size. + +Discription of driver operation +=============================== + +a) transmission + +Each transmission can take place with a different configuration of the rf +module. Therfore each application can set its own set of parameters. The driver +takes care, that each transmission takes place with the parameterset of the +application, that requests the transmission. To allow the transmission to take +place in the background, a tx thread is introduced. +The transfer of data from the main thread to the tx thread is realised by a +kfifo. With each write request of an application, the passed in data and the +corresponding parameter set gets written to the kfifo. +On the other "side" of the kfifo, the tx thread continuously checks, whether the +kfifo is empty. If not, it gets one set of config and data from the kfifo. If +there is no receive request or the receiver is still waiting for something in +the air, the rf module is set to standby, the parameters for transmission gets +set, the hardware fifo of the rf chip gets preloaded and the transmission gets +started. Upon hardware fifo threshold interrupt it gets reloaded, thus enabling +much longer telegrams then hardware fifo size. If the telegram is send and there +is more data available in the kfifo, the procedure is repeated. If not the +transmission cycle ends. + +b) reception + +Since there is only one application allowed to receive data at a time, for +reception there is only one configuration set. +As soon as an application sets an request for receiving a telegram, the reception +configuration set is written to the rf module and it gets set into receiving mode. +Now the driver is waiting, that a predefined RSSI level (signal strength at the +receiver) is reached. Until this hasn't happened, the reception can be +interrupted by the transmission thread at any time to insert a transmission cycle. +As soon as the predefined RSSI level is meat, a receiving cycle starts. Similar +as described for the transmission cycle the read out of the hardware fifo is done +dynamically. Upon each hardware fifo threshold interrupt, a portion of data gets +read. So also for reception it is possible to receive more data then the hardware +fifo can hold. + + +Driver API +========== + +The driver is currently implemented as a character device. Therefore it supports +the calls open, ioctl, read, write and close. + + +params for ioctl +---------------- + +There are four options: +PI433_IOC_RD_TX_CFG - get the transmission parameters from the driver +PI433_IOC_WR_TX_CFG - set the transmission parameters +PI433_IOC_RD_RX_CFG - get the receiving parameters from the driver +PI433_IOC_WR_RX_CFG - set the receiving parameters + +The tx configuration is transfered via struct pi433_tx_cfg, the parameterset for transmission. +It is devided into two sections: rf parameters and packet format. + +rf params: + frequency + frequency used for transmission. + Allowed values: 433050000...434790000 + bit_rate + bit rate used for transmission. + Allowed values: ##### + dev_frequency + frequency deviation in case of FSK. + Allowed values: 600...500000 + modulation + FSK - frequency shift key + OOK - On-Off-key + modShaping + shapingOff - no shaping + shaping1_0 - gauss filter with BT 1 (FSK only) + shaping0_5 - gauss filter with BT 0.5 (FSK only) + shaping0_3 - gauss filter with BT 0.3 (FSK only) + shapingBR - filter cut off at BR (OOK only) + shaping2BR - filter cut off at 2*BR (OOK only) + paRamp (FSK only) + ramp3400 - amp ramps up in 3.4ms + ramp2000 - amp ramps up in 2.0ms + ramp1000 - amp ramps up in 1ms + ramp500 - amp ramps up in 500us + ramp250 - amp ramps up in 250us + ramp125 - amp ramps up in 125us + ramp100 - amp ramps up in 100us + ramp62 - amp ramps up in 62us + ramp50 - amp ramps up in 50us + ramp40 - amp ramps up in 40us + ramp31 - amp ramps up in 31us + ramp25 - amp ramps up in 25us + ramp20 - amp ramps up in 20us + ramp15 - amp ramps up in 15us + ramp12 - amp ramps up in 12us + ramp10 - amp ramps up in 10us + tx_start_condition + fifoLevel - transmission starts, if fifo is filled to + threshold level + fifoNotEmpty - transmission starts, as soon as there is one + byte in internal fifo + repetitions + This gives the option, to send a telegram multiple times. Default: 1 + +packet format: + enable_preamble + optionOn - a preamble will be automatically generated + optionOff - no preamble will be generated + enable_sync + optionOn - a sync word will be automatically added to + the telegram after preamble + optionOff - no sync word will be added + Attention: While possible to generate sync without preamble, the + receiver won't be able to detect the sync without preamble. + enable_length_byte + optionOn - the length of the telegram will be automatically + added to the telegram. It's part of the payload + optionOff - no length information will be automatically added + to the telegram. + Attention: For telegram length over 255 bytes, this option can't be used + Attention: should be used in combination with sync, only + enable_address_byte + optionOn - the address byte will be automatically added to the + telgram. It's part of the payload + optionOff - the address byte will not be added to the telegram. + The address byte can be used for address filtering, so the receiver + will only receive telegrams with a given address byte. + Attention: should be used in combination with sync, only + enable_crc + optionOn - an crc will be automatically calculated over the + payload of the telegram and added to the telegram + after payload. + optionOff - no crc will be calculated + preamble_length + length of the preamble. Allowed values: 0...65536 + sync_length + length of the sync word. Allowed values: 0...8 + fixed_message_length + length of the payload of the telegram. Will override the length + given by the buffer, passed in with the write command. Will be + ignored if set to zero. + sync_pattern[8] + contains up to eight values, that are used as the sync pattern + on sync option + address_byte + one byte, used as address byte on address byte option. + + +The rx configuration is transfered via struct pi433_rx_cfg, the parameterset for receiving. It is devided into two sections: rf parameters and packet format. + +rf params: + frequency + frequency used for transmission. + Allowed values: 433050000...434790000 + bit_rate + bit rate used for transmission. + Allowed values: ##### + dev_frequency + frequency deviation in case of FSK. + Allowed values: 600...500000 + modulation + FSK - frequency shift key + OOK - on off key + rssi_threshold + threshold value for the signal strength on the receiver input. + If this value is exeeded, a reception cycle starts + Allowed values: 0...255 + thresholdDecrement + in order to adapt to different levels of singnal strength, over + time the receiver gets more and more sensitive. This value + determs, how fast the sensitivity increases. + step_0_5db - increase in 0,5dB steps + step_1_0db - increase in 1 db steps + step_1_5db - increase in 1,5dB steps + step_2_0db - increase in 2 db steps + step_3_0db - increase in 3 db steps + step_4_0db - increase in 4 db steps + step_5_0db - increase in 5 db steps + step_6_0db - increase in 6 db steps + antennaImpedance + sets the electrical adoption of the antenna + fiftyOhm - for antennas with an impedance of 50Ohm + twohundretOhm - for antennas with an impedance of 200Ohm + lnaGain + sets the gain of the low noise amp + automatic - lna gain is determed by an agc + max - lna gain is set to maximum + maxMinus6 - lna gain is set to 6db below max + maxMinus12 - lna gain is set to 12db below max + maxMinus24 - lna gain is set to 24db below max + maxMinus36 - lna gain is set to 36db below max + maxMinus48 - lna gain is set to 48db below max + bw_mantisse + sets the bandwidth of the channel filter - part one: mantisse. + mantisse16 - mantisse is set to 16 + mantisse20 - mantisse is set to 20 + mantisse24 - mantisse is set to 24 + bw_exponent + sets the bandwidth of the channel filter - part two: exponent. + Allowd values: 0...7 + dagc; + operation mode of the digital automatic gain control + normalMode + improve + improve4LowModulationIndex + + packet format: + enable_sync + optionOn - sync detection is enabled. If configured sync pattern + isn't found, telegram will be internally discarded + optionOff - sync detection is disabled. + enable_length_byte + optionOn - First byte of payload will be used as length byte, + regardless of the amount of bytes that were requested + by the read request. + optionOff - Number of bytes to be read will be set according to + amount of bytes that were requested by the read request. + Attention: should be used in combination with sync, only + enable_address_filtering; + filteringOff - no adress filtering will take place + nodeAddress - all telegrams, not matching the node + address will be internally discarded + nodeOrBroadcastAddress - all telegrams, neither matching the + node, nor the broadcast address will + be internally discarded + Attention: Sync option must be enabled in order to use this feature + enable_crc + optionOn - a crc will be calculated over the payload of + the telegram, that was received. If the + calculated crc doesn't match to two bytes, + that follow the payload, the telegram will be + internally discarded. + Attention: This option is only operational, if sync on and fixed length + or length byte is used + sync_length + Gives the length of the payload. + Attention: This setting must meet the setting of the transmitter, + if sync option is used. + fixed_message_length + Overrides the telegram length either given by the first byte of + payload or by the read request. + bytes_to_drop + gives the number of bytes, that will be dropped before transfering + data to the read buffer + This option is only usefull, if all packet helper are switched + off and the rf chip is used in raw receiving mode. This may be + needed, if a telegram of a third party device should be received, + using a protocol not compatible with the packet engine of the rf69 chip. + sync_pattern[8] + contains up to eight values, that are used as the sync pattern + on sync option. + This setting must meet the configuration of the transmitting device, + if sync option is enabled. + node_address + one byte, used as node address byte on address byte option. + broadcast_address + one byte, used as broadcast address byte on address byte option. + + diff --git a/drivers/staging/pi433/Kconfig b/drivers/staging/pi433/Kconfig new file mode 100644 index 000000000000..b2716b85d5af --- /dev/null +++ b/drivers/staging/pi433/Kconfig @@ -0,0 +1,16 @@ +config PI433 + tristate "Pi433 - a 433MHz radio module for Raspberry Pi" + default n + ---help--- + This option allows you to enable support for the radio module Pi433. + + Pi433 is a shield that fits onto the GPIO header of a Raspberry Pi + or compatible. It extends the Raspberry Pi with the option, to + send and receive data in the 433MHz ISM band - for example to + communicate between two systems without using ethernet or bluetooth + or for control or read sockets, actors, sensors, widely available + for low price. + + For details or the option to buy, please visit https://pi433.de/en.html + + If in doubt, say N here, but saying yes most probably won't hurt diff --git a/drivers/staging/pi433/Makefile b/drivers/staging/pi433/Makefile new file mode 100644 index 000000000000..417f3e4d12b1 --- /dev/null +++ b/drivers/staging/pi433/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_PI433) += pi433.o + +pi433-objs := pi433_if.o rf69.o diff --git a/drivers/staging/pi433/TODO b/drivers/staging/pi433/TODO new file mode 100644 index 000000000000..63a40bfcc67e --- /dev/null +++ b/drivers/staging/pi433/TODO @@ -0,0 +1,5 @@ +* coding style does not fully comply with the kernel style guide. +* still TODOs, annotated in the code +* currently the code introduces new IOCTLs. I'm afraid this is a bad idea. + -> Replace this with another interface, hints are welcome! +* Some missing data (marked with ###) needs to be added in the documentation diff --git a/drivers/staging/pi433/pi433_if.c b/drivers/staging/pi433/pi433_if.c new file mode 100644 index 000000000000..1bc478a7f49e --- /dev/null +++ b/drivers/staging/pi433/pi433_if.c @@ -0,0 +1,1314 @@ +/* + * userspace interface for pi433 radio module + * + * Pi433 is a 433MHz radio module for the Raspberry Pi. + * It is based on the HopeRf Module RFM69CW. Therefore inside of this + * driver, you'll find an abstraction of the rf69 chip. + * + * If needed, this driver could be extended, to also support other + * devices, basing on HopeRfs rf69. + * + * The driver can also be extended, to support other modules of + * HopeRf with a similar interace - e. g. RFM69HCW, RFM12, RFM95, ... + * + * Copyright (C) 2016 Wolf-Entwicklungen + * Marcus Wolf + * + * 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. + */ + +#undef DEBUG + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_COMPAT +#include +#endif + +#include "pi433_if.h" +#include "rf69.h" + + +#define N_PI433_MINORS (1U << MINORBITS) /*32*/ /* ... up to 256 */ +#define MAX_MSG_SIZE 900 /* min: FIFO_SIZE! */ +#define MSG_FIFO_SIZE 65536 /* 65536 = 2^16 */ +#define NUM_DIO 2 + +static dev_t pi433_dev; +static DEFINE_IDR(pi433_idr); +static DEFINE_MUTEX(minor_lock); /* Protect idr accesses */ + +static struct class *pi433_class; /* mainly for udev to create /dev/pi433 */ + +/* tx config is instance specific + so with each open a new tx config struct is needed */ +/* rx config is device specific + so we have just one rx config, ebedded in device struct */ +struct pi433_device { + /* device handling related values */ + dev_t devt; + int minor; + struct device *dev; + struct cdev *cdev; + struct spi_device *spi; + unsigned users; + + /* irq related values */ + struct gpio_desc *gpiod[NUM_DIO]; + int irq_num[NUM_DIO]; + u8 irq_state[NUM_DIO]; + + /* tx related values */ + STRUCT_KFIFO_REC_1(MSG_FIFO_SIZE) tx_fifo; + struct mutex tx_fifo_lock; // TODO: check, whether necessary or obsolete + struct task_struct *tx_task_struct; + wait_queue_head_t tx_wait_queue; + u8 free_in_fifo; + + /* rx related values */ + struct pi433_rx_cfg rx_cfg; + u8 *rx_buffer; + unsigned int rx_buffer_size; + u32 rx_bytes_to_drop; + u32 rx_bytes_dropped; + unsigned int rx_position; + struct mutex rx_lock; + wait_queue_head_t rx_wait_queue; + + /* fifo wait queue */ + struct task_struct *fifo_task_struct; + wait_queue_head_t fifo_wait_queue; + + /* flags */ + bool rx_active; + bool tx_active; + bool interrupt_rx_allowed; +}; + +struct pi433_instance { + struct pi433_device *device; + struct pi433_tx_cfg tx_cfg; +}; + +/*-------------------------------------------------------------------------*/ + +/* macro for checked access of registers of radio module */ +#define SET_CHECKED(retval) \ + if (retval < 0) \ + return retval; + +/*-------------------------------------------------------------------------*/ + +/* GPIO interrupt handlers */ +static irq_handler_t +DIO0_irq_handler(unsigned int irq, void *dev_id, struct pt_regs *regs) +{ + struct pi433_device *device = dev_id; + + if (device->irq_state[DIO0] == DIO_PacketSent) + { + device->free_in_fifo = FIFO_SIZE; + printk("DIO0 irq: Packet sent\n"); // TODO: printk() should include KERN_ facility level + wake_up_interruptible(&device->fifo_wait_queue); + } + else if (device->irq_state[DIO0] == DIO_Rssi_DIO0) + { + printk("DIO0 irq: RSSI level over threshold\n"); + wake_up_interruptible(&device->rx_wait_queue); + } + else if (device->irq_state[DIO0] == DIO_PayloadReady) + { + printk("DIO0 irq: PayloadReady\n"); + device->free_in_fifo = 0; + wake_up_interruptible(&device->fifo_wait_queue); + } + + return (irq_handler_t) IRQ_HANDLED; +} + +static irq_handler_t +DIO1_irq_handler(unsigned int irq, void *dev_id, struct pt_regs *regs) +{ + struct pi433_device *device = dev_id; + + if (device->irq_state[DIO1] == DIO_FifoNotEmpty_DIO1) + { + device->free_in_fifo = FIFO_SIZE; + } + else if (device->irq_state[DIO1] == DIO_FifoLevel) + { + if (device->rx_active) device->free_in_fifo = FIFO_THRESHOLD - 1; + else device->free_in_fifo = FIFO_SIZE - FIFO_THRESHOLD - 1; + } + printk("DIO1 irq: %d bytes free in fifo\n", device->free_in_fifo); // TODO: printk() should include KERN_ facility level + wake_up_interruptible(&device->fifo_wait_queue); + + return (irq_handler_t) IRQ_HANDLED; +} + +static void *DIO_irq_handler[NUM_DIO] = { + DIO0_irq_handler, + DIO1_irq_handler +}; + +/*-------------------------------------------------------------------------*/ + +static int +rf69_set_rx_cfg(struct pi433_device *dev, struct pi433_rx_cfg *rx_cfg) +{ + int payload_length; + + /* receiver config */ + SET_CHECKED(rf69_set_frequency (dev->spi, rx_cfg->frequency)); + SET_CHECKED(rf69_set_bit_rate (dev->spi, rx_cfg->bit_rate)); + SET_CHECKED(rf69_set_modulation (dev->spi, rx_cfg->modulation)); + SET_CHECKED(rf69_set_antenna_impedance (dev->spi, rx_cfg->antenna_impedance)); + SET_CHECKED(rf69_set_rssi_threshold (dev->spi, rx_cfg->rssi_threshold)); + SET_CHECKED(rf69_set_ook_threshold_dec (dev->spi, rx_cfg->thresholdDecrement)); + SET_CHECKED(rf69_set_bandwidth (dev->spi, rx_cfg->bw_mantisse, rx_cfg->bw_exponent)); + SET_CHECKED(rf69_set_bandwidth_during_afc(dev->spi, rx_cfg->bw_mantisse, rx_cfg->bw_exponent)); + SET_CHECKED(rf69_set_dagc (dev->spi, rx_cfg->dagc)); + + dev->rx_bytes_to_drop = rx_cfg->bytes_to_drop; + + /* packet config */ + /* enable */ + SET_CHECKED(rf69_set_sync_enable(dev->spi, rx_cfg->enable_sync)); + if (rx_cfg->enable_sync == optionOn) + { + SET_CHECKED(rf69_set_fifo_fill_condition(dev->spi, afterSyncInterrupt)); + } + else + { + SET_CHECKED(rf69_set_fifo_fill_condition(dev->spi, always)); + } + SET_CHECKED(rf69_set_packet_format (dev->spi, rx_cfg->enable_length_byte)); + SET_CHECKED(rf69_set_adressFiltering(dev->spi, rx_cfg->enable_address_filtering)); + SET_CHECKED(rf69_set_crc_enable (dev->spi, rx_cfg->enable_crc)); + + /* lengths */ + SET_CHECKED(rf69_set_sync_size(dev->spi, rx_cfg->sync_length)); + if (rx_cfg->enable_length_byte == optionOn) + { + SET_CHECKED(rf69_set_payload_length(dev->spi, 0xff)); + } + else if (rx_cfg->fixed_message_length != 0) + { + payload_length = rx_cfg->fixed_message_length; + if (rx_cfg->enable_length_byte == optionOn) payload_length++; + if (rx_cfg->enable_address_filtering != filteringOff) payload_length++; + SET_CHECKED(rf69_set_payload_length(dev->spi, payload_length)); + } + else + { + SET_CHECKED(rf69_set_payload_length(dev->spi, 0)); + } + + /* values */ + if (rx_cfg->enable_sync == optionOn) + { + SET_CHECKED(rf69_set_sync_values(dev->spi, rx_cfg->sync_pattern)); + } + if (rx_cfg->enable_address_filtering != filteringOff) + { + SET_CHECKED(rf69_set_node_address (dev->spi, rx_cfg->node_address)); + SET_CHECKED(rf69_set_broadcast_address(dev->spi, rx_cfg->broadcast_address)); + } + + return 0; +} + +static int +rf69_set_tx_cfg(struct pi433_device *dev, struct pi433_tx_cfg *tx_cfg) +{ + SET_CHECKED(rf69_set_frequency (dev->spi, tx_cfg->frequency)); + SET_CHECKED(rf69_set_bit_rate (dev->spi, tx_cfg->bit_rate)); + SET_CHECKED(rf69_set_modulation (dev->spi, tx_cfg->modulation)); + SET_CHECKED(rf69_set_deviation (dev->spi, tx_cfg->dev_frequency)); + SET_CHECKED(rf69_set_pa_ramp (dev->spi, tx_cfg->pa_ramp)); + SET_CHECKED(rf69_set_modulation_shaping(dev->spi, tx_cfg->modShaping)); + SET_CHECKED(rf69_set_tx_start_condition(dev->spi, tx_cfg->tx_start_condition)); + + /* packet format enable */ + if (tx_cfg->enable_preamble == optionOn) + { + SET_CHECKED(rf69_set_preamble_length(dev->spi, tx_cfg->preamble_length)); + } + else + { + SET_CHECKED(rf69_set_preamble_length(dev->spi, 0)); + } + SET_CHECKED(rf69_set_sync_enable (dev->spi, tx_cfg->enable_sync)); + SET_CHECKED(rf69_set_packet_format(dev->spi, tx_cfg->enable_length_byte)); + SET_CHECKED(rf69_set_crc_enable (dev->spi, tx_cfg->enable_crc)); + + /* configure sync, if enabled */ + if (tx_cfg->enable_sync == optionOn) + { + SET_CHECKED(rf69_set_sync_size(dev->spi, tx_cfg->sync_length)); + SET_CHECKED(rf69_set_sync_values(dev->spi, tx_cfg->sync_pattern)); + } + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static int +pi433_start_rx(struct pi433_device *dev) +{ + int retval; + + /* return without action, if no pending read request */ + if (!dev->rx_active) + return 0; + + /* setup for receiving */ + retval = rf69_set_rx_cfg(dev, &dev->rx_cfg); + if (retval) return retval; + + /* setup rssi irq */ + SET_CHECKED(rf69_set_dio_mapping(dev->spi, DIO0, DIO_Rssi_DIO0)); + dev->irq_state[DIO0] = DIO_Rssi_DIO0; + irq_set_irq_type(dev->irq_num[DIO0], IRQ_TYPE_EDGE_RISING); + + /* setup fifo level interrupt */ + SET_CHECKED(rf69_set_fifo_threshold(dev->spi, FIFO_SIZE - FIFO_THRESHOLD)); + SET_CHECKED(rf69_set_dio_mapping(dev->spi, DIO1, DIO_FifoLevel)); + dev->irq_state[DIO1] = DIO_FifoLevel; + irq_set_irq_type(dev->irq_num[DIO1], IRQ_TYPE_EDGE_RISING); + + /* set module to receiving mode */ + SET_CHECKED(rf69_set_mode(dev->spi, receive)); + + return 0; +} + + +/*-------------------------------------------------------------------------*/ + +int +pi433_receive(void *data) +{ + struct pi433_device *dev = data; + struct spi_device *spi = dev->spi; /* needed for SET_CHECKED */ + int bytes_to_read, bytes_total; + int retval; + + dev->interrupt_rx_allowed = false; + + /* wait for any tx to finish */ + dev_dbg(dev->dev,"rx: going to wait for any tx to finish"); + retval = wait_event_interruptible(dev->rx_wait_queue, !dev->tx_active); + if(retval) /* wait was interrupted */ + { + dev->interrupt_rx_allowed = true; + wake_up_interruptible(&dev->tx_wait_queue); + return retval; + } + + /* prepare status vars */ + dev->free_in_fifo = FIFO_SIZE; + dev->rx_position = 0; + dev->rx_bytes_dropped = 0; + + /* setup radio module to listen for something "in the air" */ + retval = pi433_start_rx(dev); + if (retval) + return retval; + + /* now check RSSI, if low wait for getting high (RSSI interrupt) */ + while ( !rf69_get_flag(dev->spi, rssiExceededThreshold) ) + { + /* allow tx to interrupt us while waiting for high RSSI */ + dev->interrupt_rx_allowed = true; + wake_up_interruptible(&dev->tx_wait_queue); + + /* wait for RSSI level to become high */ + dev_dbg(dev->dev, "rx: going to wait for high RSSI level"); + retval = wait_event_interruptible(dev->rx_wait_queue, + rf69_get_flag(dev->spi, + rssiExceededThreshold)); + if (retval) goto abort; /* wait was interrupted */ + dev->interrupt_rx_allowed = false; + + /* cross check for ongoing tx */ + if (!dev->tx_active) break; + } + + /* configure payload ready irq */ + SET_CHECKED(rf69_set_dio_mapping(spi, DIO0, DIO_PayloadReady)); + dev->irq_state[DIO0] = DIO_PayloadReady; + irq_set_irq_type(dev->irq_num[DIO0], IRQ_TYPE_EDGE_RISING); + + /* fixed or unlimited length? */ + if (dev->rx_cfg.fixed_message_length != 0) + { + if (dev->rx_cfg.fixed_message_length > dev->rx_buffer_size) + { + retval = -1; + goto abort; + } + bytes_total = dev->rx_cfg.fixed_message_length; + dev_dbg(dev->dev,"rx: msg len set to %d by fixed length", bytes_total); + } + else + { + bytes_total = dev->rx_buffer_size; + dev_dbg(dev->dev, "rx: msg len set to %d as requested by read", bytes_total); + } + + /* length byte enabled? */ + if (dev->rx_cfg.enable_length_byte == optionOn) + { + retval = wait_event_interruptible(dev->fifo_wait_queue, + dev->free_in_fifo < FIFO_SIZE); + if (retval) goto abort; /* wait was interrupted */ + + rf69_read_fifo(spi, (u8 *)&bytes_total, 1); + if (bytes_total > dev->rx_buffer_size) + { + retval = -1; + goto abort; + } + dev->free_in_fifo++; + dev_dbg(dev->dev, "rx: msg len reset to %d due to length byte", bytes_total); + } + + /* address byte enabled? */ + if (dev->rx_cfg.enable_address_filtering != filteringOff) + { + u8 dummy; + + bytes_total--; + + retval = wait_event_interruptible(dev->fifo_wait_queue, + dev->free_in_fifo < FIFO_SIZE); + if (retval) goto abort; /* wait was interrupted */ + + rf69_read_fifo(spi, &dummy, 1); + dev->free_in_fifo++; + dev_dbg(dev->dev, "rx: address byte stripped off"); + } + + /* get payload */ + while (dev->rx_position < bytes_total) + { + if ( !rf69_get_flag(dev->spi, payloadReady) ) + { + retval = wait_event_interruptible(dev->fifo_wait_queue, + dev->free_in_fifo < FIFO_SIZE); + if (retval) goto abort; /* wait was interrupted */ + } + + /* need to drop bytes or acquire? */ + if (dev->rx_bytes_to_drop > dev->rx_bytes_dropped) + bytes_to_read = dev->rx_bytes_to_drop - dev->rx_bytes_dropped; + else + bytes_to_read = bytes_total - dev->rx_position; + + + /* access the fifo */ + if (bytes_to_read > FIFO_SIZE - dev->free_in_fifo) + bytes_to_read = FIFO_SIZE - dev->free_in_fifo; + retval = rf69_read_fifo(spi, + &dev->rx_buffer[dev->rx_position], + bytes_to_read); + if (retval) goto abort; /* read failed */ + dev->free_in_fifo += bytes_to_read; + + /* adjust status vars */ + if (dev->rx_bytes_to_drop > dev->rx_bytes_dropped) + dev->rx_bytes_dropped += bytes_to_read; + else + dev->rx_position += bytes_to_read; + } + + + /* rx done, wait was interrupted or error occured */ +abort: + dev->interrupt_rx_allowed = true; + SET_CHECKED(rf69_set_mode(dev->spi, standby)); + wake_up_interruptible(&dev->tx_wait_queue); + + if (retval) + return retval; + else + return bytes_total; +} + +int +pi433_tx_thread(void *data) +{ + struct pi433_device *device = data; + struct spi_device *spi = device->spi; /* needed for SET_CHECKED */ + struct pi433_tx_cfg tx_cfg; + u8 buffer[MAX_MSG_SIZE]; + size_t size; + bool rx_interrupted = false; + int position, repetitions; + int retval; + + while (1) + { + /* wait for fifo to be populated or for request to terminate*/ + dev_dbg(device->dev, "thread: going to wait for new messages"); + wait_event_interruptible(device->tx_wait_queue, + ( !kfifo_is_empty(&device->tx_fifo) || + kthread_should_stop() )); + if ( kthread_should_stop() ) + return 0; + + /* get data from fifo in the following order: + - tx_cfg + - size of message + - message */ + mutex_lock(&device->tx_fifo_lock); + + retval = kfifo_out(&device->tx_fifo, &tx_cfg, sizeof(tx_cfg)); + if (retval != sizeof(tx_cfg)) + { + dev_dbg(device->dev, "reading tx_cfg from fifo failed: got %d byte(s), expected %d", retval, (unsigned int)sizeof(tx_cfg) ); + mutex_unlock(&device->tx_fifo_lock); + continue; + } + + retval = kfifo_out(&device->tx_fifo, &size, sizeof(size_t)); + if (retval != sizeof(size_t)) + { + dev_dbg(device->dev, "reading msg size from fifo failed: got %d, expected %d", retval, (unsigned int)sizeof(size_t) ); + mutex_unlock(&device->tx_fifo_lock); + continue; + } + + /* use fixed message length, if requested */ + if (tx_cfg.fixed_message_length != 0) + size = tx_cfg.fixed_message_length; + + /* increase size, if len byte is requested */ + if (tx_cfg.enable_length_byte == optionOn) + size++; + + /* increase size, if adr byte is requested */ + if (tx_cfg.enable_address_byte == optionOn) + size++; + + /* prime buffer */ + memset(buffer, 0, size); + position = 0; + + /* add length byte, if requested */ + if (tx_cfg.enable_length_byte == optionOn) + buffer[position++] = size-1; /* according to spec length byte itself must be excluded from the length calculation */ + + /* add adr byte, if requested */ + if (tx_cfg.enable_address_byte == optionOn) + buffer[position++] = tx_cfg.address_byte; + + /* finally get message data from fifo */ + retval = kfifo_out(&device->tx_fifo, &buffer[position], sizeof(buffer)-position ); + dev_dbg(device->dev, "read %d message byte(s) from fifo queue.", retval); + mutex_unlock(&device->tx_fifo_lock); + + /* if rx is active, we need to interrupt the waiting for + incoming telegrams, to be able to send something. + We are only allowed, if currently no reception takes + place otherwise we need to wait for the incoming telegram + to finish */ + wait_event_interruptible(device->tx_wait_queue, + !device->rx_active || + device->interrupt_rx_allowed == true); + + /* prevent race conditions + irq will be reenabled after tx config is set */ + disable_irq(device->irq_num[DIO0]); + device->tx_active = true; + + if (device->rx_active && rx_interrupted == false) + { + /* rx is currently waiting for a telegram; + we need to set the radio module to standby */ + SET_CHECKED(rf69_set_mode(device->spi, standby)); + rx_interrupted = true; + } + + /* clear fifo, set fifo threshold, set payload length */ + SET_CHECKED(rf69_set_mode(spi, standby)); /* this clears the fifo */ + SET_CHECKED(rf69_set_fifo_threshold(spi, FIFO_THRESHOLD)); + if (tx_cfg.enable_length_byte == optionOn) + { + SET_CHECKED(rf69_set_payload_length(spi, size * tx_cfg.repetitions)); + } + else + { + SET_CHECKED(rf69_set_payload_length(spi, 0)); + } + + /* configure the rf chip */ + rf69_set_tx_cfg(device, &tx_cfg); + + /* enable fifo level interrupt */ + SET_CHECKED(rf69_set_dio_mapping(spi, DIO1, DIO_FifoLevel)); + device->irq_state[DIO1] = DIO_FifoLevel; + irq_set_irq_type(device->irq_num[DIO1], IRQ_TYPE_EDGE_FALLING); + + /* enable packet sent interrupt */ + SET_CHECKED(rf69_set_dio_mapping(spi, DIO0, DIO_PacketSent)); + device->irq_state[DIO0] = DIO_PacketSent; + irq_set_irq_type(device->irq_num[DIO0], IRQ_TYPE_EDGE_RISING); + enable_irq(device->irq_num[DIO0]); /* was disabled by rx active check */ + + /* enable transmission */ + SET_CHECKED(rf69_set_mode(spi, transmit)); + + /* transfer this msg (and repetitions) to chip fifo */ + device->free_in_fifo = FIFO_SIZE; + position = 0; + repetitions = tx_cfg.repetitions; + while( (repetitions > 0) && (size > position) ) + { + if ( (size - position) > device->free_in_fifo) + { /* msg to big for fifo - take a part */ + int temp = device->free_in_fifo; + device->free_in_fifo = 0; + rf69_write_fifo(spi, + &buffer[position], + temp); + position +=temp; + } + else + { /* msg fits into fifo - take all */ + device->free_in_fifo -= size; + repetitions--; + rf69_write_fifo(spi, + &buffer[position], + (size - position) ); + position = 0; /* reset for next repetition */ + } + + retval = wait_event_interruptible(device->fifo_wait_queue, + device->free_in_fifo > 0); + if (retval) { printk("ABORT\n"); goto abort; } + } + + /* we are done. Wait for packet to get sent */ + dev_dbg(device->dev, "thread: wiat for packet to get sent/fifo to be empty"); + wait_event_interruptible(device->fifo_wait_queue, + device->free_in_fifo == FIFO_SIZE || + kthread_should_stop() ); + if ( kthread_should_stop() ) printk("ABORT\n"); + + + /* STOP_TRANSMISSION */ + dev_dbg(device->dev, "thread: Packet sent. Set mode to stby."); + SET_CHECKED(rf69_set_mode(spi, standby)); + + /* everything sent? */ + if ( kfifo_is_empty(&device->tx_fifo) ) + { +abort: + if (rx_interrupted) + { + rx_interrupted = false; + pi433_start_rx(device); + } + device->tx_active = false; + wake_up_interruptible(&device->rx_wait_queue); + } + } +} + +/*-------------------------------------------------------------------------*/ + +static ssize_t +pi433_read(struct file *filp, char __user *buf, size_t size, loff_t *f_pos) +{ + struct pi433_instance *instance; + struct pi433_device *device; + int bytes_received; + ssize_t retval; + + /* check, whether internal buffer is big enough for requested size */ + if (size > MAX_MSG_SIZE) + return -EMSGSIZE; + + instance = filp->private_data; + device = instance->device; + + /* just one read request at a time */ + mutex_lock(&device->rx_lock); + if (device->rx_active) + { + mutex_unlock(&device->rx_lock); + return -EAGAIN; + } + else + { + device->rx_active = true; + mutex_unlock(&device->rx_lock); + } + + /* start receiving */ + /* will block until something was received*/ + device->rx_buffer_size = size; + bytes_received = pi433_receive(device); + + /* release rx */ + mutex_lock(&device->rx_lock); + device->rx_active = false; + mutex_unlock(&device->rx_lock); + + /* if read was successful copy to user space*/ + if (bytes_received > 0) + { + retval = copy_to_user(buf, device->rx_buffer, bytes_received); + if (retval) + return retval; + } + + return bytes_received; +} + + +static ssize_t +pi433_write(struct file *filp, const char __user *buf, + size_t count, loff_t *f_pos) +{ + struct pi433_instance *instance; + struct pi433_device *device; + int copied, retval; + + instance = filp->private_data; + device = instance->device; + + /* check, whether internal buffer (tx thread) is big enough for requested size */ + if (count > MAX_MSG_SIZE) + return -EMSGSIZE; + + /* write the following sequence into fifo: + - tx_cfg + - size of message + - message */ + mutex_lock(&device->tx_fifo_lock); + retval = kfifo_in(&device->tx_fifo, &instance->tx_cfg, sizeof(instance->tx_cfg)); + if ( retval != sizeof(instance->tx_cfg) ) + goto abort; + + retval = kfifo_in (&device->tx_fifo, &count, sizeof(size_t)); + if ( retval != sizeof(size_t) ) + goto abort; + + retval = kfifo_from_user(&device->tx_fifo, buf, count, &copied); + if (retval || copied != count) + goto abort; + + mutex_unlock(&device->tx_fifo_lock); + + /* start transfer */ + wake_up_interruptible(&device->tx_wait_queue); + dev_dbg(device->dev, "write: generated new msg with %d bytes.", copied); + + return 0; + +abort: + dev_dbg(device->dev, "write to fifo failed: 0x%x", retval); + kfifo_reset(&device->tx_fifo); // TODO: maybe find a solution, not to discard already stored, valid entries + mutex_unlock(&device->tx_fifo_lock); + return -EAGAIN; +} + + +static long +pi433_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + int err = 0; + int retval = 0; + struct pi433_instance *instance; + struct pi433_device *device; + u32 tmp; + + /* Check type and command number */ + if (_IOC_TYPE(cmd) != PI433_IOC_MAGIC) + return -ENOTTY; + + /* Check access direction once here; don't repeat below. + * IOC_DIR is from the user perspective, while access_ok is + * from the kernel perspective; so they look reversed. + */ + if (_IOC_DIR(cmd) & _IOC_READ) + err = !access_ok(VERIFY_WRITE, + (void __user *)arg, + _IOC_SIZE(cmd)); + + if (err == 0 && _IOC_DIR(cmd) & _IOC_WRITE) + err = !access_ok(VERIFY_READ, + (void __user *)arg, + _IOC_SIZE(cmd)); + if (err) + return -EFAULT; + + /* TODO? guard against device removal before, or while, + * we issue this ioctl. --> device_get() + */ + instance = filp->private_data; + device = instance->device; + + if (device == NULL) + return -ESHUTDOWN; + + switch (cmd) { + case PI433_IOC_RD_TX_CFG: + tmp = _IOC_SIZE(cmd); + if ( (tmp == 0) || ((tmp % sizeof(struct pi433_tx_cfg)) != 0) ) + { + retval = -EINVAL; + break; + } + + if (__copy_to_user((void __user *)arg, + &instance->tx_cfg, + tmp)) + { + retval = -EFAULT; + break; + } + + break; + case PI433_IOC_WR_TX_CFG: + tmp = _IOC_SIZE(cmd); + if ( (tmp == 0) || ((tmp % sizeof(struct pi433_tx_cfg)) != 0) ) + { + retval = -EINVAL; + break; + } + + if (__copy_from_user(&instance->tx_cfg, + (void __user *)arg, + tmp)) + { + retval = -EFAULT; + break; + } + + break; + + case PI433_IOC_RD_RX_CFG: + tmp = _IOC_SIZE(cmd); + if ( (tmp == 0) || ((tmp % sizeof(struct pi433_rx_cfg)) != 0) ) { + retval = -EINVAL; + break; + } + + if (__copy_to_user((void __user *)arg, + &device->rx_cfg, + tmp)) + { + retval = -EFAULT; + break; + } + + break; + case PI433_IOC_WR_RX_CFG: + tmp = _IOC_SIZE(cmd); + mutex_lock(&device->rx_lock); + + /* during pendig read request, change of config not allowed */ + if (device->rx_active) { + retval = -EAGAIN; + mutex_unlock(&device->rx_lock); + break; + } + + if ( (tmp == 0) || ((tmp % sizeof(struct pi433_rx_cfg)) != 0) ) { + retval = -EINVAL; + mutex_unlock(&device->rx_lock); + break; + } + + if (__copy_from_user(&device->rx_cfg, + (void __user *)arg, + tmp)) + { + retval = -EFAULT; + mutex_unlock(&device->rx_lock); + break; + } + + mutex_unlock(&device->rx_lock); + break; + default: + retval = -EINVAL; + } + + return retval; +} + +#ifdef CONFIG_COMPAT +static long +pi433_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + return pi433_ioctl(filp, cmd, (unsigned long)compat_ptr(arg)); +} +#else +#define pi433_compat_ioctl NULL +#endif /* CONFIG_COMPAT */ + +/*-------------------------------------------------------------------------*/ + +static int pi433_open(struct inode *inode, struct file *filp) +{ + struct pi433_device *device; + struct pi433_instance *instance; + + mutex_lock(&minor_lock); + device = idr_find(&pi433_idr, iminor(inode)); + mutex_unlock(&minor_lock); + if (!device) { + pr_debug("device: minor %d unknown.\n", iminor(inode)); + return -ENODEV; + } + + if (!device->rx_buffer) { + device->rx_buffer = kmalloc(MAX_MSG_SIZE, GFP_KERNEL); + if (!device->rx_buffer) + { + dev_dbg(device->dev, "open/ENOMEM\n"); + return -ENOMEM; + } + } + + device->users++; + instance = kzalloc(sizeof(*instance), GFP_KERNEL); + if (!instance) + { + kfree(device->rx_buffer); + device->rx_buffer = NULL; + return -ENOMEM; + } + + /* setup instance data*/ + instance->device = device; + instance->tx_cfg.bit_rate = 4711; + // TODO: fill instance->tx_cfg; + + /* instance data as context */ + filp->private_data = instance; + nonseekable_open(inode, filp); + + return 0; +} + +static int pi433_release(struct inode *inode, struct file *filp) +{ + struct pi433_instance *instance; + struct pi433_device *device; + + instance = filp->private_data; + device = instance->device; + kfree(instance); + filp->private_data = NULL; + + /* last close? */ + device->users--; + + if (!device->users) { + kfree(device->rx_buffer); + device->rx_buffer = NULL; + if (device->spi == NULL) + kfree(device); + } + + return 0; +} + + +/*-------------------------------------------------------------------------*/ + +static int setup_GPIOs(struct pi433_device *device) +{ + char name[5]; + int retval; + int i; + + for (i=0; igpiod[i] = gpiod_get(&device->spi->dev, name, 0 /*GPIOD_IN*/); + + if (device->gpiod[i] == ERR_PTR(-ENOENT)) + { + dev_dbg(&device->spi->dev, "Could not find entry for %s. Ignoring.", name); + continue; + } + + if (device->gpiod[i] == ERR_PTR(-EBUSY)) + dev_dbg(&device->spi->dev, "%s is busy.", name); + + if ( IS_ERR(device->gpiod[i]) ) + { + retval = PTR_ERR(device->gpiod[i]); + /* release already allocated gpios */ + for (i--; i>=0; i--) + { + free_irq(device->irq_num[i], device); + gpiod_put(device->gpiod[i]); + } + return retval; + } + + + /* configure the pin */ + gpiod_unexport(device->gpiod[i]); + retval = gpiod_direction_input(device->gpiod[i]); + if (retval) return retval; + + + /* configure irq */ + device->irq_num[i] = gpiod_to_irq(device->gpiod[i]); + if (device->irq_num[i] < 0) + { + device->gpiod[i] = ERR_PTR(-EINVAL);//(struct gpio_desc *)device->irq_num[i]; + return device->irq_num[i]; + } + retval = request_irq(device->irq_num[i], + DIO_irq_handler[i], + 0, /* flags */ + name, + device); + + if (retval) + return retval; + + dev_dbg(&device->spi->dev, "%s succesfully configured", name); + } + + return 0; +} + +static void free_GPIOs(struct pi433_device *device) +{ + int i; + + for (i=0; igpiod[i]) ) + continue; + + free_irq(device->irq_num[i], device); + gpiod_put(device->gpiod[i]); + } + return; +} + +static int pi433_get_minor(struct pi433_device *device) +{ + int retval = -ENOMEM; + + mutex_lock(&minor_lock); + retval = idr_alloc(&pi433_idr, device, 0, N_PI433_MINORS, GFP_KERNEL); + if (retval >= 0) { + device->minor = retval; + retval = 0; + } else if (retval == -ENOSPC) { + dev_err(device->dev, "too many pi433 devices\n"); + retval = -EINVAL; + } + mutex_unlock(&minor_lock); + return retval; +} + +static void pi433_free_minor(struct pi433_device *dev) +{ + mutex_lock(&minor_lock); + idr_remove(&pi433_idr, dev->minor); + mutex_unlock(&minor_lock); +} +/*-------------------------------------------------------------------------*/ + +static const struct file_operations pi433_fops = { + .owner = THIS_MODULE, + /* REVISIT switch to aio primitives, so that userspace + * gets more complete API coverage. It'll simplify things + * too, except for the locking. + */ + .write = pi433_write, + .read = pi433_read, + .unlocked_ioctl = pi433_ioctl, + .compat_ioctl = pi433_compat_ioctl, + .open = pi433_open, + .release = pi433_release, + .llseek = no_llseek, +}; + +/*-------------------------------------------------------------------------*/ + +static int pi433_probe(struct spi_device *spi) +{ + struct pi433_device *device; + int retval; + + /* setup spi parameters */ + spi->mode = 0x00; + spi->bits_per_word = 8; + /* spi->max_speed_hz = 10000000; 1MHz already set by device tree overlay */ + + retval = spi_setup(spi); + if (retval) + { + dev_dbg(&spi->dev, "configuration of SPI interface failed!\n"); + return retval; + } + else + { + dev_dbg(&spi->dev, + "spi interface setup: mode 0x%2x, %d bits per word, %dhz max speed", + spi->mode, spi->bits_per_word, spi->max_speed_hz); + } + + /* Ping the chip by reading the version register */ + retval = spi_w8r8(spi, 0x10); + if (retval < 0) + return retval; + + switch(retval) + { + case 0x24: + dev_dbg(&spi->dev, "fonud pi433 (ver. 0x%x)", retval); + break; + default: + dev_dbg(&spi->dev, "unknown chip version: 0x%x", retval); + return -ENODEV; + } + + /* Allocate driver data */ + device = kzalloc(sizeof(*device), GFP_KERNEL); + if (!device) + return -ENOMEM; + + /* Initialize the driver data */ + device->spi = spi; + device->rx_active = false; + device->tx_active = false; + device->interrupt_rx_allowed = false; + + /* init wait queues */ + init_waitqueue_head(&device->tx_wait_queue); + init_waitqueue_head(&device->rx_wait_queue); + init_waitqueue_head(&device->fifo_wait_queue); + + /* init fifo */ + INIT_KFIFO(device->tx_fifo); + + /* init mutexes and locks */ + mutex_init(&device->tx_fifo_lock); + mutex_init(&device->rx_lock); + + /* setup GPIO (including irq_handler) for the different DIOs */ + retval = setup_GPIOs(device); + if (retval) + { + dev_dbg(&spi->dev, "setup of GPIOs failed"); + goto GPIO_failed; + } + + /* setup the radio module */ + SET_CHECKED(rf69_set_mode (spi, standby)); + SET_CHECKED(rf69_set_data_mode (spi, packet)); + SET_CHECKED(rf69_set_amplifier_0 (spi, optionOn)); + SET_CHECKED(rf69_set_amplifier_1 (spi, optionOff)); + SET_CHECKED(rf69_set_amplifier_2 (spi, optionOff)); + SET_CHECKED(rf69_set_output_power_level (spi, 13)); + SET_CHECKED(rf69_set_antenna_impedance (spi, fiftyOhm)); + + /* start tx thread */ + device->tx_task_struct = kthread_run(pi433_tx_thread, + device, + "pi433_tx_task"); + if (device->tx_task_struct < 0) + { + dev_dbg(device->dev, "start of send thread failed"); + goto send_thread_failed; + } + + /* determ minor number */ + retval = pi433_get_minor(device); + if (retval) + { + dev_dbg(device->dev, "get of minor number failed"); + goto minor_failed; + } + + /* create device */ + device->devt = MKDEV(MAJOR(pi433_dev), device->minor); + device->dev = device_create(pi433_class, + &spi->dev, + device->devt, + device, + "pi433"); + if (IS_ERR(device->dev)) { + pr_err("pi433: device register failed\n"); + retval = PTR_ERR(device->dev); + goto device_create_failed; + } + else { + dev_dbg(device->dev, + "created device for major %d, minor %d\n", + MAJOR(pi433_dev), + device->minor); + } + + /* create cdev */ + device->cdev = cdev_alloc(); + device->cdev->owner = THIS_MODULE; + cdev_init(device->cdev, &pi433_fops); + retval = cdev_add(device->cdev, device->devt, 1); + if (retval) + { + dev_dbg(device->dev, "register of cdev failed"); + goto cdev_failed; + } + + /* spi setup */ + spi_set_drvdata(spi, device); + + return 0; + +cdev_failed: + device_destroy(pi433_class, device->devt); +device_create_failed: + pi433_free_minor(device); +minor_failed: + kthread_stop(device->tx_task_struct); +send_thread_failed: + free_GPIOs(device); +GPIO_failed: + kfree(device); + + return retval; +} + +static int pi433_remove(struct spi_device *spi) +{ + struct pi433_device *device = spi_get_drvdata(spi); + + /* free GPIOs */ + free_GPIOs(device); + + /* make sure ops on existing fds can abort cleanly */ + device->spi = NULL; + + kthread_stop(device->tx_task_struct); + + device_destroy(pi433_class, device->devt); + + cdev_del(device->cdev); + + pi433_free_minor(device); + + if (device->users == 0) + kfree(device); + + return 0; +} + +static const struct of_device_id pi433_dt_ids[] = { + { .compatible = "Smarthome-Wolf,pi433" }, + {}, +}; + +MODULE_DEVICE_TABLE(of, pi433_dt_ids); + +static struct spi_driver pi433_spi_driver = { + .driver = { + .name = "pi433", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(pi433_dt_ids), + }, + .probe = pi433_probe, + .remove = pi433_remove, + + /* NOTE: suspend/resume methods are not necessary here. + * We don't do anything except pass the requests to/from + * the underlying controller. The refrigerator handles + * most issues; the controller driver handles the rest. + */ +}; + +/*-------------------------------------------------------------------------*/ + +static int __init pi433_init(void) +{ + int status; + + /* If MAX_MSG_SIZE is smaller then FIFO_SIZE, the driver won't + work stable - risk of buffer overflow */ + if (MAX_MSG_SIZE < FIFO_SIZE) + return -EINVAL; + + /* Claim device numbers. Then register a class + * that will key udev/mdev to add/remove /dev nodes. Last, register + * Last, register the driver which manages those device numbers. + */ + status = alloc_chrdev_region(&pi433_dev, 0 /*firstminor*/, N_PI433_MINORS /*count*/, "pi433" /*name*/); + if (status < 0) + return status; + + pi433_class = class_create(THIS_MODULE, "pi433"); + if (IS_ERR(pi433_class)) + { + unregister_chrdev(MAJOR(pi433_dev), pi433_spi_driver.driver.name); + return PTR_ERR(pi433_class); + } + + status = spi_register_driver(&pi433_spi_driver); + if (status < 0) + { + class_destroy(pi433_class); + unregister_chrdev(MAJOR(pi433_dev), pi433_spi_driver.driver.name); + } + + return status; +} + +module_init(pi433_init); + +static void __exit pi433_exit(void) +{ + spi_unregister_driver(&pi433_spi_driver); + class_destroy(pi433_class); + unregister_chrdev(MAJOR(pi433_dev), pi433_spi_driver.driver.name); +} +module_exit(pi433_exit); + +MODULE_AUTHOR("Marcus Wolf, "); +MODULE_DESCRIPTION("Driver for Pi433"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("spi:pi433"); diff --git a/drivers/staging/pi433/pi433_if.h b/drivers/staging/pi433/pi433_if.h new file mode 100644 index 000000000000..e6ed3cd9b2e2 --- /dev/null +++ b/drivers/staging/pi433/pi433_if.h @@ -0,0 +1,152 @@ +/* + * include/linux/TODO + * + * userspace interface for pi433 radio module + * + * Pi433 is a 433MHz radio module for the Raspberry Pi. + * It is based on the HopeRf Module RFM69CW. Therefore inside of this + * driver, you'll find an abstraction of the rf69 chip. + * + * If needed, this driver could be extended, to also support other + * devices, basing on HopeRfs rf69. + * + * The driver can also be extended, to support other modules of + * HopeRf with a similar interace - e. g. RFM69HCW, RFM12, RFM95, ... + * Copyright (C) 2016 Wolf-Entwicklungen + * Marcus Wolf + * + * 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. + */ + +#ifndef PI433_H +#define PI433_H + +#include +#include "rf69_enum.h" + +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ + +/* IOCTL structs and commands */ + +/** + * struct pi433_tx_config - describes the configuration of the radio module for sending + * @frequency: + * @bit_rate: + * @modulation: + * @data_mode: + * @preamble_length: + * @sync_pattern: + * @tx_start_condition: + * @payload_length: + * @repetitions: + * + * ATTENTION: + * If the contents of 'pi433_tx_config' ever change + * incompatibly, then the ioctl number (see define below) must change. + * + * NOTE: struct layout is the same in 64bit and 32bit userspace. + */ +#define PI433_TX_CFG_IOCTL_NR 0 +struct pi433_tx_cfg +{ + __u32 frequency; + __u16 bit_rate; + __u32 dev_frequency; + enum modulation modulation; + enum modShaping modShaping; + + enum paRamp pa_ramp; + + enum txStartCondition tx_start_condition; + + __u16 repetitions; + + + /* packet format */ + enum optionOnOff enable_preamble; + enum optionOnOff enable_sync; + enum optionOnOff enable_length_byte; + enum optionOnOff enable_address_byte; + enum optionOnOff enable_crc; + + __u16 preamble_length; + __u8 sync_length; + __u8 fixed_message_length; + + __u8 sync_pattern[8]; + __u8 address_byte; +}; + + +/** + * struct pi433_rx_config - describes the configuration of the radio module for sending + * @frequency: + * @bit_rate: + * @modulation: + * @data_mode: + * @preamble_length: + * @sync_pattern: + * @tx_start_condition: + * @payload_length: + * @repetitions: + * + * ATTENTION: + * If the contents of 'pi433_rx_config' ever change + * incompatibly, then the ioctl number (see define below) must change + * + * NOTE: struct layout is the same in 64bit and 32bit userspace. + */ +#define PI433_RX_CFG_IOCTL_NR 1 +struct pi433_rx_cfg { + __u32 frequency; + __u16 bit_rate; + __u32 dev_frequency; + + enum modulation modulation; + + __u8 rssi_threshold; + enum thresholdDecrement thresholdDecrement; + enum antennaImpedance antenna_impedance; + enum lnaGain lna_gain; + enum mantisse bw_mantisse; /* normal: 0x50 */ + __u8 bw_exponent; /* during AFC: 0x8b */ + enum dagc dagc; + + + + /* packet format */ + enum optionOnOff enable_sync; + enum optionOnOff enable_length_byte; /* should be used in combination with sync, only */ + enum addressFiltering enable_address_filtering; /* operational with sync, only */ + enum optionOnOff enable_crc; /* only operational, if sync on and fixed length or length byte is used */ + + __u8 sync_length; + __u8 fixed_message_length; + __u32 bytes_to_drop; + + __u8 sync_pattern[8]; + __u8 node_address; + __u8 broadcast_address; +}; + + +#define PI433_IOC_MAGIC 'r' + +#define PI433_IOC_RD_TX_CFG _IOR(PI433_IOC_MAGIC, PI433_TX_CFG_IOCTL_NR, char[sizeof(struct pi433_tx_cfg)]) +#define PI433_IOC_WR_TX_CFG _IOW(PI433_IOC_MAGIC, PI433_TX_CFG_IOCTL_NR, char[sizeof(struct pi433_tx_cfg)]) + +#define PI433_IOC_RD_RX_CFG _IOR(PI433_IOC_MAGIC, PI433_RX_CFG_IOCTL_NR, char[sizeof(struct pi433_rx_cfg)]) +#define PI433_IOC_WR_RX_CFG _IOW(PI433_IOC_MAGIC, PI433_RX_CFG_IOCTL_NR, char[sizeof(struct pi433_rx_cfg)]) + +#endif /* PI433_H */ diff --git a/drivers/staging/pi433/rf69.c b/drivers/staging/pi433/rf69.c new file mode 100644 index 000000000000..e391ce777bc7 --- /dev/null +++ b/drivers/staging/pi433/rf69.c @@ -0,0 +1,982 @@ +/* + * abstraction of the spi interface of HopeRf rf69 radio module + * + * Copyright (C) 2016 Wolf-Entwicklungen + * Marcus Wolf + * + * 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. + */ + +/* enable prosa debug info */ +#undef DEBUG +/* enable print of values on reg access */ +#undef DEBUG_VALUES +/* enable print of values on fifo access */ +#undef DEBUG_FIFO_ACCESS + +#include +#include + +#include "rf69.h" +#include "rf69_registers.h" + +#define F_OSC 32000000 /* in Hz */ +#define FIFO_SIZE 66 /* in byte */ + +/*-------------------------------------------------------------------------*/ + +#define READ_REG(x) rf69_read_reg (spi, x) +#define WRITE_REG(x,y) rf69_write_reg(spi, x, y) +#define INVALID_PARAM \ + { \ + dev_dbg(&spi->dev, "set: illegal input param"); \ + return -EINVAL; \ + } + +/*-------------------------------------------------------------------------*/ + +int rf69_set_mode(struct spi_device *spi, enum mode mode) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "set: mode"); + #endif + + switch (mode){ + case transmit: return WRITE_REG(REG_OPMODE, (READ_REG(REG_OPMODE) & ~MASK_OPMODE_MODE) | OPMODE_MODE_TRANSMIT); + case receive: return WRITE_REG(REG_OPMODE, (READ_REG(REG_OPMODE) & ~MASK_OPMODE_MODE) | OPMODE_MODE_RECEIVE); + case synthesizer: return WRITE_REG(REG_OPMODE, (READ_REG(REG_OPMODE) & ~MASK_OPMODE_MODE) | OPMODE_MODE_SYNTHESIZER); + case standby: return WRITE_REG(REG_OPMODE, (READ_REG(REG_OPMODE) & ~MASK_OPMODE_MODE) | OPMODE_MODE_STANDBY); + case mode_sleep: return WRITE_REG(REG_OPMODE, (READ_REG(REG_OPMODE) & ~MASK_OPMODE_MODE) | OPMODE_MODE_SLEEP); + default: INVALID_PARAM; + } + + // we are using packet mode, so this check is not really needed + // but waiting for mode ready is necessary when going from sleep because the FIFO may not be immediately available from previous mode + //while (_mode == RF69_MODE_SLEEP && (READ_REG(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00); // Wait for ModeReady + +} + +int rf69_set_data_mode(struct spi_device *spi, enum dataMode dataMode) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "set: data mode"); + #endif + + switch (dataMode) { + case packet: return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODE) | DATAMODUL_MODE_PACKET); + case continuous: return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODE) | DATAMODUL_MODE_CONTINUOUS); + case continuousNoSync: return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODE) | DATAMODUL_MODE_CONTINUOUS_NOSYNC); + default: INVALID_PARAM; + } +} + +int rf69_set_modulation(struct spi_device *spi, enum modulation modulation) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "set: modulation"); + #endif + + switch (modulation) { + case OOK: return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_TYPE) | DATAMODUL_MODULATION_TYPE_OOK); + case FSK: return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_TYPE) | DATAMODUL_MODULATION_TYPE_FSK); + default: INVALID_PARAM; + } +} + +enum modulation rf69_get_modulation(struct spi_device *spi) +{ + u8 currentValue; + + #ifdef DEBUG + dev_dbg(&spi->dev, "get: mode"); + #endif + + currentValue = READ_REG(REG_DATAMODUL); + + switch (currentValue & MASK_DATAMODUL_MODULATION_TYPE >> 3) // TODO improvement: change 3 to define + { + case DATAMODUL_MODULATION_TYPE_OOK: return OOK; + case DATAMODUL_MODULATION_TYPE_FSK: return FSK; + default: return undefined; + } +} + +int rf69_set_modulation_shaping(struct spi_device *spi, enum modShaping modShaping) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "set: mod shaping"); + #endif + + if (rf69_get_modulation(spi) == FSK) + { + switch (modShaping) { + case shapingOff: return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_SHAPE) | DATAMODUL_MODULATION_SHAPE_NONE); + case shaping1_0: return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_SHAPE) | DATAMODUL_MODULATION_SHAPE_1_0); + case shaping0_5: return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_SHAPE) | DATAMODUL_MODULATION_SHAPE_0_3); + case shaping0_3: return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_SHAPE) | DATAMODUL_MODULATION_SHAPE_0_5); + default: INVALID_PARAM; + } + } + else + { + switch (modShaping) { + case shapingOff: return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_SHAPE) | DATAMODUL_MODULATION_SHAPE_NONE); + case shapingBR: return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_SHAPE) | DATAMODUL_MODULATION_SHAPE_BR); + case shaping2BR: return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_SHAPE) | DATAMODUL_MODULATION_SHAPE_2BR); + default: INVALID_PARAM; + } + } +} + +int rf69_set_bit_rate(struct spi_device *spi, u16 bitRate) +{ + int retval; + u32 bitRate_min; + u32 bitRate_reg; + u8 msb; + u8 lsb; + + #ifdef DEBUG + dev_dbg(&spi->dev, "set: bit rate"); + #endif + + // check input value + bitRate_min = F_OSC / 8388608; // 8388608 = 2^23; + if (bitRate < bitRate_min) + { + dev_dbg(&spi->dev, "setBitRate: illegal input param"); + INVALID_PARAM; + } + + // calculate reg settings + bitRate_reg = (F_OSC / bitRate); + + msb = (bitRate_reg&0xff00) >> 8; + lsb = (bitRate_reg&0xff); + + // transmit to RF 69 + retval = WRITE_REG(REG_BITRATE_MSB, msb); + if (retval) return retval; + retval = WRITE_REG(REG_BITRATE_LSB, lsb); + if (retval) return retval; + + return 0; +} + +int rf69_set_deviation(struct spi_device *spi, u32 deviation) +{ + int retval; +// u32 f_max; TODO: Abhngigkeit von Bitrate beachten!! + u64 f_reg; + u64 f_step; + u8 msb; + u8 lsb; + u64 factor = 1000000; // to improve precision of calculation + + #ifdef DEBUG + dev_dbg(&spi->dev, "set: deviation"); + #endif + + if (deviation < 600 || deviation > 500000) //TODO: Abhngigkeit von Bitrate beachten!! + { + dev_dbg(&spi->dev, "set_deviation: illegal input param"); + INVALID_PARAM; + } + + // calculat f step + f_step = F_OSC * factor; + do_div(f_step, 524288); // 524288 = 2^19 + + // calculate register settings + f_reg = deviation * factor; + do_div(f_reg , f_step); + + msb = (f_reg&0xff00) >> 8; + lsb = (f_reg&0xff); + + // check msb + if (msb & !FDEVMASB_MASK) + { + dev_dbg(&spi->dev, "set_deviation: err in calc of msb"); + INVALID_PARAM; + } + + // write to chip + retval = WRITE_REG(REG_FDEV_MSB, msb); + if (retval) return retval; + retval = WRITE_REG(REG_FDEV_LSB, lsb); + if (retval) return retval; + + return 0; +} + +int rf69_set_frequency(struct spi_device *spi, u32 frequency) +{ + int retval; + u32 f_max; + u64 f_reg; + u64 f_step; + u8 msb; + u8 mid; + u8 lsb; + u64 factor = 1000000; // to improve precision of calculation + + #ifdef DEBUG + dev_dbg(&spi->dev, "set: frequency"); + #endif + + // calculat f step + f_step = F_OSC * factor; + do_div(f_step, 524288); // 524288 = 2^19 + + // check input value + f_max = f_step * 8388608 / factor; + if (frequency > f_max) + { + dev_dbg(&spi->dev, "setFrequency: illegal input param"); + INVALID_PARAM; + } + + // calculate reg settings + f_reg = frequency * factor; + do_div(f_reg , f_step); + + msb = (f_reg&0xff0000) >> 16; + mid = (f_reg&0xff00) >> 8; + lsb = (f_reg&0xff); + + // write to chip + retval = WRITE_REG(REG_FRF_MSB, msb); + if (retval) return retval; + retval = WRITE_REG(REG_FRF_MID, mid); + if (retval) return retval; + retval = WRITE_REG(REG_FRF_LSB, lsb); + if (retval) return retval; + + return 0; +} + +int rf69_set_amplifier_0(struct spi_device *spi, enum optionOnOff optionOnOff) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "set: amp #0"); + #endif + + switch(optionOnOff) { + case optionOn: return WRITE_REG(REG_PALEVEL, (READ_REG(REG_PALEVEL) | MASK_PALEVEL_PA0) ); + case optionOff: return WRITE_REG(REG_PALEVEL, (READ_REG(REG_PALEVEL) & ~MASK_PALEVEL_PA0) ); + default: INVALID_PARAM; + } +} + +int rf69_set_amplifier_1(struct spi_device *spi, enum optionOnOff optionOnOff) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "set: amp #1"); + #endif + + switch(optionOnOff) { + case optionOn: return WRITE_REG(REG_PALEVEL, (READ_REG(REG_PALEVEL) | MASK_PALEVEL_PA1) ); + case optionOff: return WRITE_REG(REG_PALEVEL, (READ_REG(REG_PALEVEL) & ~MASK_PALEVEL_PA1) ); + default: INVALID_PARAM; + } +} + +int rf69_set_amplifier_2(struct spi_device *spi, enum optionOnOff optionOnOff) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "set: amp #2"); + #endif + + switch(optionOnOff) { + case optionOn: return WRITE_REG(REG_PALEVEL, (READ_REG(REG_PALEVEL) | MASK_PALEVEL_PA2) ); + case optionOff: return WRITE_REG(REG_PALEVEL, (READ_REG(REG_PALEVEL) & ~MASK_PALEVEL_PA2) ); + default: INVALID_PARAM; + } +} + +int rf69_set_output_power_level(struct spi_device *spi, u8 powerLevel) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "set: power level"); + #endif + + powerLevel +=18; // TODO Abhngigkeit von PA0,1,2 setting + + // check input value + if (powerLevel > 0x1f) + INVALID_PARAM; + + // write value + return WRITE_REG(REG_PALEVEL, (READ_REG(REG_PALEVEL) & ~MASK_PALEVEL_OUTPUT_POWER) | powerLevel); +} + +int rf69_set_pa_ramp(struct spi_device *spi, enum paRamp paRamp) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "set: pa ramp"); + #endif + + switch(paRamp) { + case ramp3400: return WRITE_REG(REG_PARAMP, PARAMP_3400); + case ramp2000: return WRITE_REG(REG_PARAMP, PARAMP_2000); + case ramp1000: return WRITE_REG(REG_PARAMP, PARAMP_1000); + case ramp500: return WRITE_REG(REG_PARAMP, PARAMP_500); + case ramp250: return WRITE_REG(REG_PARAMP, PARAMP_250); + case ramp125: return WRITE_REG(REG_PARAMP, PARAMP_125); + case ramp100: return WRITE_REG(REG_PARAMP, PARAMP_100); + case ramp62: return WRITE_REG(REG_PARAMP, PARAMP_62); + case ramp50: return WRITE_REG(REG_PARAMP, PARAMP_50); + case ramp40: return WRITE_REG(REG_PARAMP, PARAMP_40); + case ramp31: return WRITE_REG(REG_PARAMP, PARAMP_31); + case ramp25: return WRITE_REG(REG_PARAMP, PARAMP_25); + case ramp20: return WRITE_REG(REG_PARAMP, PARAMP_20); + case ramp15: return WRITE_REG(REG_PARAMP, PARAMP_15); + case ramp12: return WRITE_REG(REG_PARAMP, PARAMP_12); + case ramp10: return WRITE_REG(REG_PARAMP, PARAMP_10); + default: INVALID_PARAM; + } +} + +int rf69_set_antenna_impedance(struct spi_device *spi, enum antennaImpedance antennaImpedance) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "set: antenna impedance"); + #endif + + switch(antennaImpedance) { + case fiftyOhm: return WRITE_REG(REG_LNA, (READ_REG(REG_LNA) & ~MASK_LNA_ZIN) ); + case twohundretOhm: return WRITE_REG(REG_LNA, (READ_REG(REG_LNA) | MASK_LNA_ZIN) ); + default: INVALID_PARAM; + } +} + +int rf69_set_lna_gain(struct spi_device *spi, enum lnaGain lnaGain) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "set: lna gain"); + #endif + + switch(lnaGain) { + case automatic: return WRITE_REG(REG_LNA, ( (READ_REG(REG_LNA) & ~MASK_LNA_GAIN) & LNA_GAIN_AUTO) ); + case max: return WRITE_REG(REG_LNA, ( (READ_REG(REG_LNA) & ~MASK_LNA_GAIN) & LNA_GAIN_MAX) ); + case maxMinus6: return WRITE_REG(REG_LNA, ( (READ_REG(REG_LNA) & ~MASK_LNA_GAIN) & LNA_GAIN_MAX_MINUS_6) ); + case maxMinus12: return WRITE_REG(REG_LNA, ( (READ_REG(REG_LNA) & ~MASK_LNA_GAIN) & LNA_GAIN_MAX_MINUS_12) ); + case maxMinus24: return WRITE_REG(REG_LNA, ( (READ_REG(REG_LNA) & ~MASK_LNA_GAIN) & LNA_GAIN_MAX_MINUS_24) ); + case maxMinus36: return WRITE_REG(REG_LNA, ( (READ_REG(REG_LNA) & ~MASK_LNA_GAIN) & LNA_GAIN_MAX_MINUS_36) ); + case maxMinus48: return WRITE_REG(REG_LNA, ( (READ_REG(REG_LNA) & ~MASK_LNA_GAIN) & LNA_GAIN_MAX_MINUS_48) ); + default: INVALID_PARAM; + } +} + +enum lnaGain rf69_get_lna_gain(struct spi_device *spi) +{ + u8 currentValue; + + #ifdef DEBUG + dev_dbg(&spi->dev, "get: lna gain"); + #endif + + currentValue = READ_REG(REG_LNA); + + switch (currentValue & MASK_LNA_CURRENT_GAIN >> 3) // improvement: change 3 to define + { + case LNA_GAIN_AUTO: return automatic; + case LNA_GAIN_MAX: return max; + case LNA_GAIN_MAX_MINUS_6: return maxMinus6; + case LNA_GAIN_MAX_MINUS_12: return maxMinus12; + case LNA_GAIN_MAX_MINUS_24: return maxMinus24; + case LNA_GAIN_MAX_MINUS_36: return maxMinus36; + case LNA_GAIN_MAX_MINUS_48: return maxMinus48; + default: return undefined; + } +} + +int rf69_set_dc_cut_off_frequency_intern(struct spi_device *spi ,u8 reg, enum dccPercent dccPercent) +{ + switch (dccPercent) { + case dcc16Percent: return WRITE_REG(reg, ( (READ_REG(reg) & ~MASK_BW_DCC_FREQ) | BW_DCC_16_PERCENT) ); + case dcc8Percent: return WRITE_REG(reg, ( (READ_REG(reg) & ~MASK_BW_DCC_FREQ) | BW_DCC_8_PERCENT) ); + case dcc4Percent: return WRITE_REG(reg, ( (READ_REG(reg) & ~MASK_BW_DCC_FREQ) | BW_DCC_4_PERCENT) ); + case dcc2Percent: return WRITE_REG(reg, ( (READ_REG(reg) & ~MASK_BW_DCC_FREQ) | BW_DCC_2_PERCENT) ); + case dcc1Percent: return WRITE_REG(reg, ( (READ_REG(reg) & ~MASK_BW_DCC_FREQ) | BW_DCC_1_PERCENT) ); + case dcc0_5Percent: return WRITE_REG(reg, ( (READ_REG(reg) & ~MASK_BW_DCC_FREQ) | BW_DCC_0_5_PERCENT) ); + case dcc0_25Percent: return WRITE_REG(reg, ( (READ_REG(reg) & ~MASK_BW_DCC_FREQ) | BW_DCC_0_25_PERCENT) ); + case dcc0_125Percent: return WRITE_REG(reg, ( (READ_REG(reg) & ~MASK_BW_DCC_FREQ) | BW_DCC_0_125_PERCENT) ); + default: INVALID_PARAM; + } +} + +int rf69_set_dc_cut_off_frequency(struct spi_device *spi, enum dccPercent dccPercent) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "set: cut off freq"); + #endif + + return rf69_set_dc_cut_off_frequency_intern(spi, REG_RXBW, dccPercent); +} + +int rf69_set_dc_cut_off_frequency_during_afc(struct spi_device *spi, enum dccPercent dccPercent) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "set: cut off freq during afc"); + #endif + + return rf69_set_dc_cut_off_frequency_intern(spi, REG_AFCBW, dccPercent); +} + +int rf69_set_bandwidth_intern(struct spi_device *spi, u8 reg, enum mantisse mantisse, u8 exponent) +{ + u8 newValue; + + // check value for mantisse and exponent + if (exponent > 7) INVALID_PARAM; + if ( (mantisse!=mantisse16) && + (mantisse!=mantisse20) && + (mantisse!=mantisse24) ) INVALID_PARAM; + + // read old value + newValue = READ_REG(reg); + + // "delete" mantisse and exponent = just keep the DCC setting + newValue = newValue & MASK_BW_DCC_FREQ; + + // add new mantisse + switch(mantisse) { + case mantisse16: newValue = newValue | BW_MANT_16; break; + case mantisse20: newValue = newValue | BW_MANT_20; break; + case mantisse24: newValue = newValue | BW_MANT_24; break; + } + + // add new exponent + newValue = newValue | exponent; + + // write back + return WRITE_REG(reg, newValue); +} + +int rf69_set_bandwidth(struct spi_device *spi, enum mantisse mantisse, u8 exponent) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "set: band width"); + #endif + + return rf69_set_bandwidth_intern(spi, REG_RXBW, mantisse, exponent); +} + +int rf69_set_bandwidth_during_afc(struct spi_device *spi, enum mantisse mantisse, u8 exponent) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "set: band width during afc"); + #endif + + return rf69_set_bandwidth_intern(spi, REG_AFCBW, mantisse, exponent); +} + +int rf69_set_ook_threshold_type(struct spi_device *spi, enum thresholdType thresholdType) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "set: threshold type"); + #endif + + switch (thresholdType) + { + case fixed: return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESTYPE) | OOKPEAK_THRESHTYPE_FIXED) ); + case peak: return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESTYPE) | OOKPEAK_THRESHTYPE_PEAK) ); + case average: return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESTYPE) | OOKPEAK_THRESHTYPE_AVERAGE) ); + default: INVALID_PARAM; + } +} + +int rf69_set_ook_threshold_step(struct spi_device *spi, enum thresholdStep thresholdStep) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "set: threshold step"); + #endif + + switch (thresholdStep) { + case step_0_5db: return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESSTEP) | OOKPEAK_THRESHSTEP_0_5_DB) ); + case step_1_0db: return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESSTEP) | OOKPEAK_THRESHSTEP_1_0_DB) ); + case step_1_5db: return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESSTEP) | OOKPEAK_THRESHSTEP_1_5_DB) ); + case step_2_0db: return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESSTEP) | OOKPEAK_THRESHSTEP_2_0_DB) ); + case step_3_0db: return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESSTEP) | OOKPEAK_THRESHSTEP_3_0_DB) ); + case step_4_0db: return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESSTEP) | OOKPEAK_THRESHSTEP_4_0_DB) ); + case step_5_0db: return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESSTEP) | OOKPEAK_THRESHSTEP_5_0_DB) ); + case step_6_0db: return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESSTEP) | OOKPEAK_THRESHSTEP_6_0_DB) ); + default: INVALID_PARAM; + } +} + +int rf69_set_ook_threshold_dec(struct spi_device *spi, enum thresholdDecrement thresholdDecrement) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "set: threshold decrement"); + #endif + + switch (thresholdDecrement) { + case dec_every8th: return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESDEC) | OOKPEAK_THRESHDEC_EVERY_8TH) ); + case dec_every4th: return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESDEC) | OOKPEAK_THRESHDEC_EVERY_4TH) ); + case dec_every2nd: return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESDEC) | OOKPEAK_THRESHDEC_EVERY_2ND) ); + case dec_once: return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESDEC) | OOKPEAK_THRESHDEC_ONCE) ); + case dec_twice: return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESDEC) | OOKPEAK_THRESHDEC_TWICE) ); + case dec_4times: return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESDEC) | OOKPEAK_THRESHDEC_4_TIMES) ); + case dec_8times: return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESDEC) | OOKPEAK_THRESHDEC_8_TIMES) ); + case dec_16times: return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESDEC) | OOKPEAK_THRESHDEC_16_TIMES) ); + default: INVALID_PARAM; + } +} + +int rf69_set_dio_mapping(struct spi_device *spi, u8 DIONumber, u8 value) +{ + u8 mask; + u8 shift; + u8 regaddr; + u8 regValue; + + #ifdef DEBUG + dev_dbg(&spi->dev, "set: DIO mapping"); + #endif + + // check DIO number + if (DIONumber > 5) INVALID_PARAM; + + switch (DIONumber) { + case 0: mask=MASK_DIO0; shift=SHIFT_DIO0; regaddr=REG_DIOMAPPING1; break; + case 1: mask=MASK_DIO1; shift=SHIFT_DIO1; regaddr=REG_DIOMAPPING1; break; + case 2: mask=MASK_DIO2; shift=SHIFT_DIO2; regaddr=REG_DIOMAPPING1; break; + case 3: mask=MASK_DIO3; shift=SHIFT_DIO3; regaddr=REG_DIOMAPPING1; break; + case 4: mask=MASK_DIO4; shift=SHIFT_DIO4; regaddr=REG_DIOMAPPING2; break; + case 5: mask=MASK_DIO5; shift=SHIFT_DIO5; regaddr=REG_DIOMAPPING2; break; + } + + // read reg + regValue=READ_REG(regaddr); + // delete old value + regValue = regValue & ~mask; + // add new value + regValue = regValue | value << shift; + // write back + return WRITE_REG(regaddr,regValue); +} + +bool rf69_get_flag(struct spi_device *spi, enum flag flag) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "get: flag"); + #endif + + switch(flag) { + case modeSwitchCompleted: return (READ_REG(REG_IRQFLAGS1) & MASK_IRQFLAGS1_MODE_READY); + case readyToReceive: return (READ_REG(REG_IRQFLAGS1) & MASK_IRQFLAGS1_RX_READY); + case readyToSend: return (READ_REG(REG_IRQFLAGS1) & MASK_IRQFLAGS1_TX_READY); + case pllLocked: return (READ_REG(REG_IRQFLAGS1) & MASK_IRQFLAGS1_PLL_LOCK); + case rssiExceededThreshold: return (READ_REG(REG_IRQFLAGS1) & MASK_IRQFLAGS1_RSSI); + case timeout: return (READ_REG(REG_IRQFLAGS1) & MASK_IRQFLAGS1_TIMEOUT); + case automode: return (READ_REG(REG_IRQFLAGS1) & MASK_IRQFLAGS1_AUTOMODE); + case syncAddressMatch: return (READ_REG(REG_IRQFLAGS1) & MASK_IRQFLAGS1_SYNC_ADDRESS_MATCH); + case fifoFull: return (READ_REG(REG_IRQFLAGS2) & MASK_IRQFLAGS2_FIFO_FULL); +/* case fifoNotEmpty: return (READ_REG(REG_IRQFLAGS2) & MASK_IRQFLAGS2_FIFO_NOT_EMPTY); */ + case fifoEmpty: return !(READ_REG(REG_IRQFLAGS2) & MASK_IRQFLAGS2_FIFO_NOT_EMPTY); + case fifoLevelBelowThreshold: return (READ_REG(REG_IRQFLAGS2) & MASK_IRQFLAGS2_FIFO_LEVEL); + case fifoOverrun: return (READ_REG(REG_IRQFLAGS2) & MASK_IRQFLAGS2_FIFO_OVERRUN); + case packetSent: return (READ_REG(REG_IRQFLAGS2) & MASK_IRQFLAGS2_PACKET_SENT); + case payloadReady: return (READ_REG(REG_IRQFLAGS2) & MASK_IRQFLAGS2_PAYLOAD_READY); + case crcOk: return (READ_REG(REG_IRQFLAGS2) & MASK_IRQFLAGS2_CRC_OK); + case batteryLow: return (READ_REG(REG_IRQFLAGS2) & MASK_IRQFLAGS2_LOW_BAT); + default: return false; + } +} + +int rf69_reset_flag(struct spi_device *spi, enum flag flag) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "reset: flag"); + #endif + + switch(flag) { + case rssiExceededThreshold: return WRITE_REG(REG_IRQFLAGS1, MASK_IRQFLAGS1_RSSI); + case syncAddressMatch: return WRITE_REG(REG_IRQFLAGS1, MASK_IRQFLAGS1_SYNC_ADDRESS_MATCH); + case fifoOverrun: return WRITE_REG(REG_IRQFLAGS2, MASK_IRQFLAGS2_FIFO_OVERRUN); + default: INVALID_PARAM; + } +} + +int rf69_set_rssi_threshold(struct spi_device *spi, u8 threshold) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "set: rssi threshold"); + #endif + + /* no value check needed - u8 exactly matches register size */ + + return WRITE_REG(REG_RSSITHRESH, threshold); +} + +int rf69_set_rx_start_timeout(struct spi_device *spi, u8 timeout) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "set: start timeout"); + #endif + + /* no value check needed - u8 exactly matches register size */ + + return WRITE_REG(REG_RXTIMEOUT1, timeout); +} + +int rf69_set_rssi_timeout(struct spi_device *spi, u8 timeout) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "set: rssi timeout"); + #endif + + /* no value check needed - u8 exactly matches register size */ + + return WRITE_REG(REG_RXTIMEOUT2, timeout); +} + +int rf69_set_preamble_length(struct spi_device *spi, u16 preambleLength) +{ + int retval; + u8 msb, lsb; + + #ifdef DEBUG + dev_dbg(&spi->dev, "set: preample length"); + #endif + + /* no value check needed - u16 exactly matches register size */ + + /* calculate reg settings */ + msb = (preambleLength&0xff00) >> 8; + lsb = (preambleLength&0xff); + + /* transmit to chip */ + retval = WRITE_REG(REG_PREAMBLE_MSB, msb); + if (retval) return retval; + retval = WRITE_REG(REG_PREAMBLE_LSB, lsb); + + return retval; +} + +int rf69_set_sync_enable(struct spi_device *spi, enum optionOnOff optionOnOff) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "set: sync enable"); + #endif + + switch(optionOnOff) { + case optionOn: return WRITE_REG(REG_SYNC_CONFIG, (READ_REG(REG_SYNC_CONFIG) | MASK_SYNC_CONFIG_SYNC_ON) ); + case optionOff: return WRITE_REG(REG_SYNC_CONFIG, (READ_REG(REG_SYNC_CONFIG) & ~MASK_SYNC_CONFIG_SYNC_ON) ); + default: INVALID_PARAM; + } +} + +int rf69_set_fifo_fill_condition(struct spi_device *spi, enum fifoFillCondition fifoFillCondition) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "set: fifo fill condition"); + #endif + + switch(fifoFillCondition) { + case always: return WRITE_REG(REG_SYNC_CONFIG, (READ_REG(REG_SYNC_CONFIG) | MASK_SYNC_CONFIG_FIFO_FILL_CONDITION) ); + case afterSyncInterrupt: return WRITE_REG(REG_SYNC_CONFIG, (READ_REG(REG_SYNC_CONFIG) & ~MASK_SYNC_CONFIG_FIFO_FILL_CONDITION) ); + default: INVALID_PARAM; + } +} + +int rf69_set_sync_size(struct spi_device *spi, u8 syncSize) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "set: sync size"); + #endif + + // check input value + if (syncSize > 0x07) + INVALID_PARAM; + + // write value + return WRITE_REG(REG_SYNC_CONFIG, (READ_REG(REG_SYNC_CONFIG) & ~MASK_SYNC_CONFIG_SYNC_SIZE) | (syncSize << 3) ); +} + +int rf69_set_sync_tolerance(struct spi_device *spi, u8 syncTolerance) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "set: sync tolerance"); + #endif + + // check input value + if (syncTolerance > 0x07) + INVALID_PARAM; + + // write value + return WRITE_REG(REG_SYNC_CONFIG, (READ_REG(REG_SYNC_CONFIG) & ~MASK_SYNC_CONFIG_SYNC_SIZE) | syncTolerance); +} + +int rf69_set_sync_values(struct spi_device *spi, u8 syncValues[8]) +{ + int retval = 0; + + #ifdef DEBUG + dev_dbg(&spi->dev, "set: sync values"); + #endif + + retval += WRITE_REG(REG_SYNCVALUE1, syncValues[0]); + retval += WRITE_REG(REG_SYNCVALUE2, syncValues[1]); + retval += WRITE_REG(REG_SYNCVALUE3, syncValues[2]); + retval += WRITE_REG(REG_SYNCVALUE4, syncValues[3]); + retval += WRITE_REG(REG_SYNCVALUE5, syncValues[4]); + retval += WRITE_REG(REG_SYNCVALUE6, syncValues[5]); + retval += WRITE_REG(REG_SYNCVALUE7, syncValues[6]); + retval += WRITE_REG(REG_SYNCVALUE8, syncValues[7]); + + return retval; +} + +int rf69_set_packet_format(struct spi_device * spi, enum packetFormat packetFormat) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "set: packet format"); + #endif + + switch(packetFormat) { + case packetLengthVar: return WRITE_REG(REG_PACKETCONFIG1, (READ_REG(REG_PACKETCONFIG1) | MASK_PACKETCONFIG1_PAKET_FORMAT_VARIABLE) ); + case packetLengthFix: return WRITE_REG(REG_PACKETCONFIG1, (READ_REG(REG_PACKETCONFIG1) & ~MASK_PACKETCONFIG1_PAKET_FORMAT_VARIABLE) ); + default: INVALID_PARAM; + } +} + +int rf69_set_crc_enable(struct spi_device *spi, enum optionOnOff optionOnOff) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "set: crc enable"); + #endif + + switch(optionOnOff) { + case optionOn: return WRITE_REG(REG_PACKETCONFIG1, (READ_REG(REG_PACKETCONFIG1) | MASK_PACKETCONFIG1_CRC_ON) ); + case optionOff: return WRITE_REG(REG_PACKETCONFIG1, (READ_REG(REG_PACKETCONFIG1) & ~MASK_PACKETCONFIG1_CRC_ON) ); + default: INVALID_PARAM; + } +} + +int rf69_set_adressFiltering(struct spi_device *spi, enum addressFiltering addressFiltering) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "set: address filtering"); + #endif + + switch (addressFiltering) { + case filteringOff: return WRITE_REG(REG_PACKETCONFIG1, ( (READ_REG(REG_PACKETCONFIG1) & ~MASK_PACKETCONFIG1_ADDRESSFILTERING) | PACKETCONFIG1_ADDRESSFILTERING_OFF) ); + case nodeAddress: return WRITE_REG(REG_PACKETCONFIG1, ( (READ_REG(REG_PACKETCONFIG1) & ~MASK_PACKETCONFIG1_ADDRESSFILTERING) | PACKETCONFIG1_ADDRESSFILTERING_NODE) ); + case nodeOrBroadcastAddress: return WRITE_REG(REG_PACKETCONFIG1, ( (READ_REG(REG_PACKETCONFIG1) & ~MASK_PACKETCONFIG1_ADDRESSFILTERING) | PACKETCONFIG1_ADDRESSFILTERING_NODEBROADCAST) ); + default: INVALID_PARAM; + } +} + +int rf69_set_payload_length(struct spi_device *spi, u8 payloadLength) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "set: payload length"); + #endif + + return WRITE_REG(REG_PAYLOAD_LENGTH, payloadLength); +} + +u8 rf69_get_payload_length(struct spi_device *spi) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "get: payload length"); + #endif + + return (u8) READ_REG(REG_PAYLOAD_LENGTH); +} + +int rf69_set_node_address(struct spi_device *spi, u8 nodeAddress) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "set: node address"); + #endif + + return WRITE_REG(REG_NODEADRS, nodeAddress); +} + +int rf69_set_broadcast_address(struct spi_device *spi, u8 broadcastAddress) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "set: broadcast address"); + #endif + + return WRITE_REG(REG_BROADCASTADRS, broadcastAddress); +} + +int rf69_set_tx_start_condition(struct spi_device *spi, enum txStartCondition txStartCondition) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "set: start condition"); + #endif + + switch(txStartCondition) { + case fifoLevel: return WRITE_REG(REG_FIFO_THRESH, (READ_REG(REG_FIFO_THRESH) & ~MASK_FIFO_THRESH_TXSTART) ); + case fifoNotEmpty: return WRITE_REG(REG_FIFO_THRESH, (READ_REG(REG_FIFO_THRESH) | MASK_FIFO_THRESH_TXSTART) ); + default: INVALID_PARAM; + } +} + +int rf69_set_fifo_threshold(struct spi_device *spi, u8 threshold) +{ + int retval; + + #ifdef DEBUG + dev_dbg(&spi->dev, "set: fifo threshold"); + #endif + + // check input value + if (threshold & 0x80) + INVALID_PARAM; + + // write value + retval = WRITE_REG(REG_FIFO_THRESH, (READ_REG(REG_FIFO_THRESH) & ~MASK_FIFO_THRESH_VALUE) | threshold); + if (retval) + return retval; + + // access the fifo to activate new threshold + return rf69_read_fifo (spi, (u8*) &retval, 1); // retval used as buffer +} + +int rf69_set_dagc(struct spi_device *spi, enum dagc dagc) +{ + #ifdef DEBUG + dev_dbg(&spi->dev, "set: dagc"); + #endif + + switch(dagc) { + case normalMode: return WRITE_REG(REG_TESTDAGC, DAGC_NORMAL); + case improve: return WRITE_REG(REG_TESTDAGC, DAGC_IMPROVED_LOWBETA0); + case improve4LowModulationIndex: return WRITE_REG(REG_TESTDAGC, DAGC_IMPROVED_LOWBETA1); + default: INVALID_PARAM; + } +} + +/*-------------------------------------------------------------------------*/ + +int rf69_read_fifo (struct spi_device *spi, u8 *buffer, unsigned int size) +{ + #ifdef DEBUG_FIFO_ACCESS + int i; + #endif + struct spi_transfer transfer; + u8 local_buffer[FIFO_SIZE + 1]; + int retval; + + if (size > FIFO_SIZE) + { + #ifdef DEBUG + dev_dbg(&spi->dev, "read fifo: passed in buffer bigger then internal buffer \n"); + #endif + return -EMSGSIZE; + } + + /* prepare a bidirectional transfer */ + local_buffer[0] = REG_FIFO; + memset(&transfer, 0, sizeof(transfer)); + transfer.tx_buf = local_buffer; + transfer.rx_buf = local_buffer; + transfer.len = size+1; + + retval = spi_sync_transfer(spi, &transfer, 1); + + #ifdef DEBUG_FIFO_ACCESS + for (i=0; idev, "%d - 0x%x\n", i, local_buffer[i+1]); + #endif + + memcpy(buffer, &local_buffer[1], size); // TODO: ohne memcopy wre schner + + return retval; +} + +int rf69_write_fifo(struct spi_device *spi, u8 *buffer, unsigned int size) +{ + #ifdef DEBUG_FIFO_ACCESS + int i; + #endif + char spi_address = REG_FIFO | WRITE_BIT; + u8 local_buffer[FIFO_SIZE + 1]; + + if (size > FIFO_SIZE) + { + #ifdef DEBUG + dev_dbg(&spi->dev, "read fifo: passed in buffer bigger then internal buffer \n"); + #endif + return -EMSGSIZE; + } + + local_buffer[0] = spi_address; + memcpy(&local_buffer[1], buffer, size); // TODO: ohne memcopy wre schner + + #ifdef DEBUG_FIFO_ACCESS + for (i=0; idev, "0x%x\n",buffer[i]); + #endif + + return spi_write (spi, local_buffer, size + 1); +} + +/*-------------------------------------------------------------------------*/ + +u8 rf69_read_reg(struct spi_device *spi, u8 addr) +{ + int retval; + + retval = spi_w8r8(spi, addr); + + #ifdef DEBUG_VALUES + if (retval < 0) + /* should never happen, since we already checked, + that module is connected. Therefore no error + handling, just an optional error message... */ + dev_dbg(&spi->dev, "read 0x%x FAILED\n", + addr); + else + dev_dbg(&spi->dev, "read 0x%x from reg 0x%x\n", + retval, + addr); + #endif + + return retval; +} + +int rf69_write_reg(struct spi_device *spi, u8 addr, u8 value) +{ + int retval; + char buffer[2]; + + buffer[0] = addr | WRITE_BIT; + buffer[1] = value; + + retval = spi_write(spi, &buffer, 2); + + #ifdef DEBUG_VALUES + if (retval < 0) + /* should never happen, since we already checked, + that module is connected. Therefore no error + handling, just an optional error message... */ + dev_dbg(&spi->dev, "write 0x%x to 0x%x FAILED\n", + value, + addr); + else + dev_dbg(&spi->dev, "wrote 0x%x to reg 0x%x\n", + value, + addr); + #endif + + return retval; +} + + diff --git a/drivers/staging/pi433/rf69.h b/drivers/staging/pi433/rf69.h new file mode 100644 index 000000000000..b81e0762032e --- /dev/null +++ b/drivers/staging/pi433/rf69.h @@ -0,0 +1,82 @@ +/* + * hardware abstraction/register access for HopeRf rf69 radio module + * + * Copyright (C) 2016 Wolf-Entwicklungen + * Marcus Wolf + * + * 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. + */ +#ifndef RF69_H +#define RF69_H + +#include "rf69_enum.h" +#include "rf69_registers.h" + +#define F_OSC 32000000 /* in Hz */ +#define FREQUENCY 433920000 /* in Hz, modifying this value impacts CE certification */ +#define FIFO_SIZE 66 /* in byte */ +#define FIFO_THRESHOLD 15 /* in byte */ + +int rf69_set_mode(struct spi_device *spi, enum mode mode); +int rf69_set_data_mode(struct spi_device *spi, enum dataMode dataMode); +int rf69_set_modulation(struct spi_device *spi, enum modulation modulation); +enum modulation rf69_get_modulation(struct spi_device *spi); +int rf69_set_modulation_shaping(struct spi_device *spi, enum modShaping modShaping); +int rf69_set_bit_rate(struct spi_device *spi, u16 bitRate); +int rf69_set_deviation(struct spi_device *spi, u32 deviation); +int rf69_set_frequency(struct spi_device *spi, u32 frequency); +int rf69_set_amplifier_0(struct spi_device *spi, enum optionOnOff optionOnOff); +int rf69_set_amplifier_1(struct spi_device *spi, enum optionOnOff optionOnOff); +int rf69_set_amplifier_2(struct spi_device *spi, enum optionOnOff optionOnOff); +int rf69_set_output_power_level(struct spi_device *spi, u8 powerLevel); +int rf69_set_pa_ramp(struct spi_device *spi, enum paRamp paRamp); +int rf69_set_antenna_impedance(struct spi_device *spi, enum antennaImpedance antennaImpedance); +int rf69_set_lna_gain(struct spi_device *spi, enum lnaGain lnaGain); +enum lnaGain rf69_get_lna_gain(struct spi_device *spi); +int rf69_set_dc_cut_off_frequency_intern(struct spi_device *spi, u8 reg, enum dccPercent dccPercent); +int rf69_set_dc_cut_off_frequency(struct spi_device *spi, enum dccPercent dccPercent); +int rf69_set_dc_cut_off_frequency_during_afc(struct spi_device *spi, enum dccPercent dccPercent); +int rf69_set_bandwidth(struct spi_device *spi, enum mantisse mantisse, u8 exponent); +int rf69_set_bandwidth_during_afc(struct spi_device *spi, enum mantisse mantisse, u8 exponent); +int rf69_set_ook_threshold_type(struct spi_device *spi, enum thresholdType thresholdType); +int rf69_set_ook_threshold_step(struct spi_device *spi, enum thresholdStep thresholdStep); +int rf69_set_ook_threshold_dec(struct spi_device *spi, enum thresholdDecrement thresholdDecrement); +int rf69_set_dio_mapping(struct spi_device *spi, u8 DIONumber, u8 value); +bool rf69_get_flag(struct spi_device *spi, enum flag flag); +int rf69_reset_flag(struct spi_device *spi, enum flag flag); +int rf69_set_rssi_threshold(struct spi_device *spi, u8 threshold); +int rf69_set_rx_start_timeout(struct spi_device *spi, u8 timeout); +int rf69_set_rssi_timeout(struct spi_device *spi, u8 timeout); +int rf69_set_preamble_length(struct spi_device *spi, u16 preambleLength); +int rf69_set_sync_enable(struct spi_device *spi, enum optionOnOff optionOnOff); +int rf69_set_fifo_fill_condition(struct spi_device *spi, enum fifoFillCondition fifoFillCondition); +int rf69_set_sync_size(struct spi_device *spi, u8 sync_size); +int rf69_set_sync_tolerance(struct spi_device *spi, u8 syncTolerance); +int rf69_set_sync_values(struct spi_device *spi, u8 syncValues[8]); +int rf69_set_packet_format(struct spi_device * spi, enum packetFormat packetFormat); +int rf69_set_crc_enable(struct spi_device *spi, enum optionOnOff optionOnOff); +int rf69_set_adressFiltering(struct spi_device *spi, enum addressFiltering addressFiltering); +int rf69_set_payload_length(struct spi_device *spi, u8 payloadLength); +u8 rf69_get_payload_length(struct spi_device *spi); +int rf69_set_node_address(struct spi_device *spi, u8 nodeAddress); +int rf69_set_broadcast_address(struct spi_device *spi, u8 broadcastAddress); +int rf69_set_tx_start_condition(struct spi_device *spi, enum txStartCondition txStartCondition); +int rf69_set_fifo_threshold(struct spi_device *spi, u8 threshold); +int rf69_set_dagc(struct spi_device *spi, enum dagc dagc); + +int rf69_read_fifo (struct spi_device *spi, u8 *buffer, unsigned int size); +int rf69_write_fifo(struct spi_device *spi, u8 *buffer, unsigned int size); + +u8 rf69_read_reg (struct spi_device *spi, u8 addr); +int rf69_write_reg(struct spi_device *spi, u8 addr, u8 value); + + +#endif diff --git a/drivers/staging/pi433/rf69_enum.h b/drivers/staging/pi433/rf69_enum.h new file mode 100644 index 000000000000..fbfb59bd3f3d --- /dev/null +++ b/drivers/staging/pi433/rf69_enum.h @@ -0,0 +1,201 @@ +/* + * enumerations for HopeRf rf69 radio module + * + * Copyright (C) 2016 Wolf-Entwicklungen + * Marcus Wolf + * + * 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. + */ + +#ifndef RF69_ENUM_H +#define RF69_ENUM_H + +enum optionOnOff +{ + optionOff, + optionOn +}; + +enum mode +{ + mode_sleep, + standby, + synthesizer, + transmit, + receive +}; + +enum dataMode +{ + packet, + continuous, + continuousNoSync +}; + +enum modulation +{ + OOK, + FSK +}; + +enum modShaping +{ + shapingOff, + shaping1_0, + shaping0_5, + shaping0_3, + shapingBR, + shaping2BR +}; + +enum paRamp +{ + ramp3400, + ramp2000, + ramp1000, + ramp500, + ramp250, + ramp125, + ramp100, + ramp62, + ramp50, + ramp40, + ramp31, + ramp25, + ramp20, + ramp15, + ramp12, + ramp10 +}; + +enum antennaImpedance +{ + fiftyOhm, + twohundretOhm +}; + +enum lnaGain +{ + automatic, + max, + maxMinus6, + maxMinus12, + maxMinus24, + maxMinus36, + maxMinus48, + undefined +}; + +enum dccPercent +{ + dcc16Percent, + dcc8Percent, + dcc4Percent, + dcc2Percent, + dcc1Percent, + dcc0_5Percent, + dcc0_25Percent, + dcc0_125Percent +}; + +enum mantisse +{ + mantisse16, + mantisse20, + mantisse24 +}; + +enum thresholdType +{ + fixed, + peak, + average +}; + +enum thresholdStep +{ + step_0_5db, + step_1_0db, + step_1_5db, + step_2_0db, + step_3_0db, + step_4_0db, + step_5_0db, + step_6_0db +}; + +enum thresholdDecrement +{ + dec_every8th, + dec_every4th, + dec_every2nd, + dec_once, + dec_twice, + dec_4times, + dec_8times, + dec_16times +}; + +enum flag +{ + modeSwitchCompleted, + readyToReceive, + readyToSend, + pllLocked, + rssiExceededThreshold, + timeout, + automode, + syncAddressMatch, + fifoFull, +// fifoNotEmpty, collision with next enum; replaced by following enum... + fifoEmpty, + fifoLevelBelowThreshold, + fifoOverrun, + packetSent, + payloadReady, + crcOk, + batteryLow +}; + +enum fifoFillCondition +{ + afterSyncInterrupt, + always +}; + +enum packetFormat +{ + packetLengthFix, + packetLengthVar +}; + +enum txStartCondition +{ + fifoLevel, + fifoNotEmpty +}; + +enum addressFiltering +{ + filteringOff, + nodeAddress, + nodeOrBroadcastAddress +}; + +enum dagc +{ + normalMode, + improve, + improve4LowModulationIndex +}; + + +#endif diff --git a/drivers/staging/pi433/rf69_registers.h b/drivers/staging/pi433/rf69_registers.h new file mode 100644 index 000000000000..d0c4992b0778 --- /dev/null +++ b/drivers/staging/pi433/rf69_registers.h @@ -0,0 +1,489 @@ +/* + * register description for HopeRf rf69 radio module + * + * Copyright (C) 2016 Wolf-Entwicklungen + * Marcus Wolf + * + * 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. + */ + +/*******************************************/ +/* RF69 register addresses */ +/*******************************************/ +#define REG_FIFO 0x00 +#define REG_OPMODE 0x01 +#define REG_DATAMODUL 0x02 +#define REG_BITRATE_MSB 0x03 +#define REG_BITRATE_LSB 0x04 +#define REG_FDEV_MSB 0x05 +#define REG_FDEV_LSB 0x06 +#define REG_FRF_MSB 0x07 +#define REG_FRF_MID 0x08 +#define REG_FRF_LSB 0x09 +#define REG_OSC1 0x0A +#define REG_AFCCTRL 0x0B +#define REG_LOWBAT 0x0C +#define REG_LISTEN1 0x0D +#define REG_LISTEN2 0x0E +#define REG_LISTEN3 0x0F +#define REG_VERSION 0x10 +#define REG_PALEVEL 0x11 +#define REG_PARAMP 0x12 +#define REG_OCP 0x13 +#define REG_AGCREF 0x14 /* not available on RF69 */ +#define REG_AGCTHRESH1 0x15 /* not available on RF69 */ +#define REG_AGCTHRESH2 0x16 /* not available on RF69 */ +#define REG_AGCTHRESH3 0x17 /* not available on RF69 */ +#define REG_LNA 0x18 +#define REG_RXBW 0x19 +#define REG_AFCBW 0x1A +#define REG_OOKPEAK 0x1B +#define REG_OOKAVG 0x1C +#define REG_OOKFIX 0x1D +#define REG_AFCFEI 0x1E +#define REG_AFCMSB 0x1F +#define REG_AFCLSB 0x20 +#define REG_FEIMSB 0x21 +#define REG_FEILSB 0x22 +#define REG_RSSICONFIG 0x23 +#define REG_RSSIVALUE 0x24 +#define REG_DIOMAPPING1 0x25 +#define REG_DIOMAPPING2 0x26 +#define REG_IRQFLAGS1 0x27 +#define REG_IRQFLAGS2 0x28 +#define REG_RSSITHRESH 0x29 +#define REG_RXTIMEOUT1 0x2A +#define REG_RXTIMEOUT2 0x2B +#define REG_PREAMBLE_MSB 0x2C +#define REG_PREAMBLE_LSB 0x2D +#define REG_SYNC_CONFIG 0x2E +#define REG_SYNCVALUE1 0x2F +#define REG_SYNCVALUE2 0x30 +#define REG_SYNCVALUE3 0x31 +#define REG_SYNCVALUE4 0x32 +#define REG_SYNCVALUE5 0x33 +#define REG_SYNCVALUE6 0x34 +#define REG_SYNCVALUE7 0x35 +#define REG_SYNCVALUE8 0x36 +#define REG_PACKETCONFIG1 0x37 +#define REG_PAYLOAD_LENGTH 0x38 +#define REG_NODEADRS 0x39 +#define REG_BROADCASTADRS 0x3A +#define REG_AUTOMODES 0x3B +#define REG_FIFO_THRESH 0x3C +#define REG_PACKETCONFIG2 0x3D +#define REG_AESKEY1 0x3E +#define REG_AESKEY2 0x3F +#define REG_AESKEY3 0x40 +#define REG_AESKEY4 0x41 +#define REG_AESKEY5 0x42 +#define REG_AESKEY6 0x43 +#define REG_AESKEY7 0x44 +#define REG_AESKEY8 0x45 +#define REG_AESKEY9 0x46 +#define REG_AESKEY10 0x47 +#define REG_AESKEY11 0x48 +#define REG_AESKEY12 0x49 +#define REG_AESKEY13 0x4A +#define REG_AESKEY14 0x4B +#define REG_AESKEY15 0x4C +#define REG_AESKEY16 0x4D +#define REG_TEMP1 0x4E +#define REG_TEMP2 0x4F +#define REG_TESTPA1 0x5A /* only present on RFM69HW */ +#define REG_TESTPA2 0x5C /* only present on RFM69HW */ +#define REG_TESTDAGC 0x6F + +/******************************************************/ +/* RF69/SX1231 bit definition */ +/******************************************************/ +/* write bit */ +#define WRITE_BIT 0x80 + +/* RegOpMode */ +#define MASK_OPMODE_SEQUENCER_OFF 0x80 +#define MASK_OPMODE_LISTEN_ON 0x40 +#define MASK_OPMODE_LISTEN_ABORT 0x20 +#define MASK_OPMODE_MODE 0x1C + +#define OPMODE_MODE_SLEEP 0x00 +#define OPMODE_MODE_STANDBY 0x04 /* default */ +#define OPMODE_MODE_SYNTHESIZER 0x08 +#define OPMODE_MODE_TRANSMIT 0x0C +#define OPMODE_MODE_RECEIVE 0x10 + +/* RegDataModul */ +#define MASK_DATAMODUL_MODE 0x06 +#define MASK_DATAMODUL_MODULATION_TYPE 0x18 +#define MASK_DATAMODUL_MODULATION_SHAPE 0x03 + +#define DATAMODUL_MODE_PACKET 0x00 /* default */ +#define DATAMODUL_MODE_CONTINUOUS 0x40 +#define DATAMODUL_MODE_CONTINUOUS_NOSYNC 0x60 + +#define DATAMODUL_MODULATION_TYPE_FSK 0x00 /* default */ +#define DATAMODUL_MODULATION_TYPE_OOK 0x08 + +#define DATAMODUL_MODULATION_SHAPE_NONE 0x00 /* default */ +#define DATAMODUL_MODULATION_SHAPE_1_0 0x01 +#define DATAMODUL_MODULATION_SHAPE_0_5 0x02 +#define DATAMODUL_MODULATION_SHAPE_0_3 0x03 +#define DATAMODUL_MODULATION_SHAPE_BR 0x01 +#define DATAMODUL_MODULATION_SHAPE_2BR 0x02 + +/* RegFDevMsb (0x05)*/ +#define FDEVMASB_MASK 0x3f + +/* +// RegOsc1 +#define OSC1_RCCAL_START 0x80 +#define OSC1_RCCAL_DONE 0x40 + +// RegLowBat +#define LOWBAT_MONITOR 0x10 +#define LOWBAT_ON 0x08 +#define LOWBAT_OFF 0x00 // Default + +#define LOWBAT_TRIM_1695 0x00 +#define LOWBAT_TRIM_1764 0x01 +#define LOWBAT_TRIM_1835 0x02 // Default +#define LOWBAT_TRIM_1905 0x03 +#define LOWBAT_TRIM_1976 0x04 +#define LOWBAT_TRIM_2045 0x05 +#define LOWBAT_TRIM_2116 0x06 +#define LOWBAT_TRIM_2185 0x07 + + +// RegListen1 +#define LISTEN1_RESOL_64 0x50 +#define LISTEN1_RESOL_4100 0xA0 // Default +#define LISTEN1_RESOL_262000 0xF0 + +#define LISTEN1_CRITERIA_RSSI 0x00 // Default +#define LISTEN1_CRITERIA_RSSIANDSYNC 0x08 + +#define LISTEN1_END_00 0x00 +#define LISTEN1_END_01 0x02 // Default +#define LISTEN1_END_10 0x04 + + +// RegListen2 +#define LISTEN2_COEFIDLE_VALUE 0xF5 // Default + +// RegListen3 +#define LISTEN3_COEFRX_VALUE 0x20 // Default +*/ + +// RegPaLevel +#define MASK_PALEVEL_PA0 0x80 +#define MASK_PALEVEL_PA1 0x40 +#define MASK_PALEVEL_PA2 0x20 +#define MASK_PALEVEL_OUTPUT_POWER 0x1F + + + +// RegPaRamp +#define PARAMP_3400 0x00 +#define PARAMP_2000 0x01 +#define PARAMP_1000 0x02 +#define PARAMP_500 0x03 +#define PARAMP_250 0x04 +#define PARAMP_125 0x05 +#define PARAMP_100 0x06 +#define PARAMP_62 0x07 +#define PARAMP_50 0x08 +#define PARAMP_40 0x09 /* default */ +#define PARAMP_31 0x0A +#define PARAMP_25 0x0B +#define PARAMP_20 0x0C +#define PARAMP_15 0x0D +#define PARAMP_12 0x0E +#define PARAMP_10 0x0F + +#define MASK_PARAMP 0x0F + +/* +// RegOcp +#define OCP_OFF 0x0F +#define OCP_ON 0x1A // Default + +#define OCP_TRIM_45 0x00 +#define OCP_TRIM_50 0x01 +#define OCP_TRIM_55 0x02 +#define OCP_TRIM_60 0x03 +#define OCP_TRIM_65 0x04 +#define OCP_TRIM_70 0x05 +#define OCP_TRIM_75 0x06 +#define OCP_TRIM_80 0x07 +#define OCP_TRIM_85 0x08 +#define OCP_TRIM_90 0x09 +#define OCP_TRIM_95 0x0A +#define OCP_TRIM_100 0x0B // Default +#define OCP_TRIM_105 0x0C +#define OCP_TRIM_110 0x0D +#define OCP_TRIM_115 0x0E +#define OCP_TRIM_120 0x0F +*/ + +/* RegLna (0x18) */ +#define MASK_LNA_ZIN 0x80 +#define MASK_LNA_CURRENT_GAIN 0x38 +#define MASK_LNA_GAIN 0x07 + +#define LNA_GAIN_AUTO 0x00 /* default */ +#define LNA_GAIN_MAX 0x01 +#define LNA_GAIN_MAX_MINUS_6 0x02 +#define LNA_GAIN_MAX_MINUS_12 0x03 +#define LNA_GAIN_MAX_MINUS_24 0x04 +#define LNA_GAIN_MAX_MINUS_36 0x05 +#define LNA_GAIN_MAX_MINUS_48 0x06 + + +/* RegRxBw (0x19) and RegAfcBw (0x1A) */ +#define MASK_BW_DCC_FREQ 0xE0 +#define MASK_BW_MANTISSE 0x18 +#define MASK_BW_EXPONENT 0x07 + +#define BW_DCC_16_PERCENT 0x00 +#define BW_DCC_8_PERCENT 0x20 +#define BW_DCC_4_PERCENT 0x40 /* default */ +#define BW_DCC_2_PERCENT 0x60 +#define BW_DCC_1_PERCENT 0x80 +#define BW_DCC_0_5_PERCENT 0xA0 +#define BW_DCC_0_25_PERCENT 0xC0 +#define BW_DCC_0_125_PERCENT 0xE0 + +#define BW_MANT_16 0x00 +#define BW_MANT_20 0x08 +#define BW_MANT_24 0x10 /* default */ + + +/* RegOokPeak (0x1B) */ +#define MASK_OOKPEAK_THRESTYPE 0xc0 +#define MASK_OOKPEAK_THRESSTEP 0x38 +#define MASK_OOKPEAK_THRESDEC 0x07 + +#define OOKPEAK_THRESHTYPE_FIXED 0x00 +#define OOKPEAK_THRESHTYPE_PEAK 0x40 /* default */ +#define OOKPEAK_THRESHTYPE_AVERAGE 0x80 + +#define OOKPEAK_THRESHSTEP_0_5_DB 0x00 /* default */ +#define OOKPEAK_THRESHSTEP_1_0_DB 0x08 +#define OOKPEAK_THRESHSTEP_1_5_DB 0x10 +#define OOKPEAK_THRESHSTEP_2_0_DB 0x18 +#define OOKPEAK_THRESHSTEP_3_0_DB 0x20 +#define OOKPEAK_THRESHSTEP_4_0_DB 0x28 +#define OOKPEAK_THRESHSTEP_5_0_DB 0x30 +#define OOKPEAK_THRESHSTEP_6_0_DB 0x38 + +#define OOKPEAK_THRESHDEC_ONCE 0x00 /* default */ +#define OOKPEAK_THRESHDEC_EVERY_2ND 0x01 +#define OOKPEAK_THRESHDEC_EVERY_4TH 0x02 +#define OOKPEAK_THRESHDEC_EVERY_8TH 0x03 +#define OOKPEAK_THRESHDEC_TWICE 0x04 +#define OOKPEAK_THRESHDEC_4_TIMES 0x05 +#define OOKPEAK_THRESHDEC_8_TIMES 0x06 +#define OOKPEAK_THRESHDEC_16_TIMES 0x07 + +/* +// RegOokAvg +#define OOKAVG_AVERAGETHRESHFILT_00 0x00 +#define OOKAVG_AVERAGETHRESHFILT_01 0x40 +#define OOKAVG_AVERAGETHRESHFILT_10 0x80 // Default +#define OOKAVG_AVERAGETHRESHFILT_11 0xC0 + + +// RegAfcFei +#define AFCFEI_FEI_DONE 0x40 +#define AFCFEI_FEI_START 0x20 +#define AFCFEI_AFC_DONE 0x10 +#define AFCFEI_AFCAUTOCLEAR_ON 0x08 +#define AFCFEI_AFCAUTOCLEAR_OFF 0x00 // Default + +#define AFCFEI_AFCAUTO_ON 0x04 +#define AFCFEI_AFCAUTO_OFF 0x00 // Default + +#define AFCFEI_AFC_CLEAR 0x02 +#define AFCFEI_AFC_START 0x01 + +// RegRssiConfig +#define RSSI_FASTRX_ON 0x08 +#define RSSI_FASTRX_OFF 0x00 // Default +#define RSSI_DONE 0x02 +#define RSSI_START 0x01 +*/ + +/* RegDioMapping1 */ +#define MASK_DIO0 0xC0 +#define MASK_DIO1 0x30 +#define MASK_DIO2 0x0C +#define MASK_DIO3 0x03 +#define SHIFT_DIO0 6 +#define SHIFT_DIO1 4 +#define SHIFT_DIO2 2 +#define SHIFT_DIO3 0 + +/* RegDioMapping2 */ +#define MASK_DIO4 0xC0 +#define MASK_DIO5 0x30 +#define SHIFT_DIO4 6 +#define SHIFT_DIO5 4 + +/* DIO numbers */ +#define DIO0 0 +#define DIO1 1 +#define DIO2 2 +#define DIO3 3 +#define DIO4 4 +#define DIO5 5 + +/* DIO Mapping values (packet mode) */ +#define DIO_ModeReady_DIO4 0x00 +#define DIO_ModeReady_DIO5 0x03 +#define DIO_ClkOut 0x00 +#define DIO_Data 0x01 +#define DIO_TimeOut_DIO1 0x03 +#define DIO_TimeOut_DIO4 0x00 +#define DIO_Rssi_DIO0 0x03 +#define DIO_Rssi_DIO3_4 0x01 +#define DIO_RxReady 0x02 +#define DIO_PLLLock 0x03 +#define DIO_TxReady 0x01 +#define DIO_FifoFull_DIO1 0x01 +#define DIO_FifoFull_DIO3 0x00 +#define DIO_SyncAddress 0x02 +#define DIO_FifoNotEmpty_DIO1 0x02 +#define DIO_FifoNotEmpty_FIO2 0x00 +#define DIO_Automode 0x04 +#define DIO_FifoLevel 0x00 +#define DIO_CrcOk 0x00 +#define DIO_PayloadReady 0x01 +#define DIO_PacketSent 0x00 +#define DIO_Dclk 0x00 + +/* RegDioMapping2 CLK_OUT part */ +#define MASK_DIOMAPPING2_CLK_OUT 0x07 + +#define DIOMAPPING2_CLK_OUT_NO_DIV 0x00 +#define DIOMAPPING2_CLK_OUT_DIV_2 0x01 +#define DIOMAPPING2_CLK_OUT_DIV_4 0x02 +#define DIOMAPPING2_CLK_OUT_DIV_8 0x03 +#define DIOMAPPING2_CLK_OUT_DIV_16 0x04 +#define DIOMAPPING2_CLK_OUT_DIV_32 0x05 +#define DIOMAPPING2_CLK_OUT_RC 0x06 +#define DIOMAPPING2_CLK_OUT_OFF 0x07 /* default */ + +/* RegIrqFlags1 */ +#define MASK_IRQFLAGS1_MODE_READY 0x80 +#define MASK_IRQFLAGS1_RX_READY 0x40 +#define MASK_IRQFLAGS1_TX_READY 0x20 +#define MASK_IRQFLAGS1_PLL_LOCK 0x10 +#define MASK_IRQFLAGS1_RSSI 0x08 +#define MASK_IRQFLAGS1_TIMEOUT 0x04 +#define MASK_IRQFLAGS1_AUTOMODE 0x02 +#define MASK_IRQFLAGS1_SYNC_ADDRESS_MATCH 0x01 + +/* RegIrqFlags2 */ +#define MASK_IRQFLAGS2_FIFO_FULL 0x80 +#define MASK_IRQFLAGS2_FIFO_NOT_EMPTY 0x40 +#define MASK_IRQFLAGS2_FIFO_LEVEL 0x20 +#define MASK_IRQFLAGS2_FIFO_OVERRUN 0x10 +#define MASK_IRQFLAGS2_PACKET_SENT 0x08 +#define MASK_IRQFLAGS2_PAYLOAD_READY 0x04 +#define MASK_IRQFLAGS2_CRC_OK 0x02 +#define MASK_IRQFLAGS2_LOW_BAT 0x01 + +/* RegSyncConfig */ +#define MASK_SYNC_CONFIG_SYNC_ON 0x80 /* default */ +#define MASK_SYNC_CONFIG_FIFO_FILL_CONDITION 0x40 +#define MASK_SYNC_CONFIG_SYNC_SIZE 0x38 +#define MASK_SYNC_CONFIG_SYNC_TOLERANCE 0x07 + +/* RegPacketConfig1 */ +#define MASK_PACKETCONFIG1_PAKET_FORMAT_VARIABLE 0x80 +#define MASK_PACKETCONFIG1_DCFREE 0x60 +#define MASK_PACKETCONFIG1_CRC_ON 0x10 /* default */ +#define MASK_PACKETCONFIG1_CRCAUTOCLEAR_OFF 0x08 +#define MASK_PACKETCONFIG1_ADDRESSFILTERING 0x06 + +#define PACKETCONFIG1_DCFREE_OFF 0x00 /* default */ +#define PACKETCONFIG1_DCFREE_MANCHESTER 0x20 +#define PACKETCONFIG1_DCFREE_WHITENING 0x40 +#define PACKETCONFIG1_ADDRESSFILTERING_OFF 0x00 /* default */ +#define PACKETCONFIG1_ADDRESSFILTERING_NODE 0x02 +#define PACKETCONFIG1_ADDRESSFILTERING_NODEBROADCAST 0x04 + +/* +// RegAutoModes +#define AUTOMODES_ENTER_OFF 0x00 // Default +#define AUTOMODES_ENTER_FIFONOTEMPTY 0x20 +#define AUTOMODES_ENTER_FIFOLEVEL 0x40 +#define AUTOMODES_ENTER_CRCOK 0x60 +#define AUTOMODES_ENTER_PAYLOADREADY 0x80 +#define AUTOMODES_ENTER_SYNCADRSMATCH 0xA0 +#define AUTOMODES_ENTER_PACKETSENT 0xC0 +#define AUTOMODES_ENTER_FIFOEMPTY 0xE0 + +#define AUTOMODES_EXIT_OFF 0x00 // Default +#define AUTOMODES_EXIT_FIFOEMPTY 0x04 +#define AUTOMODES_EXIT_FIFOLEVEL 0x08 +#define AUTOMODES_EXIT_CRCOK 0x0C +#define AUTOMODES_EXIT_PAYLOADREADY 0x10 +#define AUTOMODES_EXIT_SYNCADRSMATCH 0x14 +#define AUTOMODES_EXIT_PACKETSENT 0x18 +#define AUTOMODES_EXIT_RXTIMEOUT 0x1C + +#define AUTOMODES_INTERMEDIATE_SLEEP 0x00 // Default +#define AUTOMODES_INTERMEDIATE_STANDBY 0x01 +#define AUTOMODES_INTERMEDIATE_RECEIVER 0x02 +#define AUTOMODES_INTERMEDIATE_TRANSMITTER 0x03 + +*/ +/* RegFifoThresh (0x3c) */ +#define MASK_FIFO_THRESH_TXSTART 0x80 +#define MASK_FIFO_THRESH_VALUE 0x7F + +/* + +// RegPacketConfig2 +#define PACKET2_RXRESTARTDELAY_1BIT 0x00 // Default +#define PACKET2_RXRESTARTDELAY_2BITS 0x10 +#define PACKET2_RXRESTARTDELAY_4BITS 0x20 +#define PACKET2_RXRESTARTDELAY_8BITS 0x30 +#define PACKET2_RXRESTARTDELAY_16BITS 0x40 +#define PACKET2_RXRESTARTDELAY_32BITS 0x50 +#define PACKET2_RXRESTARTDELAY_64BITS 0x60 +#define PACKET2_RXRESTARTDELAY_128BITS 0x70 +#define PACKET2_RXRESTARTDELAY_256BITS 0x80 +#define PACKET2_RXRESTARTDELAY_512BITS 0x90 +#define PACKET2_RXRESTARTDELAY_1024BITS 0xA0 +#define PACKET2_RXRESTARTDELAY_2048BITS 0xB0 +#define PACKET2_RXRESTARTDELAY_NONE 0xC0 +#define PACKET2_RXRESTART 0x04 + +#define PACKET2_AUTORXRESTART_ON 0x02 // Default +#define PACKET2_AUTORXRESTART_OFF 0x00 + +#define PACKET2_AES_ON 0x01 +#define PACKET2_AES_OFF 0x00 // Default + + +// RegTemp1 +#define TEMP1_MEAS_START 0x08 +#define TEMP1_MEAS_RUNNING 0x04 +#define TEMP1_ADCLOWPOWER_ON 0x01 // Default +#define TEMP1_ADCLOWPOWER_OFF 0x00 +*/ + +// RegTestDagc (0x6F) +#define DAGC_NORMAL 0x00 /* Reset value */ +#define DAGC_IMPROVED_LOWBETA1 0x20 +#define DAGC_IMPROVED_LOWBETA0 0x30 /* Recommended val */ -- cgit v1.2.3 From 887758c325487ac747e03d552de42ec0ceaf214d Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Thu, 25 May 2017 15:58:24 +0800 Subject: soc: rockchip: disable jtag switching for RK3328 Soc Disable IO function switching between sdmmc and jtag for RK3328 Soc. Signed-off-by: Shawn Lin Signed-off-by: Heiko Stuebner --- drivers/soc/rockchip/grf.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/soc/rockchip/grf.c b/drivers/soc/rockchip/grf.c index d61db34ad6dd..15e71fd6c513 100644 --- a/drivers/soc/rockchip/grf.c +++ b/drivers/soc/rockchip/grf.c @@ -54,6 +54,17 @@ static const struct rockchip_grf_info rk3288_grf __initconst = { .num_values = ARRAY_SIZE(rk3288_defaults), }; +#define RK3328_GRF_SOC_CON4 0x410 + +static const struct rockchip_grf_value rk3328_defaults[] __initconst = { + { "jtag switching", RK3328_GRF_SOC_CON4, HIWORD_UPDATE(0, 1, 12) }, +}; + +static const struct rockchip_grf_info rk3328_grf __initconst = { + .values = rk3328_defaults, + .num_values = ARRAY_SIZE(rk3328_defaults), +}; + #define RK3368_GRF_SOC_CON15 0x43c static const struct rockchip_grf_value rk3368_defaults[] __initconst = { @@ -83,6 +94,9 @@ static const struct of_device_id rockchip_grf_dt_match[] __initconst = { }, { .compatible = "rockchip,rk3288-grf", .data = (void *)&rk3288_grf, + }, { + .compatible = "rockchip,rk3328-grf", + .data = (void *)&rk3328_grf, }, { .compatible = "rockchip,rk3368-grf", .data = (void *)&rk3368_grf, -- cgit v1.2.3 From 1055790b0df7202e363a55817688e3edbe1498a4 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 15 Jul 2017 11:58:18 +0200 Subject: leds: tlc591xx: merge conditional tests Merge conditionals that have the same then branch, to prepare for extending that branch with of_node_put. Signed-off-by: Julia Lawall Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-tlc591xx.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/leds/leds-tlc591xx.c b/drivers/leds/leds-tlc591xx.c index 304531644938..fcc87ee82453 100644 --- a/drivers/leds/leds-tlc591xx.c +++ b/drivers/leds/leds-tlc591xx.c @@ -232,9 +232,8 @@ tlc591xx_probe(struct i2c_client *client, err = of_property_read_u32(child, "reg", ®); if (err) return err; - if (reg < 0 || reg >= tlc591xx->max_leds) - return -EINVAL; - if (priv->leds[reg].active) + if (reg < 0 || reg >= tlc591xx->max_leds || + priv->leds[reg].active) return -EINVAL; priv->leds[reg].active = true; priv->leds[reg].ldev.name = -- cgit v1.2.3 From c68729119f4d2993bec3c9cb999ad76de5aeddba Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 15 Jul 2017 11:58:19 +0200 Subject: leds: tlc591xx: add missing of_node_put for_each_child_of_node performs an of_node_get on each iteration, so a return from the loop requires an of_node_put. The semantic patch that fixes this problem is as follows (http://coccinelle.lip6.fr): // @@ local idexpression n; expression e,e1; iterator name for_each_child_of_node; @@ for_each_child_of_node(e1,n) { ... ( of_node_put(n); | e = n | return n; | + of_node_put(n); ? return ...; ) ... } // Signed-off-by: Julia Lawall Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-tlc591xx.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/leds/leds-tlc591xx.c b/drivers/leds/leds-tlc591xx.c index fcc87ee82453..f5357f6d9e58 100644 --- a/drivers/leds/leds-tlc591xx.c +++ b/drivers/leds/leds-tlc591xx.c @@ -230,11 +230,15 @@ tlc591xx_probe(struct i2c_client *client, for_each_child_of_node(np, child) { err = of_property_read_u32(child, "reg", ®); - if (err) + if (err) { + of_node_put(child); return err; + } if (reg < 0 || reg >= tlc591xx->max_leds || - priv->leds[reg].active) + priv->leds[reg].active) { + of_node_put(child); return -EINVAL; + } priv->leds[reg].active = true; priv->leds[reg].ldev.name = of_get_property(child, "label", NULL) ? : child->name; -- cgit v1.2.3 From 98524e04e0500a04fc461195c99e4385001fc18f Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Thu, 6 Jul 2017 16:57:10 -0700 Subject: sunvnet: add support for IPv6 checksum offloads The original code didn't handle non-IPv4 packets very well, so the offload advertising had to be scaled back down to just IP. Here we add the bits needed to support TCP and UDP packets over IPv6 and turn the offload advertising back on. Orabug: 26289579 Signed-off-by: Shannon Nelson Signed-off-by: David S. Miller --- drivers/net/ethernet/sun/ldmvsw.c | 2 +- drivers/net/ethernet/sun/sunvnet.c | 2 +- drivers/net/ethernet/sun/sunvnet_common.c | 90 +++++++++++++++++++++++++++---- 3 files changed, 81 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sun/ldmvsw.c b/drivers/net/ethernet/sun/ldmvsw.c index 8603e397097e..5b56c24b6ed2 100644 --- a/drivers/net/ethernet/sun/ldmvsw.c +++ b/drivers/net/ethernet/sun/ldmvsw.c @@ -248,7 +248,7 @@ static struct net_device *vsw_alloc_netdev(u8 hwaddr[], dev->ethtool_ops = &vsw_ethtool_ops; dev->watchdog_timeo = VSW_TX_TIMEOUT; - dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG; + dev->hw_features = NETIF_F_HW_CSUM | NETIF_F_SG; dev->features = dev->hw_features; /* MTU range: 68 - 65535 */ diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c index 75b167e3fe98..0b95105f7060 100644 --- a/drivers/net/ethernet/sun/sunvnet.c +++ b/drivers/net/ethernet/sun/sunvnet.c @@ -312,7 +312,7 @@ static struct vnet *vnet_new(const u64 *local_mac, dev->watchdog_timeo = VNET_TX_TIMEOUT; dev->hw_features = NETIF_F_TSO | NETIF_F_GSO | NETIF_F_GSO_SOFTWARE | - NETIF_F_IP_CSUM | NETIF_F_SG; + NETIF_F_HW_CSUM | NETIF_F_SG; dev->features = dev->hw_features; /* MTU range: 68 - 65535 */ diff --git a/drivers/net/ethernet/sun/sunvnet_common.c b/drivers/net/ethernet/sun/sunvnet_common.c index 9e86833249d4..ecf456c7b6d1 100644 --- a/drivers/net/ethernet/sun/sunvnet_common.c +++ b/drivers/net/ethernet/sun/sunvnet_common.c @@ -303,7 +303,7 @@ static struct sk_buff *alloc_and_align_skb(struct net_device *dev, return skb; } -static inline void vnet_fullcsum(struct sk_buff *skb) +static inline void vnet_fullcsum_ipv4(struct sk_buff *skb) { struct iphdr *iph = ip_hdr(skb); int offset = skb_transport_offset(skb); @@ -335,6 +335,40 @@ static inline void vnet_fullcsum(struct sk_buff *skb) } } +#if IS_ENABLED(CONFIG_IPV6) +static inline void vnet_fullcsum_ipv6(struct sk_buff *skb) +{ + struct ipv6hdr *ip6h = ipv6_hdr(skb); + int offset = skb_transport_offset(skb); + + if (skb->protocol != htons(ETH_P_IPV6)) + return; + if (ip6h->nexthdr != IPPROTO_TCP && + ip6h->nexthdr != IPPROTO_UDP) + return; + skb->ip_summed = CHECKSUM_NONE; + skb->csum_level = 1; + skb->csum = 0; + if (ip6h->nexthdr == IPPROTO_TCP) { + struct tcphdr *ptcp = tcp_hdr(skb); + + ptcp->check = 0; + skb->csum = skb_checksum(skb, offset, skb->len - offset, 0); + ptcp->check = csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, + skb->len - offset, IPPROTO_TCP, + skb->csum); + } else if (ip6h->nexthdr == IPPROTO_UDP) { + struct udphdr *pudp = udp_hdr(skb); + + pudp->check = 0; + skb->csum = skb_checksum(skb, offset, skb->len - offset, 0); + pudp->check = csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, + skb->len - offset, IPPROTO_UDP, + skb->csum); + } +} +#endif + static int vnet_rx_one(struct vnet_port *port, struct vio_net_desc *desc) { struct net_device *dev = VNET_PORT_TO_NET_DEVICE(port); @@ -394,9 +428,14 @@ static int vnet_rx_one(struct vnet_port *port, struct vio_net_desc *desc) struct iphdr *iph = ip_hdr(skb); int ihl = iph->ihl * 4; - skb_reset_transport_header(skb); skb_set_transport_header(skb, ihl); - vnet_fullcsum(skb); + vnet_fullcsum_ipv4(skb); +#if IS_ENABLED(CONFIG_IPV6) + } else if (skb->protocol == htons(ETH_P_IPV6)) { + skb_set_transport_header(skb, + sizeof(struct ipv6hdr)); + vnet_fullcsum_ipv6(skb); +#endif } } if (dext->flags & VNET_PKT_HCK_IPV4_HDRCKSUM_OK) { @@ -1115,24 +1154,47 @@ static inline struct sk_buff *vnet_skb_shape(struct sk_buff *skb, int ncookies) if (skb->ip_summed == CHECKSUM_PARTIAL) start = skb_checksum_start_offset(skb); if (start) { - struct iphdr *iph = ip_hdr(nskb); int offset = start + nskb->csum_offset; + /* copy the headers, no csum here */ if (skb_copy_bits(skb, 0, nskb->data, start)) { dev_kfree_skb(nskb); dev_kfree_skb(skb); return NULL; } + + /* copy the rest, with csum calculation */ *(__sum16 *)(skb->data + offset) = 0; csum = skb_copy_and_csum_bits(skb, start, nskb->data + start, skb->len - start, 0); - if (iph->protocol == IPPROTO_TCP || - iph->protocol == IPPROTO_UDP) { - csum = csum_tcpudp_magic(iph->saddr, iph->daddr, - skb->len - start, - iph->protocol, csum); + + /* add in the header checksums */ + if (skb->protocol == htons(ETH_P_IP)) { + struct iphdr *iph = ip_hdr(nskb); + + if (iph->protocol == IPPROTO_TCP || + iph->protocol == IPPROTO_UDP) { + csum = csum_tcpudp_magic(iph->saddr, + iph->daddr, + skb->len - start, + iph->protocol, + csum); + } + } else if (skb->protocol == htons(ETH_P_IPV6)) { + struct ipv6hdr *ip6h = ipv6_hdr(nskb); + + if (ip6h->nexthdr == IPPROTO_TCP || + ip6h->nexthdr == IPPROTO_UDP) { + csum = csum_ipv6_magic(&ip6h->saddr, + &ip6h->daddr, + skb->len - start, + ip6h->nexthdr, + csum); + } } + + /* save the final result */ *(__sum16 *)(nskb->data + offset) = csum; nskb->ip_summed = CHECKSUM_NONE; @@ -1318,8 +1380,14 @@ int sunvnet_start_xmit_common(struct sk_buff *skb, struct net_device *dev, if (unlikely(!skb)) goto out_dropped; - if (skb->ip_summed == CHECKSUM_PARTIAL) - vnet_fullcsum(skb); + if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (skb->protocol == htons(ETH_P_IP)) + vnet_fullcsum_ipv4(skb); +#if IS_ENABLED(CONFIG_IPV6) + else if (skb->protocol == htons(ETH_P_IPV6)) + vnet_fullcsum_ipv6(skb); +#endif + } dr = &port->vio.drings[VIO_DRIVER_TX_RING]; i = skb_get_queue_mapping(skb); -- cgit v1.2.3 From 10244bc2ae7d8543190f4c651cdfaf030c50a802 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Sun, 16 Jul 2017 15:02:29 +0530 Subject: atm: iphase: constify pci_device_id. pci_device_id are not supposed to change at runtime. All functions working with pci_device_id provided by work with const pci_device_id. So mark the non-const structs as const. File size before: text data bss dec hex filename 23536 432 160 24128 5e40 drivers/atm/iphase.o File size After adding 'const': text data bss dec hex filename 23632 336 160 24128 5e40 drivers/atm/iphase.o Signed-off-by: Arvind Yadav Signed-off-by: David S. Miller --- drivers/atm/iphase.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c index a4fa6c82261e..fc72b763fdd7 100644 --- a/drivers/atm/iphase.c +++ b/drivers/atm/iphase.c @@ -3266,7 +3266,7 @@ static void ia_remove_one(struct pci_dev *pdev) kfree(iadev); } -static struct pci_device_id ia_pci_tbl[] = { +static const struct pci_device_id ia_pci_tbl[] = { { PCI_VENDOR_ID_IPHASE, 0x0008, PCI_ANY_ID, PCI_ANY_ID, }, { PCI_VENDOR_ID_IPHASE, 0x0009, PCI_ANY_ID, PCI_ANY_ID, }, { 0,} -- cgit v1.2.3 From c21c5a7f9dc967f41f591572bcbd29bfcff4331b Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Sun, 16 Jul 2017 15:02:30 +0530 Subject: atm: ambassador: constify pci_device_id. pci_device_id are not supposed to change at runtime. All functions working with pci_device_id provided by work with const pci_device_id. So mark the non-const structs as const. File size before: text data bss dec hex filename 13372 408 4 13784 35d8 drivers/atm/ambassador.o File size After adding 'const': text data bss dec hex filename 13484 296 4 13784 35d8 drivers/atm/ambassador.o Signed-off-by: Arvind Yadav Signed-off-by: David S. Miller --- drivers/atm/ambassador.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c index 906705e5f776..acf16c323e38 100644 --- a/drivers/atm/ambassador.c +++ b/drivers/atm/ambassador.c @@ -2374,7 +2374,7 @@ MODULE_PARM_DESC(pci_lat, "PCI latency in bus cycles"); /********** module entry **********/ -static struct pci_device_id amb_pci_tbl[] = { +static const struct pci_device_id amb_pci_tbl[] = { { PCI_VDEVICE(MADGE, PCI_DEVICE_ID_MADGE_AMBASSADOR), 0 }, { PCI_VDEVICE(MADGE, PCI_DEVICE_ID_MADGE_AMBASSADOR_BAD), 0 }, { 0, } -- cgit v1.2.3 From d5c5665d133c6288bf0e7e6fd49a46463a285bd4 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Sun, 16 Jul 2017 15:02:31 +0530 Subject: atm: fore200e: constify pci_device_id. pci_device_id are not supposed to change at runtime. All functions working with pci_device_id provided by work with const pci_device_id. So mark the non-const structs as const. File size before: text data bss dec hex filename 20025 320 16 20361 4f89 drivers/atm/fore200e.o File size After adding 'const': text data bss dec hex filename 20089 256 16 20361 4f89 drivers/atm/fore200e.o Signed-off-by: Arvind Yadav Signed-off-by: David S. Miller --- drivers/atm/fore200e.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c index f0433adcd8fc..f8b7e86907cc 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c @@ -2757,7 +2757,7 @@ static void fore200e_pca_remove_one(struct pci_dev *pci_dev) } -static struct pci_device_id fore200e_pca_tbl[] = { +static const struct pci_device_id fore200e_pca_tbl[] = { { PCI_VENDOR_ID_FORE, PCI_DEVICE_ID_FORE_PCA200E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &fore200e_bus[0] }, { 0, } -- cgit v1.2.3 From 2f3e2604fb579e34f775c799eba2afdfcb97fd66 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Sun, 16 Jul 2017 15:02:32 +0530 Subject: atm: nicstar: constify pci_device_id. pci_device_id are not supposed to change at runtime. All functions working with pci_device_id provided by work with const pci_device_id. So mark the non-const structs as const. File size before: text data bss dec hex filename 22781 464 128 23373 5b4d drivers/atm/nicstar.o File size After adding 'const': text data bss dec hex filename 22845 400 128 23373 5b4d drivers/atm/nicstar.o Signed-off-by: Arvind Yadav Signed-off-by: David S. Miller --- drivers/atm/nicstar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c index d879f3bca107..9588d80f318e 100644 --- a/drivers/atm/nicstar.c +++ b/drivers/atm/nicstar.c @@ -253,7 +253,7 @@ static void nicstar_remove_one(struct pci_dev *pcidev) kfree(card); } -static struct pci_device_id nicstar_pci_tbl[] = { +static const struct pci_device_id nicstar_pci_tbl[] = { { PCI_VDEVICE(IDT, PCI_DEVICE_ID_IDT_IDT77201), 0 }, {0,} /* terminate list */ }; -- cgit v1.2.3 From 5c007845029d1e03df765f8fb2af0a0b8f5126b9 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Sun, 16 Jul 2017 15:02:33 +0530 Subject: atm: he: constify pci_device_id. pci_device_id are not supposed to change at runtime. All functions working with pci_device_id provided by work with const pci_device_id. So mark the non-const structs as const. File size before: text data bss dec hex filename 26514 440 48 27002 697a drivers/atm/he.o File size After adding 'const': text data bss dec hex filename 26578 376 48 27002 697a drivers/atm/he.o Signed-off-by: Arvind Yadav Signed-off-by: David S. Miller --- drivers/atm/he.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/atm/he.c b/drivers/atm/he.c index 37ee21c5a5ca..8f6156d475d1 100644 --- a/drivers/atm/he.c +++ b/drivers/atm/he.c @@ -2851,7 +2851,7 @@ MODULE_PARM_DESC(irq_coalesce, "use interrupt coalescing (default 1)"); module_param(sdh, bool, 0); MODULE_PARM_DESC(sdh, "use SDH framing (default 0)"); -static struct pci_device_id he_pci_tbl[] = { +static const struct pci_device_id he_pci_tbl[] = { { PCI_VDEVICE(FORE, PCI_DEVICE_ID_FORE_HE), 0 }, { 0, } }; -- cgit v1.2.3 From 77c0805dc84977e0539134942e678fce77cfb0ef Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Sun, 16 Jul 2017 15:02:34 +0530 Subject: atm: horizon: constify pci_device_id. pci_device_id are not supposed to change at runtime. All functions working with pci_device_id provided by work with const pci_device_id. So mark the non-const structs as const. File size before: text data bss dec hex filename 9859 328 6 10193 27d1 drivers/atm/horizon.o File size After adding 'const': text data bss dec hex filename 9923 264 6 10193 27d1 drivers/atm/horizon.o Signed-off-by: Arvind Yadav Signed-off-by: David S. Miller --- drivers/atm/horizon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c index 0f18480b33b5..7e76b35f422c 100644 --- a/drivers/atm/horizon.c +++ b/drivers/atm/horizon.c @@ -2867,7 +2867,7 @@ MODULE_PARM_DESC(max_tx_size, "maximum size of TX AAL5 frames"); MODULE_PARM_DESC(max_rx_size, "maximum size of RX AAL5 frames"); MODULE_PARM_DESC(pci_lat, "PCI latency in bus cycles"); -static struct pci_device_id hrz_pci_tbl[] = { +static const struct pci_device_id hrz_pci_tbl[] = { { PCI_VENDOR_ID_MADGE, PCI_DEVICE_ID_MADGE_HORIZON, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { 0, } -- cgit v1.2.3 From 6d6148b3e650b82149c45b7597b9b2c64342b979 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Sun, 16 Jul 2017 15:02:35 +0530 Subject: atm: solos-pci: constify pci_device_id. pci_device_id are not supposed to change at runtime. All functions working with pci_device_id provided by work with const pci_device_id. So mark the non-const structs as const. File size before: text data bss dec hex filename 16138 4592 24 20754 5112 drivers/atm/solos-pci.o File size After adding 'const': text data bss dec hex filename 16218 4528 24 20754 5122 drivers/atm/solos-pci.o Signed-off-by: Arvind Yadav Signed-off-by: David S. Miller --- drivers/atm/solos-pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index c8f2ca6d8b29..585984ee7dbd 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -1476,7 +1476,7 @@ static void fpga_remove(struct pci_dev *dev) kfree(card); } -static struct pci_device_id fpga_pci_tbl[] = { +static const struct pci_device_id fpga_pci_tbl[] = { { 0x10ee, 0x0300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { 0, } }; -- cgit v1.2.3 From 626e87ca8794d1a0c30697d717a0c4b031f731c8 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Sun, 16 Jul 2017 15:02:36 +0530 Subject: atm: lanai: constify pci_device_id. pci_device_id are not supposed to change at runtime. All functions working with pci_device_id provided by work with const pci_device_id. So mark the non-const structs as const. File size before: text data bss dec hex filename 18074 352 0 18426 47fa drivers/atm/lanai.o File size After adding 'const': text data bss dec hex filename 18170 256 0 18426 47fa drivers/atm/lanai.o Signed-off-by: Arvind Yadav Signed-off-by: David S. Miller --- drivers/atm/lanai.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c index 1a9bc51284b0..2351dad78ff5 100644 --- a/drivers/atm/lanai.c +++ b/drivers/atm/lanai.c @@ -2589,7 +2589,7 @@ static int lanai_init_one(struct pci_dev *pci, return result; } -static struct pci_device_id lanai_pci_tbl[] = { +static const struct pci_device_id lanai_pci_tbl[] = { { PCI_VDEVICE(EF, PCI_DEVICE_ID_EF_ATM_LANAI2) }, { PCI_VDEVICE(EF, PCI_DEVICE_ID_EF_ATM_LANAIHB) }, { 0, } /* terminal entry */ -- cgit v1.2.3 From aea39c7f4a56dd2147270b925ed0f107f9403be9 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Sun, 16 Jul 2017 15:02:37 +0530 Subject: atm: zatm: constify pci_device_id. pci_device_id are not supposed to change at runtime. All functions working with pci_device_id provided by work with const pci_device_id. So mark the non-const structs as const. File size before: text data bss dec hex filename 14350 352 40 14742 3996 drivers/atm/zatm.o File size After adding 'const': text data bss dec hex filename 14446 256 40 14742 3996 drivers/atm/zatm.o Signed-off-by: Arvind Yadav Signed-off-by: David S. Miller --- drivers/atm/zatm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c index 292dec18ffb8..d3aa7482d1f7 100644 --- a/drivers/atm/zatm.c +++ b/drivers/atm/zatm.c @@ -1642,7 +1642,7 @@ out_free: MODULE_LICENSE("GPL"); -static struct pci_device_id zatm_pci_tbl[] = { +static const struct pci_device_id zatm_pci_tbl[] = { { PCI_VDEVICE(ZEITNET, PCI_DEVICE_ID_ZEITNET_1221), ZATM_COPPER }, { PCI_VDEVICE(ZEITNET, PCI_DEVICE_ID_ZEITNET_1225), 0 }, { 0, } -- cgit v1.2.3 From 0fdfb33bd911df8d4129f1699d78e23a174dd414 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Sun, 16 Jul 2017 15:02:38 +0530 Subject: atm: firestream: constify pci_device_id. pci_device_id are not supposed to change at runtime. All functions working with pci_device_id provided by work with const pci_device_id. So mark the non-const structs as const. File size before: text data bss dec hex filename 16884 444 28 17356 43cc drivers/atm/firestream.o File size After adding 'const': text data bss dec hex filename 16980 348 28 17356 43cc drivers/atm/firestream.o Signed-off-by: Arvind Yadav Signed-off-by: David S. Miller --- drivers/atm/firestream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c index 22dcab952a24..6b6368a56526 100644 --- a/drivers/atm/firestream.c +++ b/drivers/atm/firestream.c @@ -2030,7 +2030,7 @@ static void firestream_remove_one(struct pci_dev *pdev) func_exit (); } -static struct pci_device_id firestream_pci_tbl[] = { +static const struct pci_device_id firestream_pci_tbl[] = { { PCI_VDEVICE(FUJITSU_ME, PCI_DEVICE_ID_FUJITSU_FS50), FS_IS50}, { PCI_VDEVICE(FUJITSU_ME, PCI_DEVICE_ID_FUJITSU_FS155), FS_IS155}, { 0, } -- cgit v1.2.3 From f283974cb8770415001e5761da587eca06580fe6 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Sun, 16 Jul 2017 15:02:39 +0530 Subject: atm: eni: constify pci_device_id. pci_device_id are not supposed to change at runtime. All functions working with pci_device_id provided by work with const pci_device_id. So mark the non-const structs as const. File size before: text data bss dec hex filename 21565 352 56 21973 55d5 drivers/atm/eni.o File size After adding 'const': text data bss dec hex filename 21661 256 56 21973 55d5 drivers/atm/eni.o Signed-off-by: Arvind Yadav Signed-off-by: David S. Miller --- drivers/atm/eni.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c index b042ec458544..ce47eb17901d 100644 --- a/drivers/atm/eni.c +++ b/drivers/atm/eni.c @@ -2292,7 +2292,7 @@ err_disable: } -static struct pci_device_id eni_pci_tbl[] = { +static const struct pci_device_id eni_pci_tbl[] = { { PCI_VDEVICE(EF, PCI_DEVICE_ID_EF_ATM_FPGA), 0 /* FPGA */ }, { PCI_VDEVICE(EF, PCI_DEVICE_ID_EF_ATM_ASIC), 1 /* ASIC */ }, { 0, } -- cgit v1.2.3 From 97ae5c2aa440588d1d7975e6e76f7f99c88c08a7 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Sun, 16 Jul 2017 15:02:40 +0530 Subject: atm: idt77252: constify pci_device_id. pci_device_id are not supposed to change at runtime. All functions working with pci_device_id provided by work with const pci_device_id. So mark the non-const structs as const. File size before: text data bss dec hex filename 27702 468 16 28186 6e1a drivers/atm/idt77252.o File size After adding 'const': text data bss dec hex filename 27766 404 16 28186 6e1a drivers/atm/idt77252.o Signed-off-by: Arvind Yadav Signed-off-by: David S. Miller --- drivers/atm/idt77252.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c index 60bacba03d17..b7a168c46692 100644 --- a/drivers/atm/idt77252.c +++ b/drivers/atm/idt77252.c @@ -3725,7 +3725,7 @@ err_out_disable_pdev: return err; } -static struct pci_device_id idt77252_pci_tbl[] = +static const struct pci_device_id idt77252_pci_tbl[] = { { PCI_VDEVICE(IDT, PCI_DEVICE_ID_IDT_IDT77252), 0 }, { 0, } -- cgit v1.2.3 From d1510a2e5ab6cb3a67f1c55ca5e7a6d2c6dec340 Mon Sep 17 00:00:00 2001 From: Chris Gorman Date: Wed, 12 Jul 2017 13:31:26 -0400 Subject: i2c: mux: pinctrl: mention correct module name in Kconfig help text Kconfig says the resulting module is pinctrl-i2cmux, but the module when built is i2c-mux-pinctrl. Fixes: ae58d1e40698 ("i2c: Add generic I2C multiplexer using pinctrl API") Signed-off-by: Chris Gorman Signed-off-by: Peter Rosin --- drivers/i2c/muxes/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig index 2c64d0e0740f..17121329bb79 100644 --- a/drivers/i2c/muxes/Kconfig +++ b/drivers/i2c/muxes/Kconfig @@ -83,7 +83,7 @@ config I2C_MUX_PINCTRL different sets of pins at run-time. This driver can also be built as a module. If so, the module will be - called pinctrl-i2cmux. + called i2c-mux-pinctrl. config I2C_MUX_REG tristate "Register-based I2C multiplexer" -- cgit v1.2.3 From fbe63acf62f57f8e51adae602c5ce1025002d5ee Mon Sep 17 00:00:00 2001 From: Yazen Ghannam Date: Mon, 20 Mar 2017 15:26:51 -0500 Subject: EDAC, mce_amd: Use cpu_to_node() to find the node ID Using the homegrown amd_get_nb_id() to find a node ID on AMD was fine while the L3 to node mapping was 1:1. And Zen topology broke this. So let's start slowly moving away from it and use the topology interfaces instead. Signed-off-by: Yazen Ghannam Cc: linux-edac Cc: x86-ml Link: http://lkml.kernel.org/r/1490041614-90057-2-git-send-email-Yazen.Ghannam@amd.com [ Massage commit message. ] Signed-off-by: Borislav Petkov --- drivers/edac/mce_amd.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c index 9a2658a256a9..e8e9d7df0a6e 100644 --- a/drivers/edac/mce_amd.c +++ b/drivers/edac/mce_amd.c @@ -878,12 +878,8 @@ static void decode_smca_errors(struct mce *m) pr_cont("%s.\n", smca_mce_descs[bank_type].descs[xec]); } - /* - * amd_get_nb_id() returns the last level cache id. - * The last level cache on Fam17h is 1 level below the node. - */ if (bank_type == SMCA_UMC && xec == 0 && decode_dram_ecc) - decode_dram_ecc(amd_get_nb_id(m->extcpu) >> 1, m); + decode_dram_ecc(cpu_to_node(m->extcpu), m); } static inline void amd_decode_err_code(u16 ec) -- cgit v1.2.3 From 934d1431929bb5ecde68fb38fe4b2a6f4ab0fba6 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Mon, 3 Jul 2017 21:35:20 +0530 Subject: drm/sun4i: constify drm_plane_helper_funcs drm_plane_helper_funcs are not supposed to change at runtime. All functions working with drm_plane_helper_funcs provided by work with const drm_plane_helper_funcs. So mark the non-const structs as const. File size before: text data bss dec hex filename 981 40 0 1021 3fd drivers/gpu/drm/sun4i/sun4i_layer.o File size After adding 'const': text data bss dec hex filename 1021 0 0 1021 3fd drivers/gpu/drm/sun4i/sun4i_layer.o Signed-off-by: Arvind Yadav Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_layer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c index ead4f9d4c1ee..6a887ac28aae 100644 --- a/drivers/gpu/drm/sun4i/sun4i_layer.c +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c @@ -52,7 +52,7 @@ static void sun4i_backend_layer_atomic_update(struct drm_plane *plane, sun4i_backend_layer_enable(backend, layer->id, true); } -static struct drm_plane_helper_funcs sun4i_backend_layer_helper_funcs = { +static const struct drm_plane_helper_funcs sun4i_backend_layer_helper_funcs = { .atomic_check = sun4i_backend_layer_atomic_check, .atomic_disable = sun4i_backend_layer_atomic_disable, .atomic_update = sun4i_backend_layer_atomic_update, -- cgit v1.2.3 From f0a3dd33ba685bc50f78455aec832ebcc129a687 Mon Sep 17 00:00:00 2001 From: Jonathan Liu Date: Sun, 2 Jul 2017 17:27:10 +1000 Subject: drm/sun4i: hdmi: Implement I2C adapter for A10s DDC bus The documentation for drm_do_get_edid in drivers/gpu/drm/drm_edid.c states: "As in the general case the DDC bus is accessible by the kernel at the I2C level, drivers must make all reasonable efforts to expose it as an I2C adapter and use drm_get_edid() instead of abusing this function." Exposing the DDC bus as an I2C adapter is more beneficial as it can be used for purposes other than reading the EDID such as modifying the EDID or using the HDMI DDC pins as an I2C bus through the I2C dev interface from userspace (e.g. i2c-tools). Implement this for A10s. Signed-off-by: Jonathan Liu Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/Makefile | 1 + drivers/gpu/drm/sun4i/sun4i_hdmi.h | 24 ++++ drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c | 101 ++------------- drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c | 220 +++++++++++++++++++++++++++++++++ 4 files changed, 256 insertions(+), 90 deletions(-) create mode 100644 drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c (limited to 'drivers') diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile index e29fd3a2ba9c..43c753cafc88 100644 --- a/drivers/gpu/drm/sun4i/Makefile +++ b/drivers/gpu/drm/sun4i/Makefile @@ -2,6 +2,7 @@ sun4i-drm-y += sun4i_drv.o sun4i-drm-y += sun4i_framebuffer.o sun4i-drm-hdmi-y += sun4i_hdmi_enc.o +sun4i-drm-hdmi-y += sun4i_hdmi_i2c.o sun4i-drm-hdmi-y += sun4i_hdmi_ddc_clk.o sun4i-drm-hdmi-y += sun4i_hdmi_tmds_clk.o diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi.h b/drivers/gpu/drm/sun4i/sun4i_hdmi.h index 2f2f2ff1ea63..0957ff2076ac 100644 --- a/drivers/gpu/drm/sun4i/sun4i_hdmi.h +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi.h @@ -96,6 +96,7 @@ #define SUN4I_HDMI_DDC_CTRL_ENABLE BIT(31) #define SUN4I_HDMI_DDC_CTRL_START_CMD BIT(30) #define SUN4I_HDMI_DDC_CTRL_FIFO_DIR_MASK BIT(8) +#define SUN4I_HDMI_DDC_CTRL_FIFO_DIR_WRITE (1 << 8) #define SUN4I_HDMI_DDC_CTRL_FIFO_DIR_READ (0 << 8) #define SUN4I_HDMI_DDC_CTRL_RESET BIT(0) @@ -105,14 +106,34 @@ #define SUN4I_HDMI_DDC_ADDR_OFFSET(off) (((off) & 0xff) << 8) #define SUN4I_HDMI_DDC_ADDR_SLAVE(addr) ((addr) & 0xff) +#define SUN4I_HDMI_DDC_INT_STATUS_REG 0x50c +#define SUN4I_HDMI_DDC_INT_STATUS_ILLEGAL_FIFO_OPERATION BIT(7) +#define SUN4I_HDMI_DDC_INT_STATUS_DDC_RX_FIFO_UNDERFLOW BIT(6) +#define SUN4I_HDMI_DDC_INT_STATUS_DDC_TX_FIFO_OVERFLOW BIT(5) +#define SUN4I_HDMI_DDC_INT_STATUS_FIFO_REQUEST BIT(4) +#define SUN4I_HDMI_DDC_INT_STATUS_ARBITRATION_ERROR BIT(3) +#define SUN4I_HDMI_DDC_INT_STATUS_ACK_ERROR BIT(2) +#define SUN4I_HDMI_DDC_INT_STATUS_BUS_ERROR BIT(1) +#define SUN4I_HDMI_DDC_INT_STATUS_TRANSFER_COMPLETE BIT(0) + #define SUN4I_HDMI_DDC_FIFO_CTRL_REG 0x510 #define SUN4I_HDMI_DDC_FIFO_CTRL_CLEAR BIT(31) +#define SUN4I_HDMI_DDC_FIFO_CTRL_RX_THRES(n) (((n) & 0xf) << 4) +#define SUN4I_HDMI_DDC_FIFO_CTRL_RX_THRES_MASK GENMASK(7, 4) +#define SUN4I_HDMI_DDC_FIFO_CTRL_RX_THRES_MAX (BIT(4) - 1) +#define SUN4I_HDMI_DDC_FIFO_CTRL_TX_THRES(n) ((n) & 0xf) +#define SUN4I_HDMI_DDC_FIFO_CTRL_TX_THRES_MASK GENMASK(3, 0) +#define SUN4I_HDMI_DDC_FIFO_CTRL_TX_THRES_MAX (BIT(4) - 1) #define SUN4I_HDMI_DDC_FIFO_DATA_REG 0x518 + #define SUN4I_HDMI_DDC_BYTE_COUNT_REG 0x51c +#define SUN4I_HDMI_DDC_BYTE_COUNT_MAX (BIT(10) - 1) #define SUN4I_HDMI_DDC_CMD_REG 0x520 #define SUN4I_HDMI_DDC_CMD_EXPLICIT_EDDC_READ 6 +#define SUN4I_HDMI_DDC_CMD_IMPLICIT_READ 5 +#define SUN4I_HDMI_DDC_CMD_IMPLICIT_WRITE 3 #define SUN4I_HDMI_DDC_CLK_REG 0x528 #define SUN4I_HDMI_DDC_CLK_M(m) (((m) & 0x7) << 3) @@ -146,6 +167,8 @@ struct sun4i_hdmi { struct clk *ddc_clk; struct clk *tmds_clk; + struct i2c_adapter *i2c; + struct sun4i_drv *drv; bool hdmi_monitor; @@ -153,5 +176,6 @@ struct sun4i_hdmi { int sun4i_ddc_create(struct sun4i_hdmi *hdmi, struct clk *clk); int sun4i_tmds_create(struct sun4i_hdmi *hdmi); +int sun4i_hdmi_i2c_create(struct device *dev, struct sun4i_hdmi *hdmi); #endif /* _SUN4I_HDMI_H_ */ diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c index d3398f6250ef..b74607feb35c 100644 --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c @@ -29,8 +29,6 @@ #include "sun4i_hdmi.h" #include "sun4i_tcon.h" -#define DDC_SEGMENT_ADDR 0x30 - static inline struct sun4i_hdmi * drm_encoder_to_sun4i_hdmi(struct drm_encoder *encoder) { @@ -184,93 +182,13 @@ static const struct drm_encoder_funcs sun4i_hdmi_funcs = { .destroy = drm_encoder_cleanup, }; -static int sun4i_hdmi_read_sub_block(struct sun4i_hdmi *hdmi, - unsigned int blk, unsigned int offset, - u8 *buf, unsigned int count) -{ - unsigned long reg; - int i; - - reg = readl(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); - reg &= ~SUN4I_HDMI_DDC_CTRL_FIFO_DIR_MASK; - writel(reg | SUN4I_HDMI_DDC_CTRL_FIFO_DIR_READ, - hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); - - writel(SUN4I_HDMI_DDC_ADDR_SEGMENT(offset >> 8) | - SUN4I_HDMI_DDC_ADDR_EDDC(DDC_SEGMENT_ADDR << 1) | - SUN4I_HDMI_DDC_ADDR_OFFSET(offset) | - SUN4I_HDMI_DDC_ADDR_SLAVE(DDC_ADDR), - hdmi->base + SUN4I_HDMI_DDC_ADDR_REG); - - reg = readl(hdmi->base + SUN4I_HDMI_DDC_FIFO_CTRL_REG); - writel(reg | SUN4I_HDMI_DDC_FIFO_CTRL_CLEAR, - hdmi->base + SUN4I_HDMI_DDC_FIFO_CTRL_REG); - - writel(count, hdmi->base + SUN4I_HDMI_DDC_BYTE_COUNT_REG); - writel(SUN4I_HDMI_DDC_CMD_EXPLICIT_EDDC_READ, - hdmi->base + SUN4I_HDMI_DDC_CMD_REG); - - reg = readl(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); - writel(reg | SUN4I_HDMI_DDC_CTRL_START_CMD, - hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); - - if (readl_poll_timeout(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG, reg, - !(reg & SUN4I_HDMI_DDC_CTRL_START_CMD), - 100, 100000)) - return -EIO; - - for (i = 0; i < count; i++) - buf[i] = readb(hdmi->base + SUN4I_HDMI_DDC_FIFO_DATA_REG); - - return 0; -} - -static int sun4i_hdmi_read_edid_block(void *data, u8 *buf, unsigned int blk, - size_t length) -{ - struct sun4i_hdmi *hdmi = data; - int retry = 2, i; - - do { - for (i = 0; i < length; i += SUN4I_HDMI_DDC_FIFO_SIZE) { - unsigned char offset = blk * EDID_LENGTH + i; - unsigned int count = min((unsigned int)SUN4I_HDMI_DDC_FIFO_SIZE, - length - i); - int ret; - - ret = sun4i_hdmi_read_sub_block(hdmi, blk, offset, - buf + i, count); - if (ret) - return ret; - } - } while (!drm_edid_block_valid(buf, blk, true, NULL) && (retry--)); - - return 0; -} - static int sun4i_hdmi_get_modes(struct drm_connector *connector) { struct sun4i_hdmi *hdmi = drm_connector_to_sun4i_hdmi(connector); - unsigned long reg; struct edid *edid; int ret; - /* Reset i2c controller */ - writel(SUN4I_HDMI_DDC_CTRL_ENABLE | SUN4I_HDMI_DDC_CTRL_RESET, - hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); - if (readl_poll_timeout(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG, reg, - !(reg & SUN4I_HDMI_DDC_CTRL_RESET), - 100, 2000)) - return -EIO; - - writel(SUN4I_HDMI_DDC_LINE_CTRL_SDA_ENABLE | - SUN4I_HDMI_DDC_LINE_CTRL_SCL_ENABLE, - hdmi->base + SUN4I_HDMI_DDC_LINE_CTRL_REG); - - clk_prepare_enable(hdmi->ddc_clk); - clk_set_rate(hdmi->ddc_clk, 100000); - - edid = drm_do_get_edid(connector, sun4i_hdmi_read_edid_block, hdmi); + edid = drm_get_edid(connector, hdmi->i2c); if (!edid) return 0; @@ -282,8 +200,6 @@ static int sun4i_hdmi_get_modes(struct drm_connector *connector) ret = drm_add_edid_modes(connector, edid); kfree(edid); - clk_disable_unprepare(hdmi->ddc_clk); - return ret; } @@ -407,9 +323,9 @@ static int sun4i_hdmi_bind(struct device *dev, struct device *master, SUN4I_HDMI_PLL_CTRL_PLL_EN; writel(reg, hdmi->base + SUN4I_HDMI_PLL_CTRL_REG); - ret = sun4i_ddc_create(hdmi, hdmi->tmds_clk); + ret = sun4i_hdmi_i2c_create(dev, hdmi); if (ret) { - dev_err(dev, "Couldn't create the DDC clock\n"); + dev_err(dev, "Couldn't create the HDMI I2C adapter\n"); return ret; } @@ -422,13 +338,15 @@ static int sun4i_hdmi_bind(struct device *dev, struct device *master, NULL); if (ret) { dev_err(dev, "Couldn't initialise the HDMI encoder\n"); - return ret; + goto err_del_i2c_adapter; } hdmi->encoder.possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node); - if (!hdmi->encoder.possible_crtcs) - return -EPROBE_DEFER; + if (!hdmi->encoder.possible_crtcs) { + ret = -EPROBE_DEFER; + goto err_del_i2c_adapter; + } drm_connector_helper_add(&hdmi->connector, &sun4i_hdmi_connector_helper_funcs); @@ -451,6 +369,8 @@ static int sun4i_hdmi_bind(struct device *dev, struct device *master, err_cleanup_connector: drm_encoder_cleanup(&hdmi->encoder); +err_del_i2c_adapter: + i2c_del_adapter(hdmi->i2c); return ret; } @@ -461,6 +381,7 @@ static void sun4i_hdmi_unbind(struct device *dev, struct device *master, drm_connector_cleanup(&hdmi->connector); drm_encoder_cleanup(&hdmi->encoder); + i2c_del_adapter(hdmi->i2c); } static const struct component_ops sun4i_hdmi_ops = { diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c new file mode 100644 index 000000000000..2e42d09ab42e --- /dev/null +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2016 Maxime Ripard + * Copyright (C) 2017 Jonathan Liu + * + * 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. + */ + +#include +#include +#include + +#include "sun4i_hdmi.h" + +#define SUN4I_HDMI_DDC_INT_STATUS_ERROR_MASK ( \ + SUN4I_HDMI_DDC_INT_STATUS_ILLEGAL_FIFO_OPERATION | \ + SUN4I_HDMI_DDC_INT_STATUS_DDC_RX_FIFO_UNDERFLOW | \ + SUN4I_HDMI_DDC_INT_STATUS_DDC_TX_FIFO_OVERFLOW | \ + SUN4I_HDMI_DDC_INT_STATUS_ARBITRATION_ERROR | \ + SUN4I_HDMI_DDC_INT_STATUS_ACK_ERROR | \ + SUN4I_HDMI_DDC_INT_STATUS_BUS_ERROR \ +) + +/* FIFO request bit is set when FIFO level is above RX_THRESHOLD during read */ +#define RX_THRESHOLD SUN4I_HDMI_DDC_FIFO_CTRL_RX_THRES_MAX +/* FIFO request bit is set when FIFO level is below TX_THRESHOLD during write */ +#define TX_THRESHOLD 1 + +static int fifo_transfer(struct sun4i_hdmi *hdmi, u8 *buf, int len, bool read) +{ + /* + * 1 byte takes 9 clock cycles (8 bits + 1 ACK) = 90 us for 100 kHz + * clock. As clock rate is fixed, just round it up to 100 us. + */ + const unsigned long byte_time_ns = 100; + const u32 mask = SUN4I_HDMI_DDC_INT_STATUS_ERROR_MASK | + SUN4I_HDMI_DDC_INT_STATUS_FIFO_REQUEST | + SUN4I_HDMI_DDC_INT_STATUS_TRANSFER_COMPLETE; + u32 reg; + + /* Limit transfer length by FIFO threshold */ + len = min_t(int, len, read ? (RX_THRESHOLD + 1) : + (SUN4I_HDMI_DDC_FIFO_SIZE - TX_THRESHOLD + 1)); + + /* Wait until error, FIFO request bit set or transfer complete */ + if (readl_poll_timeout(hdmi->base + SUN4I_HDMI_DDC_INT_STATUS_REG, reg, + reg & mask, len * byte_time_ns, 100000)) + return -ETIMEDOUT; + + if (reg & SUN4I_HDMI_DDC_INT_STATUS_ERROR_MASK) + return -EIO; + + if (read) + readsb(hdmi->base + SUN4I_HDMI_DDC_FIFO_DATA_REG, buf, len); + else + writesb(hdmi->base + SUN4I_HDMI_DDC_FIFO_DATA_REG, buf, len); + + /* Clear FIFO request bit */ + writel(SUN4I_HDMI_DDC_INT_STATUS_FIFO_REQUEST, + hdmi->base + SUN4I_HDMI_DDC_INT_STATUS_REG); + + return len; +} + +static int xfer_msg(struct sun4i_hdmi *hdmi, struct i2c_msg *msg) +{ + int i, len; + u32 reg; + + /* Set FIFO direction */ + reg = readl(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); + reg &= ~SUN4I_HDMI_DDC_CTRL_FIFO_DIR_MASK; + reg |= (msg->flags & I2C_M_RD) ? + SUN4I_HDMI_DDC_CTRL_FIFO_DIR_READ : + SUN4I_HDMI_DDC_CTRL_FIFO_DIR_WRITE; + writel(reg, hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); + + /* Set I2C address */ + writel(SUN4I_HDMI_DDC_ADDR_SLAVE(msg->addr), + hdmi->base + SUN4I_HDMI_DDC_ADDR_REG); + + /* Set FIFO RX/TX thresholds and clear FIFO */ + reg = readl(hdmi->base + SUN4I_HDMI_DDC_FIFO_CTRL_REG); + reg |= SUN4I_HDMI_DDC_FIFO_CTRL_CLEAR; + reg &= ~SUN4I_HDMI_DDC_FIFO_CTRL_RX_THRES_MASK; + reg |= SUN4I_HDMI_DDC_FIFO_CTRL_RX_THRES(RX_THRESHOLD); + reg &= ~SUN4I_HDMI_DDC_FIFO_CTRL_TX_THRES_MASK; + reg |= SUN4I_HDMI_DDC_FIFO_CTRL_TX_THRES(TX_THRESHOLD); + writel(reg, hdmi->base + SUN4I_HDMI_DDC_FIFO_CTRL_REG); + if (readl_poll_timeout(hdmi->base + SUN4I_HDMI_DDC_FIFO_CTRL_REG, + reg, + !(reg & SUN4I_HDMI_DDC_FIFO_CTRL_CLEAR), + 100, 2000)) + return -EIO; + + /* Set transfer length */ + writel(msg->len, hdmi->base + SUN4I_HDMI_DDC_BYTE_COUNT_REG); + + /* Set command */ + writel(msg->flags & I2C_M_RD ? + SUN4I_HDMI_DDC_CMD_IMPLICIT_READ : + SUN4I_HDMI_DDC_CMD_IMPLICIT_WRITE, + hdmi->base + SUN4I_HDMI_DDC_CMD_REG); + + /* Clear interrupt status bits */ + writel(SUN4I_HDMI_DDC_INT_STATUS_ERROR_MASK | + SUN4I_HDMI_DDC_INT_STATUS_FIFO_REQUEST | + SUN4I_HDMI_DDC_INT_STATUS_TRANSFER_COMPLETE, + hdmi->base + SUN4I_HDMI_DDC_INT_STATUS_REG); + + /* Start command */ + reg = readl(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); + writel(reg | SUN4I_HDMI_DDC_CTRL_START_CMD, + hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); + + /* Transfer bytes */ + for (i = 0; i < msg->len; i += len) { + len = fifo_transfer(hdmi, msg->buf + i, msg->len - i, + msg->flags & I2C_M_RD); + if (len <= 0) + return len; + } + + /* Wait for command to finish */ + if (readl_poll_timeout(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG, + reg, + !(reg & SUN4I_HDMI_DDC_CTRL_START_CMD), + 100, 100000)) + return -EIO; + + /* Check for errors */ + reg = readl(hdmi->base + SUN4I_HDMI_DDC_INT_STATUS_REG); + if ((reg & SUN4I_HDMI_DDC_INT_STATUS_ERROR_MASK) || + !(reg & SUN4I_HDMI_DDC_INT_STATUS_TRANSFER_COMPLETE)) { + return -EIO; + } + + return 0; +} + +static int sun4i_hdmi_i2c_xfer(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num) +{ + struct sun4i_hdmi *hdmi = i2c_get_adapdata(adap); + u32 reg; + int err, i, ret = num; + + for (i = 0; i < num; i++) { + if (!msgs[i].len) + return -EINVAL; + if (msgs[i].len > SUN4I_HDMI_DDC_BYTE_COUNT_MAX) + return -EINVAL; + } + + /* Reset I2C controller */ + writel(SUN4I_HDMI_DDC_CTRL_ENABLE | SUN4I_HDMI_DDC_CTRL_RESET, + hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); + if (readl_poll_timeout(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG, reg, + !(reg & SUN4I_HDMI_DDC_CTRL_RESET), + 100, 2000)) + return -EIO; + + writel(SUN4I_HDMI_DDC_LINE_CTRL_SDA_ENABLE | + SUN4I_HDMI_DDC_LINE_CTRL_SCL_ENABLE, + hdmi->base + SUN4I_HDMI_DDC_LINE_CTRL_REG); + + clk_prepare_enable(hdmi->ddc_clk); + clk_set_rate(hdmi->ddc_clk, 100000); + + for (i = 0; i < num; i++) { + err = xfer_msg(hdmi, &msgs[i]); + if (err) { + ret = err; + break; + } + } + + clk_disable_unprepare(hdmi->ddc_clk); + return ret; +} + +static u32 sun4i_hdmi_i2c_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static const struct i2c_algorithm sun4i_hdmi_i2c_algorithm = { + .master_xfer = sun4i_hdmi_i2c_xfer, + .functionality = sun4i_hdmi_i2c_func, +}; + +int sun4i_hdmi_i2c_create(struct device *dev, struct sun4i_hdmi *hdmi) +{ + struct i2c_adapter *adap; + int ret = 0; + + ret = sun4i_ddc_create(hdmi, hdmi->tmds_clk); + if (ret) + return ret; + + adap = devm_kzalloc(dev, sizeof(*adap), GFP_KERNEL); + if (!adap) + return -ENOMEM; + + adap->owner = THIS_MODULE; + adap->class = I2C_CLASS_DDC; + adap->algo = &sun4i_hdmi_i2c_algorithm; + strlcpy(adap->name, "sun4i_hdmi_i2c adapter", sizeof(adap->name)); + i2c_set_adapdata(adap, hdmi); + + ret = i2c_add_adapter(adap); + if (ret) + return ret; + + hdmi->i2c = adap; + + return ret; +} -- cgit v1.2.3 From 2a596fc9d974bb040eda9ab70bf8756fcaaa6afe Mon Sep 17 00:00:00 2001 From: Jonathan Liu Date: Mon, 10 Jul 2017 16:55:04 +1000 Subject: drm/sun4i: Implement drm_driver lastclose to restore fbdev console The drm_driver lastclose callback is called when the last userspace DRM client has closed. Call drm_fbdev_cma_restore_mode to restore the fbdev console otherwise the fbdev console will stop working. Fixes: 9026e0d122ac ("drm: Add Allwinner A10 Display Engine support") Cc: stable@vger.kernel.org Tested-by: Olliver Schinagl Reviewed-by: Chen-Yu Tsai Signed-off-by: Jonathan Liu Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_drv.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c index abc7d8fe06b4..a45a627283a1 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.c +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c @@ -25,12 +25,20 @@ #include "sun4i_framebuffer.h" #include "sun4i_tcon.h" +static void sun4i_drv_lastclose(struct drm_device *dev) +{ + struct sun4i_drv *drv = dev->dev_private; + + drm_fbdev_cma_restore_mode(drv->fbdev); +} + DEFINE_DRM_GEM_CMA_FOPS(sun4i_drv_fops); static struct drm_driver sun4i_drv_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_ATOMIC, /* Generic Operations */ + .lastclose = sun4i_drv_lastclose, .fops = &sun4i_drv_fops, .name = "sun4i-drm", .desc = "Allwinner sun4i Display Engine", -- cgit v1.2.3 From 58947144af34a08eee3388c1f039f199e80c0c6f Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 17 Jul 2017 09:06:19 +0200 Subject: drm/i915: Update DRIVER_DATE to 20170717 Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b4716ce32ca2..559fdc7bb393 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -80,8 +80,8 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20170703" -#define DRIVER_TIMESTAMP 1499064041 +#define DRIVER_DATE "20170717" +#define DRIVER_TIMESTAMP 1500275179 /* Use I915_STATE_WARN(x) and I915_STATE_WARN_ON() (rather than WARN() and * WARN_ON()) for hw state sanity checks to check for unexpected conditions -- cgit v1.2.3 From bc98a42c1f7d0f886c0c1b75a92a004976a46d9f Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 17 Jul 2017 08:45:34 +0100 Subject: VFS: Convert sb->s_flags & MS_RDONLY to sb_rdonly(sb) Firstly by applying the following with coccinelle's spatch: @@ expression SB; @@ -SB->s_flags & MS_RDONLY +sb_rdonly(SB) to effect the conversion to sb_rdonly(sb), then by applying: @@ expression A, SB; @@ ( -(!sb_rdonly(SB)) && A +!sb_rdonly(SB) && A | -A != (sb_rdonly(SB)) +A != sb_rdonly(SB) | -A == (sb_rdonly(SB)) +A == sb_rdonly(SB) | -!(sb_rdonly(SB)) +!sb_rdonly(SB) | -A && (sb_rdonly(SB)) +A && sb_rdonly(SB) | -A || (sb_rdonly(SB)) +A || sb_rdonly(SB) | -(sb_rdonly(SB)) != A +sb_rdonly(SB) != A | -(sb_rdonly(SB)) == A +sb_rdonly(SB) == A | -(sb_rdonly(SB)) && A +sb_rdonly(SB) && A | -(sb_rdonly(SB)) || A +sb_rdonly(SB) || A ) @@ expression A, B, SB; @@ ( -(sb_rdonly(SB)) ? 1 : 0 +sb_rdonly(SB) | -(sb_rdonly(SB)) ? A : B +sb_rdonly(SB) ? A : B ) to remove left over excess bracketage and finally by applying: @@ expression A, SB; @@ ( -(A & MS_RDONLY) != sb_rdonly(SB) +(bool)(A & MS_RDONLY) != sb_rdonly(SB) | -(A & MS_RDONLY) == sb_rdonly(SB) +(bool)(A & MS_RDONLY) == sb_rdonly(SB) ) to make comparisons against the result of sb_rdonly() (which is a bool) work correctly. Signed-off-by: David Howells --- drivers/staging/lustre/lustre/llite/llite_lib.c | 4 +- drivers/staging/lustre/lustre/llite/namei.c | 3 +- fs/affs/amigaffs.c | 2 +- fs/affs/bitmap.c | 2 +- fs/affs/super.c | 6 +-- fs/befs/linuxvfs.c | 2 +- fs/btrfs/dev-replace.c | 2 +- fs/btrfs/disk-io.c | 12 +++--- fs/btrfs/extent_io.c | 4 +- fs/btrfs/inode.c | 2 +- fs/btrfs/ioctl.c | 2 +- fs/btrfs/root-tree.c | 2 +- fs/btrfs/super.c | 11 +++-- fs/btrfs/sysfs.c | 4 +- fs/btrfs/volumes.c | 4 +- fs/cachefiles/bind.c | 2 +- fs/ecryptfs/main.c | 3 +- fs/efs/super.c | 2 +- fs/ext2/super.c | 13 +++--- fs/ext4/ext4_jbd2.c | 2 +- fs/ext4/file.c | 2 +- fs/ext4/fsync.c | 2 +- fs/ext4/ialloc.c | 2 +- fs/ext4/mmp.c | 2 +- fs/ext4/super.c | 53 ++++++++++++------------- fs/fat/fatent.c | 2 +- fs/fat/inode.c | 4 +- fs/fat/misc.c | 2 +- fs/gfs2/glops.c | 2 +- fs/gfs2/ops_fstype.c | 4 +- fs/gfs2/quota.c | 2 +- fs/gfs2/recovery.c | 2 +- fs/gfs2/super.c | 4 +- fs/gfs2/sys.c | 2 +- fs/hfs/mdb.c | 6 +-- fs/hfs/super.c | 4 +- fs/hfsplus/super.c | 10 ++--- fs/hpfs/alloc.c | 4 +- fs/hpfs/dir.c | 2 +- fs/hpfs/super.c | 13 +++--- fs/isofs/inode.c | 2 +- fs/jffs2/fs.c | 6 +-- fs/jffs2/super.c | 2 +- fs/jffs2/wbuf.c | 4 +- fs/jfs/jfs_mount.c | 2 +- fs/jfs/super.c | 16 ++++---- fs/minix/inode.c | 6 +-- fs/namei.c | 3 +- fs/namespace.c | 6 +-- fs/nfs/super.c | 2 +- fs/nilfs2/inode.c | 4 +- fs/nilfs2/mdt.c | 2 +- fs/nilfs2/super.c | 19 +++++---- fs/ntfs/super.c | 31 +++++++-------- fs/ocfs2/super.c | 15 +++---- fs/overlayfs/super.c | 2 +- fs/proc_namespace.c | 2 +- fs/quota/quota.c | 2 +- fs/reiserfs/inode.c | 2 +- fs/reiserfs/journal.c | 2 +- fs/reiserfs/prints.c | 2 +- fs/reiserfs/super.c | 18 ++++----- fs/super.c | 10 ++--- fs/sync.c | 6 +-- fs/sysv/balloc.c | 2 +- fs/sysv/ialloc.c | 2 +- fs/sysv/inode.c | 2 +- fs/sysv/super.c | 2 +- fs/ubifs/super.c | 2 +- fs/udf/super.c | 14 +++---- fs/ufs/super.c | 24 +++++------ fs/xfs/xfs_quotaops.c | 10 ++--- fs/xfs/xfs_super.c | 2 +- init/do_mounts.c | 2 +- 74 files changed, 210 insertions(+), 226 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 974a05d6c969..2c33b92b5d4d 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -210,7 +210,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, data->ocd_ibits_known = MDS_INODELOCK_FULL; data->ocd_version = LUSTRE_VERSION_CODE; - if (sb->s_flags & MS_RDONLY) + if (sb_rdonly(sb)) data->ocd_connect_flags |= OBD_CONNECT_RDONLY; if (sbi->ll_flags & LL_SBI_USER_XATTR) data->ocd_connect_flags |= OBD_CONNECT_XATTR; @@ -2033,7 +2033,7 @@ int ll_remount_fs(struct super_block *sb, int *flags, char *data) int err; __u32 read_only; - if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY)) { + if ((bool)(*flags & MS_RDONLY) != sb_rdonly(sb)) { read_only = *flags & MS_RDONLY; err = obd_set_info_async(NULL, sbi->ll_md_exp, sizeof(KEY_READ_ONLY), diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index a208a8b02c2c..483890fa01a2 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -562,8 +562,7 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry, } } - if (it->it_op & IT_OPEN && it->it_flags & FMODE_WRITE && - dentry->d_sb->s_flags & MS_RDONLY) + if (it->it_op & IT_OPEN && it->it_flags & FMODE_WRITE && sb_rdonly(dentry->d_sb)) return ERR_PTR(-EROFS); if (it->it_op & IT_CREAT) diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c index b573c3b9a328..8cf941c3b511 100644 --- a/fs/affs/amigaffs.c +++ b/fs/affs/amigaffs.c @@ -450,7 +450,7 @@ affs_error(struct super_block *sb, const char *function, const char *fmt, ...) vaf.fmt = fmt; vaf.va = &args; pr_crit("error (device %s): %s(): %pV\n", sb->s_id, function, &vaf); - if (!(sb->s_flags & MS_RDONLY)) + if (!sb_rdonly(sb)) pr_warn("Remounting filesystem read-only\n"); sb->s_flags |= MS_RDONLY; va_end(args); diff --git a/fs/affs/bitmap.c b/fs/affs/bitmap.c index 675148950fed..2b2112475ec2 100644 --- a/fs/affs/bitmap.c +++ b/fs/affs/bitmap.c @@ -19,7 +19,7 @@ affs_count_free_blocks(struct super_block *sb) pr_debug("%s()\n", __func__); - if (sb->s_flags & MS_RDONLY) + if (sb_rdonly(sb)) return 0; mutex_lock(&AFFS_SB(sb)->s_bmlock); diff --git a/fs/affs/super.c b/fs/affs/super.c index 7bf47a41cb4f..884bedab7266 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c @@ -80,7 +80,7 @@ void affs_mark_sb_dirty(struct super_block *sb) struct affs_sb_info *sbi = AFFS_SB(sb); unsigned long delay; - if (sb->s_flags & MS_RDONLY) + if (sb_rdonly(sb)) return; spin_lock(&sbi->work_lock); @@ -464,7 +464,7 @@ got_root: * not recommended. */ if ((chksum == FS_DCFFS || chksum == MUFS_DCFFS || chksum == FS_DCOFS - || chksum == MUFS_DCOFS) && !(sb->s_flags & MS_RDONLY)) { + || chksum == MUFS_DCOFS) && !sb_rdonly(sb)) { pr_notice("Dircache FS - mounting %s read only\n", sb->s_id); sb->s_flags |= MS_RDONLY; } @@ -596,7 +596,7 @@ affs_remount(struct super_block *sb, int *flags, char *data) memcpy(sbi->s_volume, volume, 32); spin_unlock(&sbi->symlink_lock); - if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) + if ((bool)(*flags & MS_RDONLY) == sb_rdonly(sb)) return 0; if (*flags & MS_RDONLY) diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index 4a4a5a366158..a92355cc453b 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -838,7 +838,7 @@ befs_fill_super(struct super_block *sb, void *data, int silent) befs_debug(sb, "---> %s", __func__); - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { befs_warning(sb, "No write support. Marking filesystem read-only"); sb->s_flags |= MS_RDONLY; diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c index bee3edeea7a3..cd42d95e9e05 100644 --- a/fs/btrfs/dev-replace.c +++ b/fs/btrfs/dev-replace.c @@ -690,7 +690,7 @@ static u64 __btrfs_dev_replace_cancel(struct btrfs_fs_info *fs_info) u64 result; int ret; - if (fs_info->sb->s_flags & MS_RDONLY) + if (sb_rdonly(fs_info->sb)) return -EROFS; mutex_lock(&dev_replace->lock_finishing_cancel_unmount); diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 080e2ebb8aa0..4a9b40f604fa 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -2478,7 +2478,7 @@ static int btrfs_replay_log(struct btrfs_fs_info *fs_info, return ret; } - if (fs_info->sb->s_flags & MS_RDONLY) { + if (sb_rdonly(fs_info->sb)) { ret = btrfs_commit_super(fs_info); if (ret) return ret; @@ -2874,7 +2874,7 @@ int open_ctree(struct super_block *sb, features = btrfs_super_compat_ro_flags(disk_super) & ~BTRFS_FEATURE_COMPAT_RO_SUPP; - if (!(sb->s_flags & MS_RDONLY) && features) { + if (!sb_rdonly(sb) && features) { btrfs_err(fs_info, "cannot mount read-write because of unsupported optional features (%llx)", features); @@ -3039,7 +3039,7 @@ retry_root_backup: btrfs_calc_num_tolerated_disk_barrier_failures(fs_info); if (fs_info->fs_devices->missing_devices > fs_info->num_tolerated_disk_barrier_failures && - !(sb->s_flags & MS_RDONLY)) { + !sb_rdonly(sb)) { btrfs_warn(fs_info, "missing devices (%llu) exceeds the limit (%d), writeable mount is not allowed", fs_info->fs_devices->missing_devices, @@ -3102,7 +3102,7 @@ retry_root_backup: if (ret) goto fail_qgroup; - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { ret = btrfs_cleanup_fs_roots(fs_info); if (ret) goto fail_qgroup; @@ -3128,7 +3128,7 @@ retry_root_backup: goto fail_qgroup; } - if (sb->s_flags & MS_RDONLY) + if (sb_rdonly(sb)) return 0; if (btrfs_test_opt(fs_info, CLEAR_CACHE) && @@ -3928,7 +3928,7 @@ void close_ctree(struct btrfs_fs_info *fs_info) cancel_work_sync(&fs_info->async_reclaim_work); - if (!(fs_info->sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(fs_info->sb)) { /* * If the cleaner thread is stopped and there are * block groups queued for removal, the deletion will be diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 0aff9b278c19..5074e9b26f1a 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -2061,7 +2061,7 @@ int repair_eb_io_failure(struct btrfs_fs_info *fs_info, unsigned long i, num_pages = num_extent_pages(eb->start, eb->len); int ret = 0; - if (fs_info->sb->s_flags & MS_RDONLY) + if (sb_rdonly(fs_info->sb)) return -EROFS; for (i = 0; i < num_pages; i++) { @@ -2111,7 +2111,7 @@ int clean_io_failure(struct btrfs_fs_info *fs_info, failrec->start); goto out; } - if (fs_info->sb->s_flags & MS_RDONLY) + if (sb_rdonly(fs_info->sb)) goto out; spin_lock(&io_tree->lock); diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 95c212037095..07a18ce55d56 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -5817,7 +5817,7 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry) if (!IS_ERR(inode) && root != sub_root) { down_read(&fs_info->cleanup_work_sem); - if (!(inode->i_sb->s_flags & MS_RDONLY)) + if (!sb_rdonly(inode->i_sb)) ret = btrfs_orphan_cleanup(sub_root); up_read(&fs_info->cleanup_work_sem); if (ret) { diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index fa1b78cf25f6..8a27255173b7 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -4438,7 +4438,7 @@ static long btrfs_ioctl_dev_replace(struct btrfs_fs_info *fs_info, switch (p->cmd) { case BTRFS_IOCTL_DEV_REPLACE_CMD_START: - if (fs_info->sb->s_flags & MS_RDONLY) { + if (sb_rdonly(fs_info->sb)) { ret = -EROFS; goto out; } diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c index 460db0cb2d07..bfa1ae1dc0fa 100644 --- a/fs/btrfs/root-tree.c +++ b/fs/btrfs/root-tree.c @@ -228,7 +228,7 @@ int btrfs_find_orphan_roots(struct btrfs_fs_info *fs_info) int ret; bool can_recover = true; - if (fs_info->sb->s_flags & MS_RDONLY) + if (sb_rdonly(fs_info->sb)) can_recover = false; path = btrfs_alloc_path(); diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 12540b6104b5..086819312a44 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -102,7 +102,7 @@ static void btrfs_handle_error(struct btrfs_fs_info *fs_info) { struct super_block *sb = fs_info->sb; - if (sb->s_flags & MS_RDONLY) + if (sb_rdonly(sb)) return; if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state)) { @@ -138,7 +138,7 @@ void __btrfs_handle_fs_error(struct btrfs_fs_info *fs_info, const char *function * Special case: if the error is EROFS, and we're already * under MS_RDONLY, then it is safe here. */ - if (errno == -EROFS && (sb->s_flags & MS_RDONLY)) + if (errno == -EROFS && sb_rdonly(sb)) return; #ifdef CONFIG_PRINTK @@ -1687,8 +1687,7 @@ static inline void btrfs_remount_cleanup(struct btrfs_fs_info *fs_info, * close or the filesystem is read only. */ if (btrfs_raw_test_opt(old_opts, AUTO_DEFRAG) && - (!btrfs_raw_test_opt(fs_info->mount_opt, AUTO_DEFRAG) || - (fs_info->sb->s_flags & MS_RDONLY))) { + (!btrfs_raw_test_opt(fs_info->mount_opt, AUTO_DEFRAG) || sb_rdonly(fs_info->sb))) { btrfs_cleanup_defrag_inodes(fs_info); } @@ -1735,7 +1734,7 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data) btrfs_resize_thread_pool(fs_info, fs_info->thread_pool_size, old_thread_pool_size); - if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) + if ((bool)(*flags & MS_RDONLY) == sb_rdonly(sb)) goto out; if (*flags & MS_RDONLY) { @@ -1835,7 +1834,7 @@ out: restore: /* We've hit an error - don't reset MS_RDONLY */ - if (sb->s_flags & MS_RDONLY) + if (sb_rdonly(sb)) old_flags |= MS_RDONLY; sb->s_flags = old_flags; fs_info->mount_opt = old_opts; diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c index c2d5f3580b4c..432294d040d5 100644 --- a/fs/btrfs/sysfs.c +++ b/fs/btrfs/sysfs.c @@ -120,7 +120,7 @@ static ssize_t btrfs_feature_attr_store(struct kobject *kobj, if (!fs_info) return -EPERM; - if (fs_info->sb->s_flags & MS_RDONLY) + if (sb_rdonly(fs_info->sb)) return -EROFS; ret = kstrtoul(skip_spaces(buf), 0, &val); @@ -388,7 +388,7 @@ static ssize_t btrfs_label_store(struct kobject *kobj, if (!fs_info) return -EPERM; - if (fs_info->sb->s_flags & MS_RDONLY) + if (sb_rdonly(fs_info->sb)) return -EROFS; /* diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 5eb7217738ed..6646695c9072 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -2337,7 +2337,7 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path int seeding_dev = 0; int ret = 0; - if ((sb->s_flags & MS_RDONLY) && !fs_info->fs_devices->seeding) + if (sb_rdonly(sb) && !fs_info->fs_devices->seeding) return -EROFS; bdev = blkdev_get_by_path(device_path, FMODE_WRITE | FMODE_EXCL, @@ -4085,7 +4085,7 @@ int btrfs_pause_balance(struct btrfs_fs_info *fs_info) int btrfs_cancel_balance(struct btrfs_fs_info *fs_info) { - if (fs_info->sb->s_flags & MS_RDONLY) + if (sb_rdonly(fs_info->sb)) return -EROFS; mutex_lock(&fs_info->balance_mutex); diff --git a/fs/cachefiles/bind.c b/fs/cachefiles/bind.c index 3ff867f87d73..d9f001078e08 100644 --- a/fs/cachefiles/bind.c +++ b/fs/cachefiles/bind.c @@ -133,7 +133,7 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache) goto error_unsupported; ret = -EROFS; - if (root->d_sb->s_flags & MS_RDONLY) + if (sb_rdonly(root->d_sb)) goto error_unsupported; /* determine the security of the on-disk cache as this governs diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 9014479d0160..6b801186baa5 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -568,8 +568,7 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags * 1) The lower mount is ro * 2) The ecryptfs_encrypted_view mount option is specified */ - if (path.dentry->d_sb->s_flags & MS_RDONLY || - mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) + if (sb_rdonly(path.dentry->d_sb) || mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) s->s_flags |= MS_RDONLY; s->s_maxbytes = path.dentry->d_sb->s_maxbytes; diff --git a/fs/efs/super.c b/fs/efs/super.c index 368f7dd21c61..5c42f1e34a2f 100644 --- a/fs/efs/super.c +++ b/fs/efs/super.c @@ -306,7 +306,7 @@ static int efs_fill_super(struct super_block *s, void *d, int silent) } brelse(bh); - if (!(s->s_flags & MS_RDONLY)) { + if (!sb_rdonly(s)) { #ifdef DEBUG pr_info("forcing read-only mode\n"); #endif diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 7b1bc9059863..448ebfe60233 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -52,7 +52,7 @@ void ext2_error(struct super_block *sb, const char *function, struct ext2_sb_info *sbi = EXT2_SB(sb); struct ext2_super_block *es = sbi->s_es; - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { spin_lock(&sbi->s_lock); sbi->s_mount_state |= EXT2_ERROR_FS; es->s_state |= cpu_to_le16(EXT2_ERROR_FS); @@ -151,7 +151,7 @@ static void ext2_put_super (struct super_block * sb) ext2_xattr_destroy_cache(sbi->s_ea_block_cache); sbi->s_ea_block_cache = NULL; } - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { struct ext2_super_block *es = sbi->s_es; spin_lock(&sbi->s_lock); @@ -940,8 +940,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) le32_to_cpu(features)); goto failed_mount; } - if (!(sb->s_flags & MS_RDONLY) && - (features = EXT2_HAS_RO_COMPAT_FEATURE(sb, ~EXT2_FEATURE_RO_COMPAT_SUPP))){ + if (!sb_rdonly(sb) && (features = EXT2_HAS_RO_COMPAT_FEATURE(sb, ~EXT2_FEATURE_RO_COMPAT_SUPP))){ ext2_msg(sb, KERN_ERR, "error: couldn't mount RDWR because of " "unsupported optional features (%x)", le32_to_cpu(features)); @@ -1170,7 +1169,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) if (EXT2_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) ext2_msg(sb, KERN_WARNING, "warning: mounting ext3 filesystem as ext2"); - if (ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY)) + if (ext2_setup_super (sb, es, sb_rdonly(sb))) sb->s_flags |= MS_RDONLY; ext2_write_super(sb); return 0; @@ -1301,7 +1300,7 @@ static int ext2_unfreeze(struct super_block *sb) static void ext2_write_super(struct super_block *sb) { - if (!(sb->s_flags & MS_RDONLY)) + if (!sb_rdonly(sb)) ext2_sync_fs(sb, 1); } @@ -1339,7 +1338,7 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data) "dax flag with busy inodes while remounting"); sbi->s_mount_opt ^= EXT2_MOUNT_DAX; } - if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) { + if ((bool)(*flags & MS_RDONLY) == sb_rdonly(sb)) { spin_unlock(&sbi->s_lock); return 0; } diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c index dd106b1d5d89..5b342ac67d2e 100644 --- a/fs/ext4/ext4_jbd2.c +++ b/fs/ext4/ext4_jbd2.c @@ -47,7 +47,7 @@ static int ext4_journal_check_start(struct super_block *sb) if (unlikely(ext4_forced_shutdown(EXT4_SB(sb)))) return -EIO; - if (sb->s_flags & MS_RDONLY) + if (sb_rdonly(sb)) return -EROFS; WARN_ON(sb->s_writers.frozen == SB_FREEZE_COMPLETE); journal = EXT4_SB(sb)->s_journal; diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 58294c9a7e1d..b33ec8a23678 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c @@ -388,7 +388,7 @@ static int ext4_file_open(struct inode * inode, struct file * filp) return -EIO; if (unlikely(!(sbi->s_mount_flags & EXT4_MF_MNTDIR_SAMPLED) && - !(sb->s_flags & MS_RDONLY))) { + !sb_rdonly(sb))) { sbi->s_mount_flags |= EXT4_MF_MNTDIR_SAMPLED; /* * Sample where the filesystem has been mounted and diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c index aae2c3971cef..f9230580a84b 100644 --- a/fs/ext4/fsync.c +++ b/fs/ext4/fsync.c @@ -107,7 +107,7 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync) trace_ext4_sync_file_enter(file, datasync); - if (inode->i_sb->s_flags & MS_RDONLY) { + if (sb_rdonly(inode->i_sb)) { /* Make sure that we read updated s_mount_flags value */ smp_rmb(); if (EXT4_SB(inode->i_sb)->s_mount_flags & EXT4_MF_FS_ABORTED) diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 507bfb3344d4..360e87dbba74 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -1355,7 +1355,7 @@ int ext4_init_inode_table(struct super_block *sb, ext4_group_t group, int num, ret = 0, used_blks = 0; /* This should not happen, but just to be sure check this */ - if (sb->s_flags & MS_RDONLY) { + if (sb_rdonly(sb)) { ret = 1; goto out; } diff --git a/fs/ext4/mmp.c b/fs/ext4/mmp.c index eb9835638680..899b0761ca1c 100644 --- a/fs/ext4/mmp.c +++ b/fs/ext4/mmp.c @@ -185,7 +185,7 @@ static int kmmpd(void *data) goto exit_thread; } - if (sb->s_flags & MS_RDONLY) { + if (sb_rdonly(sb)) { ext4_warning(sb, "kmmpd being stopped since filesystem " "has been remounted as readonly."); goto exit_thread; diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 0886fe82e9c4..d9701c869dd3 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -405,7 +405,7 @@ static void ext4_journal_commit_callback(journal_t *journal, transaction_t *txn) static void ext4_handle_error(struct super_block *sb) { - if (sb->s_flags & MS_RDONLY) + if (sb_rdonly(sb)) return; if (!test_opt(sb, ERRORS_CONT)) { @@ -587,8 +587,7 @@ void __ext4_std_error(struct super_block *sb, const char *function, /* Special case: if the error is EROFS, and we're not already * inside a transaction, then there's really no point in logging * an error. */ - if (errno == -EROFS && journal_current_handle() == NULL && - (sb->s_flags & MS_RDONLY)) + if (errno == -EROFS && journal_current_handle() == NULL && sb_rdonly(sb)) return; if (ext4_error_ratelimit(sb)) { @@ -628,7 +627,7 @@ void __ext4_abort(struct super_block *sb, const char *function, sb->s_id, function, line, &vaf); va_end(args); - if ((sb->s_flags & MS_RDONLY) == 0) { + if (sb_rdonly(sb) == 0) { ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only"); EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FS_ABORTED; /* @@ -889,11 +888,11 @@ static void ext4_put_super(struct super_block *sb) ext4_mb_release(sb); ext4_ext_release(sb); - if (!(sb->s_flags & MS_RDONLY) && !aborted) { + if (!sb_rdonly(sb) && !aborted) { ext4_clear_feature_journal_needs_recovery(sb); es->s_state = cpu_to_le16(sbi->s_mount_state); } - if (!(sb->s_flags & MS_RDONLY)) + if (!sb_rdonly(sb)) ext4_commit_super(sb, 1); for (i = 0; i < sbi->s_gdb_count; i++) @@ -2101,7 +2100,7 @@ int ext4_seq_options_show(struct seq_file *seq, void *offset) struct super_block *sb = seq->private; int rc; - seq_puts(seq, (sb->s_flags & MS_RDONLY) ? "ro" : "rw"); + seq_puts(seq, sb_rdonly(sb) ? "ro" : "rw"); rc = _ext4_show_options(seq, sb, 1); seq_puts(seq, "\n"); return rc; @@ -2369,7 +2368,7 @@ static int ext4_check_descriptors(struct super_block *sb, "Checksum for group %u failed (%u!=%u)", i, le16_to_cpu(ext4_group_desc_csum(sb, i, gdp)), le16_to_cpu(gdp->bg_checksum)); - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { ext4_unlock_group(sb, i); return 0; } @@ -3116,8 +3115,7 @@ int ext4_register_li_request(struct super_block *sb, goto out; } - if (first_not_zeroed == ngroups || - (sb->s_flags & MS_RDONLY) || + if (first_not_zeroed == ngroups || sb_rdonly(sb) || !test_opt(sb, INIT_INODE_TABLE)) goto out; @@ -3661,7 +3659,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) * previously didn't change the revision level when setting the flags, * so there is a chance incompat flags are set on a rev 0 filesystem. */ - if (!ext4_feature_set_ok(sb, (sb->s_flags & MS_RDONLY))) + if (!ext4_feature_set_ok(sb, (sb_rdonly(sb)))) goto failed_mount; blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size); @@ -3790,12 +3788,12 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) sbi->s_hash_unsigned = 3; else if ((i & EXT2_FLAGS_SIGNED_HASH) == 0) { #ifdef __CHAR_UNSIGNED__ - if (!(sb->s_flags & MS_RDONLY)) + if (!sb_rdonly(sb)) es->s_flags |= cpu_to_le32(EXT2_FLAGS_UNSIGNED_HASH); sbi->s_hash_unsigned = 3; #else - if (!(sb->s_flags & MS_RDONLY)) + if (!sb_rdonly(sb)) es->s_flags |= cpu_to_le32(EXT2_FLAGS_SIGNED_HASH); #endif @@ -3995,7 +3993,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) needs_recovery = (es->s_last_orphan != 0 || ext4_has_feature_journal_needs_recovery(sb)); - if (ext4_has_feature_mmp(sb) && !(sb->s_flags & MS_RDONLY)) + if (ext4_has_feature_mmp(sb) && !sb_rdonly(sb)) if (ext4_multi_mount_protect(sb, le64_to_cpu(es->s_mmp_block))) goto failed_mount3a; @@ -4007,7 +4005,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) err = ext4_load_journal(sb, es, journal_devnum); if (err) goto failed_mount3a; - } else if (test_opt(sb, NOLOAD) && !(sb->s_flags & MS_RDONLY) && + } else if (test_opt(sb, NOLOAD) && !sb_rdonly(sb) && ext4_has_feature_journal_needs_recovery(sb)) { ext4_msg(sb, KERN_ERR, "required journal recovery " "suppressed and not mounted read-only"); @@ -4121,7 +4119,7 @@ no_journal: goto failed_mount_wq; } - if (DUMMY_ENCRYPTION_ENABLED(sbi) && !(sb->s_flags & MS_RDONLY) && + if (DUMMY_ENCRYPTION_ENABLED(sbi) && !sb_rdonly(sb) && !ext4_has_feature_encrypt(sb)) { ext4_set_feature_encrypt(sb); ext4_commit_super(sb, 1); @@ -4175,7 +4173,7 @@ no_journal: goto failed_mount4; } - if (ext4_setup_super(sb, es, sb->s_flags & MS_RDONLY)) + if (ext4_setup_super(sb, es, sb_rdonly(sb))) sb->s_flags |= MS_RDONLY; /* determine the minimum size of new large inodes, if present */ @@ -4263,7 +4261,7 @@ no_journal: #ifdef CONFIG_QUOTA /* Enable quota usage during mount. */ - if (ext4_has_feature_quota(sb) && !(sb->s_flags & MS_RDONLY)) { + if (ext4_has_feature_quota(sb) && !sb_rdonly(sb)) { err = ext4_enable_quotas(sb); if (err) goto failed_mount8; @@ -4586,7 +4584,7 @@ static int ext4_load_journal(struct super_block *sb, * can get read-write access to the device. */ if (ext4_has_feature_journal_needs_recovery(sb)) { - if (sb->s_flags & MS_RDONLY) { + if (sb_rdonly(sb)) { ext4_msg(sb, KERN_INFO, "INFO: recovery " "required on readonly filesystem"); if (really_read_only) { @@ -4741,8 +4739,7 @@ static void ext4_mark_recovery_complete(struct super_block *sb, if (jbd2_journal_flush(journal) < 0) goto out; - if (ext4_has_feature_journal_needs_recovery(sb) && - sb->s_flags & MS_RDONLY) { + if (ext4_has_feature_journal_needs_recovery(sb) && sb_rdonly(sb)) { ext4_clear_feature_journal_needs_recovery(sb); ext4_commit_super(sb, 1); } @@ -4798,7 +4795,7 @@ int ext4_force_commit(struct super_block *sb) { journal_t *journal; - if (sb->s_flags & MS_RDONLY) + if (sb_rdonly(sb)) return 0; journal = EXT4_SB(sb)->s_journal; @@ -4863,7 +4860,7 @@ static int ext4_freeze(struct super_block *sb) int error = 0; journal_t *journal; - if (sb->s_flags & MS_RDONLY) + if (sb_rdonly(sb)) return 0; journal = EXT4_SB(sb)->s_journal; @@ -4898,7 +4895,7 @@ out: */ static int ext4_unfreeze(struct super_block *sb) { - if ((sb->s_flags & MS_RDONLY) || ext4_forced_shutdown(EXT4_SB(sb))) + if (sb_rdonly(sb) || ext4_forced_shutdown(EXT4_SB(sb))) return 0; if (EXT4_SB(sb)->s_journal) { @@ -5036,7 +5033,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) if (*flags & MS_LAZYTIME) sb->s_flags |= MS_LAZYTIME; - if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY)) { + if ((bool)(*flags & MS_RDONLY) != sb_rdonly(sb)) { if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED) { err = -EROFS; goto restore_opts; @@ -5131,7 +5128,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) * Reinitialize lazy itable initialization thread based on * current settings */ - if ((sb->s_flags & MS_RDONLY) || !test_opt(sb, INIT_INODE_TABLE)) + if (sb_rdonly(sb) || !test_opt(sb, INIT_INODE_TABLE)) ext4_unregister_li_request(sb); else { ext4_group_t first_not_zeroed; @@ -5703,7 +5700,7 @@ static inline int ext2_feature_set_ok(struct super_block *sb) { if (ext4_has_unknown_ext2_incompat_features(sb)) return 0; - if (sb->s_flags & MS_RDONLY) + if (sb_rdonly(sb)) return 1; if (ext4_has_unknown_ext2_ro_compat_features(sb)) return 0; @@ -5734,7 +5731,7 @@ static inline int ext3_feature_set_ok(struct super_block *sb) return 0; if (!ext4_has_feature_journal(sb)) return 0; - if (sb->s_flags & MS_RDONLY) + if (sb_rdonly(sb)) return 1; if (ext4_has_unknown_ext3_ro_compat_features(sb)) return 0; diff --git a/fs/fat/fatent.c b/fs/fat/fatent.c index 1d9a8c4e9de0..48b2336692f9 100644 --- a/fs/fat/fatent.c +++ b/fs/fat/fatent.c @@ -309,7 +309,7 @@ static void mark_fsinfo_dirty(struct super_block *sb) { struct msdos_sb_info *sbi = MSDOS_SB(sb); - if (sb->s_flags & MS_RDONLY || sbi->fat_bits != 32) + if (sb_rdonly(sb) || sbi->fat_bits != 32) return; __mark_inode_dirty(sbi->fsinfo_inode, I_DIRTY_SYNC); diff --git a/fs/fat/inode.c b/fs/fat/inode.c index a2c05f2ada6d..30c52394a7ad 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -657,7 +657,7 @@ static void fat_set_state(struct super_block *sb, struct msdos_sb_info *sbi = MSDOS_SB(sb); /* do not change any thing if mounted read only */ - if ((sb->s_flags & MS_RDONLY) && !force) + if (sb_rdonly(sb) && !force) return; /* do not change state if fs was dirty */ @@ -787,7 +787,7 @@ static int fat_remount(struct super_block *sb, int *flags, char *data) /* make sure we update state on remount. */ new_rdonly = *flags & MS_RDONLY; - if (new_rdonly != (sb->s_flags & MS_RDONLY)) { + if (new_rdonly != sb_rdonly(sb)) { if (new_rdonly) fat_set_state(sb, 0, 0); else diff --git a/fs/fat/misc.c b/fs/fat/misc.c index 8a8698119ff7..acc3aa30ee54 100644 --- a/fs/fat/misc.c +++ b/fs/fat/misc.c @@ -32,7 +32,7 @@ void __fat_fs_error(struct super_block *sb, int report, const char *fmt, ...) if (opts->errors == FAT_ERRORS_PANIC) panic("FAT-fs (%s): fs panic from previous error\n", sb->s_id); - else if (opts->errors == FAT_ERRORS_RO && !(sb->s_flags & MS_RDONLY)) { + else if (opts->errors == FAT_ERRORS_RO && !sb_rdonly(sb)) { sb->s_flags |= MS_RDONLY; fat_msg(sb, KERN_ERR, "Filesystem has been set read-only"); } diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index 5e69636d4dd3..eb3ed24d85ee 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c @@ -580,7 +580,7 @@ static void iopen_go_callback(struct gfs2_glock *gl, bool remote) struct gfs2_inode *ip = gl->gl_object; struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; - if (!remote || (sdp->sd_vfs->s_flags & MS_RDONLY)) + if (!remote || sb_rdonly(sdp->sd_vfs)) return; if (gl->gl_demote_state == LM_ST_UNLOCKED && diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index e76058d34b74..49db6d0eb7c0 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -1037,7 +1037,7 @@ void gfs2_online_uevent(struct gfs2_sbd *sdp) char ro[20]; char spectator[20]; char *envp[] = { ro, spectator, NULL }; - sprintf(ro, "RDONLY=%d", (sb->s_flags & MS_RDONLY) ? 1 : 0); + sprintf(ro, "RDONLY=%d", sb_rdonly(sb)); sprintf(spectator, "SPECTATOR=%d", sdp->sd_args.ar_spectator ? 1 : 0); kobject_uevent_env(&sdp->sd_kobj, KOBJ_ONLINE, envp); } @@ -1179,7 +1179,7 @@ static int fill_super(struct super_block *sb, struct gfs2_args *args, int silent goto fail_per_node; } - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { error = gfs2_make_fs_rw(sdp); if (error) { fs_err(sdp, "can't make FS RW: %d\n", error); diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index c2ca9566b764..2d815b0fc8e8 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -452,7 +452,7 @@ static int qd_fish(struct gfs2_sbd *sdp, struct gfs2_quota_data **qdp) *qdp = NULL; - if (sdp->sd_vfs->s_flags & MS_RDONLY) + if (sb_rdonly(sdp->sd_vfs)) return 0; spin_lock(&qd_lock); diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c index 113b6095a58d..9395a3db1a60 100644 --- a/fs/gfs2/recovery.c +++ b/fs/gfs2/recovery.c @@ -522,7 +522,7 @@ void gfs2_recover_func(struct work_struct *work) if (!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) ro = 1; } else { - if (sdp->sd_vfs->s_flags & MS_RDONLY) { + if (sb_rdonly(sdp->sd_vfs)) { /* check if device itself is read-only */ ro = bdev_read_only(sdp->sd_vfs->s_bdev); if (!ro) { diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index fdedec379b78..51bf287080b4 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -893,7 +893,7 @@ restart: } spin_unlock(&sdp->sd_jindex_spin); - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { error = gfs2_make_fs_ro(sdp); if (error) gfs2_io_error(sdp); @@ -1535,7 +1535,7 @@ static void gfs2_evict_inode(struct inode *inode) return; } - if (inode->i_nlink || (sb->s_flags & MS_RDONLY)) + if (inode->i_nlink || sb_rdonly(sb)) goto out; if (test_bit(GIF_ALLOC_FAILED, &ip->i_flags)) { diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c index ca1f97ff898c..9eb9d0a1abd9 100644 --- a/fs/gfs2/sys.c +++ b/fs/gfs2/sys.c @@ -645,7 +645,7 @@ int gfs2_sys_fs_add(struct gfs2_sbd *sdp) char *envp[] = { ro, spectator, NULL }; int sysfs_frees_sdp = 0; - sprintf(ro, "RDONLY=%d", (sb->s_flags & MS_RDONLY) ? 1 : 0); + sprintf(ro, "RDONLY=%d", sb_rdonly(sb)); sprintf(spectator, "SPECTATOR=%d", sdp->sd_args.ar_spectator ? 1 : 0); sdp->sd_kobj.kset = gfs2_kset; diff --git a/fs/hfs/mdb.c b/fs/hfs/mdb.c index 482081bcdf70..894994d2c885 100644 --- a/fs/hfs/mdb.c +++ b/fs/hfs/mdb.c @@ -210,7 +210,7 @@ int hfs_mdb_get(struct super_block *sb) pr_warn("filesystem is marked locked, mounting read-only.\n"); sb->s_flags |= MS_RDONLY; } - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { /* Mark the volume uncleanly unmounted in case we crash */ attrib &= cpu_to_be16(~HFS_SB_ATTRIB_UNMNT); attrib |= cpu_to_be16(HFS_SB_ATTRIB_INCNSTNT); @@ -259,7 +259,7 @@ void hfs_mdb_commit(struct super_block *sb) { struct hfs_mdb *mdb = HFS_SB(sb)->mdb; - if (sb->s_flags & MS_RDONLY) + if (sb_rdonly(sb)) return; lock_buffer(HFS_SB(sb)->mdb_bh); @@ -334,7 +334,7 @@ void hfs_mdb_commit(struct super_block *sb) void hfs_mdb_close(struct super_block *sb) { /* update volume attributes */ - if (sb->s_flags & MS_RDONLY) + if (sb_rdonly(sb)) return; HFS_SB(sb)->mdb->drAtrb |= cpu_to_be16(HFS_SB_ATTRIB_UNMNT); HFS_SB(sb)->mdb->drAtrb &= cpu_to_be16(~HFS_SB_ATTRIB_INCNSTNT); diff --git a/fs/hfs/super.c b/fs/hfs/super.c index bf6304a350a6..7e0d65e9586c 100644 --- a/fs/hfs/super.c +++ b/fs/hfs/super.c @@ -71,7 +71,7 @@ void hfs_mark_mdb_dirty(struct super_block *sb) struct hfs_sb_info *sbi = HFS_SB(sb); unsigned long delay; - if (sb->s_flags & MS_RDONLY) + if (sb_rdonly(sb)) return; spin_lock(&sbi->work_lock); @@ -115,7 +115,7 @@ static int hfs_remount(struct super_block *sb, int *flags, char *data) { sync_filesystem(sb); *flags |= MS_NODIRATIME; - if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) + if ((bool)(*flags & MS_RDONLY) == sb_rdonly(sb)) return 0; if (!(*flags & MS_RDONLY)) { if (!(HFS_SB(sb)->mdb->drAtrb & cpu_to_be16(HFS_SB_ATTRIB_UNMNT))) { diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 67aedf4c2e7c..e5bb2de2262a 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c @@ -264,7 +264,7 @@ void hfsplus_mark_mdb_dirty(struct super_block *sb) struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); unsigned long delay; - if (sb->s_flags & MS_RDONLY) + if (sb_rdonly(sb)) return; spin_lock(&sbi->work_lock); @@ -284,7 +284,7 @@ static void hfsplus_put_super(struct super_block *sb) cancel_delayed_work_sync(&sbi->sync_work); - if (!(sb->s_flags & MS_RDONLY) && sbi->s_vhdr) { + if (!sb_rdonly(sb) && sbi->s_vhdr) { struct hfsplus_vh *vhdr = sbi->s_vhdr; vhdr->modify_date = hfsp_now2mt(); @@ -329,7 +329,7 @@ static int hfsplus_statfs(struct dentry *dentry, struct kstatfs *buf) static int hfsplus_remount(struct super_block *sb, int *flags, char *data) { sync_filesystem(sb); - if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) + if ((bool)(*flags & MS_RDONLY) == sb_rdonly(sb)) return 0; if (!(*flags & MS_RDONLY)) { struct hfsplus_vh *vhdr = HFSPLUS_SB(sb)->s_vhdr; @@ -462,7 +462,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) pr_warn("Filesystem is marked locked, mounting read-only.\n"); sb->s_flags |= MS_RDONLY; } else if ((vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) && - !(sb->s_flags & MS_RDONLY)) { + !sb_rdonly(sb)) { pr_warn("write access to a journaled filesystem is not supported, use the force option at your own risk, mounting read-only.\n"); sb->s_flags |= MS_RDONLY; } @@ -535,7 +535,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) } else hfs_find_exit(&fd); - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { /* * H+LX == hfsplusutils, H+Lx == this driver, H+lx is unused * all three are registered with Apple for our use diff --git a/fs/hpfs/alloc.c b/fs/hpfs/alloc.c index d6a4b55d2ab0..098bf0f4f386 100644 --- a/fs/hpfs/alloc.c +++ b/fs/hpfs/alloc.c @@ -538,7 +538,7 @@ int hpfs_trim_fs(struct super_block *s, u64 start, u64 end, u64 minlen, unsigned return 0; if (start < sbi->sb_dirband_start + sbi->sb_dirband_size && end > sbi->sb_dirband_start) { hpfs_lock(s); - if (s->s_flags & MS_RDONLY) { + if (sb_rdonly(s)) { err = -EROFS; goto unlock_1; } @@ -559,7 +559,7 @@ unlock_1: end_bmp = (end + 0x3fff) >> 14; while (start_bmp < end_bmp && !err) { hpfs_lock(s); - if (s->s_flags & MS_RDONLY) { + if (sb_rdonly(s)) { err = -EROFS; goto unlock_2; } diff --git a/fs/hpfs/dir.c b/fs/hpfs/dir.c index 7b9150c2e75c..fa6bbb4f509f 100644 --- a/fs/hpfs/dir.c +++ b/fs/hpfs/dir.c @@ -264,7 +264,7 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, unsigned in hpfs_result = hpfs_i(result); if (!de->directory) hpfs_result->i_parent_dir = dir->i_ino; - if (de->has_acl || de->has_xtd_perm) if (!(dir->i_sb->s_flags & MS_RDONLY)) { + if (de->has_acl || de->has_xtd_perm) if (!sb_rdonly(dir->i_sb)) { hpfs_error(result->i_sb, "ACLs or XPERM found. This is probably HPFS386. This driver doesn't support it now. Send me some info on these structures"); goto bail1; } diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index 82067ca22f2b..1516fb4e28f4 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c @@ -21,7 +21,7 @@ static void mark_dirty(struct super_block *s, int remount) { - if (hpfs_sb(s)->sb_chkdsk && (remount || !(s->s_flags & MS_RDONLY))) { + if (hpfs_sb(s)->sb_chkdsk && (remount || !sb_rdonly(s))) { struct buffer_head *bh; struct hpfs_spare_block *sb; if ((sb = hpfs_map_sector(s, 17, &bh, 0))) { @@ -41,7 +41,7 @@ static void unmark_dirty(struct super_block *s) { struct buffer_head *bh; struct hpfs_spare_block *sb; - if (s->s_flags & MS_RDONLY) return; + if (sb_rdonly(s)) return; sync_blockdev(s->s_bdev); if ((sb = hpfs_map_sector(s, 17, &bh, 0))) { sb->dirty = hpfs_sb(s)->sb_chkdsk > 1 - hpfs_sb(s)->sb_was_error; @@ -73,14 +73,14 @@ void hpfs_error(struct super_block *s, const char *fmt, ...) mark_dirty(s, 0); panic("HPFS panic"); } else if (hpfs_sb(s)->sb_err == 1) { - if (s->s_flags & MS_RDONLY) + if (sb_rdonly(s)) pr_cont("; already mounted read-only\n"); else { pr_cont("; remounting read-only\n"); mark_dirty(s, 0); s->s_flags |= MS_RDONLY; } - } else if (s->s_flags & MS_RDONLY) + } else if (sb_rdonly(s)) pr_cont("; going on - but anything won't be destroyed because it's read-only\n"); else pr_cont("; corrupted filesystem mounted read/write - your computer will explode within 20 seconds ... but you wanted it so!\n"); @@ -607,8 +607,7 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent) } /* Check version */ - if (!(s->s_flags & MS_RDONLY) && - superblock->funcversion != 2 && superblock->funcversion != 3) { + if (!sb_rdonly(s) && superblock->funcversion != 2 && superblock->funcversion != 3) { pr_err("Bad version %d,%d. Mount readonly to go around\n", (int)superblock->version, (int)superblock->funcversion); pr_err("please try recent version of HPFS driver at http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi and if it still can't understand this format, contact author - mikulas@artax.karlin.mff.cuni.cz\n"); @@ -666,7 +665,7 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent) hpfs_error(s, "improperly stopped"); } - if (!(s->s_flags & MS_RDONLY)) { + if (!sb_rdonly(s)) { spareblock->dirty = 1; spareblock->old_wrote = 0; mark_buffer_dirty(bh2); diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 8cf898a59730..2f6239c7073a 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -733,7 +733,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent) root_found: /* We don't support read-write mounts */ - if (!(s->s_flags & MS_RDONLY)) { + if (!sb_rdonly(s)) { error = -EACCES; goto out_freebh; } diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index 76fa814df3d1..e96c6b05e43e 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -395,14 +395,14 @@ int jffs2_do_remount_fs(struct super_block *sb, int *flags, char *data) { struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); - if (c->flags & JFFS2_SB_FLAG_RO && !(sb->s_flags & MS_RDONLY)) + if (c->flags & JFFS2_SB_FLAG_RO && !sb_rdonly(sb)) return -EROFS; /* We stop if it was running, then restart if it needs to. This also catches the case where it was stopped and this is just a remount to restart it. Flush the writebuffer, if neccecary, else we loose it */ - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { jffs2_stop_garbage_collect_thread(c); mutex_lock(&c->alloc_sem); jffs2_flush_wbuf_pad(c); @@ -590,7 +590,7 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent) sb->s_blocksize = PAGE_SIZE; sb->s_blocksize_bits = PAGE_SHIFT; sb->s_magic = JFFS2_SUPER_MAGIC; - if (!(sb->s_flags & MS_RDONLY)) + if (!sb_rdonly(sb)) jffs2_start_garbage_collect_thread(c); return 0; diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 5ef21f4c4c77..153f1c6eb169 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c @@ -342,7 +342,7 @@ static void jffs2_put_super (struct super_block *sb) static void jffs2_kill_sb(struct super_block *sb) { struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); - if (!(sb->s_flags & MS_RDONLY)) + if (!sb_rdonly(sb)) jffs2_stop_garbage_collect_thread(c); kill_mtd_super(sb); kfree(c); diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index b25d28a21212..707cbe72e115 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -1162,7 +1162,7 @@ static void delayed_wbuf_sync(struct work_struct *work) struct jffs2_sb_info *c = work_to_sb(work); struct super_block *sb = OFNI_BS_2SFFJ(c); - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { jffs2_dbg(1, "%s()\n", __func__); jffs2_flush_wbuf_gc(c, 0); } @@ -1173,7 +1173,7 @@ void jffs2_dirty_trigger(struct jffs2_sb_info *c) struct super_block *sb = OFNI_BS_2SFFJ(c); unsigned long delay; - if (sb->s_flags & MS_RDONLY) + if (sb_rdonly(sb)) return; delay = msecs_to_jiffies(dirty_writeback_interval * 10); diff --git a/fs/jfs/jfs_mount.c b/fs/jfs/jfs_mount.c index 9895595fd2f2..d8658607bf46 100644 --- a/fs/jfs/jfs_mount.c +++ b/fs/jfs/jfs_mount.c @@ -362,7 +362,7 @@ static int chkSuper(struct super_block *sb) /* validate fs state */ if (j_sb->s_state != cpu_to_le32(FM_CLEAN) && - !(sb->s_flags & MS_RDONLY)) { + !sb_rdonly(sb)) { jfs_err("jfs_mount: Mount Failure: File System Dirty."); rc = -EINVAL; goto out; diff --git a/fs/jfs/super.c b/fs/jfs/super.c index e8aad7d87b8c..8612a7db2a04 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c @@ -76,7 +76,7 @@ static void jfs_handle_error(struct super_block *sb) { struct jfs_sb_info *sbi = JFS_SBI(sb); - if (sb->s_flags & MS_RDONLY) + if (sb_rdonly(sb)) return; updateSuper(sb, FM_DIRTY); @@ -468,7 +468,7 @@ static int jfs_remount(struct super_block *sb, int *flags, char *data) return -EINVAL; if (newLVSize) { - if (sb->s_flags & MS_RDONLY) { + if (sb_rdonly(sb)) { pr_err("JFS: resize requires volume to be mounted read-write\n"); return -EROFS; } @@ -477,7 +477,7 @@ static int jfs_remount(struct super_block *sb, int *flags, char *data) return rc; } - if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) { + if (sb_rdonly(sb) && !(*flags & MS_RDONLY)) { /* * Invalidate any previously read metadata. fsck may have * changed the on-disk data since we mounted r/o @@ -493,7 +493,7 @@ static int jfs_remount(struct super_block *sb, int *flags, char *data) dquot_resume(sb, -1); return ret; } - if ((!(sb->s_flags & MS_RDONLY)) && (*flags & MS_RDONLY)) { + if (!sb_rdonly(sb) && (*flags & MS_RDONLY)) { rc = dquot_suspend(sb, -1); if (rc < 0) return rc; @@ -502,7 +502,7 @@ static int jfs_remount(struct super_block *sb, int *flags, char *data) return rc; } if ((JFS_SBI(sb)->flag & JFS_NOINTEGRITY) != (flag & JFS_NOINTEGRITY)) - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { rc = jfs_umount_rw(sb); if (rc) return rc; @@ -592,7 +592,7 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent) jfs_err("jfs_mount failed w/return code = %d", rc); goto out_mount_failed; } - if (sb->s_flags & MS_RDONLY) + if (sb_rdonly(sb)) sbi->log = NULL; else { rc = jfs_mount_rw(sb, 0); @@ -658,7 +658,7 @@ static int jfs_freeze(struct super_block *sb) struct jfs_log *log = sbi->log; int rc = 0; - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { txQuiesce(sb); rc = lmLogShutdown(log); if (rc) { @@ -688,7 +688,7 @@ static int jfs_unfreeze(struct super_block *sb) struct jfs_log *log = sbi->log; int rc = 0; - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { rc = updateSuper(sb, FM_MOUNT); if (rc) { jfs_error(sb, "updateSuper failed\n"); diff --git a/fs/minix/inode.c b/fs/minix/inode.c index 6ac76b0434e9..b6829d679643 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c @@ -42,7 +42,7 @@ static void minix_put_super(struct super_block *sb) int i; struct minix_sb_info *sbi = minix_sb(sb); - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { if (sbi->s_version != MINIX_V3) /* s_state is now out from V3 sb */ sbi->s_ms->s_state = sbi->s_mount_state; mark_buffer_dirty(sbi->s_sbh); @@ -125,7 +125,7 @@ static int minix_remount (struct super_block * sb, int * flags, char * data) sync_filesystem(sb); ms = sbi->s_ms; - if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) + if ((bool)(*flags & MS_RDONLY) == sb_rdonly(sb)) return 0; if (*flags & MS_RDONLY) { if (ms->s_state & MINIX_VALID_FS || @@ -293,7 +293,7 @@ static int minix_fill_super(struct super_block *s, void *data, int silent) if (!s->s_root) goto out_no_root; - if (!(s->s_flags & MS_RDONLY)) { + if (!sb_rdonly(s)) { if (sbi->s_version != MINIX_V3) /* s_state is now out from V3 sb */ ms->s_state &= ~MINIX_VALID_FS; mark_buffer_dirty(bh); diff --git a/fs/namei.c b/fs/namei.c index 88fd38d1e3e7..bf03a62e1f5d 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -447,8 +447,7 @@ static int sb_permission(struct super_block *sb, struct inode *inode, int mask) umode_t mode = inode->i_mode; /* Nobody gets write access to a read-only fs. */ - if ((sb->s_flags & MS_RDONLY) && - (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) + if (sb_rdonly(sb) && (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) return -EROFS; } return 0; diff --git a/fs/namespace.c b/fs/namespace.c index f8893dc6a989..e42c9abfeaa8 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -275,7 +275,7 @@ int __mnt_is_readonly(struct vfsmount *mnt) { if (mnt->mnt_flags & MNT_READONLY) return 1; - if (mnt->mnt_sb->s_flags & MS_RDONLY) + if (sb_rdonly(mnt->mnt_sb)) return 1; return 0; } @@ -1534,7 +1534,7 @@ static int do_umount(struct mount *mnt, int flags) if (!capable(CAP_SYS_ADMIN)) return -EPERM; down_write(&sb->s_umount); - if (!(sb->s_flags & MS_RDONLY)) + if (!sb_rdonly(sb)) retval = do_remount_sb(sb, MS_RDONLY, NULL, 0); up_write(&sb->s_umount); return retval; @@ -3300,7 +3300,7 @@ static bool mnt_already_visible(struct mnt_namespace *ns, struct vfsmount *new, mnt_flags = mnt->mnt.mnt_flags; /* Don't miss readonly hidden in the superblock flags */ - if (mnt->mnt.mnt_sb->s_flags & MS_RDONLY) + if (sb_rdonly(mnt->mnt.mnt_sb)) mnt_flags |= MNT_LOCK_READONLY; /* Verify the mount flags are equal to or more permissive diff --git a/fs/nfs/super.c b/fs/nfs/super.c index d828ef88e7db..65d247a68b07 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -812,7 +812,7 @@ int nfs_show_stats(struct seq_file *m, struct dentry *root) * Display all mount option settings */ seq_printf(m, "\n\topts:\t"); - seq_puts(m, root->d_sb->s_flags & MS_RDONLY ? "ro" : "rw"); + seq_puts(m, sb_rdonly(root->d_sb) ? "ro" : "rw"); seq_puts(m, root->d_sb->s_flags & MS_SYNCHRONOUS ? ",sync" : ""); seq_puts(m, root->d_sb->s_flags & MS_NOATIME ? ",noatime" : ""); seq_puts(m, root->d_sb->s_flags & MS_NODIRATIME ? ",nodiratime" : ""); diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 7ffe71a8dfb9..6a612d832e7d 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -174,7 +174,7 @@ static int nilfs_writepages(struct address_space *mapping, struct inode *inode = mapping->host; int err = 0; - if (inode->i_sb->s_flags & MS_RDONLY) { + if (sb_rdonly(inode->i_sb)) { nilfs_clear_dirty_pages(mapping, false); return -EROFS; } @@ -191,7 +191,7 @@ static int nilfs_writepage(struct page *page, struct writeback_control *wbc) struct inode *inode = page->mapping->host; int err; - if (inode->i_sb->s_flags & MS_RDONLY) { + if (sb_rdonly(inode->i_sb)) { /* * It means that filesystem was remounted in read-only * mode because of error or metadata corruption. But we diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c index 98835ed6bef4..c6bc1033e7d2 100644 --- a/fs/nilfs2/mdt.c +++ b/fs/nilfs2/mdt.c @@ -413,7 +413,7 @@ nilfs_mdt_write_page(struct page *page, struct writeback_control *wbc) struct super_block *sb; int err = 0; - if (inode && (inode->i_sb->s_flags & MS_RDONLY)) { + if (inode && sb_rdonly(inode->i_sb)) { /* * It means that filesystem was remounted in read-only * mode because of error or metadata corruption. But we diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 926682981d61..4fc018dfcfae 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -136,7 +136,7 @@ void __nilfs_error(struct super_block *sb, const char *function, va_end(args); - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { nilfs_set_error(sb); if (nilfs_test_opt(nilfs, ERRORS_RO)) { @@ -478,7 +478,7 @@ static void nilfs_put_super(struct super_block *sb) nilfs_detach_log_writer(sb); - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { down_write(&nilfs->ns_sem); nilfs_cleanup_super(sb); up_write(&nilfs->ns_sem); @@ -578,7 +578,7 @@ static int nilfs_freeze(struct super_block *sb) struct the_nilfs *nilfs = sb->s_fs_info; int err; - if (sb->s_flags & MS_RDONLY) + if (sb_rdonly(sb)) return 0; /* Mark super block clean */ @@ -592,7 +592,7 @@ static int nilfs_unfreeze(struct super_block *sb) { struct the_nilfs *nilfs = sb->s_fs_info; - if (sb->s_flags & MS_RDONLY) + if (sb_rdonly(sb)) return 0; down_write(&nilfs->ns_sem); @@ -898,7 +898,7 @@ int nilfs_check_feature_compatibility(struct super_block *sb, } features = le64_to_cpu(sbp->s_feature_compat_ro) & ~NILFS_FEATURE_COMPAT_RO_SUPP; - if (!(sb->s_flags & MS_RDONLY) && features) { + if (!sb_rdonly(sb) && features) { nilfs_msg(sb, KERN_ERR, "couldn't mount RDWR because of unsupported optional features (%llx)", (unsigned long long)features); @@ -1083,7 +1083,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent) goto failed_unload; } - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { err = nilfs_attach_log_writer(sb, fsroot); if (err) goto failed_checkpoint; @@ -1095,7 +1095,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent) nilfs_put_root(fsroot); - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { down_write(&nilfs->ns_sem); nilfs_setup_super(sb, true); up_write(&nilfs->ns_sem); @@ -1144,7 +1144,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) goto restore_opts; } - if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) + if ((bool)(*flags & MS_RDONLY) == sb_rdonly(sb)) goto out; if (*flags & MS_RDONLY) { /* Shutting down log writer */ @@ -1338,8 +1338,7 @@ nilfs_mount(struct file_system_type *fs_type, int flags, if ((flags ^ s->s_flags) & MS_RDONLY) { nilfs_msg(s, KERN_ERR, "the device already has a %s mount.", - (s->s_flags & MS_RDONLY) ? - "read-only" : "read/write"); + sb_rdonly(s) ? "read-only" : "read/write"); err = -EBUSY; goto failed_super; } diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index ecb49870a680..3f70f041dbe9 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c @@ -487,7 +487,7 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt) * When remounting read-only, mark the volume clean if no volume errors * have occurred. */ - if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) { + if (sb_rdonly(sb) && !(*flags & MS_RDONLY)) { static const char *es = ". Cannot remount read-write."; /* Remounting read-write. */ @@ -548,7 +548,7 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt) NVolSetErrors(vol); return -EROFS; } - } else if (!(sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY)) { + } else if (!sb_rdonly(sb) && (*flags & MS_RDONLY)) { /* Remounting read-only. */ if (!NVolErrors(vol)) { if (ntfs_clear_volume_flags(vol, VOLUME_IS_DIRTY)) @@ -732,7 +732,7 @@ hotfix_primary_boot_sector: * on a large sector device contains the whole boot loader or * just the first 512 bytes). */ - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { ntfs_warning(sb, "Hot-fix: Recovering invalid primary " "boot sector from backup copy."); memcpy(bh_primary->b_data, bh_backup->b_data, @@ -1789,7 +1789,7 @@ static bool load_system_files(ntfs_volume *vol) static const char *es3 = ". Run ntfsfix and/or chkdsk."; /* If a read-write mount, convert it to a read-only mount. */ - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { if (!(vol->on_errors & (ON_ERRORS_REMOUNT_RO | ON_ERRORS_CONTINUE))) { ntfs_error(sb, "%s and neither on_errors=" @@ -1928,7 +1928,7 @@ get_ctx_vol_failed: (unsigned)le16_to_cpu(vol->vol_flags)); } /* If a read-write mount, convert it to a read-only mount. */ - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { if (!(vol->on_errors & (ON_ERRORS_REMOUNT_RO | ON_ERRORS_CONTINUE))) { ntfs_error(sb, "%s and neither on_errors=" @@ -1961,7 +1961,7 @@ get_ctx_vol_failed: es1 = !vol->logfile_ino ? es1a : es1b; /* If a read-write mount, convert it to a read-only mount. */ - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { if (!(vol->on_errors & (ON_ERRORS_REMOUNT_RO | ON_ERRORS_CONTINUE))) { ntfs_error(sb, "%s and neither on_errors=" @@ -2010,7 +2010,7 @@ get_ctx_vol_failed: es1 = err < 0 ? es1a : es1b; /* If a read-write mount, convert it to a read-only mount. */ - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { if (!(vol->on_errors & (ON_ERRORS_REMOUNT_RO | ON_ERRORS_CONTINUE))) { ntfs_error(sb, "%s and neither on_errors=" @@ -2028,8 +2028,7 @@ get_ctx_vol_failed: NVolSetErrors(vol); } /* If (still) a read-write mount, mark the volume dirty. */ - if (!(sb->s_flags & MS_RDONLY) && - ntfs_set_volume_flags(vol, VOLUME_IS_DIRTY)) { + if (!sb_rdonly(sb) && ntfs_set_volume_flags(vol, VOLUME_IS_DIRTY)) { static const char *es1 = "Failed to set dirty bit in volume " "information flags"; static const char *es2 = ". Run chkdsk."; @@ -2075,8 +2074,7 @@ get_ctx_vol_failed: } #endif /* If (still) a read-write mount, empty the logfile. */ - if (!(sb->s_flags & MS_RDONLY) && - !ntfs_empty_logfile(vol->logfile_ino)) { + if (!sb_rdonly(sb) && !ntfs_empty_logfile(vol->logfile_ino)) { static const char *es1 = "Failed to empty $LogFile"; static const char *es2 = ". Mount in Windows."; @@ -2121,7 +2119,7 @@ get_ctx_vol_failed: static const char *es2 = ". Run chkdsk."; /* If a read-write mount, convert it to a read-only mount. */ - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { if (!(vol->on_errors & (ON_ERRORS_REMOUNT_RO | ON_ERRORS_CONTINUE))) { ntfs_error(sb, "%s and neither on_errors=" @@ -2139,8 +2137,7 @@ get_ctx_vol_failed: NVolSetErrors(vol); } /* If (still) a read-write mount, mark the quotas out of date. */ - if (!(sb->s_flags & MS_RDONLY) && - !ntfs_mark_quotas_out_of_date(vol)) { + if (!sb_rdonly(sb) && !ntfs_mark_quotas_out_of_date(vol)) { static const char *es1 = "Failed to mark quotas out of date"; static const char *es2 = ". Run chkdsk."; @@ -2165,7 +2162,7 @@ get_ctx_vol_failed: static const char *es2 = ". Run chkdsk."; /* If a read-write mount, convert it to a read-only mount. */ - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { if (!(vol->on_errors & (ON_ERRORS_REMOUNT_RO | ON_ERRORS_CONTINUE))) { ntfs_error(sb, "%s and neither on_errors=" @@ -2183,7 +2180,7 @@ get_ctx_vol_failed: NVolSetErrors(vol); } /* If (still) a read-write mount, stamp the transaction log. */ - if (!(sb->s_flags & MS_RDONLY) && !ntfs_stamp_usnjrnl(vol)) { + if (!sb_rdonly(sb) && !ntfs_stamp_usnjrnl(vol)) { static const char *es1 = "Failed to stamp transaction log " "($UsnJrnl)"; static const char *es2 = ". Run chkdsk."; @@ -2314,7 +2311,7 @@ static void ntfs_put_super(struct super_block *sb) * If a read-write mount and no volume errors have occurred, mark the * volume clean. Also, re-commit all affected inodes. */ - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { if (!NVolErrors(vol)) { if (ntfs_clear_volume_flags(vol, VOLUME_IS_DIRTY)) ntfs_warning(sb, "Failed to clear dirty bit " diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 83005f486451..1cf662ad377f 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -675,7 +675,7 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data) } /* We're going to/from readonly mode. */ - if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY)) { + if ((bool)(*flags & MS_RDONLY) != sb_rdonly(sb)) { /* Disable quota accounting before remounting RO */ if (*flags & MS_RDONLY) { ret = ocfs2_susp_quotas(osb, 0); @@ -1063,7 +1063,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) /* Hard readonly mode only if: bdev_read_only, MS_RDONLY, * heartbeat=none */ if (bdev_read_only(sb->s_bdev)) { - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { status = -EACCES; mlog(ML_ERROR, "Readonly device detected but readonly " "mount was not specified.\n"); @@ -1098,7 +1098,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) } if (!ocfs2_is_hard_readonly(osb)) { - if (sb->s_flags & MS_RDONLY) + if (sb_rdonly(sb)) ocfs2_set_ro_flag(osb, 0); } @@ -1179,7 +1179,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) /* Now we can initialize quotas because we can afford to wait * for cluster locks recovery now. That also means that truncation * log recovery can happen but that waits for proper quota setup */ - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { status = ocfs2_enable_quotas(osb); if (status < 0) { /* We have to err-out specially here because @@ -2180,8 +2180,7 @@ static int ocfs2_initialize_super(struct super_block *sb, status = -EINVAL; goto bail; } - if (!(osb->sb->s_flags & MS_RDONLY) && - (i = OCFS2_HAS_RO_COMPAT_FEATURE(osb->sb, ~OCFS2_FEATURE_RO_COMPAT_SUPP))) { + if (!sb_rdonly(osb->sb) && (i = OCFS2_HAS_RO_COMPAT_FEATURE(osb->sb, ~OCFS2_FEATURE_RO_COMPAT_SUPP))) { mlog(ML_ERROR, "couldn't mount RDWR because of " "unsupported optional features (%x).\n", i); status = -EINVAL; @@ -2568,9 +2567,7 @@ static int ocfs2_handle_error(struct super_block *sb) rv = -EIO; } else { /* default option */ rv = -EROFS; - if (sb->s_flags & MS_RDONLY && - (ocfs2_is_soft_readonly(osb) || - ocfs2_is_hard_readonly(osb))) + if (sb_rdonly(sb) && (ocfs2_is_soft_readonly(osb) || ocfs2_is_hard_readonly(osb))) return rv; pr_crit("OCFS2: File system is now read-only.\n"); diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 44dc2d6ffe0f..22ee2a9ee784 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -869,7 +869,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) goto out_free_config; /* Upper fs should not be r/o */ - if (upperpath.mnt->mnt_sb->s_flags & MS_RDONLY) { + if (sb_rdonly(upperpath.mnt->mnt_sb)) { pr_err("overlayfs: upper fs is r/o, try multi-lower layers mount\n"); err = -EINVAL; goto out_put_upperpath; diff --git a/fs/proc_namespace.c b/fs/proc_namespace.c index b5713fefb4c1..99dff222fe67 100644 --- a/fs/proc_namespace.c +++ b/fs/proc_namespace.c @@ -178,7 +178,7 @@ static int show_mountinfo(struct seq_file *m, struct vfsmount *mnt) } else { mangle(m, r->mnt_devname ? r->mnt_devname : "none"); } - seq_puts(m, sb->s_flags & MS_RDONLY ? " ro" : " rw"); + seq_puts(m, sb_rdonly(sb) ? " ro" : " rw"); err = show_sb_opts(m, sb); if (err) goto out; diff --git a/fs/quota/quota.c b/fs/quota/quota.c index 07e08c7d05ca..a9c5dfe6b83e 100644 --- a/fs/quota/quota.c +++ b/fs/quota/quota.c @@ -753,7 +753,7 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, case Q_XGETNEXTQUOTA: return quota_getnextxquota(sb, type, id, addr); case Q_XQUOTASYNC: - if (sb->s_flags & MS_RDONLY) + if (sb_rdonly(sb)) return -EROFS; /* XFS quotas are fully coherent now, making this call a noop */ return 0; diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 873fc04e9403..11a48affa882 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -1776,7 +1776,7 @@ int reiserfs_write_inode(struct inode *inode, struct writeback_control *wbc) struct reiserfs_transaction_handle th; int jbegin_count = 1; - if (inode->i_sb->s_flags & MS_RDONLY) + if (sb_rdonly(inode->i_sb)) return -EROFS; /* * memory pressure can sometimes initiate write_inode calls with diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index a11d773e5ff3..e47da919f443 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -1918,7 +1918,7 @@ static int do_journal_release(struct reiserfs_transaction_handle *th, * we only want to flush out transactions if we were * called with error == 0 */ - if (!error && !(sb->s_flags & MS_RDONLY)) { + if (!error && !sb_rdonly(sb)) { /* end the current trans */ BUG_ON(!th->t_trans_id); do_journal_end(th, FLUSH_ALL); diff --git a/fs/reiserfs/prints.c b/fs/reiserfs/prints.c index 4f3f928076f3..64f49cafbc5b 100644 --- a/fs/reiserfs/prints.c +++ b/fs/reiserfs/prints.c @@ -386,7 +386,7 @@ void __reiserfs_error(struct super_block *sb, const char *id, printk(KERN_CRIT "REISERFS error (device %s): %s: %s\n", sb->s_id, function, error_buf); - if (sb->s_flags & MS_RDONLY) + if (sb_rdonly(sb)) return; reiserfs_info(sb, "Remounting filesystem read-only\n"); diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 306e4e9d172d..5464ec517702 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -121,7 +121,7 @@ void reiserfs_schedule_old_flush(struct super_block *s) * Avoid scheduling flush when sb is being shut down. It can race * with journal shutdown and free still queued delayed work. */ - if (s->s_flags & MS_RDONLY || !(s->s_flags & MS_ACTIVE)) + if (sb_rdonly(s) || !(s->s_flags & MS_ACTIVE)) return; spin_lock(&sbi->old_work_lock); @@ -151,7 +151,7 @@ static int reiserfs_freeze(struct super_block *s) reiserfs_cancel_old_flush(s); reiserfs_write_lock(s); - if (!(s->s_flags & MS_RDONLY)) { + if (!sb_rdonly(s)) { int err = journal_begin(&th, s, 1); if (err) { reiserfs_block_writes(&th); @@ -599,7 +599,7 @@ static void reiserfs_put_super(struct super_block *s) * change file system state to current state if it was mounted * with read-write permissions */ - if (!(s->s_flags & MS_RDONLY)) { + if (!sb_rdonly(s)) { if (!journal_begin(&th, s, 10)) { reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); @@ -700,7 +700,7 @@ static void reiserfs_dirty_inode(struct inode *inode, int flags) int err = 0; - if (inode->i_sb->s_flags & MS_RDONLY) { + if (sb_rdonly(inode->i_sb)) { reiserfs_warning(inode->i_sb, "clm-6006", "writing inode %lu on readonly FS", inode->i_ino); @@ -1525,7 +1525,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) reiserfs_write_unlock(s); reiserfs_xattr_init(s, *mount_flags); /* remount read-only */ - if (s->s_flags & MS_RDONLY) + if (sb_rdonly(s)) /* it is read-only already */ goto out_ok_unlocked; @@ -1551,7 +1551,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) journal_mark_dirty(&th, SB_BUFFER_WITH_SB(s)); } else { /* remount read-write */ - if (!(s->s_flags & MS_RDONLY)) { + if (!sb_rdonly(s)) { reiserfs_write_unlock(s); reiserfs_xattr_init(s, *mount_flags); goto out_ok_unlocked; /* We are read-write already */ @@ -1855,7 +1855,7 @@ static int what_hash(struct super_block *s) * the super */ if (code != UNSET_HASH && - !(s->s_flags & MS_RDONLY) && + !sb_rdonly(s) && code != sb_hash_function_code(SB_DISK_SUPER_BLOCK(s))) { set_sb_hash_function_code(SB_DISK_SUPER_BLOCK(s), code); } @@ -2052,7 +2052,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) if (replay_only(s)) goto error_unlocked; - if (bdev_read_only(s->s_bdev) && !(s->s_flags & MS_RDONLY)) { + if (bdev_read_only(s->s_bdev) && !sb_rdonly(s)) { SWARN(silent, s, "clm-7000", "Detected readonly device, marking FS readonly"); s->s_flags |= MS_RDONLY; @@ -2101,7 +2101,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) else set_bit(REISERFS_3_6, &sbi->s_properties); - if (!(s->s_flags & MS_RDONLY)) { + if (!sb_rdonly(s)) { errval = journal_begin(&th, s, 1); if (errval) { diff --git a/fs/super.c b/fs/super.c index 6bc3352adcf3..7321958d81d8 100644 --- a/fs/super.c +++ b/fs/super.c @@ -820,7 +820,7 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force) return -EACCES; #endif - remount_ro = (flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY); + remount_ro = (flags & MS_RDONLY) && !sb_rdonly(sb); if (remount_ro) { if (!hlist_empty(&sb->s_pins)) { @@ -831,7 +831,7 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force) return 0; if (sb->s_writers.frozen != SB_UNFROZEN) return -EBUSY; - remount_ro = (flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY); + remount_ro = (flags & MS_RDONLY) && !sb_rdonly(sb); } } shrink_dcache_sb(sb); @@ -893,7 +893,7 @@ static void do_emergency_remount(struct work_struct *work) spin_unlock(&sb_lock); down_write(&sb->s_umount); if (sb->s_root && sb->s_bdev && (sb->s_flags & MS_BORN) && - !(sb->s_flags & MS_RDONLY)) { + !sb_rdonly(sb)) { /* * What lock protects sb->s_flags?? */ @@ -1439,7 +1439,7 @@ int freeze_super(struct super_block *sb) return 0; /* sic - it's "nothing to do" */ } - if (sb->s_flags & MS_RDONLY) { + if (sb_rdonly(sb)) { /* Nothing to do really... */ sb->s_writers.frozen = SB_FREEZE_COMPLETE; up_write(&sb->s_umount); @@ -1502,7 +1502,7 @@ int thaw_super(struct super_block *sb) return -EINVAL; } - if (sb->s_flags & MS_RDONLY) { + if (sb_rdonly(sb)) { sb->s_writers.frozen = SB_UNFROZEN; goto out; } diff --git a/fs/sync.c b/fs/sync.c index 2a54c1f22035..7ea61b0e2a31 100644 --- a/fs/sync.c +++ b/fs/sync.c @@ -57,7 +57,7 @@ int sync_filesystem(struct super_block *sb) /* * No point in syncing out anything if the filesystem is read-only. */ - if (sb->s_flags & MS_RDONLY) + if (sb_rdonly(sb)) return 0; ret = __sync_filesystem(sb, 0); @@ -69,13 +69,13 @@ EXPORT_SYMBOL(sync_filesystem); static void sync_inodes_one_sb(struct super_block *sb, void *arg) { - if (!(sb->s_flags & MS_RDONLY)) + if (!sb_rdonly(sb)) sync_inodes_sb(sb); } static void sync_fs_one_sb(struct super_block *sb, void *arg) { - if (!(sb->s_flags & MS_RDONLY) && sb->s_op->sync_fs) + if (!sb_rdonly(sb) && sb->s_op->sync_fs) sb->s_op->sync_fs(sb, *(int *)arg); } diff --git a/fs/sysv/balloc.c b/fs/sysv/balloc.c index 921c053fc052..862c1f74a583 100644 --- a/fs/sysv/balloc.c +++ b/fs/sysv/balloc.c @@ -231,7 +231,7 @@ trust_sb: Ecount: printk("sysv_count_free_blocks: free block count was %d, " "correcting to %d\n", sb_count, count); - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { *sbi->s_free_blocks = cpu_to_fs32(sbi, count); dirty_sb(sb); } diff --git a/fs/sysv/ialloc.c b/fs/sysv/ialloc.c index 53f1b78996dd..eb963fbb7903 100644 --- a/fs/sysv/ialloc.c +++ b/fs/sysv/ialloc.c @@ -220,7 +220,7 @@ Einval: printk("sysv_count_free_inodes: " "free inode count was %d, correcting to %d\n", sb_count, count); - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { *sbi->s_sb_total_free_inodes = cpu_to_fs16(SYSV_SB(sb), count); dirty_sb(sb); } diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index 858fb72f9e0f..1c8bf9453a71 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c @@ -70,7 +70,7 @@ static void sysv_put_super(struct super_block *sb) { struct sysv_sb_info *sbi = SYSV_SB(sb); - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { /* XXX ext2 also updates the state here */ mark_buffer_dirty(sbi->s_bh1); if (sbi->s_bh1 != sbi->s_bh2) diff --git a/fs/sysv/super.c b/fs/sysv/super.c index eda10959714f..0d56e486b392 100644 --- a/fs/sysv/super.c +++ b/fs/sysv/super.c @@ -216,7 +216,7 @@ static int detect_sysv(struct sysv_sb_info *sbi, struct buffer_head *bh) if (fs16_to_cpu(sbi, sbd->s_nfree) == 0xffff) { sbi->s_type = FSTYPE_AFS; sbi->s_forced_ro = 1; - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { printk("SysV FS: SCO EAFS on %s detected, " "forcing read-only mode.\n", sb->s_id); diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index bffadbb67e47..5496b17b959c 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1159,7 +1159,7 @@ static int mount_ubifs(struct ubifs_info *c) long long x, y; size_t sz; - c->ro_mount = !!(c->vfs_sb->s_flags & MS_RDONLY); + c->ro_mount = !!sb_rdonly(c->vfs_sb); /* Suppress error messages while probing if MS_SILENT is set */ c->probing = !!(c->vfs_sb->s_flags & MS_SILENT); diff --git a/fs/udf/super.c b/fs/udf/super.c index 462ac2e9258c..28039923114b 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -675,7 +675,7 @@ static int udf_remount_fs(struct super_block *sb, int *flags, char *options) sbi->s_dmode = uopt.dmode; write_unlock(&sbi->s_cred_lock); - if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) + if ((bool)(*flags & MS_RDONLY) == sb_rdonly(sb)) goto out_unlock; if (*flags & MS_RDONLY) @@ -1019,7 +1019,7 @@ static int udf_load_metadata_files(struct super_block *sb, int partition, fe = udf_iget_special(sb, &addr); if (IS_ERR(fe)) { - if (sb->s_flags & MS_RDONLY) + if (sb_rdonly(sb)) udf_warn(sb, "bitmap inode efe not found but it's ok since the disc is mounted read-only\n"); else { udf_err(sb, "bitmap inode efe not found and attempted read-write mount\n"); @@ -1343,7 +1343,7 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block) * writing to it (we overwrite blocks instead of relocating * them). */ - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { ret = -EACCES; goto out_bh; } @@ -2207,7 +2207,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) ret = -EINVAL; goto error_out; } else if (minUDFWriteRev > UDF_MAX_WRITE_VERSION && - !(sb->s_flags & MS_RDONLY)) { + !sb_rdonly(sb)) { ret = -EACCES; goto error_out; } @@ -2228,7 +2228,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) if (sbi->s_partmaps[sbi->s_partition].s_partition_flags & UDF_PART_FLAG_READ_ONLY && - !(sb->s_flags & MS_RDONLY)) { + !sb_rdonly(sb)) { ret = -EACCES; goto error_out; } @@ -2247,7 +2247,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) le16_to_cpu(ts.year), ts.month, ts.day, ts.hour, ts.minute, le16_to_cpu(ts.typeAndTimezone)); } - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { udf_open_lvid(sb); lvid_open = true; } @@ -2334,7 +2334,7 @@ static void udf_put_super(struct super_block *sb) if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP)) unload_nls(sbi->s_nls_map); #endif - if (!(sb->s_flags & MS_RDONLY)) + if (!sb_rdonly(sb)) udf_close_lvid(sb); brelse(sbi->s_lvid_bh); udf_sb_free_partitions(sb); diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 0a4f58a5073c..6440003f8ddc 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -278,7 +278,7 @@ void ufs_error (struct super_block * sb, const char * function, uspi = UFS_SB(sb)->s_uspi; usb1 = ubh_get_usb_first(uspi); - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { usb1->fs_clean = UFS_FSBAD; ubh_mark_buffer_dirty(USPI_UBH(uspi)); ufs_mark_sb_dirty(sb); @@ -312,7 +312,7 @@ void ufs_panic (struct super_block * sb, const char * function, uspi = UFS_SB(sb)->s_uspi; usb1 = ubh_get_usb_first(uspi); - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { usb1->fs_clean = UFS_FSBAD; ubh_mark_buffer_dirty(USPI_UBH(uspi)); ufs_mark_sb_dirty(sb); @@ -742,7 +742,7 @@ static void ufs_put_super(struct super_block *sb) UFSD("ENTER\n"); - if (!(sb->s_flags & MS_RDONLY)) + if (!sb_rdonly(sb)) ufs_put_super_internal(sb); cancel_delayed_work_sync(&sbi->sync_work); @@ -793,7 +793,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) UFSD("ENTER\n"); #ifndef CONFIG_UFS_FS_WRITE - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { pr_err("ufs was compiled with read-only support, can't be mounted as read-write\n"); return -EROFS; } @@ -805,7 +805,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) sb->s_fs_info = sbi; sbi->sb = sb; - UFSD("flag %u\n", (int)(sb->s_flags & MS_RDONLY)); + UFSD("flag %u\n", (int)(sb_rdonly(sb))); mutex_init(&sbi->s_lock); spin_lock_init(&sbi->work_lock); @@ -902,7 +902,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) uspi->s_sbsize = super_block_size = 2048; uspi->s_sbbase = 0; flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { if (!silent) pr_info("ufstype=old is supported read-only\n"); sb->s_flags |= MS_RDONLY; @@ -918,7 +918,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) uspi->s_sbbase = 0; uspi->s_dirblksize = 1024; flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { if (!silent) pr_info("ufstype=nextstep is supported read-only\n"); sb->s_flags |= MS_RDONLY; @@ -934,7 +934,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) uspi->s_sbbase = 0; uspi->s_dirblksize = 1024; flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { if (!silent) pr_info("ufstype=nextstep-cd is supported read-only\n"); sb->s_flags |= MS_RDONLY; @@ -950,7 +950,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) uspi->s_sbbase = 0; uspi->s_dirblksize = 1024; flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD; - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { if (!silent) pr_info("ufstype=openstep is supported read-only\n"); sb->s_flags |= MS_RDONLY; @@ -965,7 +965,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) uspi->s_sbsize = super_block_size = 2048; uspi->s_sbbase = 0; flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb_rdonly(sb)) { if (!silent) pr_info("ufstype=hp is supported read-only\n"); sb->s_flags |= MS_RDONLY; @@ -1273,7 +1273,7 @@ magic_found: /* * Read cylinder group structures */ - if (!(sb->s_flags & MS_RDONLY)) + if (!sb_rdonly(sb)) if (!ufs_read_cylinder_structures(sb)) goto failed; @@ -1328,7 +1328,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data) return -EINVAL; } - if ((*mount_flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) { + if ((bool)(*mount_flags & MS_RDONLY) == sb_rdonly(sb)) { UFS_SB(sb)->s_mount_opt = new_mount_opt; mutex_unlock(&UFS_SB(sb)->s_lock); return 0; diff --git a/fs/xfs/xfs_quotaops.c b/fs/xfs/xfs_quotaops.c index de9493253edf..a65108594a07 100644 --- a/fs/xfs/xfs_quotaops.c +++ b/fs/xfs/xfs_quotaops.c @@ -125,7 +125,7 @@ xfs_fs_set_info( struct xfs_mount *mp = XFS_M(sb); struct qc_dqblk newlim; - if (sb->s_flags & MS_RDONLY) + if (sb_rdonly(sb)) return -EROFS; if (!XFS_IS_QUOTA_RUNNING(mp)) return -ENOSYS; @@ -175,7 +175,7 @@ xfs_quota_enable( { struct xfs_mount *mp = XFS_M(sb); - if (sb->s_flags & MS_RDONLY) + if (sb_rdonly(sb)) return -EROFS; if (!XFS_IS_QUOTA_RUNNING(mp)) return -ENOSYS; @@ -190,7 +190,7 @@ xfs_quota_disable( { struct xfs_mount *mp = XFS_M(sb); - if (sb->s_flags & MS_RDONLY) + if (sb_rdonly(sb)) return -EROFS; if (!XFS_IS_QUOTA_RUNNING(mp)) return -ENOSYS; @@ -208,7 +208,7 @@ xfs_fs_rm_xquota( struct xfs_mount *mp = XFS_M(sb); unsigned int flags = 0; - if (sb->s_flags & MS_RDONLY) + if (sb_rdonly(sb)) return -EROFS; if (XFS_IS_QUOTA_ON(mp)) @@ -279,7 +279,7 @@ xfs_fs_set_dqblk( { struct xfs_mount *mp = XFS_M(sb); - if (sb->s_flags & MS_RDONLY) + if (sb_rdonly(sb)) return -EROFS; if (!XFS_IS_QUOTA_RUNNING(mp)) return -ENOSYS; diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 38aaacdbb8b3..7bc25d62cdc6 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -210,7 +210,7 @@ xfs_parseargs( /* * Copy binary VFS mount flags we are interested in. */ - if (sb->s_flags & MS_RDONLY) + if (sb_rdonly(sb)) mp->m_flags |= XFS_MOUNT_RDONLY; if (sb->s_flags & MS_DIRSYNC) mp->m_flags |= XFS_MOUNT_DIRSYNC; diff --git a/init/do_mounts.c b/init/do_mounts.c index c2de5104aad2..bf7ea36ca286 100644 --- a/init/do_mounts.c +++ b/init/do_mounts.c @@ -373,7 +373,7 @@ static int __init do_mount_root(char *name, char *fs, int flags, void *data) printk(KERN_INFO "VFS: Mounted root (%s filesystem)%s on device %u:%u.\n", s->s_type->name, - s->s_flags & MS_RDONLY ? " readonly" : "", + sb_rdonly(s) ? " readonly" : "", MAJOR(ROOT_DEV), MINOR(ROOT_DEV)); return 0; } -- cgit v1.2.3 From 1c18be5a4e3ecbb40fbee015711aea6cc6467417 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Mon, 17 Jul 2017 10:20:25 +0200 Subject: EDAC: Constify attribute_group structures attribute_groups are not supposed to change at runtime. All functions working with attribute_groups provided by work with const attribute_group. So mark the non-const structs as const. Signed-off-by: Arvind Yadav CC: linux-edac@vger.kernel.org Link: http://lkml.kernel.org/r/776cb8265509054abd01b0b551624cc0da3b88e7.1499078335.git.arvind.yadav.cs@gmail.com Signed-off-by: Borislav Petkov --- drivers/edac/edac_mc_sysfs.c | 6 +++--- drivers/edac/i7core_edac.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index 445862dac273..dbc64469b7da 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -287,7 +287,7 @@ static struct attribute *csrow_attrs[] = { NULL, }; -static struct attribute_group csrow_attr_grp = { +static const struct attribute_group csrow_attr_grp = { .attrs = csrow_attrs, }; @@ -627,7 +627,7 @@ static struct attribute *dimm_attrs[] = { NULL, }; -static struct attribute_group dimm_attr_grp = { +static const struct attribute_group dimm_attr_grp = { .attrs = dimm_attrs, }; @@ -902,7 +902,7 @@ static umode_t mci_attr_is_visible(struct kobject *kobj, return mode; } -static struct attribute_group mci_attr_grp = { +static const struct attribute_group mci_attr_grp = { .attrs = mci_attrs, .is_visible = mci_attr_is_visible, }; diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index 75ad847593b7..ba0fa112996f 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -1079,7 +1079,7 @@ static struct attribute *i7core_addrmatch_attrs[] = { NULL }; -static struct attribute_group addrmatch_grp = { +static const struct attribute_group addrmatch_grp = { .attrs = i7core_addrmatch_attrs, }; @@ -1110,7 +1110,7 @@ static struct attribute *i7core_udimm_counters_attrs[] = { NULL }; -static struct attribute_group all_channel_counts_grp = { +static const struct attribute_group all_channel_counts_grp = { .attrs = i7core_udimm_counters_attrs, }; -- cgit v1.2.3 From 2ebedd8d5ca8747fc7efd8a97129802bc6965468 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 21 Jun 2017 22:02:33 +0200 Subject: clk: renesas: div6: Document fields used for parent selection Add the missing documentation for the fields in struct div6_clock related to parent selection for DIV6 clocks with selectable parents, as found in R/SH-Mobile SoCs. Fixes: c6d67fb037f4eaaf ("clk: shmobile: div6: support selectable-input clocks") Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/clk-div6.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/renesas/clk-div6.c b/drivers/clk/renesas/clk-div6.c index 0627860233cb..3e0040c0ac87 100644 --- a/drivers/clk/renesas/clk-div6.c +++ b/drivers/clk/renesas/clk-div6.c @@ -29,6 +29,9 @@ * @hw: handle between common and hardware-specific interfaces * @reg: IO-remapped register * @div: divisor value (1-64) + * @src_shift: Shift to access the register bits to select the parent clock + * @src_width: Number of register bits to select the parent clock (may be 0) + * @parents: Array to map from valid parent clocks indices to hardware indices */ struct div6_clock { struct clk_hw hw; -- cgit v1.2.3 From f83fbfddd8f65ddadc0dd2b0dd7f3097d42d8def Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 5 Jul 2017 13:41:00 +0200 Subject: clk: renesas: r8a7792: Add IMR-LX3/LSX3 clocks Add the module clocks for the Image Renderer Light (SRAM) Extended 3 (IMR-LX3/LSX3) Distortion Correction Engines on R-Car V2H. Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a7792-cpg-mssr.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/renesas/r8a7792-cpg-mssr.c b/drivers/clk/renesas/r8a7792-cpg-mssr.c index a832b9b6f7b0..7f85bbf20bf7 100644 --- a/drivers/clk/renesas/r8a7792-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7792-cpg-mssr.c @@ -118,6 +118,13 @@ static const struct mssr_mod_clk r8a7792_mod_clks[] __initconst = { DEF_MOD("vin1", 810, R8A7792_CLK_ZG), DEF_MOD("vin0", 811, R8A7792_CLK_ZG), DEF_MOD("etheravb", 812, R8A7792_CLK_HP), + DEF_MOD("imr-lx3", 821, R8A7792_CLK_ZG), + DEF_MOD("imr-lsx3-1", 822, R8A7792_CLK_ZG), + DEF_MOD("imr-lsx3-0", 823, R8A7792_CLK_ZG), + DEF_MOD("imr-lsx3-5", 825, R8A7792_CLK_ZG), + DEF_MOD("imr-lsx3-4", 826, R8A7792_CLK_ZG), + DEF_MOD("imr-lsx3-3", 827, R8A7792_CLK_ZG), + DEF_MOD("imr-lsx3-2", 828, R8A7792_CLK_ZG), DEF_MOD("gyro-adc", 901, R8A7792_CLK_P), DEF_MOD("gpio7", 904, R8A7792_CLK_CP), DEF_MOD("gpio6", 905, R8A7792_CLK_CP), -- cgit v1.2.3 From 371dd373c6edd557a7cfdfe10207b498ae10a014 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 17 May 2017 17:25:47 +0200 Subject: clk: renesas: Allow compile-testing of all (sub)drivers Enable compile-testing of the remaining clock drivers and subdrivers, now dummies are available for of_clk_get_from_provider(), of_device_compatible_match(), and rcar_rst_read_mode_pins(), and the CPG/MSSR driver core has been converted from of_match_node() to of_device_get_match_data(). Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/Kconfig | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig index 78d1df9112ba..85526ca39202 100644 --- a/drivers/clk/renesas/Kconfig +++ b/drivers/clk/renesas/Kconfig @@ -34,94 +34,94 @@ config CLK_EMEV2 bool "Emma Mobile EV2 clock support" if COMPILE_TEST config CLK_RZA1 - bool + bool "RZ/A1H clock support" if COMPILE_TEST select CLK_RENESAS_CPG_MSTP config CLK_R8A73A4 - bool + bool "R-Mobile APE6 clock support" if COMPILE_TEST select CLK_RENESAS_CPG_MSTP select CLK_RENESAS_DIV6 config CLK_R8A7740 - bool + bool "R-Mobile A1 clock support" if COMPILE_TEST select CLK_RENESAS_CPG_MSTP select CLK_RENESAS_DIV6 config CLK_R8A7743 - bool + bool "RZ/G1M clock support" if COMPILE_TEST select CLK_RCAR_GEN2_CPG config CLK_R8A7745 - bool + bool "RZ/G1E clock support" if COMPILE_TEST select CLK_RCAR_GEN2_CPG config CLK_R8A7778 - bool + bool "R-Car M1A clock support" if COMPILE_TEST select CLK_RENESAS_CPG_MSTP config CLK_R8A7779 - bool + bool "R-Car H1 clock support" if COMPILE_TEST select CLK_RENESAS_CPG_MSTP config CLK_R8A7790 - bool + bool "R-Car H2 clock support" if COMPILE_TEST select CLK_RCAR_GEN2 if CLK_RENESAS_LEGACY select CLK_RCAR_GEN2_CPG select CLK_RENESAS_DIV6 config CLK_R8A7791 - bool + bool "R-Car M2-W/N clock support" if COMPILE_TEST select CLK_RCAR_GEN2 if CLK_RENESAS_LEGACY select CLK_RCAR_GEN2_CPG select CLK_RENESAS_DIV6 config CLK_R8A7792 - bool + bool "R-Car V2H clock support" if COMPILE_TEST select CLK_RCAR_GEN2 if CLK_RENESAS_LEGACY select CLK_RCAR_GEN2_CPG config CLK_R8A7794 - bool + bool "R-Car E2 clock support" if COMPILE_TEST select CLK_RCAR_GEN2 if CLK_RENESAS_LEGACY select CLK_RCAR_GEN2_CPG select CLK_RENESAS_DIV6 config CLK_R8A7795 - bool + bool "R-Car H3 clock support" if COMPILE_TEST select CLK_RCAR_GEN3_CPG config CLK_R8A7796 - bool + bool "R-Car M3-W clock support" if COMPILE_TEST select CLK_RCAR_GEN3_CPG config CLK_SH73A0 - bool + bool "SH-Mobile AG5 clock support" if COMPILE_TEST select CLK_RENESAS_CPG_MSTP select CLK_RENESAS_DIV6 # Family config CLK_RCAR_GEN2 - bool + bool "R-Car Gen2 legacy clock support" if COMPILE_TEST select CLK_RENESAS_CPG_MSTP select CLK_RENESAS_DIV6 config CLK_RCAR_GEN2_CPG - bool + bool "R-Car Gen2 CPG clock support" if COMPILE_TEST select CLK_RENESAS_CPG_MSSR config CLK_RCAR_GEN3_CPG - bool + bool "R-Car Gen3 CPG clock support" if COMPILE_TEST select CLK_RENESAS_CPG_MSSR # Generic config CLK_RENESAS_CPG_MSSR - bool + bool "CPG/MSSR clock support" if COMPILE_TEST select CLK_RENESAS_DIV6 config CLK_RENESAS_CPG_MSTP - bool + bool "MSTP clock support" if COMPILE_TEST config CLK_RENESAS_DIV6 bool "DIV6 clock support" if COMPILE_TEST -- cgit v1.2.3 From d0593c363f04ccc4bc7b6939c24a0ee65391c779 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 20 Jun 2016 08:40:22 +0200 Subject: pinctrl: sh-pfc: Propagate errors on group config On group configuration, bail out if setting one of the individual pins fails. We don't need to roll-back, the pinctrl core will do this for us. Signed-off-by: Wolfram Sang Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pinctrl.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pinctrl.c b/drivers/pinctrl/sh-pfc/pinctrl.c index a70157f0acf4..225ecccf5706 100644 --- a/drivers/pinctrl/sh-pfc/pinctrl.c +++ b/drivers/pinctrl/sh-pfc/pinctrl.c @@ -742,13 +742,16 @@ static int sh_pfc_pinconf_group_set(struct pinctrl_dev *pctldev, unsigned group, struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); const unsigned int *pins; unsigned int num_pins; - unsigned int i; + unsigned int i, ret; pins = pmx->pfc->info->groups[group].pins; num_pins = pmx->pfc->info->groups[group].nr_pins; - for (i = 0; i < num_pins; ++i) - sh_pfc_pinconf_set(pctldev, pins[i], configs, num_configs); + for (i = 0; i < num_pins; ++i) { + ret = sh_pfc_pinconf_set(pctldev, pins[i], configs, num_configs); + if (ret) + return ret; + } return 0; } -- cgit v1.2.3 From e2ab17707689c2e5bea735bc66260ecb42a81483 Mon Sep 17 00:00:00 2001 From: Takeshi Kihara Date: Tue, 30 May 2017 20:15:18 +0900 Subject: pinctrl: sh-pfc: r8a7795: Fix MSIOF3_{SS1,SS2}_E pin function definitions This patch fixes the incorrect IPSR register value definitions for MSIOF3_{SS1,SS2}_E pin functions. This is a correction to the incorrect implementation of IPSR register pin assignment of the specifications updated for R8A7795 ES2.0 SoC in R-Car Gen3 Hardware User's Manual Rev.0.53E. Fixes: b205914c8f822ef2 ("pinctrl: sh-pfc: r8a7795: Add support for R-Car H3 ES2.0") Signed-off-by: Takeshi Kihara [geert: Reword, update Fixes for upstream] Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7795.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c index 1656295af2b0..f27d80c0b2d0 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c @@ -215,8 +215,8 @@ #define IP0_15_12 FM(AVB_LINK) F_(0, 0) FM(MSIOF2_SCK_C) FM(TX4_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP0_19_16 FM(AVB_AVTP_MATCH_A) F_(0, 0) FM(MSIOF2_RXD_C) FM(CTS4_N_A) F_(0, 0) FM(FSCLKST2_N_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP0_23_20 FM(AVB_AVTP_CAPTURE_A) F_(0, 0) FM(MSIOF2_TXD_C) FM(RTS4_N_TANS_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP0_27_24 FM(IRQ0) FM(QPOLB) F_(0, 0) FM(DU_CDE) FM(VI4_DATA0_B) FM(CAN0_TX_B) FM(CANFD0_TX_B) FM(MSIOF3_SS1_E) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP0_31_28 FM(IRQ1) FM(QPOLA) F_(0, 0) FM(DU_DISP) FM(VI4_DATA1_B) FM(CAN0_RX_B) FM(CANFD0_RX_B) FM(MSIOF3_SS2_E) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0_27_24 FM(IRQ0) FM(QPOLB) F_(0, 0) FM(DU_CDE) FM(VI4_DATA0_B) FM(CAN0_TX_B) FM(CANFD0_TX_B) FM(MSIOF3_SS2_E) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0_31_28 FM(IRQ1) FM(QPOLA) F_(0, 0) FM(DU_DISP) FM(VI4_DATA1_B) FM(CAN0_RX_B) FM(CANFD0_RX_B) FM(MSIOF3_SS1_E) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1_3_0 FM(IRQ2) FM(QCPV_QDE) F_(0, 0) FM(DU_EXODDF_DU_ODDF_DISP_CDE) FM(VI4_DATA2_B) F_(0, 0) F_(0, 0) FM(MSIOF3_SYNC_E) F_(0, 0) FM(PWM3_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1_7_4 FM(IRQ3) FM(QSTVB_QVE) FM(A25) FM(DU_DOTCLKOUT1) FM(VI4_DATA3_B) F_(0, 0) F_(0, 0) FM(MSIOF3_SCK_E) F_(0, 0) FM(PWM4_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1_11_8 FM(IRQ4) FM(QSTH_QHS) FM(A24) FM(DU_EXHSYNC_DU_HSYNC) FM(VI4_DATA4_B) F_(0, 0) F_(0, 0) FM(MSIOF3_RXD_E) F_(0, 0) FM(PWM5_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -- cgit v1.2.3 From 3e6c7727c08a0d53e019444c7976bd9a2eb091b6 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 13 Mar 2017 11:59:41 +0100 Subject: pinctrl: sh-pfc: r8a7795: Add MSIOF pins, groups and functions Add pins, groups, and functions for MSIOF on R-Car H3 ES2.0. Extracted from a big patch in the BSP by Takeshi Kihara, with corrections for MSIOF3 SS1_E/SS2_E pins and SS2_E mux. Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7795.c | 912 +++++++++++++++++++++++++++++++++++ 1 file changed, 912 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c index f27d80c0b2d0..7df11d4e853a 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c @@ -1744,6 +1744,704 @@ static const unsigned int du_disp_mux[] = { DU_DISP_MARK, }; +/* - MSIOF0 ----------------------------------------------------------------- */ +static const unsigned int msiof0_clk_pins[] = { + /* SCK */ + RCAR_GP_PIN(5, 17), +}; +static const unsigned int msiof0_clk_mux[] = { + MSIOF0_SCK_MARK, +}; +static const unsigned int msiof0_sync_pins[] = { + /* SYNC */ + RCAR_GP_PIN(5, 18), +}; +static const unsigned int msiof0_sync_mux[] = { + MSIOF0_SYNC_MARK, +}; +static const unsigned int msiof0_ss1_pins[] = { + /* SS1 */ + RCAR_GP_PIN(5, 19), +}; +static const unsigned int msiof0_ss1_mux[] = { + MSIOF0_SS1_MARK, +}; +static const unsigned int msiof0_ss2_pins[] = { + /* SS2 */ + RCAR_GP_PIN(5, 21), +}; +static const unsigned int msiof0_ss2_mux[] = { + MSIOF0_SS2_MARK, +}; +static const unsigned int msiof0_txd_pins[] = { + /* TXD */ + RCAR_GP_PIN(5, 20), +}; +static const unsigned int msiof0_txd_mux[] = { + MSIOF0_TXD_MARK, +}; +static const unsigned int msiof0_rxd_pins[] = { + /* RXD */ + RCAR_GP_PIN(5, 22), +}; +static const unsigned int msiof0_rxd_mux[] = { + MSIOF0_RXD_MARK, +}; +/* - MSIOF1 ----------------------------------------------------------------- */ +static const unsigned int msiof1_clk_a_pins[] = { + /* SCK */ + RCAR_GP_PIN(6, 8), +}; +static const unsigned int msiof1_clk_a_mux[] = { + MSIOF1_SCK_A_MARK, +}; +static const unsigned int msiof1_sync_a_pins[] = { + /* SYNC */ + RCAR_GP_PIN(6, 9), +}; +static const unsigned int msiof1_sync_a_mux[] = { + MSIOF1_SYNC_A_MARK, +}; +static const unsigned int msiof1_ss1_a_pins[] = { + /* SS1 */ + RCAR_GP_PIN(6, 5), +}; +static const unsigned int msiof1_ss1_a_mux[] = { + MSIOF1_SS1_A_MARK, +}; +static const unsigned int msiof1_ss2_a_pins[] = { + /* SS2 */ + RCAR_GP_PIN(6, 6), +}; +static const unsigned int msiof1_ss2_a_mux[] = { + MSIOF1_SS2_A_MARK, +}; +static const unsigned int msiof1_txd_a_pins[] = { + /* TXD */ + RCAR_GP_PIN(6, 7), +}; +static const unsigned int msiof1_txd_a_mux[] = { + MSIOF1_TXD_A_MARK, +}; +static const unsigned int msiof1_rxd_a_pins[] = { + /* RXD */ + RCAR_GP_PIN(6, 10), +}; +static const unsigned int msiof1_rxd_a_mux[] = { + MSIOF1_RXD_A_MARK, +}; +static const unsigned int msiof1_clk_b_pins[] = { + /* SCK */ + RCAR_GP_PIN(5, 9), +}; +static const unsigned int msiof1_clk_b_mux[] = { + MSIOF1_SCK_B_MARK, +}; +static const unsigned int msiof1_sync_b_pins[] = { + /* SYNC */ + RCAR_GP_PIN(5, 3), +}; +static const unsigned int msiof1_sync_b_mux[] = { + MSIOF1_SYNC_B_MARK, +}; +static const unsigned int msiof1_ss1_b_pins[] = { + /* SS1 */ + RCAR_GP_PIN(5, 4), +}; +static const unsigned int msiof1_ss1_b_mux[] = { + MSIOF1_SS1_B_MARK, +}; +static const unsigned int msiof1_ss2_b_pins[] = { + /* SS2 */ + RCAR_GP_PIN(5, 0), +}; +static const unsigned int msiof1_ss2_b_mux[] = { + MSIOF1_SS2_B_MARK, +}; +static const unsigned int msiof1_txd_b_pins[] = { + /* TXD */ + RCAR_GP_PIN(5, 8), +}; +static const unsigned int msiof1_txd_b_mux[] = { + MSIOF1_TXD_B_MARK, +}; +static const unsigned int msiof1_rxd_b_pins[] = { + /* RXD */ + RCAR_GP_PIN(5, 7), +}; +static const unsigned int msiof1_rxd_b_mux[] = { + MSIOF1_RXD_B_MARK, +}; +static const unsigned int msiof1_clk_c_pins[] = { + /* SCK */ + RCAR_GP_PIN(6, 17), +}; +static const unsigned int msiof1_clk_c_mux[] = { + MSIOF1_SCK_C_MARK, +}; +static const unsigned int msiof1_sync_c_pins[] = { + /* SYNC */ + RCAR_GP_PIN(6, 18), +}; +static const unsigned int msiof1_sync_c_mux[] = { + MSIOF1_SYNC_C_MARK, +}; +static const unsigned int msiof1_ss1_c_pins[] = { + /* SS1 */ + RCAR_GP_PIN(6, 21), +}; +static const unsigned int msiof1_ss1_c_mux[] = { + MSIOF1_SS1_C_MARK, +}; +static const unsigned int msiof1_ss2_c_pins[] = { + /* SS2 */ + RCAR_GP_PIN(6, 27), +}; +static const unsigned int msiof1_ss2_c_mux[] = { + MSIOF1_SS2_C_MARK, +}; +static const unsigned int msiof1_txd_c_pins[] = { + /* TXD */ + RCAR_GP_PIN(6, 20), +}; +static const unsigned int msiof1_txd_c_mux[] = { + MSIOF1_TXD_C_MARK, +}; +static const unsigned int msiof1_rxd_c_pins[] = { + /* RXD */ + RCAR_GP_PIN(6, 19), +}; +static const unsigned int msiof1_rxd_c_mux[] = { + MSIOF1_RXD_C_MARK, +}; +static const unsigned int msiof1_clk_d_pins[] = { + /* SCK */ + RCAR_GP_PIN(5, 12), +}; +static const unsigned int msiof1_clk_d_mux[] = { + MSIOF1_SCK_D_MARK, +}; +static const unsigned int msiof1_sync_d_pins[] = { + /* SYNC */ + RCAR_GP_PIN(5, 15), +}; +static const unsigned int msiof1_sync_d_mux[] = { + MSIOF1_SYNC_D_MARK, +}; +static const unsigned int msiof1_ss1_d_pins[] = { + /* SS1 */ + RCAR_GP_PIN(5, 16), +}; +static const unsigned int msiof1_ss1_d_mux[] = { + MSIOF1_SS1_D_MARK, +}; +static const unsigned int msiof1_ss2_d_pins[] = { + /* SS2 */ + RCAR_GP_PIN(5, 21), +}; +static const unsigned int msiof1_ss2_d_mux[] = { + MSIOF1_SS2_D_MARK, +}; +static const unsigned int msiof1_txd_d_pins[] = { + /* TXD */ + RCAR_GP_PIN(5, 14), +}; +static const unsigned int msiof1_txd_d_mux[] = { + MSIOF1_TXD_D_MARK, +}; +static const unsigned int msiof1_rxd_d_pins[] = { + /* RXD */ + RCAR_GP_PIN(5, 13), +}; +static const unsigned int msiof1_rxd_d_mux[] = { + MSIOF1_RXD_D_MARK, +}; +static const unsigned int msiof1_clk_e_pins[] = { + /* SCK */ + RCAR_GP_PIN(3, 0), +}; +static const unsigned int msiof1_clk_e_mux[] = { + MSIOF1_SCK_E_MARK, +}; +static const unsigned int msiof1_sync_e_pins[] = { + /* SYNC */ + RCAR_GP_PIN(3, 1), +}; +static const unsigned int msiof1_sync_e_mux[] = { + MSIOF1_SYNC_E_MARK, +}; +static const unsigned int msiof1_ss1_e_pins[] = { + /* SS1 */ + RCAR_GP_PIN(3, 4), +}; +static const unsigned int msiof1_ss1_e_mux[] = { + MSIOF1_SS1_E_MARK, +}; +static const unsigned int msiof1_ss2_e_pins[] = { + /* SS2 */ + RCAR_GP_PIN(3, 5), +}; +static const unsigned int msiof1_ss2_e_mux[] = { + MSIOF1_SS2_E_MARK, +}; +static const unsigned int msiof1_txd_e_pins[] = { + /* TXD */ + RCAR_GP_PIN(3, 3), +}; +static const unsigned int msiof1_txd_e_mux[] = { + MSIOF1_TXD_E_MARK, +}; +static const unsigned int msiof1_rxd_e_pins[] = { + /* RXD */ + RCAR_GP_PIN(3, 2), +}; +static const unsigned int msiof1_rxd_e_mux[] = { + MSIOF1_RXD_E_MARK, +}; +static const unsigned int msiof1_clk_f_pins[] = { + /* SCK */ + RCAR_GP_PIN(5, 23), +}; +static const unsigned int msiof1_clk_f_mux[] = { + MSIOF1_SCK_F_MARK, +}; +static const unsigned int msiof1_sync_f_pins[] = { + /* SYNC */ + RCAR_GP_PIN(5, 24), +}; +static const unsigned int msiof1_sync_f_mux[] = { + MSIOF1_SYNC_F_MARK, +}; +static const unsigned int msiof1_ss1_f_pins[] = { + /* SS1 */ + RCAR_GP_PIN(6, 1), +}; +static const unsigned int msiof1_ss1_f_mux[] = { + MSIOF1_SS1_F_MARK, +}; +static const unsigned int msiof1_ss2_f_pins[] = { + /* SS2 */ + RCAR_GP_PIN(6, 2), +}; +static const unsigned int msiof1_ss2_f_mux[] = { + MSIOF1_SS2_F_MARK, +}; +static const unsigned int msiof1_txd_f_pins[] = { + /* TXD */ + RCAR_GP_PIN(6, 0), +}; +static const unsigned int msiof1_txd_f_mux[] = { + MSIOF1_TXD_F_MARK, +}; +static const unsigned int msiof1_rxd_f_pins[] = { + /* RXD */ + RCAR_GP_PIN(5, 25), +}; +static const unsigned int msiof1_rxd_f_mux[] = { + MSIOF1_RXD_F_MARK, +}; +static const unsigned int msiof1_clk_g_pins[] = { + /* SCK */ + RCAR_GP_PIN(3, 6), +}; +static const unsigned int msiof1_clk_g_mux[] = { + MSIOF1_SCK_G_MARK, +}; +static const unsigned int msiof1_sync_g_pins[] = { + /* SYNC */ + RCAR_GP_PIN(3, 7), +}; +static const unsigned int msiof1_sync_g_mux[] = { + MSIOF1_SYNC_G_MARK, +}; +static const unsigned int msiof1_ss1_g_pins[] = { + /* SS1 */ + RCAR_GP_PIN(3, 10), +}; +static const unsigned int msiof1_ss1_g_mux[] = { + MSIOF1_SS1_G_MARK, +}; +static const unsigned int msiof1_ss2_g_pins[] = { + /* SS2 */ + RCAR_GP_PIN(3, 11), +}; +static const unsigned int msiof1_ss2_g_mux[] = { + MSIOF1_SS2_G_MARK, +}; +static const unsigned int msiof1_txd_g_pins[] = { + /* TXD */ + RCAR_GP_PIN(3, 9), +}; +static const unsigned int msiof1_txd_g_mux[] = { + MSIOF1_TXD_G_MARK, +}; +static const unsigned int msiof1_rxd_g_pins[] = { + /* RXD */ + RCAR_GP_PIN(3, 8), +}; +static const unsigned int msiof1_rxd_g_mux[] = { + MSIOF1_RXD_G_MARK, +}; +/* - MSIOF2 ----------------------------------------------------------------- */ +static const unsigned int msiof2_clk_a_pins[] = { + /* SCK */ + RCAR_GP_PIN(1, 9), +}; +static const unsigned int msiof2_clk_a_mux[] = { + MSIOF2_SCK_A_MARK, +}; +static const unsigned int msiof2_sync_a_pins[] = { + /* SYNC */ + RCAR_GP_PIN(1, 8), +}; +static const unsigned int msiof2_sync_a_mux[] = { + MSIOF2_SYNC_A_MARK, +}; +static const unsigned int msiof2_ss1_a_pins[] = { + /* SS1 */ + RCAR_GP_PIN(1, 6), +}; +static const unsigned int msiof2_ss1_a_mux[] = { + MSIOF2_SS1_A_MARK, +}; +static const unsigned int msiof2_ss2_a_pins[] = { + /* SS2 */ + RCAR_GP_PIN(1, 7), +}; +static const unsigned int msiof2_ss2_a_mux[] = { + MSIOF2_SS2_A_MARK, +}; +static const unsigned int msiof2_txd_a_pins[] = { + /* TXD */ + RCAR_GP_PIN(1, 11), +}; +static const unsigned int msiof2_txd_a_mux[] = { + MSIOF2_TXD_A_MARK, +}; +static const unsigned int msiof2_rxd_a_pins[] = { + /* RXD */ + RCAR_GP_PIN(1, 10), +}; +static const unsigned int msiof2_rxd_a_mux[] = { + MSIOF2_RXD_A_MARK, +}; +static const unsigned int msiof2_clk_b_pins[] = { + /* SCK */ + RCAR_GP_PIN(0, 4), +}; +static const unsigned int msiof2_clk_b_mux[] = { + MSIOF2_SCK_B_MARK, +}; +static const unsigned int msiof2_sync_b_pins[] = { + /* SYNC */ + RCAR_GP_PIN(0, 5), +}; +static const unsigned int msiof2_sync_b_mux[] = { + MSIOF2_SYNC_B_MARK, +}; +static const unsigned int msiof2_ss1_b_pins[] = { + /* SS1 */ + RCAR_GP_PIN(0, 0), +}; +static const unsigned int msiof2_ss1_b_mux[] = { + MSIOF2_SS1_B_MARK, +}; +static const unsigned int msiof2_ss2_b_pins[] = { + /* SS2 */ + RCAR_GP_PIN(0, 1), +}; +static const unsigned int msiof2_ss2_b_mux[] = { + MSIOF2_SS2_B_MARK, +}; +static const unsigned int msiof2_txd_b_pins[] = { + /* TXD */ + RCAR_GP_PIN(0, 7), +}; +static const unsigned int msiof2_txd_b_mux[] = { + MSIOF2_TXD_B_MARK, +}; +static const unsigned int msiof2_rxd_b_pins[] = { + /* RXD */ + RCAR_GP_PIN(0, 6), +}; +static const unsigned int msiof2_rxd_b_mux[] = { + MSIOF2_RXD_B_MARK, +}; +static const unsigned int msiof2_clk_c_pins[] = { + /* SCK */ + RCAR_GP_PIN(2, 12), +}; +static const unsigned int msiof2_clk_c_mux[] = { + MSIOF2_SCK_C_MARK, +}; +static const unsigned int msiof2_sync_c_pins[] = { + /* SYNC */ + RCAR_GP_PIN(2, 11), +}; +static const unsigned int msiof2_sync_c_mux[] = { + MSIOF2_SYNC_C_MARK, +}; +static const unsigned int msiof2_ss1_c_pins[] = { + /* SS1 */ + RCAR_GP_PIN(2, 10), +}; +static const unsigned int msiof2_ss1_c_mux[] = { + MSIOF2_SS1_C_MARK, +}; +static const unsigned int msiof2_ss2_c_pins[] = { + /* SS2 */ + RCAR_GP_PIN(2, 9), +}; +static const unsigned int msiof2_ss2_c_mux[] = { + MSIOF2_SS2_C_MARK, +}; +static const unsigned int msiof2_txd_c_pins[] = { + /* TXD */ + RCAR_GP_PIN(2, 14), +}; +static const unsigned int msiof2_txd_c_mux[] = { + MSIOF2_TXD_C_MARK, +}; +static const unsigned int msiof2_rxd_c_pins[] = { + /* RXD */ + RCAR_GP_PIN(2, 13), +}; +static const unsigned int msiof2_rxd_c_mux[] = { + MSIOF2_RXD_C_MARK, +}; +static const unsigned int msiof2_clk_d_pins[] = { + /* SCK */ + RCAR_GP_PIN(0, 8), +}; +static const unsigned int msiof2_clk_d_mux[] = { + MSIOF2_SCK_D_MARK, +}; +static const unsigned int msiof2_sync_d_pins[] = { + /* SYNC */ + RCAR_GP_PIN(0, 9), +}; +static const unsigned int msiof2_sync_d_mux[] = { + MSIOF2_SYNC_D_MARK, +}; +static const unsigned int msiof2_ss1_d_pins[] = { + /* SS1 */ + RCAR_GP_PIN(0, 12), +}; +static const unsigned int msiof2_ss1_d_mux[] = { + MSIOF2_SS1_D_MARK, +}; +static const unsigned int msiof2_ss2_d_pins[] = { + /* SS2 */ + RCAR_GP_PIN(0, 13), +}; +static const unsigned int msiof2_ss2_d_mux[] = { + MSIOF2_SS2_D_MARK, +}; +static const unsigned int msiof2_txd_d_pins[] = { + /* TXD */ + RCAR_GP_PIN(0, 11), +}; +static const unsigned int msiof2_txd_d_mux[] = { + MSIOF2_TXD_D_MARK, +}; +static const unsigned int msiof2_rxd_d_pins[] = { + /* RXD */ + RCAR_GP_PIN(0, 10), +}; +static const unsigned int msiof2_rxd_d_mux[] = { + MSIOF2_RXD_D_MARK, +}; +/* - MSIOF3 ----------------------------------------------------------------- */ +static const unsigned int msiof3_clk_a_pins[] = { + /* SCK */ + RCAR_GP_PIN(0, 0), +}; +static const unsigned int msiof3_clk_a_mux[] = { + MSIOF3_SCK_A_MARK, +}; +static const unsigned int msiof3_sync_a_pins[] = { + /* SYNC */ + RCAR_GP_PIN(0, 1), +}; +static const unsigned int msiof3_sync_a_mux[] = { + MSIOF3_SYNC_A_MARK, +}; +static const unsigned int msiof3_ss1_a_pins[] = { + /* SS1 */ + RCAR_GP_PIN(0, 14), +}; +static const unsigned int msiof3_ss1_a_mux[] = { + MSIOF3_SS1_A_MARK, +}; +static const unsigned int msiof3_ss2_a_pins[] = { + /* SS2 */ + RCAR_GP_PIN(0, 15), +}; +static const unsigned int msiof3_ss2_a_mux[] = { + MSIOF3_SS2_A_MARK, +}; +static const unsigned int msiof3_txd_a_pins[] = { + /* TXD */ + RCAR_GP_PIN(0, 3), +}; +static const unsigned int msiof3_txd_a_mux[] = { + MSIOF3_TXD_A_MARK, +}; +static const unsigned int msiof3_rxd_a_pins[] = { + /* RXD */ + RCAR_GP_PIN(0, 2), +}; +static const unsigned int msiof3_rxd_a_mux[] = { + MSIOF3_RXD_A_MARK, +}; +static const unsigned int msiof3_clk_b_pins[] = { + /* SCK */ + RCAR_GP_PIN(1, 2), +}; +static const unsigned int msiof3_clk_b_mux[] = { + MSIOF3_SCK_B_MARK, +}; +static const unsigned int msiof3_sync_b_pins[] = { + /* SYNC */ + RCAR_GP_PIN(1, 0), +}; +static const unsigned int msiof3_sync_b_mux[] = { + MSIOF3_SYNC_B_MARK, +}; +static const unsigned int msiof3_ss1_b_pins[] = { + /* SS1 */ + RCAR_GP_PIN(1, 4), +}; +static const unsigned int msiof3_ss1_b_mux[] = { + MSIOF3_SS1_B_MARK, +}; +static const unsigned int msiof3_ss2_b_pins[] = { + /* SS2 */ + RCAR_GP_PIN(1, 5), +}; +static const unsigned int msiof3_ss2_b_mux[] = { + MSIOF3_SS2_B_MARK, +}; +static const unsigned int msiof3_txd_b_pins[] = { + /* TXD */ + RCAR_GP_PIN(1, 1), +}; +static const unsigned int msiof3_txd_b_mux[] = { + MSIOF3_TXD_B_MARK, +}; +static const unsigned int msiof3_rxd_b_pins[] = { + /* RXD */ + RCAR_GP_PIN(1, 3), +}; +static const unsigned int msiof3_rxd_b_mux[] = { + MSIOF3_RXD_B_MARK, +}; +static const unsigned int msiof3_clk_c_pins[] = { + /* SCK */ + RCAR_GP_PIN(1, 12), +}; +static const unsigned int msiof3_clk_c_mux[] = { + MSIOF3_SCK_C_MARK, +}; +static const unsigned int msiof3_sync_c_pins[] = { + /* SYNC */ + RCAR_GP_PIN(1, 13), +}; +static const unsigned int msiof3_sync_c_mux[] = { + MSIOF3_SYNC_C_MARK, +}; +static const unsigned int msiof3_txd_c_pins[] = { + /* TXD */ + RCAR_GP_PIN(1, 15), +}; +static const unsigned int msiof3_txd_c_mux[] = { + MSIOF3_TXD_C_MARK, +}; +static const unsigned int msiof3_rxd_c_pins[] = { + /* RXD */ + RCAR_GP_PIN(1, 14), +}; +static const unsigned int msiof3_rxd_c_mux[] = { + MSIOF3_RXD_C_MARK, +}; +static const unsigned int msiof3_clk_d_pins[] = { + /* SCK */ + RCAR_GP_PIN(1, 22), +}; +static const unsigned int msiof3_clk_d_mux[] = { + MSIOF3_SCK_D_MARK, +}; +static const unsigned int msiof3_sync_d_pins[] = { + /* SYNC */ + RCAR_GP_PIN(1, 23), +}; +static const unsigned int msiof3_sync_d_mux[] = { + MSIOF3_SYNC_D_MARK, +}; +static const unsigned int msiof3_ss1_d_pins[] = { + /* SS1 */ + RCAR_GP_PIN(1, 26), +}; +static const unsigned int msiof3_ss1_d_mux[] = { + MSIOF3_SS1_D_MARK, +}; +static const unsigned int msiof3_txd_d_pins[] = { + /* TXD */ + RCAR_GP_PIN(1, 25), +}; +static const unsigned int msiof3_txd_d_mux[] = { + MSIOF3_TXD_D_MARK, +}; +static const unsigned int msiof3_rxd_d_pins[] = { + /* RXD */ + RCAR_GP_PIN(1, 24), +}; +static const unsigned int msiof3_rxd_d_mux[] = { + MSIOF3_RXD_D_MARK, +}; +static const unsigned int msiof3_clk_e_pins[] = { + /* SCK */ + RCAR_GP_PIN(2, 3), +}; +static const unsigned int msiof3_clk_e_mux[] = { + MSIOF3_SCK_E_MARK, +}; +static const unsigned int msiof3_sync_e_pins[] = { + /* SYNC */ + RCAR_GP_PIN(2, 2), +}; +static const unsigned int msiof3_sync_e_mux[] = { + MSIOF3_SYNC_E_MARK, +}; +static const unsigned int msiof3_ss1_e_pins[] = { + /* SS1 */ + RCAR_GP_PIN(2, 1), +}; +static const unsigned int msiof3_ss1_e_mux[] = { + MSIOF3_SS1_E_MARK, +}; +static const unsigned int msiof3_ss2_e_pins[] = { + /* SS1 */ + RCAR_GP_PIN(2, 0), +}; +static const unsigned int msiof3_ss2_e_mux[] = { + MSIOF3_SS2_E_MARK, +}; +static const unsigned int msiof3_txd_e_pins[] = { + /* TXD */ + RCAR_GP_PIN(2, 5), +}; +static const unsigned int msiof3_txd_e_mux[] = { + MSIOF3_TXD_E_MARK, +}; +static const unsigned int msiof3_rxd_e_pins[] = { + /* RXD */ + RCAR_GP_PIN(2, 4), +}; +static const unsigned int msiof3_rxd_e_mux[] = { + MSIOF3_RXD_E_MARK, +}; + /* - PWM0 --------------------------------------------------------------------*/ static const unsigned int pwm0_pins[] = { /* PWM */ @@ -2075,6 +2773,105 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(du_oddf), SH_PFC_PIN_GROUP(du_cde), SH_PFC_PIN_GROUP(du_disp), + SH_PFC_PIN_GROUP(msiof0_clk), + SH_PFC_PIN_GROUP(msiof0_sync), + SH_PFC_PIN_GROUP(msiof0_ss1), + SH_PFC_PIN_GROUP(msiof0_ss2), + SH_PFC_PIN_GROUP(msiof0_txd), + SH_PFC_PIN_GROUP(msiof0_rxd), + SH_PFC_PIN_GROUP(msiof1_clk_a), + SH_PFC_PIN_GROUP(msiof1_sync_a), + SH_PFC_PIN_GROUP(msiof1_ss1_a), + SH_PFC_PIN_GROUP(msiof1_ss2_a), + SH_PFC_PIN_GROUP(msiof1_txd_a), + SH_PFC_PIN_GROUP(msiof1_rxd_a), + SH_PFC_PIN_GROUP(msiof1_clk_b), + SH_PFC_PIN_GROUP(msiof1_sync_b), + SH_PFC_PIN_GROUP(msiof1_ss1_b), + SH_PFC_PIN_GROUP(msiof1_ss2_b), + SH_PFC_PIN_GROUP(msiof1_txd_b), + SH_PFC_PIN_GROUP(msiof1_rxd_b), + SH_PFC_PIN_GROUP(msiof1_clk_c), + SH_PFC_PIN_GROUP(msiof1_sync_c), + SH_PFC_PIN_GROUP(msiof1_ss1_c), + SH_PFC_PIN_GROUP(msiof1_ss2_c), + SH_PFC_PIN_GROUP(msiof1_txd_c), + SH_PFC_PIN_GROUP(msiof1_rxd_c), + SH_PFC_PIN_GROUP(msiof1_clk_d), + SH_PFC_PIN_GROUP(msiof1_sync_d), + SH_PFC_PIN_GROUP(msiof1_ss1_d), + SH_PFC_PIN_GROUP(msiof1_ss2_d), + SH_PFC_PIN_GROUP(msiof1_txd_d), + SH_PFC_PIN_GROUP(msiof1_rxd_d), + SH_PFC_PIN_GROUP(msiof1_clk_e), + SH_PFC_PIN_GROUP(msiof1_sync_e), + SH_PFC_PIN_GROUP(msiof1_ss1_e), + SH_PFC_PIN_GROUP(msiof1_ss2_e), + SH_PFC_PIN_GROUP(msiof1_txd_e), + SH_PFC_PIN_GROUP(msiof1_rxd_e), + SH_PFC_PIN_GROUP(msiof1_clk_f), + SH_PFC_PIN_GROUP(msiof1_sync_f), + SH_PFC_PIN_GROUP(msiof1_ss1_f), + SH_PFC_PIN_GROUP(msiof1_ss2_f), + SH_PFC_PIN_GROUP(msiof1_txd_f), + SH_PFC_PIN_GROUP(msiof1_rxd_f), + SH_PFC_PIN_GROUP(msiof1_clk_g), + SH_PFC_PIN_GROUP(msiof1_sync_g), + SH_PFC_PIN_GROUP(msiof1_ss1_g), + SH_PFC_PIN_GROUP(msiof1_ss2_g), + SH_PFC_PIN_GROUP(msiof1_txd_g), + SH_PFC_PIN_GROUP(msiof1_rxd_g), + SH_PFC_PIN_GROUP(msiof2_clk_a), + SH_PFC_PIN_GROUP(msiof2_sync_a), + SH_PFC_PIN_GROUP(msiof2_ss1_a), + SH_PFC_PIN_GROUP(msiof2_ss2_a), + SH_PFC_PIN_GROUP(msiof2_txd_a), + SH_PFC_PIN_GROUP(msiof2_rxd_a), + SH_PFC_PIN_GROUP(msiof2_clk_b), + SH_PFC_PIN_GROUP(msiof2_sync_b), + SH_PFC_PIN_GROUP(msiof2_ss1_b), + SH_PFC_PIN_GROUP(msiof2_ss2_b), + SH_PFC_PIN_GROUP(msiof2_txd_b), + SH_PFC_PIN_GROUP(msiof2_rxd_b), + SH_PFC_PIN_GROUP(msiof2_clk_c), + SH_PFC_PIN_GROUP(msiof2_sync_c), + SH_PFC_PIN_GROUP(msiof2_ss1_c), + SH_PFC_PIN_GROUP(msiof2_ss2_c), + SH_PFC_PIN_GROUP(msiof2_txd_c), + SH_PFC_PIN_GROUP(msiof2_rxd_c), + SH_PFC_PIN_GROUP(msiof2_clk_d), + SH_PFC_PIN_GROUP(msiof2_sync_d), + SH_PFC_PIN_GROUP(msiof2_ss1_d), + SH_PFC_PIN_GROUP(msiof2_ss2_d), + SH_PFC_PIN_GROUP(msiof2_txd_d), + SH_PFC_PIN_GROUP(msiof2_rxd_d), + SH_PFC_PIN_GROUP(msiof3_clk_a), + SH_PFC_PIN_GROUP(msiof3_sync_a), + SH_PFC_PIN_GROUP(msiof3_ss1_a), + SH_PFC_PIN_GROUP(msiof3_ss2_a), + SH_PFC_PIN_GROUP(msiof3_txd_a), + SH_PFC_PIN_GROUP(msiof3_rxd_a), + SH_PFC_PIN_GROUP(msiof3_clk_b), + SH_PFC_PIN_GROUP(msiof3_sync_b), + SH_PFC_PIN_GROUP(msiof3_ss1_b), + SH_PFC_PIN_GROUP(msiof3_ss2_b), + SH_PFC_PIN_GROUP(msiof3_txd_b), + SH_PFC_PIN_GROUP(msiof3_rxd_b), + SH_PFC_PIN_GROUP(msiof3_clk_c), + SH_PFC_PIN_GROUP(msiof3_sync_c), + SH_PFC_PIN_GROUP(msiof3_txd_c), + SH_PFC_PIN_GROUP(msiof3_rxd_c), + SH_PFC_PIN_GROUP(msiof3_clk_d), + SH_PFC_PIN_GROUP(msiof3_sync_d), + SH_PFC_PIN_GROUP(msiof3_ss1_d), + SH_PFC_PIN_GROUP(msiof3_txd_d), + SH_PFC_PIN_GROUP(msiof3_rxd_d), + SH_PFC_PIN_GROUP(msiof3_clk_e), + SH_PFC_PIN_GROUP(msiof3_sync_e), + SH_PFC_PIN_GROUP(msiof3_ss1_e), + SH_PFC_PIN_GROUP(msiof3_ss2_e), + SH_PFC_PIN_GROUP(msiof3_txd_e), + SH_PFC_PIN_GROUP(msiof3_rxd_e), SH_PFC_PIN_GROUP(pwm0), SH_PFC_PIN_GROUP(pwm1_a), SH_PFC_PIN_GROUP(pwm1_b), @@ -2143,6 +2940,117 @@ static const char * const du_groups[] = { "du_disp", }; +static const char * const msiof0_groups[] = { + "msiof0_clk", + "msiof0_sync", + "msiof0_ss1", + "msiof0_ss2", + "msiof0_txd", + "msiof0_rxd", +}; + +static const char * const msiof1_groups[] = { + "msiof1_clk_a", + "msiof1_sync_a", + "msiof1_ss1_a", + "msiof1_ss2_a", + "msiof1_txd_a", + "msiof1_rxd_a", + "msiof1_clk_b", + "msiof1_sync_b", + "msiof1_ss1_b", + "msiof1_ss2_b", + "msiof1_txd_b", + "msiof1_rxd_b", + "msiof1_clk_c", + "msiof1_sync_c", + "msiof1_ss1_c", + "msiof1_ss2_c", + "msiof1_txd_c", + "msiof1_rxd_c", + "msiof1_clk_d", + "msiof1_sync_d", + "msiof1_ss1_d", + "msiof1_ss2_d", + "msiof1_txd_d", + "msiof1_rxd_d", + "msiof1_clk_e", + "msiof1_sync_e", + "msiof1_ss1_e", + "msiof1_ss2_e", + "msiof1_txd_e", + "msiof1_rxd_e", + "msiof1_clk_f", + "msiof1_sync_f", + "msiof1_ss1_f", + "msiof1_ss2_f", + "msiof1_txd_f", + "msiof1_rxd_f", + "msiof1_clk_g", + "msiof1_sync_g", + "msiof1_ss1_g", + "msiof1_ss2_g", + "msiof1_txd_g", + "msiof1_rxd_g", +}; + +static const char * const msiof2_groups[] = { + "msiof2_clk_a", + "msiof2_sync_a", + "msiof2_ss1_a", + "msiof2_ss2_a", + "msiof2_txd_a", + "msiof2_rxd_a", + "msiof2_clk_b", + "msiof2_sync_b", + "msiof2_ss1_b", + "msiof2_ss2_b", + "msiof2_txd_b", + "msiof2_rxd_b", + "msiof2_clk_c", + "msiof2_sync_c", + "msiof2_ss1_c", + "msiof2_ss2_c", + "msiof2_txd_c", + "msiof2_rxd_c", + "msiof2_clk_d", + "msiof2_sync_d", + "msiof2_ss1_d", + "msiof2_ss2_d", + "msiof2_txd_d", + "msiof2_rxd_d", +}; + +static const char * const msiof3_groups[] = { + "msiof3_clk_a", + "msiof3_sync_a", + "msiof3_ss1_a", + "msiof3_ss2_a", + "msiof3_txd_a", + "msiof3_rxd_a", + "msiof3_clk_b", + "msiof3_sync_b", + "msiof3_ss1_b", + "msiof3_ss2_b", + "msiof3_txd_b", + "msiof3_rxd_b", + "msiof3_clk_c", + "msiof3_sync_c", + "msiof3_txd_c", + "msiof3_rxd_c", + "msiof3_clk_d", + "msiof3_sync_d", + "msiof3_ss1_d", + "msiof3_txd_d", + "msiof3_rxd_d", + "msiof3_clk_e", + "msiof3_sync_e", + "msiof3_ss1_e", + "msiof3_ss2_e", + "msiof3_txd_e", + "msiof3_rxd_e", +}; + static const char * const pwm0_groups[] = { "pwm0", }; @@ -2230,6 +3138,10 @@ static const char * const scif_clk_groups[] = { static const struct sh_pfc_function pinmux_functions[] = { SH_PFC_FUNCTION(avb), SH_PFC_FUNCTION(du), + SH_PFC_FUNCTION(msiof0), + SH_PFC_FUNCTION(msiof1), + SH_PFC_FUNCTION(msiof2), + SH_PFC_FUNCTION(msiof3), SH_PFC_FUNCTION(pwm0), SH_PFC_FUNCTION(pwm1), SH_PFC_FUNCTION(pwm2), -- cgit v1.2.3 From 70070190871f831ceb46cce6c2b9a1038d1802cf Mon Sep 17 00:00:00 2001 From: Takeshi Kihara Date: Thu, 1 Jun 2017 22:37:24 +0900 Subject: pinctrl: sh-pfc: r8a7796: Fix MSIOF3_{SS1,SS2}_E pin function definitions This patch fixes the incorrect IPSR register value definitions for MSIOF3_{SS1,SS2}_E pin functions. This is a correction to the incorrect implementation of IPSR register pin assignment for R8A7796 SoC specification of R-Car Gen3 Hardware User's Manual Rev.0.51E or later. Fixes: f9aece7344bd81ce ("pinctrl: sh-pfc: Initial R8A7796 PFC support") Signed-off-by: Takeshi Kihara [geert: Reword] Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7796.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c index 98bf5d0e078e..6fa1729d784e 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c @@ -221,8 +221,8 @@ #define IP0_15_12 FM(AVB_LINK) F_(0, 0) FM(MSIOF2_SCK_C) FM(TX4_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP0_19_16 FM(AVB_AVTP_MATCH_A) F_(0, 0) FM(MSIOF2_RXD_C) FM(CTS4_N_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP0_23_20 FM(AVB_AVTP_CAPTURE_A) F_(0, 0) FM(MSIOF2_TXD_C) FM(RTS4_N_TANS_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP0_27_24 FM(IRQ0) FM(QPOLB) F_(0, 0) FM(DU_CDE) FM(VI4_DATA0_B) FM(CAN0_TX_B) FM(CANFD0_TX_B) FM(MSIOF3_SS1_E) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP0_31_28 FM(IRQ1) FM(QPOLA) F_(0, 0) FM(DU_DISP) FM(VI4_DATA1_B) FM(CAN0_RX_B) FM(CANFD0_RX_B) FM(MSIOF3_SS2_E) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0_27_24 FM(IRQ0) FM(QPOLB) F_(0, 0) FM(DU_CDE) FM(VI4_DATA0_B) FM(CAN0_TX_B) FM(CANFD0_TX_B) FM(MSIOF3_SS2_E) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0_31_28 FM(IRQ1) FM(QPOLA) F_(0, 0) FM(DU_DISP) FM(VI4_DATA1_B) FM(CAN0_RX_B) FM(CANFD0_RX_B) FM(MSIOF3_SS1_E) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1_3_0 FM(IRQ2) FM(QCPV_QDE) F_(0, 0) FM(DU_EXODDF_DU_ODDF_DISP_CDE) FM(VI4_DATA2_B) F_(0, 0) F_(0, 0) FM(MSIOF3_SYNC_E) F_(0, 0) FM(PWM3_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1_7_4 FM(IRQ3) FM(QSTVB_QVE) FM(A25) FM(DU_DOTCLKOUT1) FM(VI4_DATA3_B) F_(0, 0) F_(0, 0) FM(MSIOF3_SCK_E) F_(0, 0) FM(PWM4_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1_11_8 FM(IRQ4) FM(QSTH_QHS) FM(A24) FM(DU_EXHSYNC_DU_HSYNC) FM(VI4_DATA4_B) F_(0, 0) F_(0, 0) FM(MSIOF3_RXD_E) F_(0, 0) FM(PWM5_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -- cgit v1.2.3 From 1554b989e58c8e5327da5391ea66b6b166f09d8e Mon Sep 17 00:00:00 2001 From: Takeshi Kihara Date: Thu, 1 Jun 2017 22:25:30 +0900 Subject: pinctrl: sh-pfc: r8a7796: Fix IPSR setting for MSIOF3_SS1_E pin This patch fixes the IPSR register setting when the MSIOF3_SS1_E pin function is selected. This is a correction to the incorrect implementation of IPSR register pin assignment for R8A7796 SoC specification of R-Car Gen3 Hardware User's Manual Rev.0.51E or later. Fixes: f9aece7344bd81ce ("pinctrl: sh-pfc: Initial R8A7796 PFC support") Signed-off-by: Takeshi Kihara [geert: Reword] Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7796.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c index 6fa1729d784e..0fd96f198b4d 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c @@ -645,7 +645,7 @@ static const u16 pinmux_data[] = { PINMUX_IPSR_MSEL(IP0_31_28, VI4_DATA1_B, SEL_VIN4_1), PINMUX_IPSR_MSEL(IP0_31_28, CAN0_RX_B, SEL_RCAN0_1), PINMUX_IPSR_MSEL(IP0_31_28, CANFD0_RX_B, SEL_CANFD0_1), - PINMUX_IPSR_MSEL(IP0_27_24, MSIOF3_SS1_E, SEL_MSIOF3_4), + PINMUX_IPSR_MSEL(IP0_31_28, MSIOF3_SS1_E, SEL_MSIOF3_4), /* IPSR1 */ PINMUX_IPSR_GPSR(IP1_3_0, IRQ2), -- cgit v1.2.3 From b6db6bfe7188058b34b6385ea68c0be37cff5714 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 11 Jul 2017 11:56:24 +0200 Subject: pinctrl: sh-pfc: r8a7796: Fix MSIOF3 SS2_E mux Fix a copy-and-paste bug in the MSIOF3 SS2_E mux array. Fixes: 4753231cc9468390 ("pinctrl: sh-pfc: r8a7796: Add MSIOF pins, groups and functions") Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7796.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c index 0fd96f198b4d..1ef8d90e48ce 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c @@ -3082,7 +3082,7 @@ static const unsigned int msiof3_ss2_e_pins[] = { RCAR_GP_PIN(2, 0), }; static const unsigned int msiof3_ss2_e_mux[] = { - MSIOF3_SS1_E_MARK, + MSIOF3_SS2_E_MARK, }; static const unsigned int msiof3_txd_e_pins[] = { /* TXD */ -- cgit v1.2.3 From 2bf147a836918b14aae7aba2e598fa18a73e4f19 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 12 Jul 2017 13:53:34 +0200 Subject: pinctrl: sh-pfc: r8a7791: Add missing mmc_data8_b pin group Pins D6 and D7 of the MMC interface can be muxed to two different sets of pins, but currently only one set is supported. Add a pin group for the alternative set to fix this. Signed-off-by: Geert Uytterhoeven Reviewed-by: Chris Paterson Tested-by: Chris Paterson --- drivers/pinctrl/sh-pfc/pfc-r8a7791.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c index 4c5ffbd75be7..10bd35f8c894 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c @@ -2589,6 +2589,17 @@ static const unsigned int mmc_data8_mux[] = { MMC_D0_MARK, MMC_D1_MARK, MMC_D2_MARK, MMC_D3_MARK, MMC_D4_MARK, MMC_D5_MARK, MMC_D6_MARK, MMC_D7_MARK, }; +static const unsigned int mmc_data8_b_pins[] = { + /* D[0:7] */ + RCAR_GP_PIN(6, 18), RCAR_GP_PIN(6, 19), + RCAR_GP_PIN(6, 20), RCAR_GP_PIN(6, 21), + RCAR_GP_PIN(6, 22), RCAR_GP_PIN(6, 23), + RCAR_GP_PIN(6, 6), RCAR_GP_PIN(6, 7), +}; +static const unsigned int mmc_data8_b_mux[] = { + MMC_D0_MARK, MMC_D1_MARK, MMC_D2_MARK, MMC_D3_MARK, + MMC_D4_MARK, MMC_D5_MARK, MMC_D6_B_MARK, MMC_D7_B_MARK, +}; static const unsigned int mmc_ctrl_pins[] = { /* CLK, CMD */ RCAR_GP_PIN(6, 16), RCAR_GP_PIN(6, 17), @@ -4420,7 +4431,7 @@ static const unsigned int vin2_clk_mux[] = { }; static const struct { - struct sh_pfc_pin_group common[341]; + struct sh_pfc_pin_group common[342]; struct sh_pfc_pin_group r8a779x[9]; } pinmux_groups = { .common = { @@ -4523,6 +4534,7 @@ static const struct { SH_PFC_PIN_GROUP(mmc_data1), SH_PFC_PIN_GROUP(mmc_data4), SH_PFC_PIN_GROUP(mmc_data8), + SH_PFC_PIN_GROUP(mmc_data8_b), SH_PFC_PIN_GROUP(mmc_ctrl), SH_PFC_PIN_GROUP(msiof0_clk), SH_PFC_PIN_GROUP(msiof0_sync), @@ -4955,6 +4967,7 @@ static const char * const mmc_groups[] = { "mmc_data1", "mmc_data4", "mmc_data8", + "mmc_data8_b", "mmc_ctrl", }; -- cgit v1.2.3 From 7aa36a334dc3f11188d9cc024cfa06debb5cf7e6 Mon Sep 17 00:00:00 2001 From: Takeshi Kihara Date: Thu, 13 Jul 2017 01:55:34 +0900 Subject: pinctrl: sh-pfc: r8a7796: Fix MOD_SEL1 bit[25:24] to 0x3 when using STP_ISEN_1_D This patch fixes the implementation incorrect of MOD_SEL1 bit[25:24] value when STP_ISEN_1_D pin function is selected for IPSR17 bit[27:24]. This is a correction to the incorrect implementation of MOD_SEL register pin assignment for R8A7796 SoC specification of R-Car Gen3 Hardware User's Manual Rev.0.51E or later. Fixes: f9aece7344bd81ce ("pinctrl: sh-pfc: Initial R8A7796 PFC support") Signed-off-by: Takeshi Kihara Signed-off-by: Yoshihiro Kaneko Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7796.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c index 1ef8d90e48ce..e489653eb914 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c @@ -1461,7 +1461,7 @@ static const u16 pinmux_data[] = { PINMUX_IPSR_GPSR(IP17_27_24, AUDIO_CLKOUT_B), PINMUX_IPSR_MSEL(IP17_27_24, SSI_SCK2_B, SEL_SSI_1), PINMUX_IPSR_MSEL(IP17_27_24, TS_SDEN1_D, SEL_TSIF1_3), - PINMUX_IPSR_MSEL(IP17_27_24, STP_ISEN_1_D, SEL_SSP1_1_2), + PINMUX_IPSR_MSEL(IP17_27_24, STP_ISEN_1_D, SEL_SSP1_1_3), PINMUX_IPSR_MSEL(IP17_27_24, STP_OPWM_0_E, SEL_SSP1_0_4), PINMUX_IPSR_MSEL(IP17_27_24, RIF3_D0_B, SEL_DRIF3_1), PINMUX_IPSR_MSEL(IP17_27_24, TCLK2_B, SEL_TIMER_TMU_1), -- cgit v1.2.3 From 04ee2ab395db733c04f02b6ba0d8f13aa0a5d744 Mon Sep 17 00:00:00 2001 From: Takeshi Kihara Date: Thu, 13 Jul 2017 01:55:36 +0900 Subject: pinctrl: sh-pfc: r8a7796: Fix MOD_SEL2 bit26 to 0x0 when using SCK5_A This patch fixes the implementation incorrect of MOD_SEL2 bit26 value when SCK5_A pin function is selected for IPSR16 bit[31:28]. This is a correction to the incorrect implementation of MOD_SEL register pin assignment for R8A7796 SoC specification of R-Car Gen3 Hardware User's Manual Rev.0.51E or later. Fixes: f9aece7344bd81ce ("pinctrl: sh-pfc: Initial R8A7796 PFC support") Signed-off-by: Takeshi Kihara Signed-off-by: Yoshihiro Kaneko Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7796.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c index e489653eb914..a6d3c61ded7a 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c @@ -1410,7 +1410,7 @@ static const u16 pinmux_data[] = { PINMUX_IPSR_MSEL(IP16_31_28, SSI_WS1_B, SEL_SSI_1), PINMUX_IPSR_GPSR(IP16_31_28, SCK1), PINMUX_IPSR_MSEL(IP16_31_28, STP_IVCXO27_1_A, SEL_SSP1_1_0), - PINMUX_IPSR_GPSR(IP16_31_28, SCK5_A), + PINMUX_IPSR_MSEL(IP16_31_28, SCK5_A, SEL_SCIF5_0), /* IPSR17 */ PINMUX_IPSR_MSEL(IP17_3_0, AUDIO_CLKA_A, SEL_ADG_A_0), -- cgit v1.2.3 From dda7e6ce8e58328053242b5dbe6f9f10a673302c Mon Sep 17 00:00:00 2001 From: Takeshi Kihara Date: Thu, 13 Jul 2017 01:55:38 +0900 Subject: pinctrl: sh-pfc: r8a7796: Fix SCIF_CLK_{A,B} pin's MOD_SEL assignment to MOD_SEL1 bit10 This patch fixes SCIF_CLK_{A,B} pin's MOD_SEL assignment from MOD_SEL1 bit11 to MOD_SEL1 bit10. This is a correction to the incorrect implementation of IPSR register pin assignment for R8A7796 SoC specification of R-Car Gen3 Hardware User's Manual Rev.0.51E or later. Fixes: f9aece7344bd81ce ("pinctrl: sh-pfc: Initial R8A7796 PFC support") Signed-off-by: Takeshi Kihara Signed-off-by: Yoshihiro Kaneko Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7796.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c index a6d3c61ded7a..b110fca1b0ec 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c @@ -488,7 +488,7 @@ FM(IP16_31_28) IP16_31_28 FM(IP17_31_28) IP17_31_28 #define MOD_SEL1_13 FM(SEL_SCIF3_0) FM(SEL_SCIF3_1) #define MOD_SEL1_12 FM(SEL_SCIF2_0) FM(SEL_SCIF2_1) #define MOD_SEL1_11 FM(SEL_SCIF1_0) FM(SEL_SCIF1_1) -#define MOD_SEL1_10 FM(SEL_SATA_0) FM(SEL_SATA_1) +#define MOD_SEL1_10 FM(SEL_SCIF_0) FM(SEL_SCIF_1) #define MOD_SEL1_9 FM(SEL_REMOCON_0) FM(SEL_REMOCON_1) #define MOD_SEL1_6 FM(SEL_RCAN0_0) FM(SEL_RCAN0_1) #define MOD_SEL1_5 FM(SEL_PWM6_0) FM(SEL_PWM6_1) @@ -1205,7 +1205,7 @@ static const u16 pinmux_data[] = { PINMUX_IPSR_GPSR(IP12_27_24, ADICHS0), PINMUX_IPSR_GPSR(IP12_31_28, SCK2), - PINMUX_IPSR_MSEL(IP12_31_28, SCIF_CLK_B, SEL_SCIF1_1), + PINMUX_IPSR_MSEL(IP12_31_28, SCIF_CLK_B, SEL_SCIF_1), PINMUX_IPSR_MSEL(IP12_31_28, MSIOF1_SCK_B, SEL_MSIOF1_1), PINMUX_IPSR_MSEL(IP12_31_28, TS_SCK1_C, SEL_TSIF1_2), PINMUX_IPSR_MSEL(IP12_31_28, STP_ISCLK_1_C, SEL_SSP1_1_2), @@ -1417,7 +1417,7 @@ static const u16 pinmux_data[] = { PINMUX_IPSR_GPSR(IP17_3_0, CC5_OSCOUT), PINMUX_IPSR_MSEL(IP17_7_4, AUDIO_CLKB_B, SEL_ADG_B_1), - PINMUX_IPSR_MSEL(IP17_7_4, SCIF_CLK_A, SEL_SCIF1_0), + PINMUX_IPSR_MSEL(IP17_7_4, SCIF_CLK_A, SEL_SCIF_0), PINMUX_IPSR_MSEL(IP17_7_4, STP_IVCXO27_1_D, SEL_SSP1_1_3), PINMUX_IPSR_MSEL(IP17_7_4, REMOCON_A, SEL_REMOCON_0), PINMUX_IPSR_MSEL(IP17_7_4, TCLK1_A, SEL_TIMER_TMU_0), -- cgit v1.2.3 From 5d26ee5172dc6b0ddceac835a6a1d838cfd7f135 Mon Sep 17 00:00:00 2001 From: Takeshi Kihara Date: Thu, 13 Jul 2017 01:55:39 +0900 Subject: pinctrl: sh-pfc: r8a7796: Fix FMCLK{_C,_D} and FMIN{_C,_D} pin function definitions This patch fixes the implementation incorrect of IPSR register value definitions for FMCLK{_C,_D} and FMIN{_C,_D} pins function. This is a correction to the incorrect implementation of IPSR register pin assignment for R8A7796 SoC specification of R-Car Gen3 Hardware User's Manual Rev.0.51E or later. Fixes: f9aece7344bd81ce ("pinctrl: sh-pfc: Initial R8A7796 PFC support") Signed-off-by: Takeshi Kihara Signed-off-by: Yoshihiro Kaneko Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7796.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c index b110fca1b0ec..37778e101cb5 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c @@ -367,8 +367,8 @@ #define IP17_23_20 FM(USB1_OVC) F_(0, 0) FM(MSIOF1_SS2_C) F_(0, 0) FM(SSI_WS1_A) FM(TS_SDAT0_E) FM(STP_ISD_0_E) FM(FMIN_B) FM(RIF2_SYNC_B) F_(0, 0) FM(REMOCON_B) F_(0, 0) F_(0, 0) FM(HCTS2_N_C) F_(0, 0) F_(0, 0) #define IP17_27_24 FM(USB30_PWEN) F_(0, 0) F_(0, 0) FM(AUDIO_CLKOUT_B) FM(SSI_SCK2_B) FM(TS_SDEN1_D) FM(STP_ISEN_1_D) FM(STP_OPWM_0_E)FM(RIF3_D0_B) F_(0, 0) FM(TCLK2_B) FM(TPU0TO0) FM(BPFCLK_C) FM(HRTS2_N_C) F_(0, 0) F_(0, 0) #define IP17_31_28 FM(USB30_OVC) F_(0, 0) F_(0, 0) FM(AUDIO_CLKOUT1_B) FM(SSI_WS2_B) FM(TS_SPSYNC1_D)FM(STP_ISSYNC_1_D) FM(STP_IVCXO27_0_E)FM(RIF3_D1_B) F_(0, 0) FM(FSO_TOE_B) FM(TPU0TO1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP18_3_0 FM(GP6_30) F_(0, 0) F_(0, 0) FM(AUDIO_CLKOUT2_B) FM(SSI_SCK9_B) FM(TS_SDEN0_E) FM(STP_ISEN_0_E) F_(0, 0) FM(RIF2_D0_B) F_(0, 0) FM(FSO_CFE_0_A) FM(TPU0TO2) F_(0, 0) FM(FMCLK_C) FM(FMCLK_D) F_(0, 0) -#define IP18_7_4 FM(GP6_31) F_(0, 0) F_(0, 0) FM(AUDIO_CLKOUT3_B) FM(SSI_WS9_B) FM(TS_SPSYNC0_E)FM(STP_ISSYNC_0_E) F_(0, 0) FM(RIF2_D1_B) F_(0, 0) FM(FSO_CFE_1_A) FM(TPU0TO3) F_(0, 0) FM(FMIN_C) FM(FMIN_D) F_(0, 0) +#define IP18_3_0 FM(GP6_30) F_(0, 0) F_(0, 0) FM(AUDIO_CLKOUT2_B) FM(SSI_SCK9_B) FM(TS_SDEN0_E) FM(STP_ISEN_0_E) F_(0, 0) FM(RIF2_D0_B) F_(0, 0) FM(FSO_CFE_0_A) FM(TPU0TO2) FM(FMCLK_C) FM(FMCLK_D) F_(0, 0) F_(0, 0) +#define IP18_7_4 FM(GP6_31) F_(0, 0) F_(0, 0) FM(AUDIO_CLKOUT3_B) FM(SSI_WS9_B) FM(TS_SPSYNC0_E)FM(STP_ISSYNC_0_E) F_(0, 0) FM(RIF2_D1_B) F_(0, 0) FM(FSO_CFE_1_A) FM(TPU0TO3) FM(FMIN_C) FM(FMIN_D) F_(0, 0) F_(0, 0) #define PINMUX_GPSR \ \ -- cgit v1.2.3 From 6fb1870912f84b1d81fd21cdfe8c9a75f8aa1669 Mon Sep 17 00:00:00 2001 From: Takeshi Kihara Date: Thu, 13 Jul 2017 01:55:40 +0900 Subject: pinctrl: sh-pfc: r8a7796: Fix NFDATA{0..13} and NF{ALE,CLE,WE_N,RE_N} pin function definitions This patch fixes the implementation incorrect of IPSR register value definitions for NFDATA{0..13} and NF{ALE,CLE,WE_N,RE_N} pins function. This is a correction to the incorrect implementation of IPSR register pin assignment for R8A7796 SoC specification of R-Car Gen3 Hardware User's Manual Rev.0.51E or later. Fixes: f9aece7344bd81ce ("pinctrl: sh-pfc: Initial R8A7796 PFC support") Signed-off-by: Takeshi Kihara Signed-off-by: Yoshihiro Kaneko Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7796.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c index 37778e101cb5..169a1d6f7f5e 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c @@ -291,24 +291,24 @@ #define IP8_23_20 FM(SD1_DAT1) FM(SD2_DAT5) FM(MSIOF1_TXD_G) FM(NFDATA14_B) F_(0, 0) FM(TS_SPSYNC1_B)FM(STP_ISSYNC_1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP8_27_24 FM(SD1_DAT2) FM(SD2_DAT6) FM(MSIOF1_SS1_G) FM(NFDATA15_B) F_(0, 0) FM(TS_SDAT1_B) FM(STP_ISD_1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP8_31_28 FM(SD1_DAT3) FM(SD2_DAT7) FM(MSIOF1_SS2_G) FM(NFRB_N_B) F_(0, 0) FM(TS_SDEN1_B) FM(STP_ISEN_1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP9_3_0 FM(SD2_CLK) F_(0, 0) F_(0, 0) FM(NFDATA8) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP9_7_4 FM(SD2_CMD) F_(0, 0) F_(0, 0) FM(NFDATA9) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP9_11_8 FM(SD2_DAT0) F_(0, 0) F_(0, 0) FM(NFDATA10) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP9_15_12 FM(SD2_DAT1) F_(0, 0) F_(0, 0) FM(NFDATA11) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP9_19_16 FM(SD2_DAT2) F_(0, 0) F_(0, 0) FM(NFDATA12) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP9_23_20 FM(SD2_DAT3) F_(0, 0) F_(0, 0) FM(NFDATA13) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP9_27_24 FM(SD2_DS) F_(0, 0) F_(0, 0) FM(NFALE) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(SATA_DEVSLP_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP9_31_28 FM(SD3_CLK) F_(0, 0) F_(0, 0) FM(NFWE_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP10_3_0 FM(SD3_CMD) F_(0, 0) F_(0, 0) FM(NFRE_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP10_7_4 FM(SD3_DAT0) F_(0, 0) F_(0, 0) FM(NFDATA0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP10_11_8 FM(SD3_DAT1) F_(0, 0) F_(0, 0) FM(NFDATA1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP10_15_12 FM(SD3_DAT2) F_(0, 0) F_(0, 0) FM(NFDATA2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP10_19_16 FM(SD3_DAT3) F_(0, 0) F_(0, 0) FM(NFDATA3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP10_23_20 FM(SD3_DAT4) FM(SD2_CD_A) F_(0, 0) FM(NFDATA4) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP10_27_24 FM(SD3_DAT5) FM(SD2_WP_A) F_(0, 0) FM(NFDATA5) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP10_31_28 FM(SD3_DAT6) FM(SD3_CD) F_(0, 0) FM(NFDATA6) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP11_3_0 FM(SD3_DAT7) FM(SD3_WP) F_(0, 0) FM(NFDATA7) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP11_7_4 FM(SD3_DS) F_(0, 0) F_(0, 0) FM(NFCLE) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP9_3_0 FM(SD2_CLK) F_(0, 0) FM(NFDATA8) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP9_7_4 FM(SD2_CMD) F_(0, 0) FM(NFDATA9) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP9_11_8 FM(SD2_DAT0) F_(0, 0) FM(NFDATA10) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP9_15_12 FM(SD2_DAT1) F_(0, 0) FM(NFDATA11) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP9_19_16 FM(SD2_DAT2) F_(0, 0) FM(NFDATA12) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP9_23_20 FM(SD2_DAT3) F_(0, 0) FM(NFDATA13) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP9_27_24 FM(SD2_DS) F_(0, 0) FM(NFALE) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(SATA_DEVSLP_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP9_31_28 FM(SD3_CLK) F_(0, 0) FM(NFWE_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP10_3_0 FM(SD3_CMD) F_(0, 0) FM(NFRE_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP10_7_4 FM(SD3_DAT0) F_(0, 0) FM(NFDATA0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP10_11_8 FM(SD3_DAT1) F_(0, 0) FM(NFDATA1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP10_15_12 FM(SD3_DAT2) F_(0, 0) FM(NFDATA2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP10_19_16 FM(SD3_DAT3) F_(0, 0) FM(NFDATA3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP10_23_20 FM(SD3_DAT4) FM(SD2_CD_A) FM(NFDATA4) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP10_27_24 FM(SD3_DAT5) FM(SD2_WP_A) FM(NFDATA5) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP10_31_28 FM(SD3_DAT6) FM(SD3_CD) FM(NFDATA6) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP11_3_0 FM(SD3_DAT7) FM(SD3_WP) FM(NFDATA7) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP11_7_4 FM(SD3_DS) F_(0, 0) FM(NFCLE) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP11_11_8 FM(SD0_CD) F_(0, 0) FM(NFDATA14_A) F_(0, 0) FM(SCL2_B) FM(SIM0_RST_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) /* IPSRx */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 */ /* 7 */ /* 8 */ /* 9 */ /* A */ /* B */ /* C - F */ -- cgit v1.2.3 From f21b4fca14ad00a64fbb4460e14172ce9ced9c97 Mon Sep 17 00:00:00 2001 From: Takeshi Kihara Date: Thu, 13 Jul 2017 01:55:42 +0900 Subject: pinctrl: sh-pfc: r8a7796: Fix MOD_SEL register pin assignment for TCLK{1,2}_{A,B} pins group This patch fixes to set MOD_SEL2 bit19 when using TCLK2_A pin function is selected for IPSR16 bit[23:20] or using TCLK2_B pin function is selected for IPSR17 bit[27:24]. This is a correction to the incorrect implementation of MOD_SEL register pin assignment for R8A7796 SoC specification of R-Car Gen3 Hardware User's Manual Rev.0.51E or later. Fixes: f9aece7344bd81ce ("pinctrl: sh-pfc: Initial R8A7796 PFC support") Signed-off-by: Takeshi Kihara Signed-off-by: Yoshihiro Kaneko Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7796.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c index 169a1d6f7f5e..d878638b8306 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c @@ -1393,7 +1393,7 @@ static const u16 pinmux_data[] = { PINMUX_IPSR_MSEL(IP16_23_20, STP_ISEN_1_A, SEL_SSP1_1_0), PINMUX_IPSR_MSEL(IP16_23_20, RIF1_D0_A, SEL_DRIF1_0), PINMUX_IPSR_MSEL(IP16_23_20, RIF3_D0_A, SEL_DRIF3_0), - PINMUX_IPSR_MSEL(IP16_23_20, TCLK2_A, SEL_TIMER_TMU_0), + PINMUX_IPSR_MSEL(IP16_23_20, TCLK2_A, SEL_TIMER_TMU2_0), PINMUX_IPSR_GPSR(IP16_27_24, SSI_SDATA8), PINMUX_IPSR_MSEL(IP16_27_24, HRTS2_N_B, SEL_HSCIF2_1), @@ -1464,7 +1464,7 @@ static const u16 pinmux_data[] = { PINMUX_IPSR_MSEL(IP17_27_24, STP_ISEN_1_D, SEL_SSP1_1_3), PINMUX_IPSR_MSEL(IP17_27_24, STP_OPWM_0_E, SEL_SSP1_0_4), PINMUX_IPSR_MSEL(IP17_27_24, RIF3_D0_B, SEL_DRIF3_1), - PINMUX_IPSR_MSEL(IP17_27_24, TCLK2_B, SEL_TIMER_TMU_1), + PINMUX_IPSR_MSEL(IP17_27_24, TCLK2_B, SEL_TIMER_TMU2_1), PINMUX_IPSR_GPSR(IP17_27_24, TPU0TO0), PINMUX_IPSR_MSEL(IP17_27_24, BPFCLK_C, SEL_FM_2), PINMUX_IPSR_MSEL(IP17_27_24, HRTS2_N_C, SEL_HSCIF2_2), -- cgit v1.2.3 From 8921778241188e9752aeac2aa54584795c043ce0 Mon Sep 17 00:00:00 2001 From: Takeshi Kihara Date: Thu, 13 Jul 2017 01:55:43 +0900 Subject: pinctrl: sh-pfc: r8a7796: Fix to delete FSCLKST pin and IPSR7 bit[15:12] register definitions This patch fixes the macro definitions of FSCLKST pins function and IPSR7 bit[15:12] register deleted. This is a correction because IPSR register specification for R8A7796 SoC was changed in R-Car Gen3 Hardware User's Manual Rev.0.53E or later. Fixes: f9aece7344bd81ce ("pinctrl: sh-pfc: Initial R8A7796 PFC support") Signed-off-by: Takeshi Kihara Signed-off-by: Yoshihiro Kaneko Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7796.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c index d878638b8306..a843368baae0 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c @@ -278,7 +278,6 @@ #define IP7_3_0 FM(D13) FM(LCDOUT5) FM(MSIOF2_SS2_D) FM(TX4_C) FM(VI4_DATA5_A) F_(0, 0) FM(DU_DR5) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP7_7_4 FM(D14) FM(LCDOUT6) FM(MSIOF3_SS1_A) FM(HRX3_C) FM(VI4_DATA6_A) F_(0, 0) FM(DU_DR6) FM(SCL6_C) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP7_11_8 FM(D15) FM(LCDOUT7) FM(MSIOF3_SS2_A) FM(HTX3_C) FM(VI4_DATA7_A) F_(0, 0) FM(DU_DR7) FM(SDA6_C) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP7_15_12 FM(FSCLKST) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP7_19_16 FM(SD0_CLK) F_(0, 0) FM(MSIOF1_SCK_E) F_(0, 0) F_(0, 0) F_(0, 0) FM(STP_OPWM_0_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP7_23_20 FM(SD0_CMD) F_(0, 0) FM(MSIOF1_SYNC_E) F_(0, 0) F_(0, 0) F_(0, 0) FM(STP_IVCXO27_0_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP7_27_24 FM(SD0_DAT0) F_(0, 0) FM(MSIOF1_RXD_E) F_(0, 0) F_(0, 0) FM(TS_SCK0_B) FM(STP_ISCLK_0_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) @@ -419,7 +418,7 @@ FM(IP0_31_28) IP0_31_28 FM(IP1_31_28) IP1_31_28 FM(IP2_31_28) IP2_31_28 FM(IP3_3 FM(IP4_3_0) IP4_3_0 FM(IP5_3_0) IP5_3_0 FM(IP6_3_0) IP6_3_0 FM(IP7_3_0) IP7_3_0 \ FM(IP4_7_4) IP4_7_4 FM(IP5_7_4) IP5_7_4 FM(IP6_7_4) IP6_7_4 FM(IP7_7_4) IP7_7_4 \ FM(IP4_11_8) IP4_11_8 FM(IP5_11_8) IP5_11_8 FM(IP6_11_8) IP6_11_8 FM(IP7_11_8) IP7_11_8 \ -FM(IP4_15_12) IP4_15_12 FM(IP5_15_12) IP5_15_12 FM(IP6_15_12) IP6_15_12 FM(IP7_15_12) IP7_15_12 \ +FM(IP4_15_12) IP4_15_12 FM(IP5_15_12) IP5_15_12 FM(IP6_15_12) IP6_15_12 \ FM(IP4_19_16) IP4_19_16 FM(IP5_19_16) IP5_19_16 FM(IP6_19_16) IP6_19_16 FM(IP7_19_16) IP7_19_16 \ FM(IP4_23_20) IP4_23_20 FM(IP5_23_20) IP5_23_20 FM(IP6_23_20) IP6_23_20 FM(IP7_23_20) IP7_23_20 \ FM(IP4_27_24) IP4_27_24 FM(IP5_27_24) IP5_27_24 FM(IP6_27_24) IP6_27_24 FM(IP7_27_24) IP7_27_24 \ @@ -990,8 +989,6 @@ static const u16 pinmux_data[] = { PINMUX_IPSR_GPSR(IP7_11_8, DU_DR7), PINMUX_IPSR_MSEL(IP7_11_8, SDA6_C, SEL_I2C6_2), - PINMUX_IPSR_GPSR(IP7_15_12, FSCLKST), - PINMUX_IPSR_GPSR(IP7_19_16, SD0_CLK), PINMUX_IPSR_MSEL(IP7_19_16, MSIOF1_SCK_E, SEL_MSIOF1_4), PINMUX_IPSR_MSEL(IP7_19_16, STP_OPWM_0_B, SEL_SSP1_0_1), @@ -4927,7 +4924,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { IP7_27_24 IP7_23_20 IP7_19_16 - IP7_15_12 + /* IP7_15_12 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, IP7_11_8 IP7_7_4 IP7_3_0 } -- cgit v1.2.3 From 0a5e7370be139ecf52e09edb053be781a81ca3c1 Mon Sep 17 00:00:00 2001 From: Takeshi Kihara Date: Thu, 13 Jul 2017 01:55:44 +0900 Subject: pinctrl: sh-pfc: r8a7796: Fix to delete SATA_DEVSLP_B pins function definitions This patch fixes the macro definitions of SATA_DEVSLP_B pins function deleted. This is a correction to the incorrect implementation of IPSR register pin assignment for R8A7796 SoC specification of R-Car Gen3 Hardware User's Manual Rev.0.51E or later. Fixes: f9aece7344bd81ce ("pinctrl: sh-pfc: Initial R8A7796 PFC support") Signed-off-by: Takeshi Kihara Signed-off-by: Yoshihiro Kaneko Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7796.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c index a843368baae0..899675e19ab9 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c @@ -296,7 +296,7 @@ #define IP9_15_12 FM(SD2_DAT1) F_(0, 0) FM(NFDATA11) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP9_19_16 FM(SD2_DAT2) F_(0, 0) FM(NFDATA12) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP9_23_20 FM(SD2_DAT3) F_(0, 0) FM(NFDATA13) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP9_27_24 FM(SD2_DS) F_(0, 0) FM(NFALE) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(SATA_DEVSLP_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP9_27_24 FM(SD2_DS) F_(0, 0) FM(NFALE) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP9_31_28 FM(SD3_CLK) F_(0, 0) FM(NFWE_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP10_3_0 FM(SD3_CMD) F_(0, 0) FM(NFRE_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP10_7_4 FM(SD3_DAT0) F_(0, 0) FM(NFDATA0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -- cgit v1.2.3 From e56c513a7a2afad84bd1eba3a361a1d6d6abf5ce Mon Sep 17 00:00:00 2001 From: Takeshi Kihara Date: Thu, 13 Jul 2017 01:55:45 +0900 Subject: pinctrl: sh-pfc: r8a7796: Fix to delete MOD_SEL0 bit2 register definitions This patch fixes the macro definitions of MOD_SEL0 bit2 register deleted. This is a correction because MOD_SEL register specification for R8A7796 SoC was changed in R-Car Gen3 Hardware User's Manual Rev.0.53E. Fixes: f9aece7344bd81ce ("pinctrl: sh-pfc: Initial R8A7796 PFC support") Signed-off-by: Takeshi Kihara Signed-off-by: Yoshihiro Kaneko Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7796.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c index 899675e19ab9..fda815789c72 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c @@ -471,7 +471,6 @@ FM(IP16_31_28) IP16_31_28 FM(IP17_31_28) IP17_31_28 #define MOD_SEL0_7_6 FM(SEL_DRIF0_0) FM(SEL_DRIF0_1) FM(SEL_DRIF0_2) F_(0, 0) #define MOD_SEL0_5 FM(SEL_CANFD0_0) FM(SEL_CANFD0_1) #define MOD_SEL0_4_3 FM(SEL_ADG_A_0) FM(SEL_ADG_A_1) FM(SEL_ADG_A_2) FM(SEL_ADG_A_3) -#define MOD_SEL0_2 FM(SEL_5LINE_0) FM(SEL_5LINE_1) /* MOD_SEL1 */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 */ /* 7 */ #define MOD_SEL1_31_30 FM(SEL_TSIF1_0) FM(SEL_TSIF1_1) FM(SEL_TSIF1_2) FM(SEL_TSIF1_3) @@ -540,7 +539,7 @@ MOD_SEL0_7_6 \ MOD_SEL0_5 MOD_SEL1_5 \ MOD_SEL0_4_3 MOD_SEL1_4 \ MOD_SEL1_3 \ -MOD_SEL0_2 MOD_SEL1_2 \ + MOD_SEL1_2 \ MOD_SEL1_1 \ MOD_SEL1_0 MOD_SEL2_0 -- cgit v1.2.3 From 78864ed5f3a743a36e9000db94709eca960efdcb Mon Sep 17 00:00:00 2001 From: Takeshi Kihara Date: Thu, 13 Jul 2017 01:55:46 +0900 Subject: pinctrl: sh-pfc: r8a7796: Fix IPSR and MOD_SEL register pin assignment for FSO pins group This patch fixes IPSR{12,17,18} and MOD_SEL0 pin assignment for FSO pins group. This is a correction because GPSR and IPSR register specification for R8A7796 SoC was changed in R-Car Gen3 Hardware User's Manual Rev.0.54E. Fixes: f9aece7344bd81ce ("pinctrl: sh-pfc: Initial R8A7796 PFC support") Signed-off-by: Takeshi Kihara Signed-off-by: Yoshihiro Kaneko Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7796.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c index fda815789c72..72fb995fa653 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c @@ -318,14 +318,14 @@ #define IP11_31_28 FM(RX0) FM(HRX1_B) F_(0, 0) F_(0, 0) F_(0, 0) FM(TS_SCK0_C) FM(STP_ISCLK_0_C) FM(RIF0_D0_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP12_3_0 FM(TX0) FM(HTX1_B) F_(0, 0) F_(0, 0) F_(0, 0) FM(TS_SPSYNC0_C)FM(STP_ISSYNC_0_C) FM(RIF0_D1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP12_7_4 FM(CTS0_N) FM(HCTS1_N_B) FM(MSIOF1_SYNC_B) F_(0, 0) F_(0, 0) FM(TS_SPSYNC1_C)FM(STP_ISSYNC_1_C) FM(RIF1_SYNC_B) FM(AUDIO_CLKOUT_C) FM(ADICS_SAMP) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP12_11_8 FM(RTS0_N_TANS) FM(HRTS1_N_B) FM(MSIOF1_SS1_B) FM(AUDIO_CLKA_B) FM(SCL2_A) F_(0, 0) FM(STP_IVCXO27_1_C) FM(RIF0_SYNC_B) FM(FSO_TOE_A) FM(ADICHS1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP12_11_8 FM(RTS0_N_TANS) FM(HRTS1_N_B) FM(MSIOF1_SS1_B) FM(AUDIO_CLKA_B) FM(SCL2_A) F_(0, 0) FM(STP_IVCXO27_1_C) FM(RIF0_SYNC_B) F_(0, 0) FM(ADICHS1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP12_15_12 FM(RX1_A) FM(HRX1_A) F_(0, 0) F_(0, 0) F_(0, 0) FM(TS_SDAT0_C) FM(STP_ISD_0_C) FM(RIF1_CLK_C) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP12_19_16 FM(TX1_A) FM(HTX1_A) F_(0, 0) F_(0, 0) F_(0, 0) FM(TS_SDEN0_C) FM(STP_ISEN_0_C) FM(RIF1_D0_C) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP12_23_20 FM(CTS1_N) FM(HCTS1_N_A) FM(MSIOF1_RXD_B) F_(0, 0) F_(0, 0) FM(TS_SDEN1_C) FM(STP_ISEN_1_C) FM(RIF1_D0_B) F_(0, 0) FM(ADIDATA) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP12_27_24 FM(RTS1_N_TANS) FM(HRTS1_N_A) FM(MSIOF1_TXD_B) F_(0, 0) F_(0, 0) FM(TS_SDAT1_C) FM(STP_ISD_1_C) FM(RIF1_D1_B) F_(0, 0) FM(ADICHS0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP12_31_28 FM(SCK2) FM(SCIF_CLK_B) FM(MSIOF1_SCK_B) F_(0, 0) F_(0, 0) FM(TS_SCK1_C) FM(STP_ISCLK_1_C) FM(RIF1_CLK_B) F_(0, 0) FM(ADICLK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP13_3_0 FM(TX2_A) F_(0, 0) F_(0, 0) FM(SD2_CD_B) FM(SCL1_A) F_(0, 0) FM(FMCLK_A) FM(RIF1_D1_C) F_(0, 0) FM(FSO_CFE_0_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP13_7_4 FM(RX2_A) F_(0, 0) F_(0, 0) FM(SD2_WP_B) FM(SDA1_A) F_(0, 0) FM(FMIN_A) FM(RIF1_SYNC_C) F_(0, 0) FM(FSO_CFE_1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP13_3_0 FM(TX2_A) F_(0, 0) F_(0, 0) FM(SD2_CD_B) FM(SCL1_A) F_(0, 0) FM(FMCLK_A) FM(RIF1_D1_C) F_(0, 0) FM(FSO_CFE_0_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP13_7_4 FM(RX2_A) F_(0, 0) F_(0, 0) FM(SD2_WP_B) FM(SDA1_A) F_(0, 0) FM(FMIN_A) FM(RIF1_SYNC_C) F_(0, 0) FM(FSO_CFE_1_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP13_11_8 FM(HSCK0) F_(0, 0) FM(MSIOF1_SCK_D) FM(AUDIO_CLKB_A) FM(SSI_SDATA1_B)FM(TS_SCK0_D) FM(STP_ISCLK_0_D) FM(RIF0_CLK_C) F_(0, 0) F_(0, 0) FM(RX5_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP13_15_12 FM(HRX0) F_(0, 0) FM(MSIOF1_RXD_D) F_(0, 0) FM(SSI_SDATA2_B)FM(TS_SDEN0_D) FM(STP_ISEN_0_D) FM(RIF0_D0_C) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP13_19_16 FM(HTX0) F_(0, 0) FM(MSIOF1_TXD_D) F_(0, 0) FM(SSI_SDATA9_B)FM(TS_SDAT0_D) FM(STP_ISD_0_D) FM(RIF0_D1_C) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) @@ -365,9 +365,9 @@ #define IP17_19_16 FM(USB1_PWEN) F_(0, 0) F_(0, 0) FM(SIM0_CLK_C) FM(SSI_SCK1_A) FM(TS_SCK0_E) FM(STP_ISCLK_0_E) FM(FMCLK_B) FM(RIF2_CLK_B) F_(0, 0) FM(SPEEDIN_A) F_(0, 0) F_(0, 0) FM(HTX2_C) F_(0, 0) F_(0, 0) #define IP17_23_20 FM(USB1_OVC) F_(0, 0) FM(MSIOF1_SS2_C) F_(0, 0) FM(SSI_WS1_A) FM(TS_SDAT0_E) FM(STP_ISD_0_E) FM(FMIN_B) FM(RIF2_SYNC_B) F_(0, 0) FM(REMOCON_B) F_(0, 0) F_(0, 0) FM(HCTS2_N_C) F_(0, 0) F_(0, 0) #define IP17_27_24 FM(USB30_PWEN) F_(0, 0) F_(0, 0) FM(AUDIO_CLKOUT_B) FM(SSI_SCK2_B) FM(TS_SDEN1_D) FM(STP_ISEN_1_D) FM(STP_OPWM_0_E)FM(RIF3_D0_B) F_(0, 0) FM(TCLK2_B) FM(TPU0TO0) FM(BPFCLK_C) FM(HRTS2_N_C) F_(0, 0) F_(0, 0) -#define IP17_31_28 FM(USB30_OVC) F_(0, 0) F_(0, 0) FM(AUDIO_CLKOUT1_B) FM(SSI_WS2_B) FM(TS_SPSYNC1_D)FM(STP_ISSYNC_1_D) FM(STP_IVCXO27_0_E)FM(RIF3_D1_B) F_(0, 0) FM(FSO_TOE_B) FM(TPU0TO1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP18_3_0 FM(GP6_30) F_(0, 0) F_(0, 0) FM(AUDIO_CLKOUT2_B) FM(SSI_SCK9_B) FM(TS_SDEN0_E) FM(STP_ISEN_0_E) F_(0, 0) FM(RIF2_D0_B) F_(0, 0) FM(FSO_CFE_0_A) FM(TPU0TO2) FM(FMCLK_C) FM(FMCLK_D) F_(0, 0) F_(0, 0) -#define IP18_7_4 FM(GP6_31) F_(0, 0) F_(0, 0) FM(AUDIO_CLKOUT3_B) FM(SSI_WS9_B) FM(TS_SPSYNC0_E)FM(STP_ISSYNC_0_E) F_(0, 0) FM(RIF2_D1_B) F_(0, 0) FM(FSO_CFE_1_A) FM(TPU0TO3) FM(FMIN_C) FM(FMIN_D) F_(0, 0) F_(0, 0) +#define IP17_31_28 FM(USB30_OVC) F_(0, 0) F_(0, 0) FM(AUDIO_CLKOUT1_B) FM(SSI_WS2_B) FM(TS_SPSYNC1_D)FM(STP_ISSYNC_1_D) FM(STP_IVCXO27_0_E)FM(RIF3_D1_B) F_(0, 0) FM(FSO_TOE_N) FM(TPU0TO1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP18_3_0 FM(GP6_30) F_(0, 0) F_(0, 0) FM(AUDIO_CLKOUT2_B) FM(SSI_SCK9_B) FM(TS_SDEN0_E) FM(STP_ISEN_0_E) F_(0, 0) FM(RIF2_D0_B) F_(0, 0) F_(0, 0) FM(TPU0TO2) FM(FMCLK_C) FM(FMCLK_D) F_(0, 0) F_(0, 0) +#define IP18_7_4 FM(GP6_31) F_(0, 0) F_(0, 0) FM(AUDIO_CLKOUT3_B) FM(SSI_WS9_B) FM(TS_SPSYNC0_E)FM(STP_ISSYNC_0_E) F_(0, 0) FM(RIF2_D1_B) F_(0, 0) F_(0, 0) FM(TPU0TO3) FM(FMIN_C) FM(FMIN_D) F_(0, 0) F_(0, 0) #define PINMUX_GPSR \ \ @@ -462,7 +462,6 @@ FM(IP16_31_28) IP16_31_28 FM(IP17_31_28) IP17_31_28 #define MOD_SEL0_19 FM(SEL_HSCIF4_0) FM(SEL_HSCIF4_1) #define MOD_SEL0_18_17 FM(SEL_HSCIF3_0) FM(SEL_HSCIF3_1) FM(SEL_HSCIF3_2) FM(SEL_HSCIF3_3) #define MOD_SEL0_16 FM(SEL_HSCIF1_0) FM(SEL_HSCIF1_1) -#define MOD_SEL0_15 FM(SEL_FSO_0) FM(SEL_FSO_1) #define MOD_SEL0_14_13 FM(SEL_HSCIF2_0) FM(SEL_HSCIF2_1) FM(SEL_HSCIF2_2) F_(0, 0) #define MOD_SEL0_12 FM(SEL_ETHERAVB_0) FM(SEL_ETHERAVB_1) #define MOD_SEL0_11 FM(SEL_DRIF3_0) FM(SEL_DRIF3_1) @@ -527,7 +526,7 @@ MOD_SEL0_19 MOD_SEL1_19 MOD_SEL2_19 \ MOD_SEL0_18_17 MOD_SEL1_18_17 MOD_SEL2_18 \ MOD_SEL2_17 \ MOD_SEL0_16 MOD_SEL1_16 \ -MOD_SEL0_15 MOD_SEL1_15_14 \ + MOD_SEL1_15_14 \ MOD_SEL0_14_13 \ MOD_SEL1_13 \ MOD_SEL0_12 MOD_SEL1_12 \ @@ -1169,7 +1168,6 @@ static const u16 pinmux_data[] = { PINMUX_IPSR_MSEL(IP12_11_8, SCL2_A, SEL_I2C2_0), PINMUX_IPSR_MSEL(IP12_11_8, STP_IVCXO27_1_C, SEL_SSP1_1_2), PINMUX_IPSR_MSEL(IP12_11_8, RIF0_SYNC_B, SEL_DRIF0_1), - PINMUX_IPSR_MSEL(IP12_11_8, FSO_TOE_A, SEL_FSO_0), PINMUX_IPSR_GPSR(IP12_11_8, ADICHS1), PINMUX_IPSR_MSEL(IP12_15_12, RX1_A, SEL_SCIF1_0), @@ -1214,14 +1212,14 @@ static const u16 pinmux_data[] = { PINMUX_IPSR_MSEL(IP13_3_0, SCL1_A, SEL_I2C1_0), PINMUX_IPSR_MSEL(IP13_3_0, FMCLK_A, SEL_FM_0), PINMUX_IPSR_MSEL(IP13_3_0, RIF1_D1_C, SEL_DRIF1_2), - PINMUX_IPSR_MSEL(IP13_3_0, FSO_CFE_0_B, SEL_FSO_1), + PINMUX_IPSR_GPSR(IP13_3_0, FSO_CFE_0_N), PINMUX_IPSR_MSEL(IP13_7_4, RX2_A, SEL_SCIF2_0), PINMUX_IPSR_MSEL(IP13_7_4, SD2_WP_B, SEL_SDHI2_1), PINMUX_IPSR_MSEL(IP13_7_4, SDA1_A, SEL_I2C1_0), PINMUX_IPSR_MSEL(IP13_7_4, FMIN_A, SEL_FM_0), PINMUX_IPSR_MSEL(IP13_7_4, RIF1_SYNC_C, SEL_DRIF1_2), - PINMUX_IPSR_MSEL(IP13_7_4, FSO_CFE_1_B, SEL_FSO_1), + PINMUX_IPSR_GPSR(IP13_7_4, FSO_CFE_1_N), PINMUX_IPSR_GPSR(IP13_11_8, HSCK0), PINMUX_IPSR_MSEL(IP13_11_8, MSIOF1_SCK_D, SEL_MSIOF1_3), @@ -1472,7 +1470,7 @@ static const u16 pinmux_data[] = { PINMUX_IPSR_MSEL(IP17_31_28, STP_ISSYNC_1_D, SEL_SSP1_1_3), PINMUX_IPSR_MSEL(IP17_31_28, STP_IVCXO27_0_E, SEL_SSP1_0_4), PINMUX_IPSR_MSEL(IP17_31_28, RIF3_D1_B, SEL_DRIF3_1), - PINMUX_IPSR_MSEL(IP17_31_28, FSO_TOE_B, SEL_FSO_1), + PINMUX_IPSR_GPSR(IP17_31_28, FSO_TOE_N), PINMUX_IPSR_GPSR(IP17_31_28, TPU0TO1), /* IPSR18 */ @@ -1483,7 +1481,6 @@ static const u16 pinmux_data[] = { PINMUX_IPSR_MSEL(IP18_3_0, STP_ISEN_0_E, SEL_SSP1_0_4), PINMUX_IPSR_MSEL(IP18_3_0, RIF2_D0_B, SEL_DRIF2_1), PINMUX_IPSR_GPSR(IP18_3_0, TPU0TO2), - PINMUX_IPSR_MSEL(IP18_3_0, FSO_CFE_0_A, SEL_FSO_0), PINMUX_IPSR_MSEL(IP18_3_0, FMCLK_C, SEL_FM_2), PINMUX_IPSR_MSEL(IP18_3_0, FMCLK_D, SEL_FM_3), @@ -1494,7 +1491,6 @@ static const u16 pinmux_data[] = { PINMUX_IPSR_MSEL(IP18_7_4, STP_ISSYNC_0_E, SEL_SSP1_0_4), PINMUX_IPSR_MSEL(IP18_7_4, RIF2_D1_B, SEL_DRIF2_1), PINMUX_IPSR_GPSR(IP18_7_4, TPU0TO3), - PINMUX_IPSR_MSEL(IP18_7_4, FSO_CFE_1_A, SEL_FSO_0), PINMUX_IPSR_MSEL(IP18_7_4, FMIN_C, SEL_FM_2), PINMUX_IPSR_MSEL(IP18_7_4, FMIN_D, SEL_FM_3), @@ -5056,7 +5052,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { MOD_SEL0_19 MOD_SEL0_18_17 MOD_SEL0_16 - MOD_SEL0_15 + 0, 0, /* RESERVED 15 */ MOD_SEL0_14_13 MOD_SEL0_12 MOD_SEL0_11 -- cgit v1.2.3 From bf1a8aa0a2d6b0a6d8736de7ac07c886b092cbad Mon Sep 17 00:00:00 2001 From: Takeshi Kihara Date: Thu, 13 Jul 2017 01:55:47 +0900 Subject: pinctrl: sh-pfc: r8a7796: Rename CS1# pin function definitions This patch renames the pin function macro definitions of the GPSR1 and IPSR4 registers value for the CS1# pin. This is a correction because GPSR and IPSR register specification for R8A7796 SoC was changed in R-Car Gen3 Hardware User's Manual Rev.0.54E. Fixes: f9aece7344bd81ce ("pinctrl: sh-pfc: Initial R8A7796 PFC support") Signed-off-by: Takeshi Kihara Signed-off-by: Yoshihiro Kaneko Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7796.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c index 72fb995fa653..6d3f621f2197 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c @@ -67,7 +67,7 @@ #define GPSR1_24 F_(RD_WR_N, IP4_31_28) #define GPSR1_23 F_(RD_N, IP4_27_24) #define GPSR1_22 F_(BS_N, IP4_23_20) -#define GPSR1_21 F_(CS1_N_A26, IP4_19_16) +#define GPSR1_21 F_(CS1_N, IP4_19_16) #define GPSR1_20 F_(CS0_N, IP4_15_12) #define GPSR1_19 F_(A19, IP4_11_8) #define GPSR1_18 F_(A18, IP4_7_4) @@ -253,7 +253,7 @@ #define IP4_7_4 FM(A18) FM(LCDOUT10) F_(0, 0) F_(0, 0) FM(VI4_HSYNC_N) F_(0, 0) FM(DU_DG2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP4_11_8 FM(A19) FM(LCDOUT11) F_(0, 0) F_(0, 0) FM(VI4_CLKENB) F_(0, 0) FM(DU_DG3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP4_15_12 FM(CS0_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(VI5_CLKENB) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP4_19_16 FM(CS1_N_A26) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(VI5_CLK) F_(0, 0) FM(EX_WAIT0_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP4_19_16 FM(CS1_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(VI5_CLK) F_(0, 0) FM(EX_WAIT0_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP4_23_20 FM(BS_N) FM(QSTVA_QVS) FM(MSIOF3_SCK_D) FM(SCK3) FM(HSCK3) F_(0, 0) F_(0, 0) F_(0, 0) FM(CAN1_TX) FM(CANFD1_TX) FM(IETX_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP4_27_24 FM(RD_N) F_(0, 0) FM(MSIOF3_SYNC_D) FM(RX3_A) FM(HRX3_A) F_(0, 0) F_(0, 0) F_(0, 0) FM(CAN0_TX_A) FM(CANFD0_TX_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP4_31_28 FM(RD_WR_N) F_(0, 0) FM(MSIOF3_RXD_D) FM(TX3_A) FM(HTX3_A) F_(0, 0) F_(0, 0) F_(0, 0) FM(CAN0_RX_A) FM(CANFD0_RX_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) @@ -834,7 +834,7 @@ static const u16 pinmux_data[] = { PINMUX_IPSR_GPSR(IP4_15_12, CS0_N), PINMUX_IPSR_GPSR(IP4_15_12, VI5_CLKENB), - PINMUX_IPSR_GPSR(IP4_19_16, CS1_N_A26), + PINMUX_IPSR_GPSR(IP4_19_16, CS1_N), PINMUX_IPSR_GPSR(IP4_19_16, VI5_CLK), PINMUX_IPSR_MSEL(IP4_19_16, EX_WAIT0_B, SEL_LBSC_1), @@ -5494,7 +5494,7 @@ static const struct sh_pfc_bias_info bias_info[] = { { RCAR_GP_PIN(1, 24), PU2, 5 }, /* RD_WR_N */ { RCAR_GP_PIN(1, 23), PU2, 4 }, /* RD_N */ { RCAR_GP_PIN(1, 22), PU2, 3 }, /* BS_N */ - { RCAR_GP_PIN(1, 21), PU2, 2 }, /* CS1_N_A26 */ + { RCAR_GP_PIN(1, 21), PU2, 2 }, /* CS1_N */ { RCAR_GP_PIN(1, 20), PU2, 1 }, /* CS0_N */ { RCAR_GP_PIN(1, 28), PU2, 0 }, /* CLKOUT */ -- cgit v1.2.3 From c698316661096e036b54448039b35e1c2c5809f0 Mon Sep 17 00:00:00 2001 From: Benson Leung Date: Mon, 17 Jul 2017 11:41:39 +0200 Subject: extcon: cros-ec: Add extcon-cros-ec driver to support display out This is the driver for the USB Type C cable detection mechanism built into the ChromeOS Embedded Controller on systems that have USB Type-C ports. At present, this allows for the presence of display out, but in future, it may also be used to notify host and device type cables and the presence of power. Signed-off-by: Benson Leung Signed-off-by: Enric Balletbo i Serra Acked-by: Chanwoo Choi Acked-by: Lee Jones Signed-off-by: Chanwoo Choi --- drivers/extcon/Kconfig | 7 + drivers/extcon/Makefile | 1 + drivers/extcon/extcon-usbc-cros-ec.c | 415 +++++++++++++++++++++++++++++++++++ include/linux/mfd/cros_ec_commands.h | 75 +++++++ 4 files changed, 498 insertions(+) create mode 100644 drivers/extcon/extcon-usbc-cros-ec.c (limited to 'drivers') diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig index 6d50071f07d5..a7bca4207f44 100644 --- a/drivers/extcon/Kconfig +++ b/drivers/extcon/Kconfig @@ -150,4 +150,11 @@ config EXTCON_USB_GPIO Say Y here to enable GPIO based USB cable detection extcon support. Used typically if GPIO is used for USB ID pin detection. +config EXTCON_USBC_CROS_EC + tristate "ChromeOS Embedded Controller EXTCON support" + depends on MFD_CROS_EC + help + Say Y here to enable USB Type C cable detection extcon support when + using Chrome OS EC based USB Type-C ports. + endif diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile index ecfa95804427..a73624e76193 100644 --- a/drivers/extcon/Makefile +++ b/drivers/extcon/Makefile @@ -20,3 +20,4 @@ obj-$(CONFIG_EXTCON_QCOM_SPMI_MISC) += extcon-qcom-spmi-misc.o obj-$(CONFIG_EXTCON_RT8973A) += extcon-rt8973a.o obj-$(CONFIG_EXTCON_SM5502) += extcon-sm5502.o obj-$(CONFIG_EXTCON_USB_GPIO) += extcon-usb-gpio.o +obj-$(CONFIG_EXTCON_USBC_CROS_EC) += extcon-usbc-cros-ec.o diff --git a/drivers/extcon/extcon-usbc-cros-ec.c b/drivers/extcon/extcon-usbc-cros-ec.c new file mode 100644 index 000000000000..e759ed477735 --- /dev/null +++ b/drivers/extcon/extcon-usbc-cros-ec.c @@ -0,0 +1,415 @@ +/** + * drivers/extcon/extcon-usbc-cros-ec - ChromeOS Embedded Controller extcon + * + * Copyright (C) 2017 Google, Inc + * Author: Benson Leung + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct cros_ec_extcon_info { + struct device *dev; + struct extcon_dev *edev; + + int port_id; + + struct cros_ec_device *ec; + + struct notifier_block notifier; + + bool dp; /* DisplayPort enabled */ + bool mux; /* SuperSpeed (usb3) enabled */ + unsigned int power_type; +}; + +static const unsigned int usb_type_c_cable[] = { + EXTCON_DISP_DP, + EXTCON_NONE, +}; + +/** + * cros_ec_pd_command() - Send a command to the EC. + * @info: pointer to struct cros_ec_extcon_info + * @command: EC command + * @version: EC command version + * @outdata: EC command output data + * @outsize: Size of outdata + * @indata: EC command input data + * @insize: Size of indata + * + * Return: 0 on success, <0 on failure. + */ +static int cros_ec_pd_command(struct cros_ec_extcon_info *info, + unsigned int command, + unsigned int version, + void *outdata, + unsigned int outsize, + void *indata, + unsigned int insize) +{ + struct cros_ec_command *msg; + int ret; + + msg = kzalloc(sizeof(*msg) + max(outsize, insize), GFP_KERNEL); + + msg->version = version; + msg->command = command; + msg->outsize = outsize; + msg->insize = insize; + + if (outsize) + memcpy(msg->data, outdata, outsize); + + ret = cros_ec_cmd_xfer_status(info->ec, msg); + if (ret >= 0 && insize) + memcpy(indata, msg->data, insize); + + kfree(msg); + return ret; +} + +/** + * cros_ec_usb_get_power_type() - Get power type info about PD device attached + * to given port. + * @info: pointer to struct cros_ec_extcon_info + * + * Return: power type on success, <0 on failure. + */ +static int cros_ec_usb_get_power_type(struct cros_ec_extcon_info *info) +{ + struct ec_params_usb_pd_power_info req; + struct ec_response_usb_pd_power_info resp; + int ret; + + req.port = info->port_id; + ret = cros_ec_pd_command(info, EC_CMD_USB_PD_POWER_INFO, 0, + &req, sizeof(req), &resp, sizeof(resp)); + if (ret < 0) + return ret; + + return resp.type; +} + +/** + * cros_ec_usb_get_pd_mux_state() - Get PD mux state for given port. + * @info: pointer to struct cros_ec_extcon_info + * + * Return: PD mux state on success, <0 on failure. + */ +static int cros_ec_usb_get_pd_mux_state(struct cros_ec_extcon_info *info) +{ + struct ec_params_usb_pd_mux_info req; + struct ec_response_usb_pd_mux_info resp; + int ret; + + req.port = info->port_id; + ret = cros_ec_pd_command(info, EC_CMD_USB_PD_MUX_INFO, 0, + &req, sizeof(req), + &resp, sizeof(resp)); + if (ret < 0) + return ret; + + return resp.flags; +} + +/** + * cros_ec_usb_get_role() - Get role info about possible PD device attached to a + * given port. + * @info: pointer to struct cros_ec_extcon_info + * @polarity: pointer to cable polarity (return value) + * + * Return: role info on success, -ENOTCONN if no cable is connected, <0 on + * failure. + */ +static int cros_ec_usb_get_role(struct cros_ec_extcon_info *info, + bool *polarity) +{ + struct ec_params_usb_pd_control pd_control; + struct ec_response_usb_pd_control_v1 resp; + int ret; + + pd_control.port = info->port_id; + pd_control.role = USB_PD_CTRL_ROLE_NO_CHANGE; + pd_control.mux = USB_PD_CTRL_MUX_NO_CHANGE; + ret = cros_ec_pd_command(info, EC_CMD_USB_PD_CONTROL, 1, + &pd_control, sizeof(pd_control), + &resp, sizeof(resp)); + if (ret < 0) + return ret; + + if (!(resp.enabled & PD_CTRL_RESP_ENABLED_CONNECTED)) + return -ENOTCONN; + + *polarity = resp.polarity; + + return resp.role; +} + +/** + * cros_ec_pd_get_num_ports() - Get number of EC charge ports. + * @info: pointer to struct cros_ec_extcon_info + * + * Return: number of ports on success, <0 on failure. + */ +static int cros_ec_pd_get_num_ports(struct cros_ec_extcon_info *info) +{ + struct ec_response_usb_pd_ports resp; + int ret; + + ret = cros_ec_pd_command(info, EC_CMD_USB_PD_PORTS, + 0, NULL, 0, &resp, sizeof(resp)); + if (ret < 0) + return ret; + + return resp.num_ports; +} + +static int extcon_cros_ec_detect_cable(struct cros_ec_extcon_info *info, + bool force) +{ + struct device *dev = info->dev; + int role, power_type; + bool polarity = false; + bool dp = false; + bool mux = false; + bool hpd = false; + + power_type = cros_ec_usb_get_power_type(info); + if (power_type < 0) { + dev_err(dev, "failed getting power type err = %d\n", + power_type); + return power_type; + } + + role = cros_ec_usb_get_role(info, &polarity); + if (role < 0) { + if (role != -ENOTCONN) { + dev_err(dev, "failed getting role err = %d\n", role); + return role; + } + } else { + int pd_mux_state; + + pd_mux_state = cros_ec_usb_get_pd_mux_state(info); + if (pd_mux_state < 0) + pd_mux_state = USB_PD_MUX_USB_ENABLED; + + dp = pd_mux_state & USB_PD_MUX_DP_ENABLED; + mux = pd_mux_state & USB_PD_MUX_USB_ENABLED; + hpd = pd_mux_state & USB_PD_MUX_HPD_IRQ; + } + + if (force || info->dp != dp || info->mux != mux || + info->power_type != power_type) { + + info->dp = dp; + info->mux = mux; + info->power_type = power_type; + + extcon_set_state(info->edev, EXTCON_DISP_DP, dp); + + extcon_set_property(info->edev, EXTCON_DISP_DP, + EXTCON_PROP_USB_TYPEC_POLARITY, + (union extcon_property_value)(int)polarity); + extcon_set_property(info->edev, EXTCON_DISP_DP, + EXTCON_PROP_USB_SS, + (union extcon_property_value)(int)mux); + extcon_set_property(info->edev, EXTCON_DISP_DP, + EXTCON_PROP_DISP_HPD, + (union extcon_property_value)(int)hpd); + + extcon_sync(info->edev, EXTCON_DISP_DP); + + } else if (hpd) { + extcon_set_property(info->edev, EXTCON_DISP_DP, + EXTCON_PROP_DISP_HPD, + (union extcon_property_value)(int)hpd); + extcon_sync(info->edev, EXTCON_DISP_DP); + } + + return 0; +} + +static int extcon_cros_ec_event(struct notifier_block *nb, + unsigned long queued_during_suspend, + void *_notify) +{ + struct cros_ec_extcon_info *info; + struct cros_ec_device *ec; + u32 host_event; + + info = container_of(nb, struct cros_ec_extcon_info, notifier); + ec = info->ec; + + host_event = cros_ec_get_host_event(ec); + if (host_event & (EC_HOST_EVENT_MASK(EC_HOST_EVENT_PD_MCU) | + EC_HOST_EVENT_MASK(EC_HOST_EVENT_USB_MUX))) { + extcon_cros_ec_detect_cable(info, false); + return NOTIFY_OK; + } + + return NOTIFY_DONE; +} + +static int extcon_cros_ec_probe(struct platform_device *pdev) +{ + struct cros_ec_extcon_info *info; + struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent); + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + int numports, ret; + + info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + info->dev = dev; + info->ec = ec; + + if (np) { + u32 port; + + ret = of_property_read_u32(np, "google,usb-port-id", &port); + if (ret < 0) { + dev_err(dev, "Missing google,usb-port-id property\n"); + return ret; + } + info->port_id = port; + } else { + info->port_id = pdev->id; + } + + numports = cros_ec_pd_get_num_ports(info); + if (numports < 0) { + dev_err(dev, "failed getting number of ports! ret = %d\n", + numports); + return numports; + } + + if (info->port_id >= numports) { + dev_err(dev, "This system only supports %d ports\n", numports); + return -ENODEV; + } + + info->edev = devm_extcon_dev_allocate(dev, usb_type_c_cable); + if (IS_ERR(info->edev)) { + dev_err(dev, "failed to allocate extcon device\n"); + return -ENOMEM; + } + + ret = devm_extcon_dev_register(dev, info->edev); + if (ret < 0) { + dev_err(dev, "failed to register extcon device\n"); + return ret; + } + + extcon_set_property_capability(info->edev, EXTCON_DISP_DP, + EXTCON_PROP_USB_TYPEC_POLARITY); + extcon_set_property_capability(info->edev, EXTCON_DISP_DP, + EXTCON_PROP_USB_SS); + extcon_set_property_capability(info->edev, EXTCON_DISP_DP, + EXTCON_PROP_DISP_HPD); + + platform_set_drvdata(pdev, info); + + /* Get PD events from the EC */ + info->notifier.notifier_call = extcon_cros_ec_event; + ret = blocking_notifier_chain_register(&info->ec->event_notifier, + &info->notifier); + if (ret < 0) { + dev_err(dev, "failed to register notifier\n"); + return ret; + } + + /* Perform initial detection */ + ret = extcon_cros_ec_detect_cable(info, true); + if (ret < 0) { + dev_err(dev, "failed to detect initial cable state\n"); + goto unregister_notifier; + } + + return 0; + +unregister_notifier: + blocking_notifier_chain_unregister(&info->ec->event_notifier, + &info->notifier); + return ret; +} + +static int extcon_cros_ec_remove(struct platform_device *pdev) +{ + struct cros_ec_extcon_info *info = platform_get_drvdata(pdev); + + blocking_notifier_chain_unregister(&info->ec->event_notifier, + &info->notifier); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int extcon_cros_ec_suspend(struct device *dev) +{ + return 0; +} + +static int extcon_cros_ec_resume(struct device *dev) +{ + int ret; + struct cros_ec_extcon_info *info = dev_get_drvdata(dev); + + ret = extcon_cros_ec_detect_cable(info, true); + if (ret < 0) + dev_err(dev, "failed to detect cable state on resume\n"); + + return 0; +} + +static const struct dev_pm_ops extcon_cros_ec_dev_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(extcon_cros_ec_suspend, extcon_cros_ec_resume) +}; + +#define DEV_PM_OPS (&extcon_cros_ec_dev_pm_ops) +#else +#define DEV_PM_OPS NULL +#endif /* CONFIG_PM_SLEEP */ + +#ifdef CONFIG_OF +static const struct of_device_id extcon_cros_ec_of_match[] = { + { .compatible = "google,extcon-usbc-cros-ec" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, extcon_cros_ec_of_match); +#endif /* CONFIG_OF */ + +static struct platform_driver extcon_cros_ec_driver = { + .driver = { + .name = "extcon-usbc-cros-ec", + .of_match_table = of_match_ptr(extcon_cros_ec_of_match), + .pm = DEV_PM_OPS, + }, + .remove = extcon_cros_ec_remove, + .probe = extcon_cros_ec_probe, +}; + +module_platform_driver(extcon_cros_ec_driver); + +MODULE_DESCRIPTION("ChromeOS Embedded Controller extcon driver"); +MODULE_AUTHOR("Benson Leung "); +MODULE_LICENSE("GPL"); diff --git a/include/linux/mfd/cros_ec_commands.h b/include/linux/mfd/cros_ec_commands.h index 190c8f4afa02..2b16e95b9bb8 100644 --- a/include/linux/mfd/cros_ec_commands.h +++ b/include/linux/mfd/cros_ec_commands.h @@ -285,6 +285,11 @@ enum host_event_code { EC_HOST_EVENT_HANG_DETECT = 20, /* Hang detect logic detected a hang and warm rebooted the AP */ EC_HOST_EVENT_HANG_REBOOT = 21, + /* PD MCU triggering host event */ + EC_HOST_EVENT_PD_MCU = 22, + + /* EC desires to change state of host-controlled USB mux */ + EC_HOST_EVENT_USB_MUX = 28, /* * The high bit of the event mask is not used as a host event code. If @@ -2905,6 +2910,76 @@ struct ec_params_usb_pd_control { uint8_t mux; } __packed; +#define PD_CTRL_RESP_ENABLED_COMMS (1 << 0) /* Communication enabled */ +#define PD_CTRL_RESP_ENABLED_CONNECTED (1 << 1) /* Device connected */ +#define PD_CTRL_RESP_ENABLED_PD_CAPABLE (1 << 2) /* Partner is PD capable */ + +struct ec_response_usb_pd_control_v1 { + uint8_t enabled; + uint8_t role; + uint8_t polarity; + char state[32]; +} __packed; + +#define EC_CMD_USB_PD_PORTS 0x102 + +struct ec_response_usb_pd_ports { + uint8_t num_ports; +} __packed; + +#define EC_CMD_USB_PD_POWER_INFO 0x103 + +#define PD_POWER_CHARGING_PORT 0xff +struct ec_params_usb_pd_power_info { + uint8_t port; +} __packed; + +enum usb_chg_type { + USB_CHG_TYPE_NONE, + USB_CHG_TYPE_PD, + USB_CHG_TYPE_C, + USB_CHG_TYPE_PROPRIETARY, + USB_CHG_TYPE_BC12_DCP, + USB_CHG_TYPE_BC12_CDP, + USB_CHG_TYPE_BC12_SDP, + USB_CHG_TYPE_OTHER, + USB_CHG_TYPE_VBUS, + USB_CHG_TYPE_UNKNOWN, +}; + +struct usb_chg_measures { + uint16_t voltage_max; + uint16_t voltage_now; + uint16_t current_max; + uint16_t current_lim; +} __packed; + +struct ec_response_usb_pd_power_info { + uint8_t role; + uint8_t type; + uint8_t dualrole; + uint8_t reserved1; + struct usb_chg_measures meas; + uint32_t max_power; +} __packed; + +/* Get info about USB-C SS muxes */ +#define EC_CMD_USB_PD_MUX_INFO 0x11a + +struct ec_params_usb_pd_mux_info { + uint8_t port; /* USB-C port number */ +} __packed; + +/* Flags representing mux state */ +#define USB_PD_MUX_USB_ENABLED (1 << 0) +#define USB_PD_MUX_DP_ENABLED (1 << 1) +#define USB_PD_MUX_POLARITY_INVERTED (1 << 2) +#define USB_PD_MUX_HPD_IRQ (1 << 3) + +struct ec_response_usb_pd_mux_info { + uint8_t flags; /* USB_PD_MUX_*-encoded USB mux state */ +} __packed; + /*****************************************************************************/ /* * Passthru commands -- cgit v1.2.3 From 9585e340db9f6cc1c0928d82c3a23cc4460f0a3f Mon Sep 17 00:00:00 2001 From: Stefan Triller Date: Fri, 30 Jun 2017 14:44:03 +0200 Subject: USB: serial: cp210x: add support for Qivicon USB ZigBee dongle The German Telekom offers a ZigBee USB Stick under the brand name Qivicon for their SmartHome Home Base in its 1. Generation. The productId is not known by the according kernel module, this patch adds support for it. Signed-off-by: Stefan Triller Reviewed-by: Frans Klaver Cc: stable Signed-off-by: Johan Hovold --- drivers/usb/serial/cp210x.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index f64e914a8985..2d945c9f975c 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -142,6 +142,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x8998) }, /* KCF Technologies PRN */ { USB_DEVICE(0x10C4, 0x8A2A) }, /* HubZ dual ZigBee and Z-Wave dongle */ { USB_DEVICE(0x10C4, 0x8A5E) }, /* CEL EM3588 ZigBee USB Stick Long Range */ + { USB_DEVICE(0x10C4, 0x8B34) }, /* Qivicon ZigBee USB Radio Stick */ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */ -- cgit v1.2.3 From 58dff39904c02199b80395dac2fa3dec0d8f3861 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Fri, 19 May 2017 17:47:33 +0200 Subject: drm/imx: ipuv3-plane: use fb local variable instead of state->fb We already have a local variable assigned to state->fb, use it. Signed-off-by: Philipp Zabel --- drivers/gpu/drm/imx/ipuv3-plane.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index 49546222c6d3..553dc9926e49 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -525,8 +525,8 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, ipu_prg_channel_configure(ipu_plane->ipu_ch, axi_id, drm_rect_width(&state->src) >> 16, drm_rect_height(&state->src) >> 16, - state->fb->pitches[0], - state->fb->format->format, &eba); + fb->pitches[0], + fb->format->format, &eba); } if (old_state->fb && !drm_atomic_crtc_needs_modeset(crtc_state)) { @@ -553,11 +553,11 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, ipu_dp_set_global_alpha(ipu_plane->dp, true, 0, true); break; case IPU_DP_FLOW_SYNC_FG: - ics = ipu_drm_fourcc_to_colorspace(state->fb->format->format); + ics = ipu_drm_fourcc_to_colorspace(fb->format->format); ipu_dp_setup_channel(ipu_plane->dp, ics, IPUV3_COLORSPACE_UNKNOWN); /* Enable local alpha on partial plane */ - switch (state->fb->format->format) { + switch (fb->format->format) { case DRM_FORMAT_ARGB1555: case DRM_FORMAT_ABGR1555: case DRM_FORMAT_RGBA5551: @@ -587,10 +587,10 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, ipu_cpmem_set_resolution(ipu_plane->ipu_ch, drm_rect_width(&state->src) >> 16, drm_rect_height(&state->src) >> 16); - ipu_cpmem_set_fmt(ipu_plane->ipu_ch, state->fb->format->format); + ipu_cpmem_set_fmt(ipu_plane->ipu_ch, fb->format->format); ipu_cpmem_set_high_priority(ipu_plane->ipu_ch); ipu_idmac_set_double_buffer(ipu_plane->ipu_ch, 1); - ipu_cpmem_set_stride(ipu_plane->ipu_ch, state->fb->pitches[0]); + ipu_cpmem_set_stride(ipu_plane->ipu_ch, fb->pitches[0]); ipu_cpmem_set_axi_id(ipu_plane->ipu_ch, axi_id); switch (fb->format->format) { case DRM_FORMAT_YUV420: @@ -644,8 +644,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, ipu_cpmem_set_format_passthrough(ipu_plane->alpha_ch, 8); ipu_cpmem_set_high_priority(ipu_plane->alpha_ch); ipu_idmac_set_double_buffer(ipu_plane->alpha_ch, 1); - ipu_cpmem_set_stride(ipu_plane->alpha_ch, - state->fb->pitches[1]); + ipu_cpmem_set_stride(ipu_plane->alpha_ch, fb->pitches[1]); ipu_cpmem_set_burstsize(ipu_plane->alpha_ch, 16); ipu_cpmem_set_buffer(ipu_plane->alpha_ch, 0, alpha_eba); ipu_cpmem_set_buffer(ipu_plane->alpha_ch, 1, alpha_eba); -- cgit v1.2.3 From 790cb4c7c9545953d22d3d425e49b36a711bae5b Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Fri, 19 May 2017 16:05:51 +0200 Subject: drm/imx: lock scanout transfers for consecutive bursts Because of its shallow queues and limited reordering ability, the i.MX6Q memory controller likes AXI bursts of consecutive addresses a lot. To optimize memory access performance, lock the IPU scanout channels for a number of burst accesses each, before switching to the next channel. The burst size and length of a locked burst chain are chosen not to overshoot the stride. Enabling the 8-burst channel lock on a single 1920x1080@60Hz RGBx scanout (474 MiB/s of 64-byte IPU memory read accesses) reduces the reported memory controller busy cycles from 46% to below 28% on an otherwise idle i.MX6Q. Tested-by: Lucas Stach Signed-off-by: Philipp Zabel --- drivers/gpu/drm/imx/ipuv3-plane.c | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index 553dc9926e49..0be08c654a7a 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -496,6 +496,27 @@ static int ipu_chan_assign_axi_id(int ipu_chan) } } +static void ipu_calculate_bursts(u32 width, u32 cpp, u32 stride, + u8 *burstsize, u8 *num_bursts) +{ + const unsigned int width_bytes = width * cpp; + unsigned int npb, bursts; + + /* Maximum number of pixels per burst without overshooting stride */ + for (npb = 64 / cpp; npb > 0; --npb) { + if (round_up(width_bytes, npb * cpp) <= stride) + break; + } + *burstsize = npb; + + /* Maximum number of consecutive bursts without overshooting stride */ + for (bursts = 8; bursts > 1; bursts /= 2) { + if (round_up(width_bytes, npb * cpp * bursts) <= stride) + break; + } + *num_bursts = bursts; +} + static void ipu_plane_atomic_update(struct drm_plane *plane, struct drm_plane_state *old_state) { @@ -509,6 +530,9 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, unsigned long alpha_eba = 0; enum ipu_color_space ics; unsigned int axi_id = 0; + const struct drm_format_info *info; + u8 burstsize, num_bursts; + u32 width, height; int active; if (ipu_plane->dp_flow == IPU_DP_FLOW_SYNC_FG) @@ -583,15 +607,21 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, ipu_dmfc_config_wait4eot(ipu_plane->dmfc, drm_rect_width(dst)); + width = drm_rect_width(&state->src) >> 16; + height = drm_rect_height(&state->src) >> 16; + info = drm_format_info(fb->format->format); + ipu_calculate_bursts(width, info->cpp[0], fb->pitches[0], + &burstsize, &num_bursts); + ipu_cpmem_zero(ipu_plane->ipu_ch); - ipu_cpmem_set_resolution(ipu_plane->ipu_ch, - drm_rect_width(&state->src) >> 16, - drm_rect_height(&state->src) >> 16); + ipu_cpmem_set_resolution(ipu_plane->ipu_ch, width, height); ipu_cpmem_set_fmt(ipu_plane->ipu_ch, fb->format->format); + ipu_cpmem_set_burstsize(ipu_plane->ipu_ch, burstsize); ipu_cpmem_set_high_priority(ipu_plane->ipu_ch); ipu_idmac_set_double_buffer(ipu_plane->ipu_ch, 1); ipu_cpmem_set_stride(ipu_plane->ipu_ch, fb->pitches[0]); ipu_cpmem_set_axi_id(ipu_plane->ipu_ch, axi_id); + switch (fb->format->format) { case DRM_FORMAT_YUV420: case DRM_FORMAT_YVU420: @@ -631,6 +661,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, case DRM_FORMAT_RGBX8888_A8: case DRM_FORMAT_BGRX8888_A8: alpha_eba = drm_plane_state_to_eba(state, 1); + num_bursts = 0; dev_dbg(ipu_plane->base.dev->dev, "phys = %lu %lu, x = %d, y = %d", eba, alpha_eba, state->src.x1 >> 16, state->src.y1 >> 16); @@ -656,6 +687,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, } ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 0, eba); ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 1, eba); + ipu_idmac_lock_enable(ipu_plane->ipu_ch, num_bursts); ipu_plane_enable(ipu_plane); } -- cgit v1.2.3 From da470d6ab857d04fa99ca3d5c16e6d87457d3e1d Mon Sep 17 00:00:00 2001 From: Aravind Thokala Date: Tue, 27 Jun 2017 22:01:11 +0530 Subject: spi/ath79: Fix checkpatch warnings This patch fixes the checkpatch.pl warnings on the driver file. Signed-off-by: Aravind Thokala Signed-off-by: Mark Brown --- drivers/spi/spi-ath79.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c index b89cee11f418..0719bd484891 100644 --- a/drivers/spi/spi-ath79.c +++ b/drivers/spi/spi-ath79.c @@ -39,15 +39,15 @@ struct ath79_spi { u32 reg_ctrl; void __iomem *base; struct clk *clk; - unsigned rrw_delay; + unsigned int rrw_delay; }; -static inline u32 ath79_spi_rr(struct ath79_spi *sp, unsigned reg) +static inline u32 ath79_spi_rr(struct ath79_spi *sp, unsigned int reg) { return ioread32(sp->base + reg); } -static inline void ath79_spi_wr(struct ath79_spi *sp, unsigned reg, u32 val) +static inline void ath79_spi_wr(struct ath79_spi *sp, unsigned int reg, u32 val) { iowrite32(val, sp->base + reg); } @@ -57,7 +57,7 @@ static inline struct ath79_spi *ath79_spidev_to_sp(struct spi_device *spi) return spi_master_get_devdata(spi->master); } -static inline void ath79_spi_delay(struct ath79_spi *sp, unsigned nsecs) +static inline void ath79_spi_delay(struct ath79_spi *sp, unsigned int nsecs) { if (nsecs > sp->rrw_delay) ndelay(nsecs - sp->rrw_delay); @@ -148,9 +148,8 @@ static int ath79_spi_setup_cs(struct spi_device *spi) static void ath79_spi_cleanup_cs(struct spi_device *spi) { - if (gpio_is_valid(spi->cs_gpio)) { + if (gpio_is_valid(spi->cs_gpio)) gpio_free(spi->cs_gpio); - } } static int ath79_spi_setup(struct spi_device *spi) @@ -176,7 +175,7 @@ static void ath79_spi_cleanup(struct spi_device *spi) spi_bitbang_cleanup(spi); } -static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned nsecs, +static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned int nsecs, u32 word, u8 bits) { struct ath79_spi *sp = ath79_spidev_to_sp(spi); -- cgit v1.2.3 From c3c25ea712c909e40d11024dcf6e4b19a2fc247b Mon Sep 17 00:00:00 2001 From: Aravind Thokala Date: Tue, 27 Jun 2017 21:37:10 +0530 Subject: spi/bcm63xx-hspi: Fix checkpatch warnings This patch fixes the checkpatch.pl warnings on the driver file. Signed-off-by: Aravind Thokala Signed-off-by: Mark Brown --- drivers/spi/spi-bcm63xx-hsspi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c index 4da2d4a524ca..475a79015aa6 100644 --- a/drivers/spi/spi-bcm63xx-hsspi.c +++ b/drivers/spi/spi-bcm63xx-hsspi.c @@ -108,7 +108,7 @@ struct bcm63xx_hsspi { u8 cs_polarity; }; -static void bcm63xx_hsspi_set_cs(struct bcm63xx_hsspi *bs, unsigned cs, +static void bcm63xx_hsspi_set_cs(struct bcm63xx_hsspi *bs, unsigned int cs, bool active) { u32 reg; @@ -127,7 +127,7 @@ static void bcm63xx_hsspi_set_cs(struct bcm63xx_hsspi *bs, unsigned cs, static void bcm63xx_hsspi_set_clk(struct bcm63xx_hsspi *bs, struct spi_device *spi, int hz) { - unsigned profile = spi->chip_select; + unsigned int profile = spi->chip_select; u32 reg; reg = DIV_ROUND_UP(2048, DIV_ROUND_UP(bs->speed_hz, hz)); @@ -154,7 +154,7 @@ static void bcm63xx_hsspi_set_clk(struct bcm63xx_hsspi *bs, static int bcm63xx_hsspi_do_txrx(struct spi_device *spi, struct spi_transfer *t) { struct bcm63xx_hsspi *bs = spi_master_get_devdata(spi->master); - unsigned chip_select = spi->chip_select; + unsigned int chip_select = spi->chip_select; u16 opcode = 0; int pending = t->len; int step_size = HSSPI_BUFFER_LEN; -- cgit v1.2.3 From fd8d4e2d1f20e9a5dbbdb16ee9b594726a7c5a2d Mon Sep 17 00:00:00 2001 From: jiada wang Date: Thu, 8 Jun 2017 14:16:00 +0900 Subject: spi: imx: introduce fifo_size and has_dmamode in spi_imx_devtype_data Different ECSPI controller has different fifosize and DMA capability, instead of calling functions to identify these information by check devtype. add fifo_size and has_dmamode to spi_imx_devtype_data. so that these information can be directly accessed. Signed-off-by: Jiada Wang Reviewed-by: Sascha Hauer Signed-off-by: Mark Brown --- drivers/spi/spi-imx.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index f9698b7aeb3b..d3093f355dfb 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -74,6 +74,8 @@ struct spi_imx_devtype_data { void (*trigger)(struct spi_imx_data *); int (*rx_available)(struct spi_imx_data *); void (*reset)(struct spi_imx_data *); + bool has_dmamode; + unsigned int fifo_size; enum spi_imx_devtype devtype; }; @@ -125,11 +127,6 @@ static inline int is_imx51_ecspi(struct spi_imx_data *d) return d->devtype_data->devtype == IMX51_ECSPI; } -static inline unsigned spi_imx_get_fifosize(struct spi_imx_data *d) -{ - return is_imx51_ecspi(d) ? 64 : 8; -} - #define MXC_SPI_BUF_RX(type) \ static void spi_imx_buf_rx_##type(struct spi_imx_data *spi_imx) \ { \ @@ -219,7 +216,7 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi, if (bytes_per_word != 1 && bytes_per_word != 2 && bytes_per_word != 4) return false; - for (i = spi_imx_get_fifosize(spi_imx) / 2; i > 0; i--) { + for (i = spi_imx->devtype_data->fifo_size / 2; i > 0; i--) { if (!(transfer->len % (i * bytes_per_word))) break; } @@ -693,6 +690,8 @@ static struct spi_imx_devtype_data imx1_cspi_devtype_data = { .trigger = mx1_trigger, .rx_available = mx1_rx_available, .reset = mx1_reset, + .fifo_size = 8, + .has_dmamode = false, .devtype = IMX1_CSPI, }; @@ -702,6 +701,8 @@ static struct spi_imx_devtype_data imx21_cspi_devtype_data = { .trigger = mx21_trigger, .rx_available = mx21_rx_available, .reset = mx21_reset, + .fifo_size = 8, + .has_dmamode = false, .devtype = IMX21_CSPI, }; @@ -712,6 +713,8 @@ static struct spi_imx_devtype_data imx27_cspi_devtype_data = { .trigger = mx21_trigger, .rx_available = mx21_rx_available, .reset = mx21_reset, + .fifo_size = 8, + .has_dmamode = false, .devtype = IMX27_CSPI, }; @@ -721,6 +724,8 @@ static struct spi_imx_devtype_data imx31_cspi_devtype_data = { .trigger = mx31_trigger, .rx_available = mx31_rx_available, .reset = mx31_reset, + .fifo_size = 8, + .has_dmamode = false, .devtype = IMX31_CSPI, }; @@ -731,6 +736,8 @@ static struct spi_imx_devtype_data imx35_cspi_devtype_data = { .trigger = mx31_trigger, .rx_available = mx31_rx_available, .reset = mx31_reset, + .fifo_size = 8, + .has_dmamode = true, .devtype = IMX35_CSPI, }; @@ -740,6 +747,8 @@ static struct spi_imx_devtype_data imx51_ecspi_devtype_data = { .trigger = mx51_ecspi_trigger, .rx_available = mx51_ecspi_rx_available, .reset = mx51_ecspi_reset, + .fifo_size = 64, + .has_dmamode = true, .devtype = IMX51_ECSPI, }; @@ -791,7 +800,7 @@ static void spi_imx_chipselect(struct spi_device *spi, int is_active) static void spi_imx_push(struct spi_imx_data *spi_imx) { - while (spi_imx->txfifo < spi_imx_get_fifosize(spi_imx)) { + while (spi_imx->txfifo < spi_imx->devtype_data->fifo_size) { if (!spi_imx->count) break; spi_imx->tx(spi_imx); @@ -938,7 +947,7 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx, if (of_machine_is_compatible("fsl,imx6dl")) return 0; - spi_imx->wml = spi_imx_get_fifosize(spi_imx) / 2; + spi_imx->wml = spi_imx->devtype_data->fifo_size / 2; /* Prepare for TX DMA: */ master->dma_tx = dma_request_slave_channel_reason(dev, "tx"); @@ -1262,7 +1271,7 @@ static int spi_imx_probe(struct platform_device *pdev) * Only validated on i.mx35 and i.mx6 now, can remove the constraint * if validated on other chips. */ - if (is_imx35_cspi(spi_imx) || is_imx51_ecspi(spi_imx)) { + if (spi_imx->devtype_data->has_dmamode) { ret = spi_imx_sdma_init(&pdev->dev, spi_imx, master); if (ret == -EPROBE_DEFER) goto out_clk_put; -- cgit v1.2.3 From 26e4bb8670fc615aaaf26bd1332511333d2b6363 Mon Sep 17 00:00:00 2001 From: jiada wang Date: Thu, 8 Jun 2017 14:16:01 +0900 Subject: spi: imx: add selection for iMX53 and iMX6 controller ECSPI contorller for iMX53 and iMX6 has few hardware issues comparing to iMX51. The change add possibility to detect which controller is used to apply possible workaround and limitations. Signed-off-by: Jiada Wang Acked-by: Rob Herring Reviewed-by: Sascha Hauer Signed-off-by: Mark Brown --- .../devicetree/bindings/spi/fsl-imx-cspi.txt | 1 + drivers/spi/spi-imx.c | 26 ++++++++++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt b/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt index 31b5b21598ff..5bf13960f7f4 100644 --- a/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt +++ b/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt @@ -9,6 +9,7 @@ Required properties: - "fsl,imx31-cspi" for SPI compatible with the one integrated on i.MX31 - "fsl,imx35-cspi" for SPI compatible with the one integrated on i.MX35 - "fsl,imx51-ecspi" for SPI compatible with the one integrated on i.MX51 + - "fsl,imx53-ecspi" for SPI compatible with the one integrated on i.MX53 and later Soc - reg : Offset and length of the register set for the device - interrupts : Should contain CSPI/eCSPI interrupt - cs-gpios : Specifies the gpio pins to be used for chipselects. diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index d3093f355dfb..424dd013451e 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -63,7 +63,8 @@ enum spi_imx_devtype { IMX27_CSPI, IMX31_CSPI, IMX35_CSPI, /* CSPI on all i.mx except above */ - IMX51_ECSPI, /* ECSPI on i.mx51 and later */ + IMX51_ECSPI, /* ECSPI on i.mx51 */ + IMX53_ECSPI, /* ECSPI on i.mx53 and later */ }; struct spi_imx_data; @@ -127,6 +128,11 @@ static inline int is_imx51_ecspi(struct spi_imx_data *d) return d->devtype_data->devtype == IMX51_ECSPI; } +static inline int is_imx53_ecspi(struct spi_imx_data *d) +{ + return d->devtype_data->devtype == IMX53_ECSPI; +} + #define MXC_SPI_BUF_RX(type) \ static void spi_imx_buf_rx_##type(struct spi_imx_data *spi_imx) \ { \ @@ -752,6 +758,17 @@ static struct spi_imx_devtype_data imx51_ecspi_devtype_data = { .devtype = IMX51_ECSPI, }; +static struct spi_imx_devtype_data imx53_ecspi_devtype_data = { + .intctrl = mx51_ecspi_intctrl, + .config = mx51_ecspi_config, + .trigger = mx51_ecspi_trigger, + .rx_available = mx51_ecspi_rx_available, + .reset = mx51_ecspi_reset, + .fifo_size = 64, + .has_dmamode = true, + .devtype = IMX53_ECSPI, +}; + static const struct platform_device_id spi_imx_devtype[] = { { .name = "imx1-cspi", @@ -771,6 +788,9 @@ static const struct platform_device_id spi_imx_devtype[] = { }, { .name = "imx51-ecspi", .driver_data = (kernel_ulong_t) &imx51_ecspi_devtype_data, + }, { + .name = "imx53-ecspi", + .driver_data = (kernel_ulong_t) &imx53_ecspi_devtype_data, }, { /* sentinel */ } @@ -783,6 +803,7 @@ static const struct of_device_id spi_imx_dt_ids[] = { { .compatible = "fsl,imx31-cspi", .data = &imx31_cspi_devtype_data, }, { .compatible = "fsl,imx35-cspi", .data = &imx35_cspi_devtype_data, }, { .compatible = "fsl,imx51-ecspi", .data = &imx51_ecspi_devtype_data, }, + { .compatible = "fsl,imx53-ecspi", .data = &imx53_ecspi_devtype_data, }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, spi_imx_dt_ids); @@ -1218,7 +1239,8 @@ static int spi_imx_probe(struct platform_device *pdev) spi_imx->bitbang.master->prepare_message = spi_imx_prepare_message; spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message; spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; - if (is_imx35_cspi(spi_imx) || is_imx51_ecspi(spi_imx)) + if (is_imx35_cspi(spi_imx) || is_imx51_ecspi(spi_imx) || + is_imx53_ecspi(spi_imx)) spi_imx->bitbang.master->mode_bits |= SPI_LOOP | SPI_READY; spi_imx->spi_drctl = spi_drctl; -- cgit v1.2.3 From 676a4e3bab445d53fca4756865e2c0e2a87c38d6 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Sat, 8 Jul 2017 10:41:18 +0200 Subject: spi: pxa2xx: Only claim CS GPIOs when the slave device is created Avoid hogging chip select GPIOs just because they are listed for the master. They might be mulitplexed and, if no slave device is attached, used for different purposes. Moreover, this strategy avoids having to allocate a cs_gpiods structure. Tested on the IOT2000 where the second SPI bus is connected to an Arduino-compatible connector and multiplexed between SPI, GPIO and PWM usage. Signed-off-by: Jan Kiszka Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx.c | 59 +++++++++++++++++------------------------------- 1 file changed, 21 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index 38d053682892..be991266a6ce 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -1213,21 +1213,33 @@ static int setup_cs(struct spi_device *spi, struct chip_data *chip, struct pxa2xx_spi_chip *chip_info) { struct driver_data *drv_data = spi_master_get_devdata(spi->master); + struct device *pdev = &drv_data->pdev->dev; + struct gpio_desc *gpiod; int err = 0; + int count; if (chip == NULL) return 0; - if (drv_data->cs_gpiods) { - struct gpio_desc *gpiod; + count = gpiod_count(pdev, "cs"); + if (count > 0) { + if (spi->chip_select >= count) + return -EINVAL; + + gpiod = gpiod_get_index(pdev, "cs", spi->chip_select, + GPIOD_OUT_HIGH); + if (IS_ERR(gpiod)) { + /* Means use native chip select */ + if (PTR_ERR(gpiod) == -ENOENT) + return 0; - gpiod = drv_data->cs_gpiods[spi->chip_select]; - if (gpiod) { - chip->gpio_cs = desc_to_gpio(gpiod); - chip->gpio_cs_inverted = spi->mode & SPI_CS_HIGH; - gpiod_set_value(gpiod, chip->gpio_cs_inverted); + return PTR_ERR(gpiod); } + chip->gpio_cs = desc_to_gpio(gpiod); + chip->gpio_cs_inverted = spi->mode & SPI_CS_HIGH; + gpiod_set_value(gpiod, chip->gpio_cs_inverted); + return 0; } @@ -1415,8 +1427,7 @@ static void cleanup(struct spi_device *spi) if (!chip) return; - if (drv_data->ssp_type != CE4100_SSP && !drv_data->cs_gpiods && - gpio_is_valid(chip->gpio_cs)) + if (drv_data->ssp_type != CE4100_SSP && gpio_is_valid(chip->gpio_cs)) gpio_free(chip->gpio_cs); kfree(chip); @@ -1752,38 +1763,10 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) master->num_chipselect = platform_info->num_chipselect; count = gpiod_count(&pdev->dev, "cs"); - if (count > 0) { - int i; - + if (count > 0) master->num_chipselect = max_t(int, count, master->num_chipselect); - drv_data->cs_gpiods = devm_kcalloc(&pdev->dev, - master->num_chipselect, sizeof(struct gpio_desc *), - GFP_KERNEL); - if (!drv_data->cs_gpiods) { - status = -ENOMEM; - goto out_error_clock_enabled; - } - - for (i = 0; i < master->num_chipselect; i++) { - struct gpio_desc *gpiod; - - gpiod = devm_gpiod_get_index(dev, "cs", i, - GPIOD_OUT_HIGH); - if (IS_ERR(gpiod)) { - /* Means use native chip select */ - if (PTR_ERR(gpiod) == -ENOENT) - continue; - - status = (int)PTR_ERR(gpiod); - goto out_error_clock_enabled; - } else { - drv_data->cs_gpiods[i] = gpiod; - } - } - } - tasklet_init(&drv_data->pump_transfers, pump_transfers, (unsigned long)drv_data); -- cgit v1.2.3 From 61a8dec502b873879fa240ec7614601523b46a43 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 12 Jul 2017 12:26:01 +0200 Subject: spi: sh-msiof: Limit minimum divider on R-Car Gen3 On R-Car Gen3 SoCs (excluding R-Car H3 ES1.x, which cannot be used for SPI due to a hardware erratum), BRPS x BRDV = 1/1 is an invalid divider setting. Implement this limitation using an SoC/family-specific minimum divider. Signed-off-by: Geert Uytterhoeven Signed-off-by: Mark Brown --- drivers/spi/spi-sh-msiof.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index c304c7167866..0eb1e9583485 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -38,6 +38,7 @@ struct sh_msiof_chipdata { u16 tx_fifo_size; u16 rx_fifo_size; u16 master_flags; + u16 min_div; }; struct sh_msiof_spi_priv { @@ -49,6 +50,7 @@ struct sh_msiof_spi_priv { struct completion done; unsigned int tx_fifo_size; unsigned int rx_fifo_size; + unsigned int min_div; void *tx_dma_page; void *rx_dma_page; dma_addr_t tx_dma_addr; @@ -261,6 +263,8 @@ static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p, if (!WARN_ON(!spi_hz || !parent_rate)) div = DIV_ROUND_UP(parent_rate, spi_hz); + div = max_t(unsigned long, div, p->min_div); + for (k = 0; k < ARRAY_SIZE(sh_msiof_spi_div_table); k++) { brps = DIV_ROUND_UP(div, sh_msiof_spi_div_table[k].div); /* SCR_BRDV_DIV_1 is valid only if BRPS is x 1/1 or x 1/2 */ @@ -998,24 +1002,33 @@ static const struct sh_msiof_chipdata sh_data = { .tx_fifo_size = 64, .rx_fifo_size = 64, .master_flags = 0, + .min_div = 1, +}; + +static const struct sh_msiof_chipdata rcar_gen2_data = { + .tx_fifo_size = 64, + .rx_fifo_size = 64, + .master_flags = SPI_MASTER_MUST_TX, + .min_div = 1, }; -static const struct sh_msiof_chipdata r8a779x_data = { +static const struct sh_msiof_chipdata rcar_gen3_data = { .tx_fifo_size = 64, .rx_fifo_size = 64, .master_flags = SPI_MASTER_MUST_TX, + .min_div = 2, }; static const struct of_device_id sh_msiof_match[] = { { .compatible = "renesas,sh-mobile-msiof", .data = &sh_data }, - { .compatible = "renesas,msiof-r8a7790", .data = &r8a779x_data }, - { .compatible = "renesas,msiof-r8a7791", .data = &r8a779x_data }, - { .compatible = "renesas,msiof-r8a7792", .data = &r8a779x_data }, - { .compatible = "renesas,msiof-r8a7793", .data = &r8a779x_data }, - { .compatible = "renesas,msiof-r8a7794", .data = &r8a779x_data }, - { .compatible = "renesas,rcar-gen2-msiof", .data = &r8a779x_data }, - { .compatible = "renesas,msiof-r8a7796", .data = &r8a779x_data }, - { .compatible = "renesas,rcar-gen3-msiof", .data = &r8a779x_data }, + { .compatible = "renesas,msiof-r8a7790", .data = &rcar_gen2_data }, + { .compatible = "renesas,msiof-r8a7791", .data = &rcar_gen2_data }, + { .compatible = "renesas,msiof-r8a7792", .data = &rcar_gen2_data }, + { .compatible = "renesas,msiof-r8a7793", .data = &rcar_gen2_data }, + { .compatible = "renesas,msiof-r8a7794", .data = &rcar_gen2_data }, + { .compatible = "renesas,rcar-gen2-msiof", .data = &rcar_gen2_data }, + { .compatible = "renesas,msiof-r8a7796", .data = &rcar_gen3_data }, + { .compatible = "renesas,rcar-gen3-msiof", .data = &rcar_gen3_data }, { .compatible = "renesas,sh-msiof", .data = &sh_data }, /* Deprecated */ {}, }; @@ -1230,6 +1243,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, p); p->master = master; p->info = info; + p->min_div = chipdata->min_div; init_completion(&p->done); -- cgit v1.2.3 From 91a024e80336528d12b67b5a2e636b9e4467d3ec Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Mon, 10 Jul 2017 16:33:39 +0200 Subject: regulator: cpcap: Fix standby mode The original patch from Tony uses standby mode bit inverted, which is not correct. This fixes all instances in the driver code for get & set mode. This did not yet make problems, since mode has not been changed by any mainline driver so far. Fixes: 0ad4c07edd41 ("regulator: cpcap: Add basic regulator support") Acked-by: Tony Lindgren Signed-off-by: Sebastian Reichel Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- drivers/regulator/cpcap-regulator.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/regulator/cpcap-regulator.c b/drivers/regulator/cpcap-regulator.c index cc98aceed1c1..ce1cab320f6f 100644 --- a/drivers/regulator/cpcap-regulator.c +++ b/drivers/regulator/cpcap-regulator.c @@ -77,6 +77,8 @@ #define CPCAP_BIT_VAUDIO_MODE0 BIT(1) #define CPCAP_BIT_V_AUDIO_EN BIT(0) +#define CPCAP_BIT_AUDIO_NORMAL_MODE 0x00 + /* * Off mode configuration bit. Used currently only by SW5 on omap4. There's * the following comment in Motorola Linux kernel tree for it: @@ -217,7 +219,7 @@ static unsigned int cpcap_regulator_get_mode(struct regulator_dev *rdev) regmap_read(rdev->regmap, rdev->desc->enable_reg, &value); - if (!(value & CPCAP_BIT_AUDIO_LOW_PWR)) + if (value & CPCAP_BIT_AUDIO_LOW_PWR) return REGULATOR_MODE_STANDBY; return REGULATOR_MODE_NORMAL; @@ -230,10 +232,10 @@ static int cpcap_regulator_set_mode(struct regulator_dev *rdev, switch (mode) { case REGULATOR_MODE_NORMAL: - value = CPCAP_BIT_AUDIO_LOW_PWR; + value = CPCAP_BIT_AUDIO_NORMAL_MODE; break; case REGULATOR_MODE_STANDBY: - value = 0; + value = CPCAP_BIT_AUDIO_LOW_PWR; break; default: return -EINVAL; -- cgit v1.2.3 From 74ff8e06510196dfa31679010d9a05c5cdc39754 Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Mon, 10 Jul 2017 16:33:40 +0200 Subject: regulator: cpcap: Add OF mode mapping Add device tree mode mapping capabilities to the cpcap driver. Acked-by: Tony Lindgren Signed-off-by: Sebastian Reichel Signed-off-by: Mark Brown --- drivers/regulator/cpcap-regulator.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/regulator/cpcap-regulator.c b/drivers/regulator/cpcap-regulator.c index ce1cab320f6f..f541b80f1b54 100644 --- a/drivers/regulator/cpcap-regulator.c +++ b/drivers/regulator/cpcap-regulator.c @@ -123,6 +123,7 @@ struct cpcap_regulator { .enable_val = (mode_val), \ .disable_val = (off_val), \ .ramp_delay = (volt_trans_time), \ + .of_map_mode = cpcap_map_mode, \ }, \ .assign_reg = (assignment_reg), \ .assign_mask = (assignment_mask), \ @@ -213,6 +214,18 @@ static int cpcap_regulator_disable(struct regulator_dev *rdev) return error; } +static unsigned int cpcap_map_mode(unsigned int mode) +{ + switch (mode) { + case CPCAP_BIT_AUDIO_NORMAL_MODE: + return REGULATOR_MODE_NORMAL; + case CPCAP_BIT_AUDIO_LOW_PWR: + return REGULATOR_MODE_STANDBY; + default: + return -EINVAL; + } +} + static unsigned int cpcap_regulator_get_mode(struct regulator_dev *rdev) { int value; -- cgit v1.2.3 From 992510f3b60d84ce098e6cfb00a70266bdfbc4c0 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sun, 9 Jul 2017 21:00:07 -0500 Subject: usb: isp1760: compress return logic into one line Simplify return logic to avoid unnecessary variable assignment. This issue was detected using Coccinelle and the following semantic patch: @@ local idexpression ret; expression e; @@ -ret = +return e; -return ret; Signed-off-by: Gustavo A. R. Silva Signed-off-by: Greg Kroah-Hartman --- drivers/usb/isp1760/isp1760-hcd.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/isp1760/isp1760-hcd.c b/drivers/usb/isp1760/isp1760-hcd.c index ac31d19cc54b..8e59e0c02b8a 100644 --- a/drivers/usb/isp1760/isp1760-hcd.c +++ b/drivers/usb/isp1760/isp1760-hcd.c @@ -396,7 +396,6 @@ static int handshake(struct usb_hcd *hcd, u32 reg, /* reset a non-running (STS_HALT == 1) controller */ static int ehci_reset(struct usb_hcd *hcd) { - int retval; struct isp1760_hcd *priv = hcd_to_priv(hcd); u32 command = reg_read32(hcd->regs, HC_USBCMD); @@ -405,9 +404,8 @@ static int ehci_reset(struct usb_hcd *hcd) reg_write32(hcd->regs, HC_USBCMD, command); hcd->state = HC_STATE_HALT; priv->next_statechange = jiffies; - retval = handshake(hcd, HC_USBCMD, - CMD_RESET, 0, 250 * 1000); - return retval; + + return handshake(hcd, HC_USBCMD, CMD_RESET, 0, 250 * 1000); } static struct isp1760_qh *qh_alloc(gfp_t flags) -- cgit v1.2.3 From e6f9e13b62bad739a9fc095e061dc9fc8cf4168c Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sun, 9 Jul 2017 22:31:31 -0500 Subject: usb: misc: sisusbvga: compress return logic into one line Simplify return logic to avoid unnecessary variable declaration and assignment. These issues were detected using Coccinelle and the following semantic patch: @@ local idexpression ret; expression e; @@ -ret = +return e; -return ret; Signed-off-by: Gustavo A. R. Silva Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/sisusbvga/sisusb.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index 440d7fef58cc..30774e0aeadd 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -610,13 +610,11 @@ static int sisusb_write_memio_byte(struct sisusb_usb_data *sisusb, int type, u32 addr, u8 data) { struct sisusb_packet packet; - int ret; packet.header = (1 << (addr & 3)) | (type << 6); packet.address = addr & ~3; packet.data = data << ((addr & 3) << 3); - ret = sisusb_send_packet(sisusb, 10, &packet); - return ret; + return sisusb_send_packet(sisusb, 10, &packet); } static int sisusb_write_memio_word(struct sisusb_usb_data *sisusb, int type, @@ -1333,13 +1331,11 @@ static int sisusb_write_pci_config(struct sisusb_usb_data *sisusb, int regnum, u32 data) { struct sisusb_packet packet; - int ret; packet.header = 0x008f; packet.address = regnum | 0x10000; packet.data = data; - ret = sisusb_send_packet(sisusb, 10, &packet); - return ret; + return sisusb_send_packet(sisusb, 10, &packet); } static int sisusb_read_pci_config(struct sisusb_usb_data *sisusb, @@ -2982,14 +2978,11 @@ err_out: static long sisusb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg) { - long retval; - switch (cmd) { case SISUSB_GET_CONFIG_SIZE: case SISUSB_GET_CONFIG: case SISUSB_COMMAND: - retval = sisusb_ioctl(f, cmd, arg); - return retval; + return sisusb_ioctl(f, cmd, arg); default: return -ENOIOCTLCMD; -- cgit v1.2.3 From 020e03b78312ab0df1fd3c4ea62e675724cd18cf Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sun, 9 Jul 2017 22:22:46 -0500 Subject: usb: misc: ftdi-elan: compress return logic into one line Simplify return logic to avoid unnecessary variable declaration and assignment. This issue was detected using Coccinelle and the following semantic patch: @@ local idexpression ret; expression e; @@ -ret = +return e; -return ret; Signed-off-by: Gustavo A. R. Silva Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/ftdi-elan.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index 8291499d0581..c45904f08274 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c @@ -305,9 +305,9 @@ static int ftdi_elan_command_engine(struct usb_ftdi *ftdi); static int ftdi_elan_respond_engine(struct usb_ftdi *ftdi); static int ftdi_elan_hcd_init(struct usb_ftdi *ftdi) { - int result; if (ftdi->platform_dev.dev.parent) return -EBUSY; + ftdi_elan_get_kref(ftdi); ftdi->platform_data.potpg = 100; ftdi->platform_data.reset = NULL; @@ -324,8 +324,8 @@ static int ftdi_elan_hcd_init(struct usb_ftdi *ftdi) request_module("u132_hcd"); dev_info(&ftdi->udev->dev, "registering '%s'\n", ftdi->platform_dev.name); - result = platform_device_register(&ftdi->platform_dev); - return result; + + return platform_device_register(&ftdi->platform_dev); } static void ftdi_elan_abandon_completions(struct usb_ftdi *ftdi) -- cgit v1.2.3 From 013668f3dc5d4e54f1c081e99802c42bb02bcb80 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 4 Jul 2017 11:31:24 +0100 Subject: usb: renesas_usbhs: make array type_array static const Array type_array can be made static const rather than being populated on the stack. Makes the object code smaller: Before: text data bss dec hex filename 8087 1496 0 9583 256f drivers/usb/renesas_usbhs/pipe.o After: text data bss dec hex filename 7883 1584 0 9467 24fb drivers/usb/renesas_usbhs/pipe.o Signed-off-by: Colin Ian King Signed-off-by: Greg Kroah-Hartman --- drivers/usb/renesas_usbhs/pipe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/renesas_usbhs/pipe.c b/drivers/usb/renesas_usbhs/pipe.c index 9396a8c14af8..d811f0550c04 100644 --- a/drivers/usb/renesas_usbhs/pipe.c +++ b/drivers/usb/renesas_usbhs/pipe.c @@ -401,7 +401,7 @@ static int usbhsp_setup_pipecfg(struct usbhs_pipe *pipe, int is_host, u16 dir = 0; u16 epnum = 0; u16 shtnak = 0; - u16 type_array[] = { + static const u16 type_array[] = { [USB_ENDPOINT_XFER_BULK] = TYPE_BULK, [USB_ENDPOINT_XFER_INT] = TYPE_INT, [USB_ENDPOINT_XFER_ISOC] = TYPE_ISO, -- cgit v1.2.3 From 4b26ebacb6cc8a86ce55dbeabbf5fe8887f5b1de Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 3 Jul 2017 10:18:57 +0100 Subject: usb: atm: ueagle-atm: fix spelling mistake: "submition" -> "submission" Trivial fix to spelling mistake in uea_err error message Signed-off-by: Colin Ian King Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/ueagle-atm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index df67815f74e6..a7b69360949e 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c @@ -2212,7 +2212,7 @@ static int uea_boot(struct uea_softc *sc) ret = usb_submit_urb(sc->urb_int, GFP_KERNEL); if (ret < 0) { uea_err(INS_TO_USBDEV(sc), - "urb submition failed with error %d\n", ret); + "urb submission failed with error %d\n", ret); goto err1; } -- cgit v1.2.3 From 635f56c342cd195a8059f24296fe7fd795aaa33d Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 14 Jul 2017 18:12:41 +0300 Subject: drm/i915: Fix error checking/locking in perf/lookup_context() 1acfc104cdf8 missed to convert this one caller to be lockless. The side effect of that was that the error check in lookup_context() became incorrect. Convert now this caller too. Fixes: 1acfc104cdf ("drm/i915: Enable rcu-only context lookups") Cc: Chris Wilson Cc: Joonas Lahtinen Reviewed-by: Chris Wilson Reviewed-by: Lionel Landwerlin Signed-off-by: Imre Deak Link: http://patchwork.freedesktop.org/patch/msgid/20170714151242.517-1-imre.deak@intel.com --- drivers/gpu/drm/i915/i915_perf.c | 32 +++++--------------------------- 1 file changed, 5 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index d9f77a4d85db..96682fd86f82 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -2483,27 +2483,6 @@ static const struct file_operations fops = { }; -static struct i915_gem_context * -lookup_context(struct drm_i915_private *dev_priv, - struct drm_i915_file_private *file_priv, - u32 ctx_user_handle) -{ - struct i915_gem_context *ctx; - int ret; - - ret = i915_mutex_lock_interruptible(&dev_priv->drm); - if (ret) - return ERR_PTR(ret); - - ctx = i915_gem_context_lookup(file_priv, ctx_user_handle); - if (!IS_ERR(ctx)) - i915_gem_context_get(ctx); - - mutex_unlock(&dev_priv->drm.struct_mutex); - - return ctx; -} - /** * i915_perf_open_ioctl_locked - DRM ioctl() for userspace to open a stream FD * @dev_priv: i915 device instance @@ -2545,12 +2524,11 @@ i915_perf_open_ioctl_locked(struct drm_i915_private *dev_priv, u32 ctx_handle = props->ctx_handle; struct drm_i915_file_private *file_priv = file->driver_priv; - specific_ctx = lookup_context(dev_priv, file_priv, ctx_handle); - if (IS_ERR(specific_ctx)) { - ret = PTR_ERR(specific_ctx); - if (ret != -EINTR) - DRM_DEBUG("Failed to look up context with ID %u for opening perf stream\n", - ctx_handle); + specific_ctx = i915_gem_context_lookup(file_priv, ctx_handle); + if (!specific_ctx) { + DRM_DEBUG("Failed to look up context with ID %u for opening perf stream\n", + ctx_handle); + ret = -ENOENT; goto err; } } -- cgit v1.2.3 From edd9003f7f9dddd28fdd768e6e7569d996c769cb Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 14 Jul 2017 18:12:42 +0300 Subject: drm/i915: Fix user ptr check size in eb_relocate_vma() Fix the sizeof(ptr) vs. sizeof(*ptr) typo. Fixes: 2889caa92321 ("drm/i915: Eliminate lots of iterations over the execobjects array") Cc: Chris Wilson Cc: Joonas Lahtinen Signed-off-by: Imre Deak Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/20170714151242.517-2-imre.deak@intel.com --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 929f275e67aa..fe3e0d40034c 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1459,7 +1459,7 @@ static int eb_relocate_vma(struct i915_execbuffer *eb, struct i915_vma *vma) * to read. However, if the array is not writable the user loses * the updated relocation values. */ - if (unlikely(!access_ok(VERIFY_READ, urelocs, remain*sizeof(urelocs)))) + if (unlikely(!access_ok(VERIFY_READ, urelocs, remain*sizeof(*urelocs)))) return -EFAULT; do { -- cgit v1.2.3 From c54182ec0e157988f0cafd1e8d37b68ab4210f87 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Thu, 29 Jun 2017 12:00:05 +0200 Subject: EDAC: Get rid of mci->mod_ver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is a write-only variable so get rid of it. Signed-off-by: Borislav Petkov Acked-by: Robert Richter Acked-by: Michal Simek Acked-by: Thor Thayer Acked-by: Tony Luck Cc: Mark Gross Cc: Tim Small Cc: Ranganathan Desikan Cc: "Arvind R." Cc: Jason Baron Cc: "Sören Brinkmann" Cc: Ralf Baechle Cc: David Daney Cc: Loc Ho Cc: linux-edac@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-mips@linux-mips.org --- drivers/edac/altera_edac.c | 2 -- drivers/edac/amd64_edac.c | 1 - drivers/edac/amd76x_edac.c | 2 -- drivers/edac/cpc925_edac.c | 1 - drivers/edac/e752x_edac.c | 2 -- drivers/edac/e7xxx_edac.c | 2 -- drivers/edac/ghes_edac.c | 3 --- drivers/edac/highbank_mc_edac.c | 1 - drivers/edac/i3000_edac.c | 3 --- drivers/edac/i3200_edac.c | 3 --- drivers/edac/i5000_edac.c | 1 - drivers/edac/i5100_edac.c | 1 - drivers/edac/i5400_edac.c | 1 - drivers/edac/i7300_edac.c | 1 - drivers/edac/i7core_edac.c | 1 - drivers/edac/i82443bxgx_edac.c | 3 --- drivers/edac/i82860_edac.c | 2 -- drivers/edac/i82875p_edac.c | 2 -- drivers/edac/i82975x_edac.c | 2 -- drivers/edac/ie31200_edac.c | 2 -- drivers/edac/mv64x60_edac.c | 1 - drivers/edac/ppc4xx_edac.c | 1 - drivers/edac/r82600_edac.c | 2 -- drivers/edac/sb_edac.c | 1 - drivers/edac/skx_edac.c | 3 --- drivers/edac/synopsys_edac.c | 1 - drivers/edac/thunderx_edac.c | 1 - drivers/edac/x38_edac.c | 3 --- drivers/edac/xgene_edac.c | 1 - include/linux/edac.h | 1 - 30 files changed, 51 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c index db75d4b614f7..fa2e5db56d24 100644 --- a/drivers/edac/altera_edac.c +++ b/drivers/edac/altera_edac.c @@ -38,7 +38,6 @@ #include "edac_module.h" #define EDAC_MOD_STR "altera_edac" -#define EDAC_VERSION "1" #define EDAC_DEVICE "Altera" static const struct altr_sdram_prv_data c5_data = { @@ -392,7 +391,6 @@ static int altr_sdram_probe(struct platform_device *pdev) mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; mci->edac_cap = EDAC_FLAG_SECDED; mci->mod_name = EDAC_MOD_STR; - mci->mod_ver = EDAC_VERSION; mci->ctl_name = dev_name(&pdev->dev); mci->scrub_mode = SCRUB_SW_SRC; mci->dev_name = dev_name(&pdev->dev); diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 3aea55698165..ac2f30295efe 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -3130,7 +3130,6 @@ static void setup_mci_misc_attrs(struct mem_ctl_info *mci, mci->edac_cap = determine_edac_cap(pvt); mci->mod_name = EDAC_MOD_STR; - mci->mod_ver = EDAC_AMD64_VERSION; mci->ctl_name = fam->ctl_name; mci->dev_name = pci_name(pvt->F3); mci->ctl_page_to_phys = NULL; diff --git a/drivers/edac/amd76x_edac.c b/drivers/edac/amd76x_edac.c index a7450275ad28..9c6e326b4c14 100644 --- a/drivers/edac/amd76x_edac.c +++ b/drivers/edac/amd76x_edac.c @@ -19,7 +19,6 @@ #include #include "edac_module.h" -#define AMD76X_REVISION " Ver: 2.0.2" #define EDAC_MOD_STR "amd76x_edac" #define amd76x_printk(level, fmt, arg...) \ @@ -263,7 +262,6 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) mci->edac_cap = ems_mode ? (EDAC_FLAG_EC | EDAC_FLAG_SECDED) : EDAC_FLAG_NONE; mci->mod_name = EDAC_MOD_STR; - mci->mod_ver = AMD76X_REVISION; mci->ctl_name = amd76x_devs[dev_idx].ctl_name; mci->dev_name = pci_name(pdev); mci->edac_check = amd76x_check; diff --git a/drivers/edac/cpc925_edac.c b/drivers/edac/cpc925_edac.c index 837b62c4993d..cba8ee14a067 100644 --- a/drivers/edac/cpc925_edac.c +++ b/drivers/edac/cpc925_edac.c @@ -999,7 +999,6 @@ static int cpc925_probe(struct platform_device *pdev) mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; mci->edac_cap = EDAC_FLAG_SECDED; mci->mod_name = CPC925_EDAC_MOD_STR; - mci->mod_ver = CPC925_EDAC_REVISION; mci->ctl_name = pdev->name; if (edac_op_state == EDAC_OPSTATE_POLL) diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index 1a352cae1f52..b5de9a13ea3f 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c @@ -26,7 +26,6 @@ #include #include "edac_module.h" -#define E752X_REVISION " Ver: 2.0.2" #define EDAC_MOD_STR "e752x_edac" static int report_non_memory_errors; @@ -1303,7 +1302,6 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) (EDAC_FLAG_NONE | EDAC_FLAG_SECDED | EDAC_FLAG_S4ECD4ED); /* FIXME - what if different memory types are in different csrows? */ mci->mod_name = EDAC_MOD_STR; - mci->mod_ver = E752X_REVISION; mci->pdev = &pdev->dev; edac_dbg(3, "init pvt\n"); diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c index 67ef07aed923..75d7ce62b3be 100644 --- a/drivers/edac/e7xxx_edac.c +++ b/drivers/edac/e7xxx_edac.c @@ -32,7 +32,6 @@ #include #include "edac_module.h" -#define E7XXX_REVISION " Ver: 2.0.2" #define EDAC_MOD_STR "e7xxx_edac" #define e7xxx_printk(level, fmt, arg...) \ @@ -458,7 +457,6 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) EDAC_FLAG_S4ECD4ED; /* FIXME - what if different memory types are in different csrows? */ mci->mod_name = EDAC_MOD_STR; - mci->mod_ver = E7XXX_REVISION; mci->pdev = &pdev->dev; edac_dbg(3, "init pvt\n"); pvt = (struct e7xxx_pvt *)mci->pvt_info; diff --git a/drivers/edac/ghes_edac.c b/drivers/edac/ghes_edac.c index 4e61a6229dd2..6f80eb65c26c 100644 --- a/drivers/edac/ghes_edac.c +++ b/drivers/edac/ghes_edac.c @@ -17,8 +17,6 @@ #include "edac_module.h" #include -#define GHES_EDAC_REVISION " Ver: 1.0.0" - struct ghes_edac_pvt { struct list_head list; struct ghes *ghes; @@ -451,7 +449,6 @@ int ghes_edac_register(struct ghes *ghes, struct device *dev) mci->edac_ctl_cap = EDAC_FLAG_NONE; mci->edac_cap = EDAC_FLAG_NONE; mci->mod_name = "ghes_edac.c"; - mci->mod_ver = GHES_EDAC_REVISION; mci->ctl_name = "ghes_edac"; mci->dev_name = "ghes"; diff --git a/drivers/edac/highbank_mc_edac.c b/drivers/edac/highbank_mc_edac.c index 0e7e0a404d89..6092e61be605 100644 --- a/drivers/edac/highbank_mc_edac.c +++ b/drivers/edac/highbank_mc_edac.c @@ -224,7 +224,6 @@ static int highbank_mc_probe(struct platform_device *pdev) mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; mci->edac_cap = EDAC_FLAG_SECDED; mci->mod_name = pdev->dev.driver->name; - mci->mod_ver = "1"; mci->ctl_name = id->compatible; mci->dev_name = dev_name(&pdev->dev); mci->scrub_mode = SCRUB_SW_SRC; diff --git a/drivers/edac/i3000_edac.c b/drivers/edac/i3000_edac.c index 5306240570d7..8085a32ec3bd 100644 --- a/drivers/edac/i3000_edac.c +++ b/drivers/edac/i3000_edac.c @@ -16,8 +16,6 @@ #include #include "edac_module.h" -#define I3000_REVISION "1.1" - #define EDAC_MOD_STR "i3000_edac" #define I3000_RANKS 8 @@ -375,7 +373,6 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx) mci->edac_cap = EDAC_FLAG_SECDED; mci->mod_name = EDAC_MOD_STR; - mci->mod_ver = I3000_REVISION; mci->ctl_name = i3000_devs[dev_idx].ctl_name; mci->dev_name = pci_name(pdev); mci->edac_check = i3000_check; diff --git a/drivers/edac/i3200_edac.c b/drivers/edac/i3200_edac.c index 77c58d201a30..d92d56cee101 100644 --- a/drivers/edac/i3200_edac.c +++ b/drivers/edac/i3200_edac.c @@ -17,8 +17,6 @@ #include -#define I3200_REVISION "1.1" - #define EDAC_MOD_STR "i3200_edac" #define PCI_DEVICE_ID_INTEL_3200_HB 0x29f0 @@ -375,7 +373,6 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx) mci->edac_cap = EDAC_FLAG_SECDED; mci->mod_name = EDAC_MOD_STR; - mci->mod_ver = I3200_REVISION; mci->ctl_name = i3200_devs[dev_idx].ctl_name; mci->dev_name = pci_name(pdev); mci->edac_check = i3200_check; diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index 8f5a56e25bd2..53f24b18cd61 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c @@ -1430,7 +1430,6 @@ static int i5000_probe1(struct pci_dev *pdev, int dev_idx) mci->edac_ctl_cap = EDAC_FLAG_NONE; mci->edac_cap = EDAC_FLAG_NONE; mci->mod_name = "i5000_edac.c"; - mci->mod_ver = I5000_REVISION; mci->ctl_name = i5000_devs[dev_idx].ctl_name; mci->dev_name = pci_name(pdev); mci->ctl_page_to_phys = NULL; diff --git a/drivers/edac/i5100_edac.c b/drivers/edac/i5100_edac.c index a8334c4acea7..b506eef6b146 100644 --- a/drivers/edac/i5100_edac.c +++ b/drivers/edac/i5100_edac.c @@ -1108,7 +1108,6 @@ static int i5100_init_one(struct pci_dev *pdev, const struct pci_device_id *id) mci->edac_ctl_cap = EDAC_FLAG_SECDED; mci->edac_cap = EDAC_FLAG_SECDED; mci->mod_name = "i5100_edac.c"; - mci->mod_ver = "not versioned"; mci->ctl_name = "i5100"; mci->dev_name = pci_name(pdev); mci->ctl_page_to_phys = NULL; diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c index cd889edc8516..6f8bcdb9256a 100644 --- a/drivers/edac/i5400_edac.c +++ b/drivers/edac/i5400_edac.c @@ -1315,7 +1315,6 @@ static int i5400_probe1(struct pci_dev *pdev, int dev_idx) mci->edac_ctl_cap = EDAC_FLAG_NONE; mci->edac_cap = EDAC_FLAG_NONE; mci->mod_name = "i5400_edac.c"; - mci->mod_ver = I5400_REVISION; mci->ctl_name = i5400_devs[dev_idx].ctl_name; mci->dev_name = pci_name(pdev); mci->ctl_page_to_phys = NULL; diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index e391f5a716be..6b5a554ba8e4 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -1077,7 +1077,6 @@ static int i7300_init_one(struct pci_dev *pdev, const struct pci_device_id *id) mci->edac_ctl_cap = EDAC_FLAG_NONE; mci->edac_cap = EDAC_FLAG_NONE; mci->mod_name = "i7300_edac.c"; - mci->mod_ver = I7300_REVISION; mci->ctl_name = i7300_devs[0].ctl_name; mci->dev_name = pci_name(pdev); mci->ctl_page_to_phys = NULL; diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index ba0fa112996f..d36cc8498084 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -2159,7 +2159,6 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev) mci->edac_ctl_cap = EDAC_FLAG_NONE; mci->edac_cap = EDAC_FLAG_NONE; mci->mod_name = "i7core_edac.c"; - mci->mod_ver = I7CORE_REVISION; mci->ctl_name = kasprintf(GFP_KERNEL, "i7 core #%d", i7core_dev->socket); mci->dev_name = pci_name(i7core_dev->pdev[0]); diff --git a/drivers/edac/i82443bxgx_edac.c b/drivers/edac/i82443bxgx_edac.c index cb61a5b7d080..a2ca929e2168 100644 --- a/drivers/edac/i82443bxgx_edac.c +++ b/drivers/edac/i82443bxgx_edac.c @@ -31,8 +31,6 @@ #include #include "edac_module.h" -#define I82443_REVISION "0.1" - #define EDAC_MOD_STR "i82443bxgx_edac" /* The 82443BX supports SDRAM, or EDO (EDO for mobile only), "Memory @@ -320,7 +318,6 @@ static int i82443bxgx_edacmc_probe1(struct pci_dev *pdev, int dev_idx) I82443BXGX_EAP_OFFSET_MBE)); mci->mod_name = EDAC_MOD_STR; - mci->mod_ver = I82443_REVISION; mci->ctl_name = "I82443BXGX"; mci->dev_name = pci_name(pdev); mci->edac_check = i82443bxgx_edacmc_check; diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c index 236c813227fc..3e3a80ffb322 100644 --- a/drivers/edac/i82860_edac.c +++ b/drivers/edac/i82860_edac.c @@ -16,7 +16,6 @@ #include #include "edac_module.h" -#define I82860_REVISION " Ver: 2.0.2" #define EDAC_MOD_STR "i82860_edac" #define i82860_printk(level, fmt, arg...) \ @@ -216,7 +215,6 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx) /* I"m not sure about this but I think that all RDRAM is SECDED */ mci->edac_cap = EDAC_FLAG_SECDED; mci->mod_name = EDAC_MOD_STR; - mci->mod_ver = I82860_REVISION; mci->ctl_name = i82860_devs[dev_idx].ctl_name; mci->dev_name = pci_name(pdev); mci->edac_check = i82860_check; diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c index e286b7e74c7a..ceac925af38c 100644 --- a/drivers/edac/i82875p_edac.c +++ b/drivers/edac/i82875p_edac.c @@ -20,7 +20,6 @@ #include #include "edac_module.h" -#define I82875P_REVISION " Ver: 2.0.2" #define EDAC_MOD_STR "i82875p_edac" #define i82875p_printk(level, fmt, arg...) \ @@ -423,7 +422,6 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; mci->edac_cap = EDAC_FLAG_UNKNOWN; mci->mod_name = EDAC_MOD_STR; - mci->mod_ver = I82875P_REVISION; mci->ctl_name = i82875p_devs[dev_idx].ctl_name; mci->dev_name = pci_name(pdev); mci->edac_check = i82875p_check; diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c index 9dcdab28f665..892815eaa97b 100644 --- a/drivers/edac/i82975x_edac.c +++ b/drivers/edac/i82975x_edac.c @@ -16,7 +16,6 @@ #include #include "edac_module.h" -#define I82975X_REVISION " Ver: 1.0.0" #define EDAC_MOD_STR "i82975x_edac" #define i82975x_printk(level, fmt, arg...) \ @@ -564,7 +563,6 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; mci->edac_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; mci->mod_name = EDAC_MOD_STR; - mci->mod_ver = I82975X_REVISION; mci->ctl_name = i82975x_devs[dev_idx].ctl_name; mci->dev_name = pci_name(pdev); mci->edac_check = i82975x_check; diff --git a/drivers/edac/ie31200_edac.c b/drivers/edac/ie31200_edac.c index 4260579e6901..aac9b9b360b8 100644 --- a/drivers/edac/ie31200_edac.c +++ b/drivers/edac/ie31200_edac.c @@ -45,7 +45,6 @@ #include #include "edac_module.h" -#define IE31200_REVISION "1.0" #define EDAC_MOD_STR "ie31200_edac" #define ie31200_printk(level, fmt, arg...) \ @@ -420,7 +419,6 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx) mci->edac_ctl_cap = EDAC_FLAG_SECDED; mci->edac_cap = EDAC_FLAG_SECDED; mci->mod_name = EDAC_MOD_STR; - mci->mod_ver = IE31200_REVISION; mci->ctl_name = ie31200_devs[dev_idx].ctl_name; mci->dev_name = pci_name(pdev); mci->edac_check = ie31200_check; diff --git a/drivers/edac/mv64x60_edac.c b/drivers/edac/mv64x60_edac.c index d3650df94fe8..ec5d695bbb72 100644 --- a/drivers/edac/mv64x60_edac.c +++ b/drivers/edac/mv64x60_edac.c @@ -766,7 +766,6 @@ static int mv64x60_mc_err_probe(struct platform_device *pdev) mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; mci->edac_cap = EDAC_FLAG_SECDED; mci->mod_name = EDAC_MOD_STR; - mci->mod_ver = MV64x60_REVISION; mci->ctl_name = mv64x60_ctl_name; if (edac_op_state == EDAC_OPSTATE_POLL) diff --git a/drivers/edac/ppc4xx_edac.c b/drivers/edac/ppc4xx_edac.c index e55e92590106..98d6dc7ef8e8 100644 --- a/drivers/edac/ppc4xx_edac.c +++ b/drivers/edac/ppc4xx_edac.c @@ -1063,7 +1063,6 @@ static int ppc4xx_edac_mc_init(struct mem_ctl_info *mci, /* Initialize strings */ mci->mod_name = PPC4XX_EDAC_MODULE_NAME; - mci->mod_ver = PPC4XX_EDAC_MODULE_REVISION; mci->ctl_name = ppc4xx_edac_match->compatible, mci->dev_name = np->full_name; diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c index 978916625ced..851e53e122aa 100644 --- a/drivers/edac/r82600_edac.c +++ b/drivers/edac/r82600_edac.c @@ -22,7 +22,6 @@ #include #include "edac_module.h" -#define R82600_REVISION " Ver: 2.0.2" #define EDAC_MOD_STR "r82600_edac" #define r82600_printk(level, fmt, arg...) \ @@ -316,7 +315,6 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) mci->edac_cap = EDAC_FLAG_NONE; mci->mod_name = EDAC_MOD_STR; - mci->mod_ver = R82600_REVISION; mci->ctl_name = "R82600"; mci->dev_name = pci_name(pdev); mci->edac_check = r82600_check; diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index 80d860cb0746..687d0f23b9cc 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -3125,7 +3125,6 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) mci->edac_ctl_cap = EDAC_FLAG_NONE; mci->edac_cap = EDAC_FLAG_NONE; mci->mod_name = "sb_edac.c"; - mci->mod_ver = SBRIDGE_REVISION; mci->dev_name = pci_name(pdev); mci->ctl_page_to_phys = NULL; diff --git a/drivers/edac/skx_edac.c b/drivers/edac/skx_edac.c index 64bef6c9cfb4..16dea97568a1 100644 --- a/drivers/edac/skx_edac.c +++ b/drivers/edac/skx_edac.c @@ -31,8 +31,6 @@ #include "edac_module.h" -#define SKX_REVISION " Ver: 1.0 " - /* * Debug macros */ @@ -473,7 +471,6 @@ static int skx_register_mci(struct skx_imc *imc) mci->edac_cap = EDAC_FLAG_NONE; mci->mod_name = "skx_edac.c"; mci->dev_name = pci_name(imc->chan[0].cdev); - mci->mod_ver = SKX_REVISION; mci->ctl_page_to_phys = NULL; rc = skx_get_dimm_config(mci); diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c index 1c01dec78ec3..0c9c59e2b5a3 100644 --- a/drivers/edac/synopsys_edac.c +++ b/drivers/edac/synopsys_edac.c @@ -413,7 +413,6 @@ static int synps_edac_mc_init(struct mem_ctl_info *mci, mci->ctl_name = "synps_ddr_controller"; mci->dev_name = SYNPS_EDAC_MOD_STRING; mci->mod_name = SYNPS_EDAC_MOD_VER; - mci->mod_ver = "1"; edac_op_state = EDAC_OPSTATE_POLL; mci->edac_check = synps_edac_check; diff --git a/drivers/edac/thunderx_edac.c b/drivers/edac/thunderx_edac.c index 2d352b40ae1c..c8e8b9fd4772 100644 --- a/drivers/edac/thunderx_edac.c +++ b/drivers/edac/thunderx_edac.c @@ -732,7 +732,6 @@ static int thunderx_lmc_probe(struct pci_dev *pdev, mci->edac_cap = EDAC_FLAG_SECDED; mci->mod_name = "thunderx-lmc"; - mci->mod_ver = "1"; mci->ctl_name = "thunderx-lmc"; mci->dev_name = dev_name(&pdev->dev); mci->scrub_mode = SCRUB_NONE; diff --git a/drivers/edac/x38_edac.c b/drivers/edac/x38_edac.c index 03c97a4bf590..cc779f3f9e2d 100644 --- a/drivers/edac/x38_edac.c +++ b/drivers/edac/x38_edac.c @@ -18,8 +18,6 @@ #include #include "edac_module.h" -#define X38_REVISION "1.1" - #define EDAC_MOD_STR "x38_edac" #define PCI_DEVICE_ID_INTEL_X38_HB 0x29e0 @@ -357,7 +355,6 @@ static int x38_probe1(struct pci_dev *pdev, int dev_idx) mci->edac_cap = EDAC_FLAG_SECDED; mci->mod_name = EDAC_MOD_STR; - mci->mod_ver = X38_REVISION; mci->ctl_name = x38_devs[dev_idx].ctl_name; mci->dev_name = pci_name(pdev); mci->edac_check = x38_check; diff --git a/drivers/edac/xgene_edac.c b/drivers/edac/xgene_edac.c index 669246056812..e8b81d7ef61f 100644 --- a/drivers/edac/xgene_edac.c +++ b/drivers/edac/xgene_edac.c @@ -415,7 +415,6 @@ static int xgene_edac_mc_add(struct xgene_edac *edac, struct device_node *np) mci->edac_ctl_cap = EDAC_FLAG_SECDED; mci->edac_cap = EDAC_FLAG_SECDED; mci->mod_name = EDAC_MOD_STR; - mci->mod_ver = "0.1"; mci->ctl_page_to_phys = NULL; mci->scrub_cap = SCRUB_FLAG_HW_SRC; mci->scrub_mode = SCRUB_HW_SRC; diff --git a/include/linux/edac.h b/include/linux/edac.h index 8ae0f45fafd6..cd75c173fd00 100644 --- a/include/linux/edac.h +++ b/include/linux/edac.h @@ -619,7 +619,6 @@ struct mem_ctl_info { */ struct device *pdev; const char *mod_name; - const char *mod_ver; const char *ctl_name; const char *dev_name; void *pvt_info; -- cgit v1.2.3 From 06168a64b1ae346816fcd0a0c3ea5276c778408b Mon Sep 17 00:00:00 2001 From: Bhushan Shah Date: Fri, 23 Jun 2017 09:24:33 +0530 Subject: backlight: lm3630a: Bump REG_MAX value to 0x50 instead of 0x1F In the lm3630a_chip_init we try to write to 0x50 register, which is higher value then the max_register value, this resulted in regmap_write return -EIO. Fix this by bumping REG_MAX value to 0x50. This code was introduced with the chip revision in commit 28e64a68a2ef, however setting filter strength was failing silently because it used unsigned int for storing and comparing the return values. Bug related to signedness was fixed in 2a0c316bf3cc, which made it error out correctly instead of failing silently. I found this issue by using this driver on LGE Nexus 5 (hammerhead). After this commit lm3630a_chip_init succeeds instead of failing with -EIO. Fixes: 28e64a68a2ef ("backlight: lm3630: apply chip revision") Fixes: 2a0c316bf3cc ("drivers/video/backlight/lm3630a_bl.c: fix signedness bug in lm3630a_chip_init()") Suggested-by: Bjorn Andersson Signed-off-by: Bhushan Shah Acked-by: Daniel Thompson Signed-off-by: Lee Jones --- drivers/video/backlight/lm3630a_bl.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/video/backlight/lm3630a_bl.c b/drivers/video/backlight/lm3630a_bl.c index 60d6c2ac87aa..2030a6b77a09 100644 --- a/drivers/video/backlight/lm3630a_bl.c +++ b/drivers/video/backlight/lm3630a_bl.c @@ -31,7 +31,8 @@ #define REG_FAULT 0x0B #define REG_PWM_OUTLOW 0x12 #define REG_PWM_OUTHIGH 0x13 -#define REG_MAX 0x1F +#define REG_FILTER_STRENGTH 0x50 +#define REG_MAX 0x50 #define INT_DEBOUNCE_MSEC 10 struct lm3630a_chip { @@ -80,7 +81,7 @@ static int lm3630a_chip_init(struct lm3630a_chip *pchip) usleep_range(1000, 2000); /* set Filter Strength Register */ - rval = lm3630a_write(pchip, 0x50, 0x03); + rval = lm3630a_write(pchip, REG_FILTER_STRENGTH, 0x03); /* set Cofig. register */ rval |= lm3630a_update(pchip, REG_CONFIG, 0x07, pdata->pwm_ctrl); /* set boost control */ -- cgit v1.2.3 From 09dad3120804b81d3dfdbd928946787837af7f9e Mon Sep 17 00:00:00 2001 From: Shreeya Patel Date: Sun, 16 Jul 2017 15:20:42 +0530 Subject: Staging: rtl8192u: Use __func__ instead of function name. Current function name is accessed using __func__. Use '%s and __func__' instead of a function name. Problem found by checkpatch. Signed-off-by: Shreeya Patel Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/r8192U_core.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c index 779ecdbc4e17..46b3f19e0878 100644 --- a/drivers/staging/rtl8192u/r8192U_core.c +++ b/drivers/staging/rtl8192u/r8192U_core.c @@ -270,8 +270,7 @@ int write_nic_byte_E(struct net_device *dev, int indx, u8 data) kfree(usbdata); if (status < 0) { - netdev_err(dev, "write_nic_byte_E TimeOut! status: %d\n", - status); + netdev_err(dev, "%s TimeOut! status: %d\n", __func__, status); return status; } return 0; @@ -321,7 +320,7 @@ int write_nic_byte(struct net_device *dev, int indx, u8 data) kfree(usbdata); if (status < 0) { - netdev_err(dev, "write_nic_byte TimeOut! status: %d\n", status); + netdev_err(dev, "%s TimeOut! status: %d\n", __func__, status); return status; } @@ -348,7 +347,7 @@ int write_nic_word(struct net_device *dev, int indx, u16 data) kfree(usbdata); if (status < 0) { - netdev_err(dev, "write_nic_word TimeOut! status: %d\n", status); + netdev_err(dev, "%s TimeOut! status: %d\n", __func__, status); return status; } @@ -376,8 +375,7 @@ int write_nic_dword(struct net_device *dev, int indx, u32 data) if (status < 0) { - netdev_err(dev, "write_nic_dword TimeOut! status: %d\n", - status); + netdev_err(dev, "%s TimeOut! status: %d\n", __func__, status); return status; } @@ -3095,7 +3093,8 @@ static RESET_TYPE TxCheckStuck(struct net_device *dev) if (bCheckFwTxCnt) { if (HalTxCheckStuck819xUsb(dev)) { RT_TRACE(COMP_RESET, - "TxCheckStuck(): Fw indicates no Tx condition!\n"); + "%s: Fw indicates no Tx condition!\n", + __func__); return RESET_TYPE_SILENT; } } @@ -3237,7 +3236,7 @@ static void CamRestoreAllEntry(struct net_device *dev) static u8 CAM_CONST_BROAD[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - RT_TRACE(COMP_SEC, "CamRestoreAllEntry:\n"); + RT_TRACE(COMP_SEC, "%s:\n", __func__); if ((priv->ieee80211->pairwise_key_type == KEY_TYPE_WEP40) || @@ -3835,8 +3834,8 @@ static u8 HwRateToMRate90(bool bIsHT, u8 rate) default: ret_rate = 0xff; RT_TRACE(COMP_RECV, - "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n", - rate, bIsHT); + "%s: Non supported Rate [%x], bIsHT = %d!!!\n", + __func__, rate, bIsHT); break; } @@ -3897,8 +3896,8 @@ static u8 HwRateToMRate90(bool bIsHT, u8 rate) default: ret_rate = 0xff; RT_TRACE(COMP_RECV, - "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n", - rate, bIsHT); + "%s: Non supported Rate [%x], bIsHT = %d!!!\n", + __func__, rate, bIsHT); break; } } -- cgit v1.2.3 From b6c82cc87f46d0f7b9ed215a3305f45d22ad1892 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Sat, 15 Jul 2017 11:39:22 -0400 Subject: staging: lustre: lustre: fix all braces issues reported by checkpatch Cleanup all braces that was reported by checkpatch. The only issue not fixed up is in mdc_lock.c. Removing the braces in the case of mdc_lock.c will break the build. Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/fld/fld_cache.c | 3 ++- drivers/staging/lustre/lustre/ldlm/ldlm_lock.c | 9 +++++---- drivers/staging/lustre/lustre/llite/vvp_dev.c | 5 +++-- 3 files changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/fld/fld_cache.c b/drivers/staging/lustre/lustre/fld/fld_cache.c index b852fed0b10f..adaa0942130f 100644 --- a/drivers/staging/lustre/lustre/fld/fld_cache.c +++ b/drivers/staging/lustre/lustre/fld/fld_cache.c @@ -348,9 +348,10 @@ static void fld_cache_overlap_handle(struct fld_cache *cache, f_curr->fce_range.lsr_end = new_start; fld_cache_entry_add(cache, f_new, &f_curr->fce_list); - } else + } else { CERROR("NEW range =" DRANGE " curr = " DRANGE "\n", PRANGE(range), PRANGE(&f_curr->fce_range)); + } } struct fld_cache_entry diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c index ddb46428093f..181025dc36c3 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c @@ -1029,11 +1029,11 @@ void ldlm_grant_lock(struct ldlm_lock *lock, struct list_head *work_list) if (work_list && lock->l_completion_ast) ldlm_add_ast_work_item(lock, NULL, work_list); - if (res->lr_type == LDLM_PLAIN || res->lr_type == LDLM_IBITS) + if (res->lr_type == LDLM_PLAIN || res->lr_type == LDLM_IBITS) { ldlm_grant_lock_with_skiplist(lock); - else if (res->lr_type == LDLM_EXTENT) + } else if (res->lr_type == LDLM_EXTENT) { ldlm_extent_add_lock(res, lock); - else if (res->lr_type == LDLM_FLOCK) { + } else if (res->lr_type == LDLM_FLOCK) { /* * We should not add locks to granted list in the following cases: * - this is an UNLOCK but not a real lock; @@ -1045,8 +1045,9 @@ void ldlm_grant_lock(struct ldlm_lock *lock, struct list_head *work_list) ldlm_is_test_lock(lock) || ldlm_is_flock_deadlock(lock)) return; ldlm_resource_add_lock(res, &res->lr_granted, lock); - } else + } else { LBUG(); + } ldlm_pool_add(&ldlm_res_to_ns(res)->ns_pool, lock); } diff --git a/drivers/staging/lustre/lustre/llite/vvp_dev.c b/drivers/staging/lustre/lustre/llite/vvp_dev.c index 8e45672b4617..2b6069983ac2 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_dev.c +++ b/drivers/staging/lustre/lustre/llite/vvp_dev.c @@ -591,9 +591,10 @@ static void *vvp_pgcache_start(struct seq_file *f, loff_t *pos) env = cl_env_get(&refcheck); if (!IS_ERR(env)) { sbi = f->private; - if (sbi->ll_site->ls_obj_hash->hs_cur_bits > 64 - PGC_OBJ_SHIFT) + if (sbi->ll_site->ls_obj_hash->hs_cur_bits > + 64 - PGC_OBJ_SHIFT) { pos = ERR_PTR(-EFBIG); - else { + } else { *pos = vvp_pgcache_find(env, &sbi->ll_cl->cd_lu_dev, *pos); if (*pos == ~0ULL) -- cgit v1.2.3 From d56c160cb62583cb47174c2a0948b658650505f5 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 14 Jul 2017 22:33:54 +0100 Subject: staging: lustre: fix spelling mistake, "grranted" -> "granted" Trivial fix to spelling mistake in CERROR error message. Also clean up the grammar. Signed-off-by: Colin Ian King Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ptlrpc/import.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ptlrpc/import.c b/drivers/staging/lustre/lustre/ptlrpc/import.c index 52cb1f0c9c94..b19dac15e901 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/import.c +++ b/drivers/staging/lustre/lustre/ptlrpc/import.c @@ -1026,7 +1026,7 @@ static int ptlrpc_connect_interpret(const struct lu_env *env, /* check that server granted subset of flags we asked for. */ if ((ocd->ocd_connect_flags & imp->imp_connect_flags_orig) != ocd->ocd_connect_flags) { - CERROR("%s: Server didn't granted asked subset of flags: asked=%#llx grranted=%#llx\n", + CERROR("%s: Server didn't grant the asked for subset of flags: asked=%#llx granted=%#llx\n", imp->imp_obd->obd_name, imp->imp_connect_flags_orig, ocd->ocd_connect_flags); rc = -EPROTO; -- cgit v1.2.3 From fdfb4a99b6ab8c393db19e3b92968b74ca2757b0 Mon Sep 17 00:00:00 2001 From: Todd Kjos Date: Thu, 29 Jun 2017 12:01:38 -0700 Subject: binder: separate binder allocator structure from binder proc The binder allocator is logically separate from the rest of the binder drivers. Separating the data structures to prepare for splitting into separate file with separate locking. Signed-off-by: Todd Kjos Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 212 +++++++++++++++++++++++++---------------- drivers/android/binder_trace.h | 2 +- 2 files changed, 129 insertions(+), 85 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index f7665c31feca..1097d056ea6b 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -319,6 +319,41 @@ enum binder_deferred_state { BINDER_DEFERRED_RELEASE = 0x04, }; +/** + * struct binder_alloc - per-binder proc state for binder allocator + * @vma: vm_area_struct passed to mmap_handler + * (invarient after mmap) + * @vma_vm_mm: copy of vma->vm_mm (invarient after mmap) + * @buffer: base of per-proc address space mapped via mmap + * @user_buffer_offset: offset between user and kernel VAs for buffer + * @buffers: list of all buffers for this proc + * @free_buffers: rb tree of buffers available for allocation + * sorted by size + * @allocated_buffers: rb tree of allocated buffers sorted by address + * @free_async_space: VA space available for async buffers. This is + * initialized at mmap time to 1/2 the full VA space + * @pages: array of physical page addresses for each page of + * mmap'd space + * @buffer_size: size of address space (could be less than requested) + * + * Bookkeeping structure for per-proc address space management for binder + * buffers. It is normally initialized during binder_init() and binder_mmap() + * calls. The address space is used for both user-visible buffers and for + * struct binder_buffer objects used to track the user buffers + */ +struct binder_alloc { + struct vm_area_struct *vma; + struct mm_struct *vma_vm_mm; + void *buffer; + ptrdiff_t user_buffer_offset; + struct list_head buffers; + struct rb_root free_buffers; + struct rb_root allocated_buffers; + size_t free_async_space; + struct page **pages; + size_t buffer_size; +}; + struct binder_proc { struct hlist_node proc_node; struct rb_root threads; @@ -326,23 +361,11 @@ struct binder_proc { struct rb_root refs_by_desc; struct rb_root refs_by_node; int pid; - struct vm_area_struct *vma; - struct mm_struct *vma_vm_mm; struct task_struct *tsk; struct files_struct *files; struct hlist_node deferred_work_node; int deferred_work; - void *buffer; - ptrdiff_t user_buffer_offset; - struct list_head buffers; - struct rb_root free_buffers; - struct rb_root allocated_buffers; - size_t free_async_space; - - struct page **pages; - size_t buffer_size; - uint32_t buffer_free; struct list_head todo; wait_queue_head_t wait; struct binder_stats stats; @@ -353,6 +376,7 @@ struct binder_proc { int ready_threads; long default_priority; struct dentry *debugfs_entry; + struct binder_alloc alloc; struct binder_context *context; }; @@ -485,8 +509,10 @@ static void binder_set_nice(long nice) static size_t binder_buffer_size(struct binder_proc *proc, struct binder_buffer *buffer) { - if (list_is_last(&buffer->entry, &proc->buffers)) - return proc->buffer + proc->buffer_size - (void *)buffer->data; + if (list_is_last(&buffer->entry, &proc->alloc.buffers)) + return proc->alloc.buffer + + proc->alloc.buffer_size - + (void *)buffer->data; return (size_t)list_entry(buffer->entry.next, struct binder_buffer, entry) - (size_t)buffer->data; } @@ -494,7 +520,7 @@ static size_t binder_buffer_size(struct binder_proc *proc, static void binder_insert_free_buffer(struct binder_proc *proc, struct binder_buffer *new_buffer) { - struct rb_node **p = &proc->free_buffers.rb_node; + struct rb_node **p = &proc->alloc.free_buffers.rb_node; struct rb_node *parent = NULL; struct binder_buffer *buffer; size_t buffer_size; @@ -521,13 +547,13 @@ static void binder_insert_free_buffer(struct binder_proc *proc, p = &parent->rb_right; } rb_link_node(&new_buffer->rb_node, parent, p); - rb_insert_color(&new_buffer->rb_node, &proc->free_buffers); + rb_insert_color(&new_buffer->rb_node, &proc->alloc.free_buffers); } static void binder_insert_allocated_buffer(struct binder_proc *proc, struct binder_buffer *new_buffer) { - struct rb_node **p = &proc->allocated_buffers.rb_node; + struct rb_node **p = &proc->alloc.allocated_buffers.rb_node; struct rb_node *parent = NULL; struct binder_buffer *buffer; @@ -546,18 +572,19 @@ static void binder_insert_allocated_buffer(struct binder_proc *proc, BUG(); } rb_link_node(&new_buffer->rb_node, parent, p); - rb_insert_color(&new_buffer->rb_node, &proc->allocated_buffers); + rb_insert_color(&new_buffer->rb_node, &proc->alloc.allocated_buffers); } static struct binder_buffer *binder_buffer_lookup(struct binder_proc *proc, uintptr_t user_ptr) { - struct rb_node *n = proc->allocated_buffers.rb_node; + struct rb_node *n = proc->alloc.allocated_buffers.rb_node; struct binder_buffer *buffer; struct binder_buffer *kern_ptr; - kern_ptr = (struct binder_buffer *)(user_ptr - proc->user_buffer_offset - - offsetof(struct binder_buffer, data)); + kern_ptr = (struct binder_buffer *) + (user_ptr - proc->alloc.user_buffer_offset - + offsetof(struct binder_buffer, data)); while (n) { buffer = rb_entry(n, struct binder_buffer, rb_node); @@ -598,8 +625,8 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate, if (mm) { down_write(&mm->mmap_sem); - vma = proc->vma; - if (vma && mm != proc->vma_vm_mm) { + vma = proc->alloc.vma; + if (vma && mm != proc->alloc.vma_vm_mm) { pr_err("%d: vma mm and task mm mismatch\n", proc->pid); vma = NULL; @@ -618,7 +645,8 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate, for (page_addr = start; page_addr < end; page_addr += PAGE_SIZE) { int ret; - page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE]; + page = &proc->alloc.pages[ + (page_addr - proc->alloc.buffer) / PAGE_SIZE]; BUG_ON(*page); *page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO); @@ -637,7 +665,7 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate, goto err_map_kernel_failed; } user_page_addr = - (uintptr_t)page_addr + proc->user_buffer_offset; + (uintptr_t)page_addr + proc->alloc.user_buffer_offset; ret = vm_insert_page(vma, user_page_addr, page[0]); if (ret) { pr_err("%d: binder_alloc_buf failed to map page at %lx in userspace\n", @@ -655,10 +683,11 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate, free_range: for (page_addr = end - PAGE_SIZE; page_addr >= start; page_addr -= PAGE_SIZE) { - page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE]; + page = &proc->alloc.pages[ + (page_addr - proc->alloc.buffer) / PAGE_SIZE]; if (vma) zap_page_range(vma, (uintptr_t)page_addr + - proc->user_buffer_offset, PAGE_SIZE); + proc->alloc.user_buffer_offset, PAGE_SIZE); err_vm_insert_page_failed: unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE); err_map_kernel_failed: @@ -681,7 +710,7 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc, size_t extra_buffers_size, int is_async) { - struct rb_node *n = proc->free_buffers.rb_node; + struct rb_node *n = proc->alloc.free_buffers.rb_node; struct binder_buffer *buffer; size_t buffer_size; struct rb_node *best_fit = NULL; @@ -689,7 +718,7 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc, void *end_page_addr; size_t size, data_offsets_size; - if (proc->vma == NULL) { + if (proc->alloc.vma == NULL) { pr_err("%d: binder_alloc_buf, no vma\n", proc->pid); return NULL; @@ -710,7 +739,8 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc, return NULL; } if (is_async && - proc->free_async_space < size + sizeof(struct binder_buffer)) { + proc->alloc.free_async_space < + size + sizeof(struct binder_buffer)) { binder_debug(BINDER_DEBUG_BUFFER_ALLOC, "%d: binder_alloc_buf size %zd failed, no async space left\n", proc->pid, size); @@ -762,7 +792,7 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc, (void *)PAGE_ALIGN((uintptr_t)buffer->data), end_page_addr, NULL)) return NULL; - rb_erase(best_fit, &proc->free_buffers); + rb_erase(best_fit, &proc->alloc.free_buffers); buffer->free = 0; binder_insert_allocated_buffer(proc, buffer); if (buffer_size != size) { @@ -780,10 +810,11 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc, buffer->extra_buffers_size = extra_buffers_size; buffer->async_transaction = is_async; if (is_async) { - proc->free_async_space -= size + sizeof(struct binder_buffer); + proc->alloc.free_async_space -= + size + sizeof(struct binder_buffer); binder_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC, "%d: binder_alloc_buf size %zd async free %zd\n", - proc->pid, size, proc->free_async_space); + proc->pid, size, proc->alloc.free_async_space); } return buffer; @@ -806,7 +837,7 @@ static void binder_delete_free_buffer(struct binder_proc *proc, int free_page_end = 1; int free_page_start = 1; - BUG_ON(proc->buffers.next == &buffer->entry); + BUG_ON(proc->alloc.buffers.next == &buffer->entry); prev = list_entry(buffer->entry.prev, struct binder_buffer, entry); BUG_ON(!prev->free); if (buffer_end_page(prev) == buffer_start_page(buffer)) { @@ -818,7 +849,7 @@ static void binder_delete_free_buffer(struct binder_proc *proc, proc->pid, buffer, prev); } - if (!list_is_last(&buffer->entry, &proc->buffers)) { + if (!list_is_last(&buffer->entry, &proc->alloc.buffers)) { next = list_entry(buffer->entry.next, struct binder_buffer, entry); if (buffer_start_page(next) == buffer_end_page(buffer)) { @@ -862,39 +893,40 @@ static void binder_free_buf(struct binder_proc *proc, BUG_ON(buffer->free); BUG_ON(size > buffer_size); BUG_ON(buffer->transaction != NULL); - BUG_ON((void *)buffer < proc->buffer); - BUG_ON((void *)buffer > proc->buffer + proc->buffer_size); + BUG_ON((void *)buffer < proc->alloc.buffer); + BUG_ON((void *)buffer > proc->alloc.buffer + proc->alloc.buffer_size); if (buffer->async_transaction) { - proc->free_async_space += size + sizeof(struct binder_buffer); + proc->alloc.free_async_space += + size + sizeof(struct binder_buffer); binder_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC, "%d: binder_free_buf size %zd async free %zd\n", - proc->pid, size, proc->free_async_space); + proc->pid, size, proc->alloc.free_async_space); } binder_update_page_range(proc, 0, (void *)PAGE_ALIGN((uintptr_t)buffer->data), (void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK), NULL); - rb_erase(&buffer->rb_node, &proc->allocated_buffers); + rb_erase(&buffer->rb_node, &proc->alloc.allocated_buffers); buffer->free = 1; - if (!list_is_last(&buffer->entry, &proc->buffers)) { + if (!list_is_last(&buffer->entry, &proc->alloc.buffers)) { struct binder_buffer *next = list_entry(buffer->entry.next, struct binder_buffer, entry); if (next->free) { - rb_erase(&next->rb_node, &proc->free_buffers); + rb_erase(&next->rb_node, &proc->alloc.free_buffers); binder_delete_free_buffer(proc, next); } } - if (proc->buffers.next != &buffer->entry) { + if (proc->alloc.buffers.next != &buffer->entry) { struct binder_buffer *prev = list_entry(buffer->entry.prev, struct binder_buffer, entry); if (prev->free) { binder_delete_free_buffer(proc, buffer); - rb_erase(&prev->rb_node, &proc->free_buffers); + rb_erase(&prev->rb_node, &proc->alloc.free_buffers); buffer = prev; } } @@ -1532,7 +1564,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, * back to kernel address space to access it */ parent_buffer = parent->buffer - - proc->user_buffer_offset; + proc->alloc.user_buffer_offset; fd_buf_size = sizeof(u32) * fda->num_fds; if (fda->num_fds >= SIZE_MAX / sizeof(u32)) { @@ -1750,7 +1782,7 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda, * Since the parent was already fixed up, convert it * back to the kernel address space to access it */ - parent_buffer = parent->buffer - target_proc->user_buffer_offset; + parent_buffer = parent->buffer - target_proc->alloc.user_buffer_offset; fd_array = (u32 *)(parent_buffer + fda->parent_offset); if (!IS_ALIGNED((unsigned long)fd_array, sizeof(u32))) { binder_user_error("%d:%d parent offset not aligned correctly.\n", @@ -1818,7 +1850,7 @@ static int binder_fixup_parent(struct binder_transaction *t, return -EINVAL; } parent_buffer = (u8 *)(parent->buffer - - target_proc->user_buffer_offset); + target_proc->alloc.user_buffer_offset); *(binder_uintptr_t *)(parent_buffer + bp->parent_offset) = bp->buffer; return 0; @@ -2158,7 +2190,7 @@ static void binder_transaction(struct binder_proc *proc, } /* Fixup buffer pointer to target proc address space */ bp->buffer = (uintptr_t)sg_bufp + - target_proc->user_buffer_offset; + target_proc->alloc.user_buffer_offset; sg_bufp += ALIGN(bp->length, sizeof(u64)); ret = binder_fixup_parent(t, thread, bp, off_start, @@ -2920,7 +2952,7 @@ retry: tr.offsets_size = t->buffer->offsets_size; tr.data.ptr.buffer = (binder_uintptr_t)( (uintptr_t)t->buffer->data + - proc->user_buffer_offset); + proc->alloc.user_buffer_offset); tr.data.ptr.offsets = tr.data.ptr.buffer + ALIGN(t->buffer->data_size, sizeof(void *)); @@ -3338,8 +3370,8 @@ static void binder_vma_close(struct vm_area_struct *vma) proc->pid, vma->vm_start, vma->vm_end, (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, (unsigned long)pgprot_val(vma->vm_page_prot)); - proc->vma = NULL; - proc->vma_vm_mm = NULL; + proc->alloc.vma = NULL; + proc->alloc.vma_vm_mm = NULL; binder_defer_work(proc, BINDER_DEFERRED_PUT_FILES); } @@ -3382,7 +3414,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma) vma->vm_flags = (vma->vm_flags | VM_DONTCOPY) & ~VM_MAYWRITE; mutex_lock(&binder_mmap_lock); - if (proc->buffer) { + if (proc->alloc.buffer) { ret = -EBUSY; failure_string = "already mapped"; goto err_already_mapped; @@ -3394,56 +3426,66 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma) failure_string = "get_vm_area"; goto err_get_vm_area_failed; } - proc->buffer = area->addr; - proc->user_buffer_offset = vma->vm_start - (uintptr_t)proc->buffer; + proc->alloc.buffer = area->addr; + proc->alloc.user_buffer_offset = + vma->vm_start - (uintptr_t)proc->alloc.buffer; mutex_unlock(&binder_mmap_lock); #ifdef CONFIG_CPU_CACHE_VIPT if (cache_is_vipt_aliasing()) { - while (CACHE_COLOUR((vma->vm_start ^ (uint32_t)proc->buffer))) { - pr_info("binder_mmap: %d %lx-%lx maps %p bad alignment\n", proc->pid, vma->vm_start, vma->vm_end, proc->buffer); + while (CACHE_COLOUR( + (vma->vm_start ^ (uint32_t)proc->alloc.buffer))) { + pr_info("%s: %d %lx-%lx maps %pK bad alignment\n", + __func__, + proc->pid, vma->vm_start, + vma->vm_end, proc->alloc.buffer); vma->vm_start += PAGE_SIZE; } } #endif - proc->pages = kzalloc(sizeof(proc->pages[0]) * ((vma->vm_end - vma->vm_start) / PAGE_SIZE), GFP_KERNEL); - if (proc->pages == NULL) { + proc->alloc.pages = + kzalloc(sizeof(proc->alloc.pages[0]) * + ((vma->vm_end - vma->vm_start) / PAGE_SIZE), + GFP_KERNEL); + if (proc->alloc.pages == NULL) { ret = -ENOMEM; failure_string = "alloc page array"; goto err_alloc_pages_failed; } - proc->buffer_size = vma->vm_end - vma->vm_start; + proc->alloc.buffer_size = vma->vm_end - vma->vm_start; vma->vm_ops = &binder_vm_ops; vma->vm_private_data = proc; - if (binder_update_page_range(proc, 1, proc->buffer, proc->buffer + PAGE_SIZE, vma)) { + if (binder_update_page_range(proc, 1, proc->alloc.buffer, + proc->alloc.buffer + PAGE_SIZE, vma)) { ret = -ENOMEM; failure_string = "alloc small buf"; goto err_alloc_small_buf_failed; } - buffer = proc->buffer; - INIT_LIST_HEAD(&proc->buffers); - list_add(&buffer->entry, &proc->buffers); + buffer = proc->alloc.buffer; + INIT_LIST_HEAD(&proc->alloc.buffers); + list_add(&buffer->entry, &proc->alloc.buffers); buffer->free = 1; binder_insert_free_buffer(proc, buffer); - proc->free_async_space = proc->buffer_size / 2; + proc->alloc.free_async_space = proc->alloc.buffer_size / 2; barrier(); proc->files = get_files_struct(current); - proc->vma = vma; - proc->vma_vm_mm = vma->vm_mm; + proc->alloc.vma = vma; + proc->alloc.vma_vm_mm = vma->vm_mm; - /*pr_info("binder_mmap: %d %lx-%lx maps %p\n", - proc->pid, vma->vm_start, vma->vm_end, proc->buffer);*/ + /*pr_info("binder_mmap: %d %lx-%lx maps %pK\n", + * proc->pid, vma->vm_start, vma->vm_end, proc->alloc.buffer); + */ return 0; err_alloc_small_buf_failed: - kfree(proc->pages); - proc->pages = NULL; + kfree(proc->alloc.pages); + proc->alloc.pages = NULL; err_alloc_pages_failed: mutex_lock(&binder_mmap_lock); - vfree(proc->buffer); - proc->buffer = NULL; + vfree(proc->alloc.buffer); + proc->alloc.buffer = NULL; err_get_vm_area_failed: err_already_mapped: mutex_unlock(&binder_mmap_lock); @@ -3595,7 +3637,7 @@ static void binder_deferred_release(struct binder_proc *proc) int threads, nodes, incoming_refs, outgoing_refs, buffers, active_transactions, page_count; - BUG_ON(proc->vma); + BUG_ON(proc->alloc.vma); BUG_ON(proc->files); hlist_del(&proc->proc_node); @@ -3642,7 +3684,7 @@ static void binder_deferred_release(struct binder_proc *proc) binder_release_work(&proc->delivered_death); buffers = 0; - while ((n = rb_first(&proc->allocated_buffers))) { + while ((n = rb_first(&proc->alloc.allocated_buffers))) { struct binder_buffer *buffer; buffer = rb_entry(n, struct binder_buffer, rb_node); @@ -3663,25 +3705,25 @@ static void binder_deferred_release(struct binder_proc *proc) binder_stats_deleted(BINDER_STAT_PROC); page_count = 0; - if (proc->pages) { + if (proc->alloc.pages) { int i; - for (i = 0; i < proc->buffer_size / PAGE_SIZE; i++) { + for (i = 0; i < proc->alloc.buffer_size / PAGE_SIZE; i++) { void *page_addr; - if (!proc->pages[i]) + if (!proc->alloc.pages[i]) continue; - page_addr = proc->buffer + i * PAGE_SIZE; + page_addr = proc->alloc.buffer + i * PAGE_SIZE; binder_debug(BINDER_DEBUG_BUFFER_ALLOC, "%s: %d: page %d at %p not freed\n", __func__, proc->pid, i, page_addr); unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE); - __free_page(proc->pages[i]); + __free_page(proc->alloc.pages[i]); page_count++; } - kfree(proc->pages); - vfree(proc->buffer); + kfree(proc->alloc.pages); + vfree(proc->alloc.buffer); } put_task_struct(proc->tsk); @@ -3911,7 +3953,8 @@ static void print_binder_proc(struct seq_file *m, print_binder_ref(m, rb_entry(n, struct binder_ref, rb_node_desc)); } - for (n = rb_first(&proc->allocated_buffers); n != NULL; n = rb_next(n)) + for (n = rb_first(&proc->alloc.allocated_buffers); + n != NULL; n = rb_next(n)) print_binder_buffer(m, " buffer", rb_entry(n, struct binder_buffer, rb_node)); list_for_each_entry(w, &proc->todo, entry) @@ -4028,7 +4071,7 @@ static void print_binder_proc_stats(struct seq_file *m, " ready threads %d\n" " free async space %zd\n", proc->requested_threads, proc->requested_threads_started, proc->max_threads, - proc->ready_threads, proc->free_async_space); + proc->ready_threads, proc->alloc.free_async_space); count = 0; for (n = rb_first(&proc->nodes); n != NULL; n = rb_next(n)) count++; @@ -4046,7 +4089,8 @@ static void print_binder_proc_stats(struct seq_file *m, seq_printf(m, " refs: %d s %d w %d\n", count, strong, weak); count = 0; - for (n = rb_first(&proc->allocated_buffers); n != NULL; n = rb_next(n)) + for (n = rb_first(&proc->alloc.allocated_buffers); + n != NULL; n = rb_next(n)) count++; seq_printf(m, " buffers: %d\n", count); diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h index 7f20f3dc8369..c835f09656c1 100644 --- a/drivers/android/binder_trace.h +++ b/drivers/android/binder_trace.h @@ -280,7 +280,7 @@ TRACE_EVENT(binder_update_page_range, TP_fast_assign( __entry->proc = proc->pid; __entry->allocate = allocate; - __entry->offset = start - proc->buffer; + __entry->offset = start - proc->alloc.buffer; __entry->size = end - start; ), TP_printk("proc=%d allocate=%d offset=%zu size=%zu", -- cgit v1.2.3 From 7c03f0d6163a500b655467bd8306d435bef18a83 Mon Sep 17 00:00:00 2001 From: Todd Kjos Date: Thu, 29 Jun 2017 12:01:39 -0700 Subject: binder: remove unneeded cleanup code The buffer's transaction has already been freed before binder_deferred_release. No need to do it again. Signed-off-by: Todd Kjos Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 1097d056ea6b..2cbd7558fc3f 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -3631,7 +3631,6 @@ static int binder_node_release(struct binder_node *node, int refs) static void binder_deferred_release(struct binder_proc *proc) { - struct binder_transaction *t; struct binder_context *context = proc->context; struct rb_node *n; int threads, nodes, incoming_refs, outgoing_refs, buffers, @@ -3689,14 +3688,8 @@ static void binder_deferred_release(struct binder_proc *proc) buffer = rb_entry(n, struct binder_buffer, rb_node); - t = buffer->transaction; - if (t) { - t->buffer = NULL; - buffer->transaction = NULL; - pr_err("release proc %d, transaction %d, not freed\n", - proc->pid, t->debug_id); - /*BUG();*/ - } + /* Transaction should already have been freed */ + BUG_ON(buffer->transaction); binder_free_buf(proc, buffer); buffers++; -- cgit v1.2.3 From 19c987241ca1216a51118b2bd0185b8bc5081783 Mon Sep 17 00:00:00 2001 From: Todd Kjos Date: Thu, 29 Jun 2017 12:01:40 -0700 Subject: binder: separate out binder_alloc functions Continuation of splitting the binder allocator from the binder driver. Separate binder_alloc functions from normal binder functions. Protect the allocator with a separate mutex. Signed-off-by: Todd Kjos Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 649 +++++++++++++++++++++++++---------------- drivers/android/binder_trace.h | 9 +- 2 files changed, 410 insertions(+), 248 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 2cbd7558fc3f..6c1d0b5b352b 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -49,7 +49,7 @@ static DEFINE_MUTEX(binder_main_lock); static DEFINE_MUTEX(binder_deferred_lock); -static DEFINE_MUTEX(binder_mmap_lock); +static DEFINE_MUTEX(binder_alloc_mmap_lock); static HLIST_HEAD(binder_devices); static HLIST_HEAD(binder_procs); @@ -104,9 +104,7 @@ enum { BINDER_DEBUG_TRANSACTION_COMPLETE = 1U << 10, BINDER_DEBUG_FREE_BUFFER = 1U << 11, BINDER_DEBUG_INTERNAL_REFS = 1U << 12, - BINDER_DEBUG_BUFFER_ALLOC = 1U << 13, - BINDER_DEBUG_PRIORITY_CAP = 1U << 14, - BINDER_DEBUG_BUFFER_ALLOC_ASYNC = 1U << 15, + BINDER_DEBUG_PRIORITY_CAP = 1U << 13, }; static uint32_t binder_debug_mask = BINDER_DEBUG_USER_ERROR | BINDER_DEBUG_FAILED_TRANSACTION | BINDER_DEBUG_DEAD_TRANSACTION; @@ -159,6 +157,27 @@ module_param_call(stop_on_user_error, binder_set_stop_on_user_error, #define to_binder_fd_array_object(hdr) \ container_of(hdr, struct binder_fd_array_object, hdr) +/* + * debug declarations for binder_alloc. To be + * moved to binder_alloc.c + */ +enum { + BINDER_ALLOC_DEBUG_OPEN_CLOSE = 1U << 1, + BINDER_ALLOC_DEBUG_BUFFER_ALLOC = 1U << 2, + BINDER_ALLOC_DEBUG_BUFFER_ALLOC_ASYNC = 1U << 3, +}; +static uint32_t binder_alloc_debug_mask; + +module_param_named(alloc_debug_mask, binder_alloc_debug_mask, + uint, 0644); + +#define binder_alloc_debug(mask, x...) \ + do { \ + if (binder_alloc_debug_mask & mask) \ + pr_info(x); \ + } while (0) +/* end of binder_alloc debug declarations */ + enum binder_stat_types { BINDER_STAT_PROC, BINDER_STAT_THREAD, @@ -342,6 +361,8 @@ enum binder_deferred_state { * struct binder_buffer objects used to track the user buffers */ struct binder_alloc { + struct mutex mutex; + struct task_struct *tsk; struct vm_area_struct *vma; struct mm_struct *vma_vm_mm; void *buffer; @@ -352,6 +373,7 @@ struct binder_alloc { size_t free_async_space; struct page **pages; size_t buffer_size; + int pid; }; struct binder_proc { @@ -423,6 +445,56 @@ struct binder_transaction { kuid_t sender_euid; }; +/* + * Forward declarations of binder_alloc functions. + * These will be moved to binder_alloc.h when + * binder_alloc is moved to its own files. + */ +extern struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc, + size_t data_size, + size_t offsets_size, + size_t extra_buffers_size, + int is_async); +extern void binder_alloc_init(struct binder_alloc *alloc); +extern void binder_alloc_vma_close(struct binder_alloc *alloc); +extern struct binder_buffer * +binder_alloc_buffer_lookup(struct binder_alloc *alloc, + uintptr_t user_ptr); +extern void binder_alloc_free_buf(struct binder_alloc *alloc, + struct binder_buffer *buffer); +extern int binder_alloc_mmap_handler(struct binder_alloc *alloc, + struct vm_area_struct *vma); +extern void binder_alloc_deferred_release(struct binder_alloc *alloc); +extern int binder_alloc_get_allocated_count(struct binder_alloc *alloc); +extern void binder_alloc_print_allocated(struct seq_file *m, + struct binder_alloc *alloc); + +static inline size_t +binder_alloc_get_free_async_space(struct binder_alloc *alloc) +{ + size_t free_async_space; + + mutex_lock(&alloc->mutex); + free_async_space = alloc->free_async_space; + mutex_unlock(&alloc->mutex); + return free_async_space; +} + +static inline ptrdiff_t +binder_alloc_get_user_buffer_offset(struct binder_alloc *alloc) +{ + /* + * user_buffer_offset is constant if vma is set and + * undefined if vma is not set. It is possible to + * get here with !alloc->vma if the target process + * is dying while a transaction is being initiated. + * Returning the old value is ok in this case and + * the transaction will fail. + */ + return alloc->user_buffer_offset; +} +/* end of binder_alloc declarations */ + static void binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer); @@ -506,21 +578,20 @@ static void binder_set_nice(long nice) binder_user_error("%d RLIMIT_NICE not set\n", current->pid); } -static size_t binder_buffer_size(struct binder_proc *proc, - struct binder_buffer *buffer) +static size_t binder_alloc_buffer_size(struct binder_alloc *alloc, + struct binder_buffer *buffer) { - if (list_is_last(&buffer->entry, &proc->alloc.buffers)) - return proc->alloc.buffer + - proc->alloc.buffer_size - - (void *)buffer->data; + if (list_is_last(&buffer->entry, &alloc->buffers)) + return alloc->buffer + + alloc->buffer_size - (void *)buffer->data; return (size_t)list_entry(buffer->entry.next, struct binder_buffer, entry) - (size_t)buffer->data; } -static void binder_insert_free_buffer(struct binder_proc *proc, +static void binder_insert_free_buffer(struct binder_alloc *alloc, struct binder_buffer *new_buffer) { - struct rb_node **p = &proc->alloc.free_buffers.rb_node; + struct rb_node **p = &alloc->free_buffers.rb_node; struct rb_node *parent = NULL; struct binder_buffer *buffer; size_t buffer_size; @@ -528,18 +599,18 @@ static void binder_insert_free_buffer(struct binder_proc *proc, BUG_ON(!new_buffer->free); - new_buffer_size = binder_buffer_size(proc, new_buffer); + new_buffer_size = binder_alloc_buffer_size(alloc, new_buffer); - binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: add free buffer, size %zd, at %p\n", - proc->pid, new_buffer_size, new_buffer); + binder_alloc_debug(BINDER_ALLOC_DEBUG_BUFFER_ALLOC, + "%d: add free buffer, size %zd, at %pK\n", + alloc->pid, new_buffer_size, new_buffer); while (*p) { parent = *p; buffer = rb_entry(parent, struct binder_buffer, rb_node); BUG_ON(!buffer->free); - buffer_size = binder_buffer_size(proc, buffer); + buffer_size = binder_alloc_buffer_size(alloc, buffer); if (new_buffer_size < buffer_size) p = &parent->rb_left; @@ -547,13 +618,13 @@ static void binder_insert_free_buffer(struct binder_proc *proc, p = &parent->rb_right; } rb_link_node(&new_buffer->rb_node, parent, p); - rb_insert_color(&new_buffer->rb_node, &proc->alloc.free_buffers); + rb_insert_color(&new_buffer->rb_node, &alloc->free_buffers); } -static void binder_insert_allocated_buffer(struct binder_proc *proc, +static void binder_insert_allocated_buffer(struct binder_alloc *alloc, struct binder_buffer *new_buffer) { - struct rb_node **p = &proc->alloc.allocated_buffers.rb_node; + struct rb_node **p = &alloc->allocated_buffers.rb_node; struct rb_node *parent = NULL; struct binder_buffer *buffer; @@ -572,19 +643,19 @@ static void binder_insert_allocated_buffer(struct binder_proc *proc, BUG(); } rb_link_node(&new_buffer->rb_node, parent, p); - rb_insert_color(&new_buffer->rb_node, &proc->alloc.allocated_buffers); + rb_insert_color(&new_buffer->rb_node, &alloc->allocated_buffers); } -static struct binder_buffer *binder_buffer_lookup(struct binder_proc *proc, - uintptr_t user_ptr) +static struct binder_buffer *binder_alloc_buffer_lookup_locked( + struct binder_alloc *alloc, + uintptr_t user_ptr) { - struct rb_node *n = proc->alloc.allocated_buffers.rb_node; + struct rb_node *n = alloc->allocated_buffers.rb_node; struct binder_buffer *buffer; struct binder_buffer *kern_ptr; - kern_ptr = (struct binder_buffer *) - (user_ptr - proc->alloc.user_buffer_offset - - offsetof(struct binder_buffer, data)); + kern_ptr = (struct binder_buffer *)(user_ptr - alloc->user_buffer_offset + - offsetof(struct binder_buffer, data)); while (n) { buffer = rb_entry(n, struct binder_buffer, rb_node); @@ -600,7 +671,18 @@ static struct binder_buffer *binder_buffer_lookup(struct binder_proc *proc, return NULL; } -static int binder_update_page_range(struct binder_proc *proc, int allocate, +struct binder_buffer *binder_alloc_buffer_lookup(struct binder_alloc *alloc, + uintptr_t user_ptr) +{ + struct binder_buffer *buffer; + + mutex_lock(&alloc->mutex); + buffer = binder_alloc_buffer_lookup_locked(alloc, user_ptr); + mutex_unlock(&alloc->mutex); + return buffer; +} + +static int binder_update_page_range(struct binder_alloc *alloc, int allocate, void *start, void *end, struct vm_area_struct *vma) { @@ -609,26 +691,26 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate, struct page **page; struct mm_struct *mm; - binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: %s pages %p-%p\n", proc->pid, + binder_alloc_debug(BINDER_ALLOC_DEBUG_BUFFER_ALLOC, + "%d: %s pages %pK-%pK\n", alloc->pid, allocate ? "allocate" : "free", start, end); if (end <= start) return 0; - trace_binder_update_page_range(proc, allocate, start, end); + trace_binder_update_page_range(alloc, allocate, start, end); if (vma) mm = NULL; else - mm = get_task_mm(proc->tsk); + mm = get_task_mm(alloc->tsk); if (mm) { down_write(&mm->mmap_sem); - vma = proc->alloc.vma; - if (vma && mm != proc->alloc.vma_vm_mm) { + vma = alloc->vma; + if (vma && mm != alloc->vma_vm_mm) { pr_err("%d: vma mm and task mm mismatch\n", - proc->pid); + alloc->pid); vma = NULL; } } @@ -638,21 +720,20 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate, if (vma == NULL) { pr_err("%d: binder_alloc_buf failed to map pages in userspace, no vma\n", - proc->pid); + alloc->pid); goto err_no_vma; } for (page_addr = start; page_addr < end; page_addr += PAGE_SIZE) { int ret; - page = &proc->alloc.pages[ - (page_addr - proc->alloc.buffer) / PAGE_SIZE]; + page = &alloc->pages[(page_addr - alloc->buffer) / PAGE_SIZE]; BUG_ON(*page); *page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO); if (*page == NULL) { - pr_err("%d: binder_alloc_buf failed for page at %p\n", - proc->pid, page_addr); + pr_err("%d: binder_alloc_buf failed for page at %pK\n", + alloc->pid, page_addr); goto err_alloc_page_failed; } ret = map_kernel_range_noflush((unsigned long)page_addr, @@ -660,16 +741,16 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate, flush_cache_vmap((unsigned long)page_addr, (unsigned long)page_addr + PAGE_SIZE); if (ret != 1) { - pr_err("%d: binder_alloc_buf failed to map page at %p in kernel\n", - proc->pid, page_addr); + pr_err("%d: binder_alloc_buf failed to map page at %pK in kernel\n", + alloc->pid, page_addr); goto err_map_kernel_failed; } user_page_addr = - (uintptr_t)page_addr + proc->alloc.user_buffer_offset; + (uintptr_t)page_addr + alloc->user_buffer_offset; ret = vm_insert_page(vma, user_page_addr, page[0]); if (ret) { pr_err("%d: binder_alloc_buf failed to map page at %lx in userspace\n", - proc->pid, user_page_addr); + alloc->pid, user_page_addr); goto err_vm_insert_page_failed; } /* vm_insert_page does not seem to increment the refcount */ @@ -683,11 +764,10 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate, free_range: for (page_addr = end - PAGE_SIZE; page_addr >= start; page_addr -= PAGE_SIZE) { - page = &proc->alloc.pages[ - (page_addr - proc->alloc.buffer) / PAGE_SIZE]; + page = &alloc->pages[(page_addr - alloc->buffer) / PAGE_SIZE]; if (vma) zap_page_range(vma, (uintptr_t)page_addr + - proc->alloc.user_buffer_offset, PAGE_SIZE); + alloc->user_buffer_offset, PAGE_SIZE); err_vm_insert_page_failed: unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE); err_map_kernel_failed: @@ -704,13 +784,11 @@ err_no_vma: return -ENOMEM; } -static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc, - size_t data_size, - size_t offsets_size, - size_t extra_buffers_size, - int is_async) +static struct binder_buffer *binder_alloc_new_buf_locked( + struct binder_alloc *alloc, size_t data_size, + size_t offsets_size, size_t extra_buffers_size, int is_async) { - struct rb_node *n = proc->alloc.free_buffers.rb_node; + struct rb_node *n = alloc->free_buffers.rb_node; struct binder_buffer *buffer; size_t buffer_size; struct rb_node *best_fit = NULL; @@ -718,9 +796,9 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc, void *end_page_addr; size_t size, data_offsets_size; - if (proc->alloc.vma == NULL) { + if (alloc->vma == NULL) { pr_err("%d: binder_alloc_buf, no vma\n", - proc->pid); + alloc->pid); return NULL; } @@ -728,29 +806,30 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc, ALIGN(offsets_size, sizeof(void *)); if (data_offsets_size < data_size || data_offsets_size < offsets_size) { - binder_user_error("%d: got transaction with invalid size %zd-%zd\n", - proc->pid, data_size, offsets_size); + binder_alloc_debug(BINDER_ALLOC_DEBUG_BUFFER_ALLOC, + "%d: got transaction with invalid size %zd-%zd\n", + alloc->pid, data_size, offsets_size); return NULL; } size = data_offsets_size + ALIGN(extra_buffers_size, sizeof(void *)); if (size < data_offsets_size || size < extra_buffers_size) { - binder_user_error("%d: got transaction with invalid extra_buffers_size %zd\n", - proc->pid, extra_buffers_size); + binder_alloc_debug(BINDER_ALLOC_DEBUG_BUFFER_ALLOC, + "%d: got transaction with invalid extra_buffers_size %zd\n", + alloc->pid, extra_buffers_size); return NULL; } if (is_async && - proc->alloc.free_async_space < - size + sizeof(struct binder_buffer)) { - binder_debug(BINDER_DEBUG_BUFFER_ALLOC, + alloc->free_async_space < size + sizeof(struct binder_buffer)) { + binder_alloc_debug(BINDER_ALLOC_DEBUG_BUFFER_ALLOC, "%d: binder_alloc_buf size %zd failed, no async space left\n", - proc->pid, size); + alloc->pid, size); return NULL; } while (n) { buffer = rb_entry(n, struct binder_buffer, rb_node); BUG_ON(!buffer->free); - buffer_size = binder_buffer_size(proc, buffer); + buffer_size = binder_alloc_buffer_size(alloc, buffer); if (size < buffer_size) { best_fit = n; @@ -764,17 +843,17 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc, } if (best_fit == NULL) { pr_err("%d: binder_alloc_buf size %zd failed, no address space\n", - proc->pid, size); + alloc->pid, size); return NULL; } if (n == NULL) { buffer = rb_entry(best_fit, struct binder_buffer, rb_node); - buffer_size = binder_buffer_size(proc, buffer); + buffer_size = binder_alloc_buffer_size(alloc, buffer); } - binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: binder_alloc_buf size %zd got buffer %p size %zd\n", - proc->pid, size, buffer, buffer_size); + binder_alloc_debug(BINDER_ALLOC_DEBUG_BUFFER_ALLOC, + "%d: %s size %zd got buffer %pK size %zd\n", + alloc->pid, __func__, size, buffer, buffer_size); has_page_addr = (void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK); @@ -788,38 +867,52 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc, (void *)PAGE_ALIGN((uintptr_t)buffer->data + buffer_size); if (end_page_addr > has_page_addr) end_page_addr = has_page_addr; - if (binder_update_page_range(proc, 1, + if (binder_update_page_range(alloc, 1, (void *)PAGE_ALIGN((uintptr_t)buffer->data), end_page_addr, NULL)) return NULL; - rb_erase(best_fit, &proc->alloc.free_buffers); + rb_erase(best_fit, &alloc->free_buffers); buffer->free = 0; - binder_insert_allocated_buffer(proc, buffer); + binder_insert_allocated_buffer(alloc, buffer); if (buffer_size != size) { struct binder_buffer *new_buffer = (void *)buffer->data + size; list_add(&new_buffer->entry, &buffer->entry); new_buffer->free = 1; - binder_insert_free_buffer(proc, new_buffer); + binder_insert_free_buffer(alloc, new_buffer); } - binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: binder_alloc_buf size %zd got %p\n", - proc->pid, size, buffer); + binder_alloc_debug(BINDER_ALLOC_DEBUG_BUFFER_ALLOC, + "%d: %s size %zd got %pK\n", + alloc->pid, __func__, size, buffer); buffer->data_size = data_size; buffer->offsets_size = offsets_size; - buffer->extra_buffers_size = extra_buffers_size; buffer->async_transaction = is_async; + buffer->extra_buffers_size = extra_buffers_size; if (is_async) { - proc->alloc.free_async_space -= - size + sizeof(struct binder_buffer); - binder_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC, + alloc->free_async_space -= size + sizeof(struct binder_buffer); + binder_alloc_debug(BINDER_ALLOC_DEBUG_BUFFER_ALLOC_ASYNC, "%d: binder_alloc_buf size %zd async free %zd\n", - proc->pid, size, proc->alloc.free_async_space); + alloc->pid, size, alloc->free_async_space); } return buffer; } +struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc, + size_t data_size, + size_t offsets_size, + size_t extra_buffers_size, + int is_async) +{ + struct binder_buffer *buffer; + + mutex_lock(&alloc->mutex); + buffer = binder_alloc_new_buf_locked(alloc, data_size, offsets_size, + extra_buffers_size, is_async); + mutex_unlock(&alloc->mutex); + return buffer; +} + static void *buffer_start_page(struct binder_buffer *buffer) { return (void *)((uintptr_t)buffer & PAGE_MASK); @@ -830,26 +923,26 @@ static void *buffer_end_page(struct binder_buffer *buffer) return (void *)(((uintptr_t)(buffer + 1) - 1) & PAGE_MASK); } -static void binder_delete_free_buffer(struct binder_proc *proc, +static void binder_delete_free_buffer(struct binder_alloc *alloc, struct binder_buffer *buffer) { struct binder_buffer *prev, *next = NULL; int free_page_end = 1; int free_page_start = 1; - BUG_ON(proc->alloc.buffers.next == &buffer->entry); + BUG_ON(alloc->buffers.next == &buffer->entry); prev = list_entry(buffer->entry.prev, struct binder_buffer, entry); BUG_ON(!prev->free); if (buffer_end_page(prev) == buffer_start_page(buffer)) { free_page_start = 0; if (buffer_end_page(prev) == buffer_end_page(buffer)) free_page_end = 0; - binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: merge free, buffer %p share page with %p\n", - proc->pid, buffer, prev); + binder_alloc_debug(BINDER_ALLOC_DEBUG_BUFFER_ALLOC, + "%d: merge free, buffer %pK share page with %pK\n", + alloc->pid, buffer, prev); } - if (!list_is_last(&buffer->entry, &proc->alloc.buffers)) { + if (!list_is_last(&buffer->entry, &alloc->buffers)) { next = list_entry(buffer->entry.next, struct binder_buffer, entry); if (buffer_start_page(next) == buffer_end_page(buffer)) { @@ -857,80 +950,88 @@ static void binder_delete_free_buffer(struct binder_proc *proc, if (buffer_start_page(next) == buffer_start_page(buffer)) free_page_start = 0; - binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: merge free, buffer %p share page with %p\n", - proc->pid, buffer, prev); + binder_alloc_debug(BINDER_ALLOC_DEBUG_BUFFER_ALLOC, + "%d: merge free, buffer %pK share page with %pK\n", + alloc->pid, buffer, prev); } } list_del(&buffer->entry); if (free_page_start || free_page_end) { - binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: merge free, buffer %p do not share page%s%s with %p or %p\n", - proc->pid, buffer, free_page_start ? "" : " end", + binder_alloc_debug(BINDER_ALLOC_DEBUG_BUFFER_ALLOC, + "%d: merge free, buffer %pK do not share page%s%s with %pK or %pK\n", + alloc->pid, buffer, free_page_start ? "" : " end", free_page_end ? "" : " start", prev, next); - binder_update_page_range(proc, 0, free_page_start ? + binder_update_page_range(alloc, 0, free_page_start ? buffer_start_page(buffer) : buffer_end_page(buffer), (free_page_end ? buffer_end_page(buffer) : buffer_start_page(buffer)) + PAGE_SIZE, NULL); } } -static void binder_free_buf(struct binder_proc *proc, - struct binder_buffer *buffer) +static void binder_free_buf_locked(struct binder_alloc *alloc, + struct binder_buffer *buffer) { size_t size, buffer_size; - buffer_size = binder_buffer_size(proc, buffer); + buffer_size = binder_alloc_buffer_size(alloc, buffer); size = ALIGN(buffer->data_size, sizeof(void *)) + ALIGN(buffer->offsets_size, sizeof(void *)) + ALIGN(buffer->extra_buffers_size, sizeof(void *)); - binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: binder_free_buf %p size %zd buffer_size %zd\n", - proc->pid, buffer, size, buffer_size); + binder_alloc_debug(BINDER_ALLOC_DEBUG_BUFFER_ALLOC, + "%d: binder_free_buf %pK size %zd buffer_size %zd\n", + alloc->pid, buffer, size, buffer_size); BUG_ON(buffer->free); BUG_ON(size > buffer_size); BUG_ON(buffer->transaction != NULL); - BUG_ON((void *)buffer < proc->alloc.buffer); - BUG_ON((void *)buffer > proc->alloc.buffer + proc->alloc.buffer_size); + BUG_ON((void *)buffer < alloc->buffer); + BUG_ON((void *)buffer > alloc->buffer + alloc->buffer_size); if (buffer->async_transaction) { - proc->alloc.free_async_space += - size + sizeof(struct binder_buffer); + alloc->free_async_space += size + sizeof(struct binder_buffer); - binder_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC, + binder_alloc_debug(BINDER_ALLOC_DEBUG_BUFFER_ALLOC_ASYNC, "%d: binder_free_buf size %zd async free %zd\n", - proc->pid, size, proc->alloc.free_async_space); + alloc->pid, size, alloc->free_async_space); } - binder_update_page_range(proc, 0, + binder_update_page_range(alloc, 0, (void *)PAGE_ALIGN((uintptr_t)buffer->data), (void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK), NULL); - rb_erase(&buffer->rb_node, &proc->alloc.allocated_buffers); + + rb_erase(&buffer->rb_node, &alloc->allocated_buffers); buffer->free = 1; - if (!list_is_last(&buffer->entry, &proc->alloc.buffers)) { + if (!list_is_last(&buffer->entry, &alloc->buffers)) { struct binder_buffer *next = list_entry(buffer->entry.next, struct binder_buffer, entry); if (next->free) { - rb_erase(&next->rb_node, &proc->alloc.free_buffers); - binder_delete_free_buffer(proc, next); + rb_erase(&next->rb_node, &alloc->free_buffers); + binder_delete_free_buffer(alloc, next); } } - if (proc->alloc.buffers.next != &buffer->entry) { + if (alloc->buffers.next != &buffer->entry) { struct binder_buffer *prev = list_entry(buffer->entry.prev, struct binder_buffer, entry); if (prev->free) { - binder_delete_free_buffer(proc, buffer); - rb_erase(&prev->rb_node, &proc->alloc.free_buffers); + binder_delete_free_buffer(alloc, buffer); + rb_erase(&prev->rb_node, &alloc->free_buffers); buffer = prev; } } - binder_insert_free_buffer(proc, buffer); + binder_insert_free_buffer(alloc, buffer); +} + +void binder_alloc_free_buf(struct binder_alloc *alloc, + struct binder_buffer *buffer) +{ + mutex_lock(&alloc->mutex); + binder_free_buf_locked(alloc, buffer); + mutex_unlock(&alloc->mutex); } static struct binder_node *binder_get_node(struct binder_proc *proc, @@ -1564,7 +1665,8 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, * back to kernel address space to access it */ parent_buffer = parent->buffer - - proc->alloc.user_buffer_offset; + binder_alloc_get_user_buffer_offset( + &proc->alloc); fd_buf_size = sizeof(u32) * fda->num_fds; if (fda->num_fds >= SIZE_MAX / sizeof(u32)) { @@ -1782,7 +1884,8 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda, * Since the parent was already fixed up, convert it * back to the kernel address space to access it */ - parent_buffer = parent->buffer - target_proc->alloc.user_buffer_offset; + parent_buffer = parent->buffer - + binder_alloc_get_user_buffer_offset(&target_proc->alloc); fd_array = (u32 *)(parent_buffer + fda->parent_offset); if (!IS_ALIGNED((unsigned long)fd_array, sizeof(u32))) { binder_user_error("%d:%d parent offset not aligned correctly.\n", @@ -1850,7 +1953,8 @@ static int binder_fixup_parent(struct binder_transaction *t, return -EINVAL; } parent_buffer = (u8 *)(parent->buffer - - target_proc->alloc.user_buffer_offset); + binder_alloc_get_user_buffer_offset( + &target_proc->alloc)); *(binder_uintptr_t *)(parent_buffer + bp->parent_offset) = bp->buffer; return 0; @@ -2036,7 +2140,7 @@ static void binder_transaction(struct binder_proc *proc, trace_binder_transaction(reply, t, target_node); - t->buffer = binder_alloc_buf(target_proc, tr->data_size, + t->buffer = binder_alloc_new_buf(&target_proc->alloc, tr->data_size, tr->offsets_size, extra_buffers_size, !reply && (t->flags & TF_ONE_WAY)); if (t->buffer == NULL) { @@ -2190,7 +2294,8 @@ static void binder_transaction(struct binder_proc *proc, } /* Fixup buffer pointer to target proc address space */ bp->buffer = (uintptr_t)sg_bufp + - target_proc->alloc.user_buffer_offset; + binder_alloc_get_user_buffer_offset( + &target_proc->alloc); sg_bufp += ALIGN(bp->length, sizeof(u64)); ret = binder_fixup_parent(t, thread, bp, off_start, @@ -2248,7 +2353,7 @@ err_copy_data_failed: trace_binder_transaction_failed_buffer_release(t->buffer); binder_transaction_buffer_release(target_proc, t->buffer, offp); t->buffer->transaction = NULL; - binder_free_buf(target_proc, t->buffer); + binder_alloc_free_buf(&target_proc->alloc, t->buffer); err_binder_alloc_buf_failed: kfree(tcomplete); binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE); @@ -2428,7 +2533,8 @@ static int binder_thread_write(struct binder_proc *proc, return -EFAULT; ptr += sizeof(binder_uintptr_t); - buffer = binder_buffer_lookup(proc, data_ptr); + buffer = binder_alloc_buffer_lookup(&proc->alloc, + data_ptr); if (buffer == NULL) { binder_user_error("%d:%d BC_FREE_BUFFER u%016llx no match\n", proc->pid, thread->pid, (u64)data_ptr); @@ -2458,7 +2564,7 @@ static int binder_thread_write(struct binder_proc *proc, } trace_binder_transaction_buffer_release(buffer); binder_transaction_buffer_release(proc, buffer, NULL); - binder_free_buf(proc, buffer); + binder_alloc_free_buf(&proc->alloc, buffer); break; } @@ -2950,9 +3056,9 @@ retry: tr.data_size = t->buffer->data_size; tr.offsets_size = t->buffer->offsets_size; - tr.data.ptr.buffer = (binder_uintptr_t)( - (uintptr_t)t->buffer->data + - proc->alloc.user_buffer_offset); + tr.data.ptr.buffer = (binder_uintptr_t) + ((uintptr_t)t->buffer->data + + binder_alloc_get_user_buffer_offset(&proc->alloc)); tr.data.ptr.offsets = tr.data.ptr.buffer + ALIGN(t->buffer->data_size, sizeof(void *)); @@ -3361,6 +3467,12 @@ static void binder_vma_open(struct vm_area_struct *vma) (unsigned long)pgprot_val(vma->vm_page_prot)); } +void binder_alloc_vma_close(struct binder_alloc *alloc) +{ + WRITE_ONCE(alloc->vma, NULL); + WRITE_ONCE(alloc->vma_vm_mm, NULL); +} + static void binder_vma_close(struct vm_area_struct *vma) { struct binder_proc *proc = vma->vm_private_data; @@ -3370,8 +3482,7 @@ static void binder_vma_close(struct vm_area_struct *vma) proc->pid, vma->vm_start, vma->vm_end, (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, (unsigned long)pgprot_val(vma->vm_page_prot)); - proc->alloc.vma = NULL; - proc->alloc.vma_vm_mm = NULL; + binder_alloc_vma_close(&proc->alloc); binder_defer_work(proc, BINDER_DEFERRED_PUT_FILES); } @@ -3386,35 +3497,16 @@ static const struct vm_operations_struct binder_vm_ops = { .fault = binder_vm_fault, }; -static int binder_mmap(struct file *filp, struct vm_area_struct *vma) +int binder_alloc_mmap_handler(struct binder_alloc *alloc, + struct vm_area_struct *vma) { int ret; struct vm_struct *area; - struct binder_proc *proc = filp->private_data; const char *failure_string; struct binder_buffer *buffer; - if (proc->tsk != current) - return -EINVAL; - - if ((vma->vm_end - vma->vm_start) > SZ_4M) - vma->vm_end = vma->vm_start + SZ_4M; - - binder_debug(BINDER_DEBUG_OPEN_CLOSE, - "binder_mmap: %d %lx-%lx (%ld K) vma %lx pagep %lx\n", - proc->pid, vma->vm_start, vma->vm_end, - (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, - (unsigned long)pgprot_val(vma->vm_page_prot)); - - if (vma->vm_flags & FORBIDDEN_MMAP_FLAGS) { - ret = -EPERM; - failure_string = "bad vm_flags"; - goto err_bad_arg; - } - vma->vm_flags = (vma->vm_flags | VM_DONTCOPY) & ~VM_MAYWRITE; - - mutex_lock(&binder_mmap_lock); - if (proc->alloc.buffer) { + mutex_lock(&binder_alloc_mmap_lock); + if (alloc->buffer) { ret = -EBUSY; failure_string = "already mapped"; goto err_already_mapped; @@ -3426,75 +3518,111 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma) failure_string = "get_vm_area"; goto err_get_vm_area_failed; } - proc->alloc.buffer = area->addr; - proc->alloc.user_buffer_offset = - vma->vm_start - (uintptr_t)proc->alloc.buffer; - mutex_unlock(&binder_mmap_lock); + alloc->buffer = area->addr; + alloc->user_buffer_offset = + vma->vm_start - (uintptr_t)alloc->buffer; + mutex_unlock(&binder_alloc_mmap_lock); #ifdef CONFIG_CPU_CACHE_VIPT if (cache_is_vipt_aliasing()) { while (CACHE_COLOUR( - (vma->vm_start ^ (uint32_t)proc->alloc.buffer))) { pr_info("%s: %d %lx-%lx maps %pK bad alignment\n", __func__, - proc->pid, vma->vm_start, - vma->vm_end, proc->alloc.buffer); + alloc->pid, vma->vm_start, vma->vm_end, + alloc->buffer); vma->vm_start += PAGE_SIZE; } } #endif - proc->alloc.pages = - kzalloc(sizeof(proc->alloc.pages[0]) * - ((vma->vm_end - vma->vm_start) / PAGE_SIZE), - GFP_KERNEL); - if (proc->alloc.pages == NULL) { + alloc->pages = kzalloc(sizeof(alloc->pages[0]) * + ((vma->vm_end - vma->vm_start) / PAGE_SIZE), + GFP_KERNEL); + if (alloc->pages == NULL) { ret = -ENOMEM; failure_string = "alloc page array"; goto err_alloc_pages_failed; } - proc->alloc.buffer_size = vma->vm_end - vma->vm_start; + alloc->buffer_size = vma->vm_end - vma->vm_start; - vma->vm_ops = &binder_vm_ops; - vma->vm_private_data = proc; - - if (binder_update_page_range(proc, 1, proc->alloc.buffer, - proc->alloc.buffer + PAGE_SIZE, vma)) { + if (binder_update_page_range(alloc, 1, alloc->buffer, + alloc->buffer + PAGE_SIZE, vma)) { ret = -ENOMEM; failure_string = "alloc small buf"; goto err_alloc_small_buf_failed; } - buffer = proc->alloc.buffer; - INIT_LIST_HEAD(&proc->alloc.buffers); - list_add(&buffer->entry, &proc->alloc.buffers); + buffer = alloc->buffer; + INIT_LIST_HEAD(&alloc->buffers); + list_add(&buffer->entry, &alloc->buffers); buffer->free = 1; - binder_insert_free_buffer(proc, buffer); - proc->alloc.free_async_space = proc->alloc.buffer_size / 2; + binder_insert_free_buffer(alloc, buffer); + alloc->free_async_space = alloc->buffer_size / 2; barrier(); - proc->files = get_files_struct(current); - proc->alloc.vma = vma; - proc->alloc.vma_vm_mm = vma->vm_mm; + alloc->vma = vma; + alloc->vma_vm_mm = vma->vm_mm; - /*pr_info("binder_mmap: %d %lx-%lx maps %pK\n", - * proc->pid, vma->vm_start, vma->vm_end, proc->alloc.buffer); - */ return 0; err_alloc_small_buf_failed: - kfree(proc->alloc.pages); - proc->alloc.pages = NULL; + kfree(alloc->pages); + alloc->pages = NULL; err_alloc_pages_failed: - mutex_lock(&binder_mmap_lock); - vfree(proc->alloc.buffer); - proc->alloc.buffer = NULL; + mutex_lock(&binder_alloc_mmap_lock); + vfree(alloc->buffer); + alloc->buffer = NULL; err_get_vm_area_failed: err_already_mapped: - mutex_unlock(&binder_mmap_lock); + mutex_unlock(&binder_alloc_mmap_lock); + pr_err("%s: %d %lx-%lx %s failed %d\n", __func__, + alloc->pid, vma->vm_start, vma->vm_end, failure_string, ret); + return ret; +} + +static int binder_mmap(struct file *filp, struct vm_area_struct *vma) +{ + int ret; + struct binder_proc *proc = filp->private_data; + const char *failure_string; + + if (proc->tsk != current->group_leader) + return -EINVAL; + + if ((vma->vm_end - vma->vm_start) > SZ_4M) + vma->vm_end = vma->vm_start + SZ_4M; + + binder_debug(BINDER_DEBUG_OPEN_CLOSE, + "%s: %d %lx-%lx (%ld K) vma %lx pagep %lx\n", + __func__, proc->pid, vma->vm_start, vma->vm_end, + (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, + (unsigned long)pgprot_val(vma->vm_page_prot)); + + if (vma->vm_flags & FORBIDDEN_MMAP_FLAGS) { + ret = -EPERM; + failure_string = "bad vm_flags"; + goto err_bad_arg; + } + vma->vm_flags = (vma->vm_flags | VM_DONTCOPY) & ~VM_MAYWRITE; + vma->vm_ops = &binder_vm_ops; + vma->vm_private_data = proc; + + ret = binder_alloc_mmap_handler(&proc->alloc, vma); + if (ret) + return ret; + proc->files = get_files_struct(current); + return 0; + err_bad_arg: pr_err("binder_mmap: %d %lx-%lx %s failed %d\n", proc->pid, vma->vm_start, vma->vm_end, failure_string, ret); return ret; } +void binder_alloc_init(struct binder_alloc *alloc) +{ + alloc->tsk = current->group_leader; + alloc->pid = current->group_leader->pid; + mutex_init(&alloc->mutex); +} + static int binder_open(struct inode *nodp, struct file *filp) { struct binder_proc *proc; @@ -3514,6 +3642,7 @@ static int binder_open(struct inode *nodp, struct file *filp) binder_dev = container_of(filp->private_data, struct binder_device, miscdev); proc->context = &binder_dev->context; + binder_alloc_init(&proc->alloc); binder_lock(__func__); @@ -3629,14 +3758,61 @@ static int binder_node_release(struct binder_node *node, int refs) return refs; } +void binder_alloc_deferred_release(struct binder_alloc *alloc) +{ + struct rb_node *n; + int buffers, page_count; + + BUG_ON(alloc->vma); + + buffers = 0; + mutex_lock(&alloc->mutex); + while ((n = rb_first(&alloc->allocated_buffers))) { + struct binder_buffer *buffer; + + buffer = rb_entry(n, struct binder_buffer, rb_node); + + /* Transaction should already have been freed */ + BUG_ON(buffer->transaction); + + binder_free_buf_locked(alloc, buffer); + buffers++; + } + + page_count = 0; + if (alloc->pages) { + int i; + + for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) { + void *page_addr; + + if (!alloc->pages[i]) + continue; + + page_addr = alloc->buffer + i * PAGE_SIZE; + binder_alloc_debug(BINDER_ALLOC_DEBUG_BUFFER_ALLOC, + "%s: %d: page %d at %pK not freed\n", + __func__, alloc->pid, i, page_addr); + unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE); + __free_page(alloc->pages[i]); + page_count++; + } + kfree(alloc->pages); + vfree(alloc->buffer); + } + mutex_unlock(&alloc->mutex); + + binder_alloc_debug(BINDER_ALLOC_DEBUG_OPEN_CLOSE, + "%s: %d buffers %d, pages %d\n", + __func__, alloc->pid, buffers, page_count); +} + static void binder_deferred_release(struct binder_proc *proc) { struct binder_context *context = proc->context; struct rb_node *n; - int threads, nodes, incoming_refs, outgoing_refs, buffers, - active_transactions, page_count; + int threads, nodes, incoming_refs, outgoing_refs, active_transactions; - BUG_ON(proc->alloc.vma); BUG_ON(proc->files); hlist_del(&proc->proc_node); @@ -3682,49 +3858,15 @@ static void binder_deferred_release(struct binder_proc *proc) binder_release_work(&proc->todo); binder_release_work(&proc->delivered_death); - buffers = 0; - while ((n = rb_first(&proc->alloc.allocated_buffers))) { - struct binder_buffer *buffer; - - buffer = rb_entry(n, struct binder_buffer, rb_node); - - /* Transaction should already have been freed */ - BUG_ON(buffer->transaction); - - binder_free_buf(proc, buffer); - buffers++; - } - + binder_alloc_deferred_release(&proc->alloc); binder_stats_deleted(BINDER_STAT_PROC); - page_count = 0; - if (proc->alloc.pages) { - int i; - - for (i = 0; i < proc->alloc.buffer_size / PAGE_SIZE; i++) { - void *page_addr; - - if (!proc->alloc.pages[i]) - continue; - - page_addr = proc->alloc.buffer + i * PAGE_SIZE; - binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%s: %d: page %d at %p not freed\n", - __func__, proc->pid, i, page_addr); - unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE); - __free_page(proc->alloc.pages[i]); - page_count++; - } - kfree(proc->alloc.pages); - vfree(proc->alloc.buffer); - } - put_task_struct(proc->tsk); binder_debug(BINDER_DEBUG_OPEN_CLOSE, - "%s: %d threads %d, nodes %d (ref %d), refs %d, active transactions %d, buffers %d, pages %d\n", + "%s: %d threads %d, nodes %d (ref %d), refs %d, active transactions %d\n", __func__, proc->pid, threads, nodes, incoming_refs, - outgoing_refs, active_transactions, buffers, page_count); + outgoing_refs, active_transactions); kfree(proc); } @@ -3807,15 +3949,6 @@ static void print_binder_transaction(struct seq_file *m, const char *prefix, t->buffer->data); } -static void print_binder_buffer(struct seq_file *m, const char *prefix, - struct binder_buffer *buffer) -{ - seq_printf(m, "%s %d: %p size %zd:%zd %s\n", - prefix, buffer->debug_id, buffer->data, - buffer->data_size, buffer->offsets_size, - buffer->transaction ? "active" : "delivered"); -} - static void print_binder_work(struct seq_file *m, const char *prefix, const char *transaction_prefix, struct binder_work *w) @@ -3918,6 +4051,27 @@ static void print_binder_ref(struct seq_file *m, struct binder_ref *ref) ref->node->debug_id, ref->strong, ref->weak, ref->death); } +static void print_binder_buffer(struct seq_file *m, const char *prefix, + struct binder_buffer *buffer) +{ + seq_printf(m, "%s %d: %pK size %zd:%zd %s\n", + prefix, buffer->debug_id, buffer->data, + buffer->data_size, buffer->offsets_size, + buffer->transaction ? "active" : "delivered"); +} + +void binder_alloc_print_allocated(struct seq_file *m, + struct binder_alloc *alloc) +{ + struct rb_node *n; + + mutex_lock(&alloc->mutex); + for (n = rb_first(&alloc->allocated_buffers); n != NULL; n = rb_next(n)) + print_binder_buffer(m, " buffer", + rb_entry(n, struct binder_buffer, rb_node)); + mutex_unlock(&alloc->mutex); +} + static void print_binder_proc(struct seq_file *m, struct binder_proc *proc, int print_all) { @@ -3946,10 +4100,7 @@ static void print_binder_proc(struct seq_file *m, print_binder_ref(m, rb_entry(n, struct binder_ref, rb_node_desc)); } - for (n = rb_first(&proc->alloc.allocated_buffers); - n != NULL; n = rb_next(n)) - print_binder_buffer(m, " buffer", - rb_entry(n, struct binder_buffer, rb_node)); + binder_alloc_print_allocated(m, &proc->alloc); list_for_each_entry(w, &proc->todo, entry) print_binder_work(m, " ", " pending transaction", w); list_for_each_entry(w, &proc->delivered_death, entry) { @@ -4047,6 +4198,18 @@ static void print_binder_stats(struct seq_file *m, const char *prefix, } } +int binder_alloc_get_allocated_count(struct binder_alloc *alloc) +{ + struct rb_node *n; + int count = 0; + + mutex_lock(&alloc->mutex); + for (n = rb_first(&alloc->allocated_buffers); n != NULL; n = rb_next(n)) + count++; + mutex_unlock(&alloc->mutex); + return count; +} + static void print_binder_proc_stats(struct seq_file *m, struct binder_proc *proc) { @@ -4064,7 +4227,8 @@ static void print_binder_proc_stats(struct seq_file *m, " ready threads %d\n" " free async space %zd\n", proc->requested_threads, proc->requested_threads_started, proc->max_threads, - proc->ready_threads, proc->alloc.free_async_space); + proc->ready_threads, + binder_alloc_get_free_async_space(&proc->alloc)); count = 0; for (n = rb_first(&proc->nodes); n != NULL; n = rb_next(n)) count++; @@ -4081,10 +4245,7 @@ static void print_binder_proc_stats(struct seq_file *m, } seq_printf(m, " refs: %d s %d w %d\n", count, strong, weak); - count = 0; - for (n = rb_first(&proc->alloc.allocated_buffers); - n != NULL; n = rb_next(n)) - count++; + count = binder_alloc_get_allocated_count(&proc->alloc); seq_printf(m, " buffers: %d\n", count); count = 0; diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h index c835f09656c1..50b0d21f42cf 100644 --- a/drivers/android/binder_trace.h +++ b/drivers/android/binder_trace.h @@ -23,6 +23,7 @@ struct binder_buffer; struct binder_node; struct binder_proc; +struct binder_alloc; struct binder_ref; struct binder_thread; struct binder_transaction; @@ -268,9 +269,9 @@ DEFINE_EVENT(binder_buffer_class, binder_transaction_failed_buffer_release, TP_ARGS(buffer)); TRACE_EVENT(binder_update_page_range, - TP_PROTO(struct binder_proc *proc, bool allocate, + TP_PROTO(struct binder_alloc *alloc, bool allocate, void *start, void *end), - TP_ARGS(proc, allocate, start, end), + TP_ARGS(alloc, allocate, start, end), TP_STRUCT__entry( __field(int, proc) __field(bool, allocate) @@ -278,9 +279,9 @@ TRACE_EVENT(binder_update_page_range, __field(size_t, size) ), TP_fast_assign( - __entry->proc = proc->pid; + __entry->proc = alloc->pid; __entry->allocate = allocate; - __entry->offset = start - proc->alloc.buffer; + __entry->offset = start - alloc->buffer; __entry->size = end - start; ), TP_printk("proc=%d allocate=%d offset=%zu size=%zu", -- cgit v1.2.3 From 0c972a05cde66e3d448419c120627083d6419f8f Mon Sep 17 00:00:00 2001 From: Todd Kjos Date: Thu, 29 Jun 2017 12:01:41 -0700 Subject: binder: move binder_alloc to separate file Move the binder allocator functionality to its own file Continuation of splitting the binder allocator from the binder driver. Split binder_alloc functions from normal binder functions. Add kernel doc comments to functions declared extern in binder_alloc.h Signed-off-by: Todd Kjos Signed-off-by: Greg Kroah-Hartman --- drivers/android/Makefile | 2 +- drivers/android/binder.c | 763 +---------------------------------------- drivers/android/binder_alloc.c | 759 ++++++++++++++++++++++++++++++++++++++++ drivers/android/binder_alloc.h | 162 +++++++++ 4 files changed, 923 insertions(+), 763 deletions(-) create mode 100644 drivers/android/binder_alloc.c create mode 100644 drivers/android/binder_alloc.h (limited to 'drivers') diff --git a/drivers/android/Makefile b/drivers/android/Makefile index 3b7e4b072c58..4b7c726bb560 100644 --- a/drivers/android/Makefile +++ b/drivers/android/Makefile @@ -1,3 +1,3 @@ ccflags-y += -I$(src) # needed for trace events -obj-$(CONFIG_ANDROID_BINDER_IPC) += binder.o +obj-$(CONFIG_ANDROID_BINDER_IPC) += binder.o binder_alloc.o diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 6c1d0b5b352b..0512971cfc53 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -35,8 +34,6 @@ #include #include #include -#include -#include #include #include @@ -45,11 +42,11 @@ #endif #include +#include "binder_alloc.h" #include "binder_trace.h" static DEFINE_MUTEX(binder_main_lock); static DEFINE_MUTEX(binder_deferred_lock); -static DEFINE_MUTEX(binder_alloc_mmap_lock); static HLIST_HEAD(binder_devices); static HLIST_HEAD(binder_procs); @@ -157,27 +154,6 @@ module_param_call(stop_on_user_error, binder_set_stop_on_user_error, #define to_binder_fd_array_object(hdr) \ container_of(hdr, struct binder_fd_array_object, hdr) -/* - * debug declarations for binder_alloc. To be - * moved to binder_alloc.c - */ -enum { - BINDER_ALLOC_DEBUG_OPEN_CLOSE = 1U << 1, - BINDER_ALLOC_DEBUG_BUFFER_ALLOC = 1U << 2, - BINDER_ALLOC_DEBUG_BUFFER_ALLOC_ASYNC = 1U << 3, -}; -static uint32_t binder_alloc_debug_mask; - -module_param_named(alloc_debug_mask, binder_alloc_debug_mask, - uint, 0644); - -#define binder_alloc_debug(mask, x...) \ - do { \ - if (binder_alloc_debug_mask & mask) \ - pr_info(x); \ - } while (0) -/* end of binder_alloc debug declarations */ - enum binder_stat_types { BINDER_STAT_PROC, BINDER_STAT_THREAD, @@ -314,68 +290,12 @@ struct binder_ref { struct binder_ref_death *death; }; -struct binder_buffer { - struct list_head entry; /* free and allocated entries by address */ - struct rb_node rb_node; /* free entry by size or allocated entry */ - /* by address */ - unsigned free:1; - unsigned allow_user_free:1; - unsigned async_transaction:1; - unsigned debug_id:29; - - struct binder_transaction *transaction; - - struct binder_node *target_node; - size_t data_size; - size_t offsets_size; - size_t extra_buffers_size; - uint8_t data[0]; -}; - enum binder_deferred_state { BINDER_DEFERRED_PUT_FILES = 0x01, BINDER_DEFERRED_FLUSH = 0x02, BINDER_DEFERRED_RELEASE = 0x04, }; -/** - * struct binder_alloc - per-binder proc state for binder allocator - * @vma: vm_area_struct passed to mmap_handler - * (invarient after mmap) - * @vma_vm_mm: copy of vma->vm_mm (invarient after mmap) - * @buffer: base of per-proc address space mapped via mmap - * @user_buffer_offset: offset between user and kernel VAs for buffer - * @buffers: list of all buffers for this proc - * @free_buffers: rb tree of buffers available for allocation - * sorted by size - * @allocated_buffers: rb tree of allocated buffers sorted by address - * @free_async_space: VA space available for async buffers. This is - * initialized at mmap time to 1/2 the full VA space - * @pages: array of physical page addresses for each page of - * mmap'd space - * @buffer_size: size of address space (could be less than requested) - * - * Bookkeeping structure for per-proc address space management for binder - * buffers. It is normally initialized during binder_init() and binder_mmap() - * calls. The address space is used for both user-visible buffers and for - * struct binder_buffer objects used to track the user buffers - */ -struct binder_alloc { - struct mutex mutex; - struct task_struct *tsk; - struct vm_area_struct *vma; - struct mm_struct *vma_vm_mm; - void *buffer; - ptrdiff_t user_buffer_offset; - struct list_head buffers; - struct rb_root free_buffers; - struct rb_root allocated_buffers; - size_t free_async_space; - struct page **pages; - size_t buffer_size; - int pid; -}; - struct binder_proc { struct hlist_node proc_node; struct rb_root threads; @@ -445,56 +365,6 @@ struct binder_transaction { kuid_t sender_euid; }; -/* - * Forward declarations of binder_alloc functions. - * These will be moved to binder_alloc.h when - * binder_alloc is moved to its own files. - */ -extern struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc, - size_t data_size, - size_t offsets_size, - size_t extra_buffers_size, - int is_async); -extern void binder_alloc_init(struct binder_alloc *alloc); -extern void binder_alloc_vma_close(struct binder_alloc *alloc); -extern struct binder_buffer * -binder_alloc_buffer_lookup(struct binder_alloc *alloc, - uintptr_t user_ptr); -extern void binder_alloc_free_buf(struct binder_alloc *alloc, - struct binder_buffer *buffer); -extern int binder_alloc_mmap_handler(struct binder_alloc *alloc, - struct vm_area_struct *vma); -extern void binder_alloc_deferred_release(struct binder_alloc *alloc); -extern int binder_alloc_get_allocated_count(struct binder_alloc *alloc); -extern void binder_alloc_print_allocated(struct seq_file *m, - struct binder_alloc *alloc); - -static inline size_t -binder_alloc_get_free_async_space(struct binder_alloc *alloc) -{ - size_t free_async_space; - - mutex_lock(&alloc->mutex); - free_async_space = alloc->free_async_space; - mutex_unlock(&alloc->mutex); - return free_async_space; -} - -static inline ptrdiff_t -binder_alloc_get_user_buffer_offset(struct binder_alloc *alloc) -{ - /* - * user_buffer_offset is constant if vma is set and - * undefined if vma is not set. It is possible to - * get here with !alloc->vma if the target process - * is dying while a transaction is being initiated. - * Returning the old value is ok in this case and - * the transaction will fail. - */ - return alloc->user_buffer_offset; -} -/* end of binder_alloc declarations */ - static void binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer); @@ -578,462 +448,6 @@ static void binder_set_nice(long nice) binder_user_error("%d RLIMIT_NICE not set\n", current->pid); } -static size_t binder_alloc_buffer_size(struct binder_alloc *alloc, - struct binder_buffer *buffer) -{ - if (list_is_last(&buffer->entry, &alloc->buffers)) - return alloc->buffer + - alloc->buffer_size - (void *)buffer->data; - return (size_t)list_entry(buffer->entry.next, - struct binder_buffer, entry) - (size_t)buffer->data; -} - -static void binder_insert_free_buffer(struct binder_alloc *alloc, - struct binder_buffer *new_buffer) -{ - struct rb_node **p = &alloc->free_buffers.rb_node; - struct rb_node *parent = NULL; - struct binder_buffer *buffer; - size_t buffer_size; - size_t new_buffer_size; - - BUG_ON(!new_buffer->free); - - new_buffer_size = binder_alloc_buffer_size(alloc, new_buffer); - - binder_alloc_debug(BINDER_ALLOC_DEBUG_BUFFER_ALLOC, - "%d: add free buffer, size %zd, at %pK\n", - alloc->pid, new_buffer_size, new_buffer); - - while (*p) { - parent = *p; - buffer = rb_entry(parent, struct binder_buffer, rb_node); - BUG_ON(!buffer->free); - - buffer_size = binder_alloc_buffer_size(alloc, buffer); - - if (new_buffer_size < buffer_size) - p = &parent->rb_left; - else - p = &parent->rb_right; - } - rb_link_node(&new_buffer->rb_node, parent, p); - rb_insert_color(&new_buffer->rb_node, &alloc->free_buffers); -} - -static void binder_insert_allocated_buffer(struct binder_alloc *alloc, - struct binder_buffer *new_buffer) -{ - struct rb_node **p = &alloc->allocated_buffers.rb_node; - struct rb_node *parent = NULL; - struct binder_buffer *buffer; - - BUG_ON(new_buffer->free); - - while (*p) { - parent = *p; - buffer = rb_entry(parent, struct binder_buffer, rb_node); - BUG_ON(buffer->free); - - if (new_buffer < buffer) - p = &parent->rb_left; - else if (new_buffer > buffer) - p = &parent->rb_right; - else - BUG(); - } - rb_link_node(&new_buffer->rb_node, parent, p); - rb_insert_color(&new_buffer->rb_node, &alloc->allocated_buffers); -} - -static struct binder_buffer *binder_alloc_buffer_lookup_locked( - struct binder_alloc *alloc, - uintptr_t user_ptr) -{ - struct rb_node *n = alloc->allocated_buffers.rb_node; - struct binder_buffer *buffer; - struct binder_buffer *kern_ptr; - - kern_ptr = (struct binder_buffer *)(user_ptr - alloc->user_buffer_offset - - offsetof(struct binder_buffer, data)); - - while (n) { - buffer = rb_entry(n, struct binder_buffer, rb_node); - BUG_ON(buffer->free); - - if (kern_ptr < buffer) - n = n->rb_left; - else if (kern_ptr > buffer) - n = n->rb_right; - else - return buffer; - } - return NULL; -} - -struct binder_buffer *binder_alloc_buffer_lookup(struct binder_alloc *alloc, - uintptr_t user_ptr) -{ - struct binder_buffer *buffer; - - mutex_lock(&alloc->mutex); - buffer = binder_alloc_buffer_lookup_locked(alloc, user_ptr); - mutex_unlock(&alloc->mutex); - return buffer; -} - -static int binder_update_page_range(struct binder_alloc *alloc, int allocate, - void *start, void *end, - struct vm_area_struct *vma) -{ - void *page_addr; - unsigned long user_page_addr; - struct page **page; - struct mm_struct *mm; - - binder_alloc_debug(BINDER_ALLOC_DEBUG_BUFFER_ALLOC, - "%d: %s pages %pK-%pK\n", alloc->pid, - allocate ? "allocate" : "free", start, end); - - if (end <= start) - return 0; - - trace_binder_update_page_range(alloc, allocate, start, end); - - if (vma) - mm = NULL; - else - mm = get_task_mm(alloc->tsk); - - if (mm) { - down_write(&mm->mmap_sem); - vma = alloc->vma; - if (vma && mm != alloc->vma_vm_mm) { - pr_err("%d: vma mm and task mm mismatch\n", - alloc->pid); - vma = NULL; - } - } - - if (allocate == 0) - goto free_range; - - if (vma == NULL) { - pr_err("%d: binder_alloc_buf failed to map pages in userspace, no vma\n", - alloc->pid); - goto err_no_vma; - } - - for (page_addr = start; page_addr < end; page_addr += PAGE_SIZE) { - int ret; - - page = &alloc->pages[(page_addr - alloc->buffer) / PAGE_SIZE]; - - BUG_ON(*page); - *page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO); - if (*page == NULL) { - pr_err("%d: binder_alloc_buf failed for page at %pK\n", - alloc->pid, page_addr); - goto err_alloc_page_failed; - } - ret = map_kernel_range_noflush((unsigned long)page_addr, - PAGE_SIZE, PAGE_KERNEL, page); - flush_cache_vmap((unsigned long)page_addr, - (unsigned long)page_addr + PAGE_SIZE); - if (ret != 1) { - pr_err("%d: binder_alloc_buf failed to map page at %pK in kernel\n", - alloc->pid, page_addr); - goto err_map_kernel_failed; - } - user_page_addr = - (uintptr_t)page_addr + alloc->user_buffer_offset; - ret = vm_insert_page(vma, user_page_addr, page[0]); - if (ret) { - pr_err("%d: binder_alloc_buf failed to map page at %lx in userspace\n", - alloc->pid, user_page_addr); - goto err_vm_insert_page_failed; - } - /* vm_insert_page does not seem to increment the refcount */ - } - if (mm) { - up_write(&mm->mmap_sem); - mmput(mm); - } - return 0; - -free_range: - for (page_addr = end - PAGE_SIZE; page_addr >= start; - page_addr -= PAGE_SIZE) { - page = &alloc->pages[(page_addr - alloc->buffer) / PAGE_SIZE]; - if (vma) - zap_page_range(vma, (uintptr_t)page_addr + - alloc->user_buffer_offset, PAGE_SIZE); -err_vm_insert_page_failed: - unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE); -err_map_kernel_failed: - __free_page(*page); - *page = NULL; -err_alloc_page_failed: - ; - } -err_no_vma: - if (mm) { - up_write(&mm->mmap_sem); - mmput(mm); - } - return -ENOMEM; -} - -static struct binder_buffer *binder_alloc_new_buf_locked( - struct binder_alloc *alloc, size_t data_size, - size_t offsets_size, size_t extra_buffers_size, int is_async) -{ - struct rb_node *n = alloc->free_buffers.rb_node; - struct binder_buffer *buffer; - size_t buffer_size; - struct rb_node *best_fit = NULL; - void *has_page_addr; - void *end_page_addr; - size_t size, data_offsets_size; - - if (alloc->vma == NULL) { - pr_err("%d: binder_alloc_buf, no vma\n", - alloc->pid); - return NULL; - } - - data_offsets_size = ALIGN(data_size, sizeof(void *)) + - ALIGN(offsets_size, sizeof(void *)); - - if (data_offsets_size < data_size || data_offsets_size < offsets_size) { - binder_alloc_debug(BINDER_ALLOC_DEBUG_BUFFER_ALLOC, - "%d: got transaction with invalid size %zd-%zd\n", - alloc->pid, data_size, offsets_size); - return NULL; - } - size = data_offsets_size + ALIGN(extra_buffers_size, sizeof(void *)); - if (size < data_offsets_size || size < extra_buffers_size) { - binder_alloc_debug(BINDER_ALLOC_DEBUG_BUFFER_ALLOC, - "%d: got transaction with invalid extra_buffers_size %zd\n", - alloc->pid, extra_buffers_size); - return NULL; - } - if (is_async && - alloc->free_async_space < size + sizeof(struct binder_buffer)) { - binder_alloc_debug(BINDER_ALLOC_DEBUG_BUFFER_ALLOC, - "%d: binder_alloc_buf size %zd failed, no async space left\n", - alloc->pid, size); - return NULL; - } - - while (n) { - buffer = rb_entry(n, struct binder_buffer, rb_node); - BUG_ON(!buffer->free); - buffer_size = binder_alloc_buffer_size(alloc, buffer); - - if (size < buffer_size) { - best_fit = n; - n = n->rb_left; - } else if (size > buffer_size) - n = n->rb_right; - else { - best_fit = n; - break; - } - } - if (best_fit == NULL) { - pr_err("%d: binder_alloc_buf size %zd failed, no address space\n", - alloc->pid, size); - return NULL; - } - if (n == NULL) { - buffer = rb_entry(best_fit, struct binder_buffer, rb_node); - buffer_size = binder_alloc_buffer_size(alloc, buffer); - } - - binder_alloc_debug(BINDER_ALLOC_DEBUG_BUFFER_ALLOC, - "%d: %s size %zd got buffer %pK size %zd\n", - alloc->pid, __func__, size, buffer, buffer_size); - - has_page_addr = - (void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK); - if (n == NULL) { - if (size + sizeof(struct binder_buffer) + 4 >= buffer_size) - buffer_size = size; /* no room for other buffers */ - else - buffer_size = size + sizeof(struct binder_buffer); - } - end_page_addr = - (void *)PAGE_ALIGN((uintptr_t)buffer->data + buffer_size); - if (end_page_addr > has_page_addr) - end_page_addr = has_page_addr; - if (binder_update_page_range(alloc, 1, - (void *)PAGE_ALIGN((uintptr_t)buffer->data), end_page_addr, NULL)) - return NULL; - - rb_erase(best_fit, &alloc->free_buffers); - buffer->free = 0; - binder_insert_allocated_buffer(alloc, buffer); - if (buffer_size != size) { - struct binder_buffer *new_buffer = (void *)buffer->data + size; - - list_add(&new_buffer->entry, &buffer->entry); - new_buffer->free = 1; - binder_insert_free_buffer(alloc, new_buffer); - } - binder_alloc_debug(BINDER_ALLOC_DEBUG_BUFFER_ALLOC, - "%d: %s size %zd got %pK\n", - alloc->pid, __func__, size, buffer); - buffer->data_size = data_size; - buffer->offsets_size = offsets_size; - buffer->async_transaction = is_async; - buffer->extra_buffers_size = extra_buffers_size; - if (is_async) { - alloc->free_async_space -= size + sizeof(struct binder_buffer); - binder_alloc_debug(BINDER_ALLOC_DEBUG_BUFFER_ALLOC_ASYNC, - "%d: binder_alloc_buf size %zd async free %zd\n", - alloc->pid, size, alloc->free_async_space); - } - - return buffer; -} - -struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc, - size_t data_size, - size_t offsets_size, - size_t extra_buffers_size, - int is_async) -{ - struct binder_buffer *buffer; - - mutex_lock(&alloc->mutex); - buffer = binder_alloc_new_buf_locked(alloc, data_size, offsets_size, - extra_buffers_size, is_async); - mutex_unlock(&alloc->mutex); - return buffer; -} - -static void *buffer_start_page(struct binder_buffer *buffer) -{ - return (void *)((uintptr_t)buffer & PAGE_MASK); -} - -static void *buffer_end_page(struct binder_buffer *buffer) -{ - return (void *)(((uintptr_t)(buffer + 1) - 1) & PAGE_MASK); -} - -static void binder_delete_free_buffer(struct binder_alloc *alloc, - struct binder_buffer *buffer) -{ - struct binder_buffer *prev, *next = NULL; - int free_page_end = 1; - int free_page_start = 1; - - BUG_ON(alloc->buffers.next == &buffer->entry); - prev = list_entry(buffer->entry.prev, struct binder_buffer, entry); - BUG_ON(!prev->free); - if (buffer_end_page(prev) == buffer_start_page(buffer)) { - free_page_start = 0; - if (buffer_end_page(prev) == buffer_end_page(buffer)) - free_page_end = 0; - binder_alloc_debug(BINDER_ALLOC_DEBUG_BUFFER_ALLOC, - "%d: merge free, buffer %pK share page with %pK\n", - alloc->pid, buffer, prev); - } - - if (!list_is_last(&buffer->entry, &alloc->buffers)) { - next = list_entry(buffer->entry.next, - struct binder_buffer, entry); - if (buffer_start_page(next) == buffer_end_page(buffer)) { - free_page_end = 0; - if (buffer_start_page(next) == - buffer_start_page(buffer)) - free_page_start = 0; - binder_alloc_debug(BINDER_ALLOC_DEBUG_BUFFER_ALLOC, - "%d: merge free, buffer %pK share page with %pK\n", - alloc->pid, buffer, prev); - } - } - list_del(&buffer->entry); - if (free_page_start || free_page_end) { - binder_alloc_debug(BINDER_ALLOC_DEBUG_BUFFER_ALLOC, - "%d: merge free, buffer %pK do not share page%s%s with %pK or %pK\n", - alloc->pid, buffer, free_page_start ? "" : " end", - free_page_end ? "" : " start", prev, next); - binder_update_page_range(alloc, 0, free_page_start ? - buffer_start_page(buffer) : buffer_end_page(buffer), - (free_page_end ? buffer_end_page(buffer) : - buffer_start_page(buffer)) + PAGE_SIZE, NULL); - } -} - -static void binder_free_buf_locked(struct binder_alloc *alloc, - struct binder_buffer *buffer) -{ - size_t size, buffer_size; - - buffer_size = binder_alloc_buffer_size(alloc, buffer); - - size = ALIGN(buffer->data_size, sizeof(void *)) + - ALIGN(buffer->offsets_size, sizeof(void *)) + - ALIGN(buffer->extra_buffers_size, sizeof(void *)); - - binder_alloc_debug(BINDER_ALLOC_DEBUG_BUFFER_ALLOC, - "%d: binder_free_buf %pK size %zd buffer_size %zd\n", - alloc->pid, buffer, size, buffer_size); - - BUG_ON(buffer->free); - BUG_ON(size > buffer_size); - BUG_ON(buffer->transaction != NULL); - BUG_ON((void *)buffer < alloc->buffer); - BUG_ON((void *)buffer > alloc->buffer + alloc->buffer_size); - - if (buffer->async_transaction) { - alloc->free_async_space += size + sizeof(struct binder_buffer); - - binder_alloc_debug(BINDER_ALLOC_DEBUG_BUFFER_ALLOC_ASYNC, - "%d: binder_free_buf size %zd async free %zd\n", - alloc->pid, size, alloc->free_async_space); - } - - binder_update_page_range(alloc, 0, - (void *)PAGE_ALIGN((uintptr_t)buffer->data), - (void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK), - NULL); - - rb_erase(&buffer->rb_node, &alloc->allocated_buffers); - buffer->free = 1; - if (!list_is_last(&buffer->entry, &alloc->buffers)) { - struct binder_buffer *next = list_entry(buffer->entry.next, - struct binder_buffer, entry); - - if (next->free) { - rb_erase(&next->rb_node, &alloc->free_buffers); - binder_delete_free_buffer(alloc, next); - } - } - if (alloc->buffers.next != &buffer->entry) { - struct binder_buffer *prev = list_entry(buffer->entry.prev, - struct binder_buffer, entry); - - if (prev->free) { - binder_delete_free_buffer(alloc, buffer); - rb_erase(&prev->rb_node, &alloc->free_buffers); - buffer = prev; - } - } - binder_insert_free_buffer(alloc, buffer); -} - -void binder_alloc_free_buf(struct binder_alloc *alloc, - struct binder_buffer *buffer) -{ - mutex_lock(&alloc->mutex); - binder_free_buf_locked(alloc, buffer); - mutex_unlock(&alloc->mutex); -} - static struct binder_node *binder_get_node(struct binder_proc *proc, binder_uintptr_t ptr) { @@ -3467,12 +2881,6 @@ static void binder_vma_open(struct vm_area_struct *vma) (unsigned long)pgprot_val(vma->vm_page_prot)); } -void binder_alloc_vma_close(struct binder_alloc *alloc) -{ - WRITE_ONCE(alloc->vma, NULL); - WRITE_ONCE(alloc->vma_vm_mm, NULL); -} - static void binder_vma_close(struct vm_area_struct *vma) { struct binder_proc *proc = vma->vm_private_data; @@ -3497,86 +2905,6 @@ static const struct vm_operations_struct binder_vm_ops = { .fault = binder_vm_fault, }; -int binder_alloc_mmap_handler(struct binder_alloc *alloc, - struct vm_area_struct *vma) -{ - int ret; - struct vm_struct *area; - const char *failure_string; - struct binder_buffer *buffer; - - mutex_lock(&binder_alloc_mmap_lock); - if (alloc->buffer) { - ret = -EBUSY; - failure_string = "already mapped"; - goto err_already_mapped; - } - - area = get_vm_area(vma->vm_end - vma->vm_start, VM_IOREMAP); - if (area == NULL) { - ret = -ENOMEM; - failure_string = "get_vm_area"; - goto err_get_vm_area_failed; - } - alloc->buffer = area->addr; - alloc->user_buffer_offset = - vma->vm_start - (uintptr_t)alloc->buffer; - mutex_unlock(&binder_alloc_mmap_lock); - -#ifdef CONFIG_CPU_CACHE_VIPT - if (cache_is_vipt_aliasing()) { - while (CACHE_COLOUR( - pr_info("%s: %d %lx-%lx maps %pK bad alignment\n", - __func__, - alloc->pid, vma->vm_start, vma->vm_end, - alloc->buffer); - vma->vm_start += PAGE_SIZE; - } - } -#endif - alloc->pages = kzalloc(sizeof(alloc->pages[0]) * - ((vma->vm_end - vma->vm_start) / PAGE_SIZE), - GFP_KERNEL); - if (alloc->pages == NULL) { - ret = -ENOMEM; - failure_string = "alloc page array"; - goto err_alloc_pages_failed; - } - alloc->buffer_size = vma->vm_end - vma->vm_start; - - if (binder_update_page_range(alloc, 1, alloc->buffer, - alloc->buffer + PAGE_SIZE, vma)) { - ret = -ENOMEM; - failure_string = "alloc small buf"; - goto err_alloc_small_buf_failed; - } - buffer = alloc->buffer; - INIT_LIST_HEAD(&alloc->buffers); - list_add(&buffer->entry, &alloc->buffers); - buffer->free = 1; - binder_insert_free_buffer(alloc, buffer); - alloc->free_async_space = alloc->buffer_size / 2; - barrier(); - alloc->vma = vma; - alloc->vma_vm_mm = vma->vm_mm; - - return 0; - -err_alloc_small_buf_failed: - kfree(alloc->pages); - alloc->pages = NULL; -err_alloc_pages_failed: - mutex_lock(&binder_alloc_mmap_lock); - vfree(alloc->buffer); - alloc->buffer = NULL; -err_get_vm_area_failed: -err_already_mapped: - mutex_unlock(&binder_alloc_mmap_lock); - pr_err("%s: %d %lx-%lx %s failed %d\n", __func__, - alloc->pid, vma->vm_start, vma->vm_end, failure_string, ret); - return ret; -} - static int binder_mmap(struct file *filp, struct vm_area_struct *vma) { int ret; @@ -3616,13 +2944,6 @@ err_bad_arg: return ret; } -void binder_alloc_init(struct binder_alloc *alloc) -{ - alloc->tsk = current->group_leader; - alloc->pid = current->group_leader->pid; - mutex_init(&alloc->mutex); -} - static int binder_open(struct inode *nodp, struct file *filp) { struct binder_proc *proc; @@ -3758,55 +3079,6 @@ static int binder_node_release(struct binder_node *node, int refs) return refs; } -void binder_alloc_deferred_release(struct binder_alloc *alloc) -{ - struct rb_node *n; - int buffers, page_count; - - BUG_ON(alloc->vma); - - buffers = 0; - mutex_lock(&alloc->mutex); - while ((n = rb_first(&alloc->allocated_buffers))) { - struct binder_buffer *buffer; - - buffer = rb_entry(n, struct binder_buffer, rb_node); - - /* Transaction should already have been freed */ - BUG_ON(buffer->transaction); - - binder_free_buf_locked(alloc, buffer); - buffers++; - } - - page_count = 0; - if (alloc->pages) { - int i; - - for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) { - void *page_addr; - - if (!alloc->pages[i]) - continue; - - page_addr = alloc->buffer + i * PAGE_SIZE; - binder_alloc_debug(BINDER_ALLOC_DEBUG_BUFFER_ALLOC, - "%s: %d: page %d at %pK not freed\n", - __func__, alloc->pid, i, page_addr); - unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE); - __free_page(alloc->pages[i]); - page_count++; - } - kfree(alloc->pages); - vfree(alloc->buffer); - } - mutex_unlock(&alloc->mutex); - - binder_alloc_debug(BINDER_ALLOC_DEBUG_OPEN_CLOSE, - "%s: %d buffers %d, pages %d\n", - __func__, alloc->pid, buffers, page_count); -} - static void binder_deferred_release(struct binder_proc *proc) { struct binder_context *context = proc->context; @@ -4051,27 +3323,6 @@ static void print_binder_ref(struct seq_file *m, struct binder_ref *ref) ref->node->debug_id, ref->strong, ref->weak, ref->death); } -static void print_binder_buffer(struct seq_file *m, const char *prefix, - struct binder_buffer *buffer) -{ - seq_printf(m, "%s %d: %pK size %zd:%zd %s\n", - prefix, buffer->debug_id, buffer->data, - buffer->data_size, buffer->offsets_size, - buffer->transaction ? "active" : "delivered"); -} - -void binder_alloc_print_allocated(struct seq_file *m, - struct binder_alloc *alloc) -{ - struct rb_node *n; - - mutex_lock(&alloc->mutex); - for (n = rb_first(&alloc->allocated_buffers); n != NULL; n = rb_next(n)) - print_binder_buffer(m, " buffer", - rb_entry(n, struct binder_buffer, rb_node)); - mutex_unlock(&alloc->mutex); -} - static void print_binder_proc(struct seq_file *m, struct binder_proc *proc, int print_all) { @@ -4198,18 +3449,6 @@ static void print_binder_stats(struct seq_file *m, const char *prefix, } } -int binder_alloc_get_allocated_count(struct binder_alloc *alloc) -{ - struct rb_node *n; - int count = 0; - - mutex_lock(&alloc->mutex); - for (n = rb_first(&alloc->allocated_buffers); n != NULL; n = rb_next(n)) - count++; - mutex_unlock(&alloc->mutex); - return count; -} - static void print_binder_proc_stats(struct seq_file *m, struct binder_proc *proc) { diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c new file mode 100644 index 000000000000..198d04c5d958 --- /dev/null +++ b/drivers/android/binder_alloc.c @@ -0,0 +1,759 @@ +/* binder_alloc.c + * + * Android IPC Subsystem + * + * Copyright (C) 2007-2017 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "binder_alloc.h" +#include "binder_trace.h" + +static DEFINE_MUTEX(binder_alloc_mmap_lock); + +enum { + BINDER_DEBUG_OPEN_CLOSE = 1U << 1, + BINDER_DEBUG_BUFFER_ALLOC = 1U << 2, + BINDER_DEBUG_BUFFER_ALLOC_ASYNC = 1U << 3, +}; +static uint32_t binder_alloc_debug_mask; + +module_param_named(debug_mask, binder_alloc_debug_mask, + uint, 0644); + +#define binder_alloc_debug(mask, x...) \ + do { \ + if (binder_alloc_debug_mask & mask) \ + pr_info(x); \ + } while (0) + +static size_t binder_alloc_buffer_size(struct binder_alloc *alloc, + struct binder_buffer *buffer) +{ + if (list_is_last(&buffer->entry, &alloc->buffers)) + return alloc->buffer + + alloc->buffer_size - (void *)buffer->data; + return (size_t)list_entry(buffer->entry.next, + struct binder_buffer, entry) - (size_t)buffer->data; +} + +static void binder_insert_free_buffer(struct binder_alloc *alloc, + struct binder_buffer *new_buffer) +{ + struct rb_node **p = &alloc->free_buffers.rb_node; + struct rb_node *parent = NULL; + struct binder_buffer *buffer; + size_t buffer_size; + size_t new_buffer_size; + + BUG_ON(!new_buffer->free); + + new_buffer_size = binder_alloc_buffer_size(alloc, new_buffer); + + binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, + "%d: add free buffer, size %zd, at %pK\n", + alloc->pid, new_buffer_size, new_buffer); + + while (*p) { + parent = *p; + buffer = rb_entry(parent, struct binder_buffer, rb_node); + BUG_ON(!buffer->free); + + buffer_size = binder_alloc_buffer_size(alloc, buffer); + + if (new_buffer_size < buffer_size) + p = &parent->rb_left; + else + p = &parent->rb_right; + } + rb_link_node(&new_buffer->rb_node, parent, p); + rb_insert_color(&new_buffer->rb_node, &alloc->free_buffers); +} + +static void binder_insert_allocated_buffer_locked( + struct binder_alloc *alloc, struct binder_buffer *new_buffer) +{ + struct rb_node **p = &alloc->allocated_buffers.rb_node; + struct rb_node *parent = NULL; + struct binder_buffer *buffer; + + BUG_ON(new_buffer->free); + + while (*p) { + parent = *p; + buffer = rb_entry(parent, struct binder_buffer, rb_node); + BUG_ON(buffer->free); + + if (new_buffer < buffer) + p = &parent->rb_left; + else if (new_buffer > buffer) + p = &parent->rb_right; + else + BUG(); + } + rb_link_node(&new_buffer->rb_node, parent, p); + rb_insert_color(&new_buffer->rb_node, &alloc->allocated_buffers); +} + +static struct binder_buffer *binder_alloc_buffer_lookup_locked( + struct binder_alloc *alloc, + uintptr_t user_ptr) +{ + struct rb_node *n = alloc->allocated_buffers.rb_node; + struct binder_buffer *buffer; + struct binder_buffer *kern_ptr; + + kern_ptr = (struct binder_buffer *)(user_ptr - alloc->user_buffer_offset + - offsetof(struct binder_buffer, data)); + + while (n) { + buffer = rb_entry(n, struct binder_buffer, rb_node); + BUG_ON(buffer->free); + + if (kern_ptr < buffer) + n = n->rb_left; + else if (kern_ptr > buffer) + n = n->rb_right; + else + return buffer; + } + return NULL; +} + +/** + * binder_alloc_buffer_lookup() - get buffer given user ptr + * @alloc: binder_alloc for this proc + * @user_ptr: User pointer to buffer data + * + * Validate userspace pointer to buffer data and return buffer corresponding to + * that user pointer. Search the rb tree for buffer that matches user data + * pointer. + * + * Return: Pointer to buffer or NULL + */ +struct binder_buffer *binder_alloc_buffer_lookup(struct binder_alloc *alloc, + uintptr_t user_ptr) +{ + struct binder_buffer *buffer; + + mutex_lock(&alloc->mutex); + buffer = binder_alloc_buffer_lookup_locked(alloc, user_ptr); + mutex_unlock(&alloc->mutex); + return buffer; +} + +static int binder_update_page_range(struct binder_alloc *alloc, int allocate, + void *start, void *end, + struct vm_area_struct *vma) +{ + void *page_addr; + unsigned long user_page_addr; + struct page **page; + struct mm_struct *mm; + + binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, + "%d: %s pages %pK-%pK\n", alloc->pid, + allocate ? "allocate" : "free", start, end); + + if (end <= start) + return 0; + + trace_binder_update_page_range(alloc, allocate, start, end); + + if (vma) + mm = NULL; + else + mm = get_task_mm(alloc->tsk); + + if (mm) { + down_write(&mm->mmap_sem); + vma = alloc->vma; + if (vma && mm != alloc->vma_vm_mm) { + pr_err("%d: vma mm and task mm mismatch\n", + alloc->pid); + vma = NULL; + } + } + + if (allocate == 0) + goto free_range; + + if (vma == NULL) { + pr_err("%d: binder_alloc_buf failed to map pages in userspace, no vma\n", + alloc->pid); + goto err_no_vma; + } + + for (page_addr = start; page_addr < end; page_addr += PAGE_SIZE) { + int ret; + + page = &alloc->pages[(page_addr - alloc->buffer) / PAGE_SIZE]; + + BUG_ON(*page); + *page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO); + if (*page == NULL) { + pr_err("%d: binder_alloc_buf failed for page at %pK\n", + alloc->pid, page_addr); + goto err_alloc_page_failed; + } + ret = map_kernel_range_noflush((unsigned long)page_addr, + PAGE_SIZE, PAGE_KERNEL, page); + flush_cache_vmap((unsigned long)page_addr, + (unsigned long)page_addr + PAGE_SIZE); + if (ret != 1) { + pr_err("%d: binder_alloc_buf failed to map page at %pK in kernel\n", + alloc->pid, page_addr); + goto err_map_kernel_failed; + } + user_page_addr = + (uintptr_t)page_addr + alloc->user_buffer_offset; + ret = vm_insert_page(vma, user_page_addr, page[0]); + if (ret) { + pr_err("%d: binder_alloc_buf failed to map page at %lx in userspace\n", + alloc->pid, user_page_addr); + goto err_vm_insert_page_failed; + } + /* vm_insert_page does not seem to increment the refcount */ + } + if (mm) { + up_write(&mm->mmap_sem); + mmput(mm); + } + return 0; + +free_range: + for (page_addr = end - PAGE_SIZE; page_addr >= start; + page_addr -= PAGE_SIZE) { + page = &alloc->pages[(page_addr - alloc->buffer) / PAGE_SIZE]; + if (vma) + zap_page_range(vma, (uintptr_t)page_addr + + alloc->user_buffer_offset, PAGE_SIZE); +err_vm_insert_page_failed: + unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE); +err_map_kernel_failed: + __free_page(*page); + *page = NULL; +err_alloc_page_failed: + ; + } +err_no_vma: + if (mm) { + up_write(&mm->mmap_sem); + mmput(mm); + } + return -ENOMEM; +} + +struct binder_buffer *binder_alloc_new_buf_locked(struct binder_alloc *alloc, + size_t data_size, + size_t offsets_size, + size_t extra_buffers_size, + int is_async) +{ + struct rb_node *n = alloc->free_buffers.rb_node; + struct binder_buffer *buffer; + size_t buffer_size; + struct rb_node *best_fit = NULL; + void *has_page_addr; + void *end_page_addr; + size_t size, data_offsets_size; + + if (alloc->vma == NULL) { + pr_err("%d: binder_alloc_buf, no vma\n", + alloc->pid); + return NULL; + } + + data_offsets_size = ALIGN(data_size, sizeof(void *)) + + ALIGN(offsets_size, sizeof(void *)); + + if (data_offsets_size < data_size || data_offsets_size < offsets_size) { + binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, + "%d: got transaction with invalid size %zd-%zd\n", + alloc->pid, data_size, offsets_size); + return NULL; + } + size = data_offsets_size + ALIGN(extra_buffers_size, sizeof(void *)); + if (size < data_offsets_size || size < extra_buffers_size) { + binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, + "%d: got transaction with invalid extra_buffers_size %zd\n", + alloc->pid, extra_buffers_size); + return NULL; + } + if (is_async && + alloc->free_async_space < size + sizeof(struct binder_buffer)) { + binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, + "%d: binder_alloc_buf size %zd failed, no async space left\n", + alloc->pid, size); + return NULL; + } + + while (n) { + buffer = rb_entry(n, struct binder_buffer, rb_node); + BUG_ON(!buffer->free); + buffer_size = binder_alloc_buffer_size(alloc, buffer); + + if (size < buffer_size) { + best_fit = n; + n = n->rb_left; + } else if (size > buffer_size) + n = n->rb_right; + else { + best_fit = n; + break; + } + } + if (best_fit == NULL) { + pr_err("%d: binder_alloc_buf size %zd failed, no address space\n", + alloc->pid, size); + return NULL; + } + if (n == NULL) { + buffer = rb_entry(best_fit, struct binder_buffer, rb_node); + buffer_size = binder_alloc_buffer_size(alloc, buffer); + } + + binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, + "%d: binder_alloc_buf size %zd got buffer %pK size %zd\n", + alloc->pid, size, buffer, buffer_size); + + has_page_addr = + (void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK); + if (n == NULL) { + if (size + sizeof(struct binder_buffer) + 4 >= buffer_size) + buffer_size = size; /* no room for other buffers */ + else + buffer_size = size + sizeof(struct binder_buffer); + } + end_page_addr = + (void *)PAGE_ALIGN((uintptr_t)buffer->data + buffer_size); + if (end_page_addr > has_page_addr) + end_page_addr = has_page_addr; + if (binder_update_page_range(alloc, 1, + (void *)PAGE_ALIGN((uintptr_t)buffer->data), end_page_addr, NULL)) + return NULL; + + rb_erase(best_fit, &alloc->free_buffers); + buffer->free = 0; + binder_insert_allocated_buffer_locked(alloc, buffer); + if (buffer_size != size) { + struct binder_buffer *new_buffer = (void *)buffer->data + size; + + list_add(&new_buffer->entry, &buffer->entry); + new_buffer->free = 1; + binder_insert_free_buffer(alloc, new_buffer); + } + binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, + "%d: binder_alloc_buf size %zd got %pK\n", + alloc->pid, size, buffer); + buffer->data_size = data_size; + buffer->offsets_size = offsets_size; + buffer->async_transaction = is_async; + buffer->extra_buffers_size = extra_buffers_size; + if (is_async) { + alloc->free_async_space -= size + sizeof(struct binder_buffer); + binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC, + "%d: binder_alloc_buf size %zd async free %zd\n", + alloc->pid, size, alloc->free_async_space); + } + return buffer; +} + +/** + * binder_alloc_new_buf() - Allocate a new binder buffer + * @alloc: binder_alloc for this proc + * @data_size: size of user data buffer + * @offsets_size: user specified buffer offset + * @extra_buffers_size: size of extra space for meta-data (eg, security context) + * @is_async: buffer for async transaction + * + * Allocate a new buffer given the requested sizes. Returns + * the kernel version of the buffer pointer. The size allocated + * is the sum of the three given sizes (each rounded up to + * pointer-sized boundary) + * + * Return: The allocated buffer or %NULL if error + */ +struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc, + size_t data_size, + size_t offsets_size, + size_t extra_buffers_size, + int is_async) +{ + struct binder_buffer *buffer; + + mutex_lock(&alloc->mutex); + buffer = binder_alloc_new_buf_locked(alloc, data_size, offsets_size, + extra_buffers_size, is_async); + mutex_unlock(&alloc->mutex); + return buffer; +} + +static void *buffer_start_page(struct binder_buffer *buffer) +{ + return (void *)((uintptr_t)buffer & PAGE_MASK); +} + +static void *buffer_end_page(struct binder_buffer *buffer) +{ + return (void *)(((uintptr_t)(buffer + 1) - 1) & PAGE_MASK); +} + +static void binder_delete_free_buffer(struct binder_alloc *alloc, + struct binder_buffer *buffer) +{ + struct binder_buffer *prev, *next = NULL; + int free_page_end = 1; + int free_page_start = 1; + + BUG_ON(alloc->buffers.next == &buffer->entry); + prev = list_entry(buffer->entry.prev, struct binder_buffer, entry); + BUG_ON(!prev->free); + if (buffer_end_page(prev) == buffer_start_page(buffer)) { + free_page_start = 0; + if (buffer_end_page(prev) == buffer_end_page(buffer)) + free_page_end = 0; + binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, + "%d: merge free, buffer %pK share page with %pK\n", + alloc->pid, buffer, prev); + } + + if (!list_is_last(&buffer->entry, &alloc->buffers)) { + next = list_entry(buffer->entry.next, + struct binder_buffer, entry); + if (buffer_start_page(next) == buffer_end_page(buffer)) { + free_page_end = 0; + if (buffer_start_page(next) == + buffer_start_page(buffer)) + free_page_start = 0; + binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, + "%d: merge free, buffer %pK share page with %pK\n", + alloc->pid, buffer, prev); + } + } + list_del(&buffer->entry); + if (free_page_start || free_page_end) { + binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, + "%d: merge free, buffer %pK do not share page%s%s with %pK or %pK\n", + alloc->pid, buffer, free_page_start ? "" : " end", + free_page_end ? "" : " start", prev, next); + binder_update_page_range(alloc, 0, free_page_start ? + buffer_start_page(buffer) : buffer_end_page(buffer), + (free_page_end ? buffer_end_page(buffer) : + buffer_start_page(buffer)) + PAGE_SIZE, NULL); + } +} + +static void binder_free_buf_locked(struct binder_alloc *alloc, + struct binder_buffer *buffer) +{ + size_t size, buffer_size; + + buffer_size = binder_alloc_buffer_size(alloc, buffer); + + size = ALIGN(buffer->data_size, sizeof(void *)) + + ALIGN(buffer->offsets_size, sizeof(void *)) + + ALIGN(buffer->extra_buffers_size, sizeof(void *)); + + binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, + "%d: binder_free_buf %pK size %zd buffer_size %zd\n", + alloc->pid, buffer, size, buffer_size); + + BUG_ON(buffer->free); + BUG_ON(size > buffer_size); + BUG_ON(buffer->transaction != NULL); + BUG_ON((void *)buffer < alloc->buffer); + BUG_ON((void *)buffer > alloc->buffer + alloc->buffer_size); + + if (buffer->async_transaction) { + alloc->free_async_space += size + sizeof(struct binder_buffer); + + binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC, + "%d: binder_free_buf size %zd async free %zd\n", + alloc->pid, size, alloc->free_async_space); + } + + binder_update_page_range(alloc, 0, + (void *)PAGE_ALIGN((uintptr_t)buffer->data), + (void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK), + NULL); + + rb_erase(&buffer->rb_node, &alloc->allocated_buffers); + buffer->free = 1; + if (!list_is_last(&buffer->entry, &alloc->buffers)) { + struct binder_buffer *next = list_entry(buffer->entry.next, + struct binder_buffer, entry); + + if (next->free) { + rb_erase(&next->rb_node, &alloc->free_buffers); + binder_delete_free_buffer(alloc, next); + } + } + if (alloc->buffers.next != &buffer->entry) { + struct binder_buffer *prev = list_entry(buffer->entry.prev, + struct binder_buffer, entry); + + if (prev->free) { + binder_delete_free_buffer(alloc, buffer); + rb_erase(&prev->rb_node, &alloc->free_buffers); + buffer = prev; + } + } + binder_insert_free_buffer(alloc, buffer); +} + +/** + * binder_alloc_free_buf() - free a binder buffer + * @alloc: binder_alloc for this proc + * @buffer: kernel pointer to buffer + * + * Free the buffer allocated via binder_alloc_new_buffer() + */ +void binder_alloc_free_buf(struct binder_alloc *alloc, + struct binder_buffer *buffer) +{ + mutex_lock(&alloc->mutex); + binder_free_buf_locked(alloc, buffer); + mutex_unlock(&alloc->mutex); +} + +/** + * binder_alloc_mmap_handler() - map virtual address space for proc + * @alloc: alloc structure for this proc + * @vma: vma passed to mmap() + * + * Called by binder_mmap() to initialize the space specified in + * vma for allocating binder buffers + * + * Return: + * 0 = success + * -EBUSY = address space already mapped + * -ENOMEM = failed to map memory to given address space + */ +int binder_alloc_mmap_handler(struct binder_alloc *alloc, + struct vm_area_struct *vma) +{ + int ret; + struct vm_struct *area; + const char *failure_string; + struct binder_buffer *buffer; + + mutex_lock(&binder_alloc_mmap_lock); + if (alloc->buffer) { + ret = -EBUSY; + failure_string = "already mapped"; + goto err_already_mapped; + } + + area = get_vm_area(vma->vm_end - vma->vm_start, VM_IOREMAP); + if (area == NULL) { + ret = -ENOMEM; + failure_string = "get_vm_area"; + goto err_get_vm_area_failed; + } + alloc->buffer = area->addr; + alloc->user_buffer_offset = + vma->vm_start - (uintptr_t)alloc->buffer; + mutex_unlock(&binder_alloc_mmap_lock); + +#ifdef CONFIG_CPU_CACHE_VIPT + if (cache_is_vipt_aliasing()) { + while (CACHE_COLOUR( + (vma->vm_start ^ (uint32_t)alloc->buffer))) { + pr_info("%s: %d %lx-%lx maps %pK bad alignment\n", + __func__, alloc->pid, vma->vm_start, + vma->vm_end, alloc->buffer); + vma->vm_start += PAGE_SIZE; + } + } +#endif + alloc->pages = kzalloc(sizeof(alloc->pages[0]) * + ((vma->vm_end - vma->vm_start) / PAGE_SIZE), + GFP_KERNEL); + if (alloc->pages == NULL) { + ret = -ENOMEM; + failure_string = "alloc page array"; + goto err_alloc_pages_failed; + } + alloc->buffer_size = vma->vm_end - vma->vm_start; + + if (binder_update_page_range(alloc, 1, alloc->buffer, + alloc->buffer + PAGE_SIZE, vma)) { + ret = -ENOMEM; + failure_string = "alloc small buf"; + goto err_alloc_small_buf_failed; + } + buffer = alloc->buffer; + INIT_LIST_HEAD(&alloc->buffers); + list_add(&buffer->entry, &alloc->buffers); + buffer->free = 1; + binder_insert_free_buffer(alloc, buffer); + alloc->free_async_space = alloc->buffer_size / 2; + barrier(); + alloc->vma = vma; + alloc->vma_vm_mm = vma->vm_mm; + + return 0; + +err_alloc_small_buf_failed: + kfree(alloc->pages); + alloc->pages = NULL; +err_alloc_pages_failed: + mutex_lock(&binder_alloc_mmap_lock); + vfree(alloc->buffer); + alloc->buffer = NULL; +err_get_vm_area_failed: +err_already_mapped: + mutex_unlock(&binder_alloc_mmap_lock); + pr_err("%s: %d %lx-%lx %s failed %d\n", __func__, + alloc->pid, vma->vm_start, vma->vm_end, failure_string, ret); + return ret; +} + + +void binder_alloc_deferred_release(struct binder_alloc *alloc) +{ + struct rb_node *n; + int buffers, page_count; + + BUG_ON(alloc->vma); + + buffers = 0; + mutex_lock(&alloc->mutex); + while ((n = rb_first(&alloc->allocated_buffers))) { + struct binder_buffer *buffer; + + buffer = rb_entry(n, struct binder_buffer, rb_node); + + /* Transaction should already have been freed */ + BUG_ON(buffer->transaction); + + binder_free_buf_locked(alloc, buffer); + buffers++; + } + + page_count = 0; + if (alloc->pages) { + int i; + + for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) { + void *page_addr; + + if (!alloc->pages[i]) + continue; + + page_addr = alloc->buffer + i * PAGE_SIZE; + binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, + "%s: %d: page %d at %pK not freed\n", + __func__, alloc->pid, i, page_addr); + unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE); + __free_page(alloc->pages[i]); + page_count++; + } + kfree(alloc->pages); + vfree(alloc->buffer); + } + mutex_unlock(&alloc->mutex); + + binder_alloc_debug(BINDER_DEBUG_OPEN_CLOSE, + "%s: %d buffers %d, pages %d\n", + __func__, alloc->pid, buffers, page_count); +} + +static void print_binder_buffer(struct seq_file *m, const char *prefix, + struct binder_buffer *buffer) +{ + seq_printf(m, "%s %d: %pK size %zd:%zd %s\n", + prefix, buffer->debug_id, buffer->data, + buffer->data_size, buffer->offsets_size, + buffer->transaction ? "active" : "delivered"); +} + +/** + * binder_alloc_print_allocated() - print buffer info + * @m: seq_file for output via seq_printf() + * @alloc: binder_alloc for this proc + * + * Prints information about every buffer associated with + * the binder_alloc state to the given seq_file + */ +void binder_alloc_print_allocated(struct seq_file *m, + struct binder_alloc *alloc) +{ + struct rb_node *n; + + mutex_lock(&alloc->mutex); + for (n = rb_first(&alloc->allocated_buffers); n != NULL; n = rb_next(n)) + print_binder_buffer(m, " buffer", + rb_entry(n, struct binder_buffer, rb_node)); + mutex_unlock(&alloc->mutex); +} + +/** + * binder_alloc_get_allocated_count() - return count of buffers + * @alloc: binder_alloc for this proc + * + * Return: count of allocated buffers + */ +int binder_alloc_get_allocated_count(struct binder_alloc *alloc) +{ + struct rb_node *n; + int count = 0; + + mutex_lock(&alloc->mutex); + for (n = rb_first(&alloc->allocated_buffers); n != NULL; n = rb_next(n)) + count++; + mutex_unlock(&alloc->mutex); + return count; +} + + +/** + * binder_alloc_vma_close() - invalidate address space + * @alloc: binder_alloc for this proc + * + * Called from binder_vma_close() when releasing address space. + * Clears alloc->vma to prevent new incoming transactions from + * allocating more buffers. + */ +void binder_alloc_vma_close(struct binder_alloc *alloc) +{ + WRITE_ONCE(alloc->vma, NULL); + WRITE_ONCE(alloc->vma_vm_mm, NULL); +} + +/** + * binder_alloc_init() - called by binder_open() for per-proc initialization + * @alloc: binder_alloc for this proc + * + * Called from binder_open() to initialize binder_alloc fields for + * new binder proc + */ +void binder_alloc_init(struct binder_alloc *alloc) +{ + alloc->tsk = current->group_leader; + alloc->pid = current->group_leader->pid; + mutex_init(&alloc->mutex); +} + diff --git a/drivers/android/binder_alloc.h b/drivers/android/binder_alloc.h new file mode 100644 index 000000000000..721c511431f9 --- /dev/null +++ b/drivers/android/binder_alloc.h @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2017 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#ifndef _LINUX_BINDER_ALLOC_H +#define _LINUX_BINDER_ALLOC_H + +#include +#include +#include +#include +#include +#include + +struct binder_transaction; + +/** + * struct binder_buffer - buffer used for binder transactions + * @entry: entry alloc->buffers + * @rb_node: node for allocated_buffers/free_buffers rb trees + * @free: true if buffer is free + * @allow_user_free: describe the second member of struct blah, + * @async_transaction: describe the second member of struct blah, + * @debug_id: describe the second member of struct blah, + * @transaction: describe the second member of struct blah, + * @target_node: describe the second member of struct blah, + * @data_size: describe the second member of struct blah, + * @offsets_size: describe the second member of struct blah, + * @extra_buffers_size: describe the second member of struct blah, + * @data:i describe the second member of struct blah, + * + * Bookkeeping structure for binder transaction buffers + */ +struct binder_buffer { + struct list_head entry; /* free and allocated entries by address */ + struct rb_node rb_node; /* free entry by size or allocated entry */ + /* by address */ + unsigned free:1; + unsigned allow_user_free:1; + unsigned async_transaction:1; + unsigned debug_id:29; + + struct binder_transaction *transaction; + + struct binder_node *target_node; + size_t data_size; + size_t offsets_size; + size_t extra_buffers_size; + uint8_t data[0]; +}; + +/** + * struct binder_alloc - per-binder proc state for binder allocator + * @vma: vm_area_struct passed to mmap_handler + * (invarient after mmap) + * @tsk: tid for task that called init for this proc + * (invariant after init) + * @vma_vm_mm: copy of vma->vm_mm (invarient after mmap) + * @buffer: base of per-proc address space mapped via mmap + * @user_buffer_offset: offset between user and kernel VAs for buffer + * @buffers: list of all buffers for this proc + * @free_buffers: rb tree of buffers available for allocation + * sorted by size + * @allocated_buffers: rb tree of allocated buffers sorted by address + * @free_async_space: VA space available for async buffers. This is + * initialized at mmap time to 1/2 the full VA space + * @pages: array of physical page addresses for each + * page of mmap'd space + * @buffer_size: size of address space specified via mmap + * @pid: pid for associated binder_proc (invariant after init) + * + * Bookkeeping structure for per-proc address space management for binder + * buffers. It is normally initialized during binder_init() and binder_mmap() + * calls. The address space is used for both user-visible buffers and for + * struct binder_buffer objects used to track the user buffers + */ +struct binder_alloc { + struct mutex mutex; + struct task_struct *tsk; + struct vm_area_struct *vma; + struct mm_struct *vma_vm_mm; + void *buffer; + ptrdiff_t user_buffer_offset; + struct list_head buffers; + struct rb_root free_buffers; + struct rb_root allocated_buffers; + size_t free_async_space; + struct page **pages; + size_t buffer_size; + uint32_t buffer_free; + int pid; +}; + +extern struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc, + size_t data_size, + size_t offsets_size, + size_t extra_buffers_size, + int is_async); +extern void binder_alloc_init(struct binder_alloc *alloc); +extern void binder_alloc_vma_close(struct binder_alloc *alloc); +extern struct binder_buffer * +binder_alloc_buffer_lookup(struct binder_alloc *alloc, + uintptr_t user_ptr); +extern void binder_alloc_free_buf(struct binder_alloc *alloc, + struct binder_buffer *buffer); +extern int binder_alloc_mmap_handler(struct binder_alloc *alloc, + struct vm_area_struct *vma); +extern void binder_alloc_deferred_release(struct binder_alloc *alloc); +extern int binder_alloc_get_allocated_count(struct binder_alloc *alloc); +extern void binder_alloc_print_allocated(struct seq_file *m, + struct binder_alloc *alloc); + +/** + * binder_alloc_get_free_async_space() - get free space available for async + * @alloc: binder_alloc for this proc + * + * Return: the bytes remaining in the address-space for async transactions + */ +static inline size_t +binder_alloc_get_free_async_space(struct binder_alloc *alloc) +{ + size_t free_async_space; + + mutex_lock(&alloc->mutex); + free_async_space = alloc->free_async_space; + mutex_unlock(&alloc->mutex); + return free_async_space; +} + +/** + * binder_alloc_get_user_buffer_offset() - get offset between kernel/user addrs + * @alloc: binder_alloc for this proc + * + * Return: the offset between kernel and user-space addresses to use for + * virtual address conversion + */ +static inline ptrdiff_t +binder_alloc_get_user_buffer_offset(struct binder_alloc *alloc) +{ + /* + * user_buffer_offset is constant if vma is set and + * undefined if vma is not set. It is possible to + * get here with !alloc->vma if the target process + * is dying while a transaction is being initiated. + * Returning the old value is ok in this case and + * the transaction will fail. + */ + return alloc->user_buffer_offset; +} + +#endif /* _LINUX_BINDER_ALLOC_H */ + -- cgit v1.2.3 From 1cf29cf4295ad2dc2009b421702ba4197b85acfd Mon Sep 17 00:00:00 2001 From: Todd Kjos Date: Thu, 29 Jun 2017 12:01:42 -0700 Subject: binder: remove binder_debug_no_lock mechanism With the global lock, there was a mechanism to access binder driver debugging information with the global lock disabled to debug deadlocks or other issues. This mechanism is rarely (if ever) used anymore and wasn't needed during the development of fine-grained locking in the binder driver. Removing it. Signed-off-by: Todd Kjos Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 31 ++++++++----------------------- 1 file changed, 8 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 0512971cfc53..10fda7ab9fa5 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -107,9 +107,6 @@ static uint32_t binder_debug_mask = BINDER_DEBUG_USER_ERROR | BINDER_DEBUG_FAILED_TRANSACTION | BINDER_DEBUG_DEAD_TRANSACTION; module_param_named(debug_mask, binder_debug_mask, uint, S_IWUSR | S_IRUGO); -static bool binder_debug_no_lock; -module_param_named(proc_no_lock, binder_debug_no_lock, bool, S_IWUSR | S_IRUGO); - static char *binder_devices_param = CONFIG_ANDROID_BINDER_DEVICES; module_param_named(devices, binder_devices_param, charp, 0444); @@ -3507,10 +3504,8 @@ static int binder_state_show(struct seq_file *m, void *unused) { struct binder_proc *proc; struct binder_node *node; - int do_lock = !binder_debug_no_lock; - if (do_lock) - binder_lock(__func__); + binder_lock(__func__); seq_puts(m, "binder state:\n"); @@ -3521,18 +3516,15 @@ static int binder_state_show(struct seq_file *m, void *unused) hlist_for_each_entry(proc, &binder_procs, proc_node) print_binder_proc(m, proc, 1); - if (do_lock) - binder_unlock(__func__); + binder_unlock(__func__); return 0; } static int binder_stats_show(struct seq_file *m, void *unused) { struct binder_proc *proc; - int do_lock = !binder_debug_no_lock; - if (do_lock) - binder_lock(__func__); + binder_lock(__func__); seq_puts(m, "binder stats:\n"); @@ -3540,24 +3532,20 @@ static int binder_stats_show(struct seq_file *m, void *unused) hlist_for_each_entry(proc, &binder_procs, proc_node) print_binder_proc_stats(m, proc); - if (do_lock) - binder_unlock(__func__); + binder_unlock(__func__); return 0; } static int binder_transactions_show(struct seq_file *m, void *unused) { struct binder_proc *proc; - int do_lock = !binder_debug_no_lock; - if (do_lock) - binder_lock(__func__); + binder_lock(__func__); seq_puts(m, "binder transactions:\n"); hlist_for_each_entry(proc, &binder_procs, proc_node) print_binder_proc(m, proc, 0); - if (do_lock) - binder_unlock(__func__); + binder_unlock(__func__); return 0; } @@ -3565,10 +3553,8 @@ static int binder_proc_show(struct seq_file *m, void *unused) { struct binder_proc *itr; int pid = (unsigned long)m->private; - int do_lock = !binder_debug_no_lock; - if (do_lock) - binder_lock(__func__); + binder_lock(__func__); hlist_for_each_entry(itr, &binder_procs, proc_node) { if (itr->pid == pid) { @@ -3576,8 +3562,7 @@ static int binder_proc_show(struct seq_file *m, void *unused) print_binder_proc(m, itr, 1); } } - if (do_lock) - binder_unlock(__func__); + binder_unlock(__func__); return 0; } -- cgit v1.2.3 From c44b1231ff1170971c1f27fc33a8cc3188de99cb Mon Sep 17 00:00:00 2001 From: Todd Kjos Date: Thu, 29 Jun 2017 12:01:43 -0700 Subject: binder: add protection for non-perf cases Add binder_dead_nodes_lock, binder_procs_lock, and binder_context_mgr_node_lock to protect the associated global lists Signed-off-by: Todd Kjos Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 81 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 63 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 10fda7ab9fa5..fb484c6acd3e 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -46,12 +46,16 @@ #include "binder_trace.h" static DEFINE_MUTEX(binder_main_lock); + +static HLIST_HEAD(binder_deferred_list); static DEFINE_MUTEX(binder_deferred_lock); static HLIST_HEAD(binder_devices); static HLIST_HEAD(binder_procs); -static HLIST_HEAD(binder_deferred_list); +static DEFINE_MUTEX(binder_procs_lock); + static HLIST_HEAD(binder_dead_nodes); +static DEFINE_SPINLOCK(binder_dead_nodes_lock); static struct dentry *binder_debugfs_dir_entry_root; static struct dentry *binder_debugfs_dir_entry_proc; @@ -219,6 +223,8 @@ static struct binder_transaction_log_entry *binder_transaction_log_add( struct binder_context { struct binder_node *binder_context_mgr_node; + struct mutex context_mgr_node_lock; + kuid_t binder_context_mgr_uid; const char *name; }; @@ -570,7 +576,9 @@ static int binder_dec_node(struct binder_node *node, int strong, int internal) "refless node %d deleted\n", node->debug_id); } else { + spin_lock(&binder_dead_nodes_lock); hlist_del(&node->dead_node); + spin_unlock(&binder_dead_nodes_lock); binder_debug(BINDER_DEBUG_INTERNAL_REFS, "dead node %d deleted\n", node->debug_id); @@ -1454,11 +1462,14 @@ static void binder_transaction(struct binder_proc *proc, } target_node = ref->node; } else { + mutex_lock(&context->context_mgr_node_lock); target_node = context->binder_context_mgr_node; if (target_node == NULL) { return_error = BR_DEAD_REPLY; + mutex_unlock(&context->context_mgr_node_lock); goto err_no_context_mgr_node; } + mutex_unlock(&context->context_mgr_node_lock); } e->to_node = target_node->debug_id; target_proc = target_node->proc; @@ -1824,22 +1835,31 @@ static int binder_thread_write(struct binder_proc *proc, case BC_RELEASE: case BC_DECREFS: { uint32_t target; - struct binder_ref *ref; + struct binder_ref *ref = NULL; const char *debug_string; if (get_user(target, (uint32_t __user *)ptr)) return -EFAULT; + ptr += sizeof(uint32_t); - if (target == 0 && context->binder_context_mgr_node && + if (target == 0 && (cmd == BC_INCREFS || cmd == BC_ACQUIRE)) { - ref = binder_get_ref_for_node(proc, - context->binder_context_mgr_node); - if (ref->desc != target) { - binder_user_error("%d:%d tried to acquire reference to desc 0, got %d instead\n", - proc->pid, thread->pid, - ref->desc); + struct binder_node *ctx_mgr_node; + + mutex_lock(&context->context_mgr_node_lock); + ctx_mgr_node = context->binder_context_mgr_node; + if (ctx_mgr_node) { + ref = binder_get_ref_for_node(proc, + ctx_mgr_node); + if (ref && ref->desc != target) { + binder_user_error("%d:%d tried to acquire reference to desc 0, got %d instead\n", + proc->pid, thread->pid, + ref->desc); + } } - } else + mutex_unlock(&context->context_mgr_node_lock); + } + if (ref == NULL) ref = binder_get_ref(proc, target, cmd == BC_ACQUIRE || cmd == BC_RELEASE); @@ -2753,9 +2773,10 @@ static int binder_ioctl_set_ctx_mgr(struct file *filp) int ret = 0; struct binder_proc *proc = filp->private_data; struct binder_context *context = proc->context; - + struct binder_node *new_node; kuid_t curr_euid = current_euid(); + mutex_lock(&context->context_mgr_node_lock); if (context->binder_context_mgr_node) { pr_err("BINDER_SET_CONTEXT_MGR already set\n"); ret = -EBUSY; @@ -2776,16 +2797,18 @@ static int binder_ioctl_set_ctx_mgr(struct file *filp) } else { context->binder_context_mgr_uid = curr_euid; } - context->binder_context_mgr_node = binder_new_node(proc, 0, 0); - if (!context->binder_context_mgr_node) { + new_node = binder_new_node(proc, 0, 0); + if (!new_node) { ret = -ENOMEM; goto out; } - context->binder_context_mgr_node->local_weak_refs++; - context->binder_context_mgr_node->local_strong_refs++; - context->binder_context_mgr_node->has_strong_ref = 1; - context->binder_context_mgr_node->has_weak_ref = 1; + new_node->local_weak_refs++; + new_node->local_strong_refs++; + new_node->has_strong_ref = 1; + new_node->has_weak_ref = 1; + context->binder_context_mgr_node = new_node; out: + mutex_unlock(&context->context_mgr_node_lock); return ret; } @@ -2965,13 +2988,16 @@ static int binder_open(struct inode *nodp, struct file *filp) binder_lock(__func__); binder_stats_created(BINDER_STAT_PROC); - hlist_add_head(&proc->proc_node, &binder_procs); proc->pid = current->group_leader->pid; INIT_LIST_HEAD(&proc->delivered_death); filp->private_data = proc; binder_unlock(__func__); + mutex_lock(&binder_procs_lock); + hlist_add_head(&proc->proc_node, &binder_procs); + mutex_unlock(&binder_procs_lock); + if (binder_debugfs_dir_entry_proc) { char strbuf[11]; @@ -3050,7 +3076,10 @@ static int binder_node_release(struct binder_node *node, int refs) node->proc = NULL; node->local_strong_refs = 0; node->local_weak_refs = 0; + + spin_lock(&binder_dead_nodes_lock); hlist_add_head(&node->dead_node, &binder_dead_nodes); + spin_unlock(&binder_dead_nodes_lock); hlist_for_each_entry(ref, &node->refs, node_entry) { refs++; @@ -3084,8 +3113,11 @@ static void binder_deferred_release(struct binder_proc *proc) BUG_ON(proc->files); + mutex_lock(&binder_procs_lock); hlist_del(&proc->proc_node); + mutex_unlock(&binder_procs_lock); + mutex_lock(&context->context_mgr_node_lock); if (context->binder_context_mgr_node && context->binder_context_mgr_node->proc == proc) { binder_debug(BINDER_DEBUG_DEAD_BINDER, @@ -3093,6 +3125,7 @@ static void binder_deferred_release(struct binder_proc *proc) __func__, proc->pid); context->binder_context_mgr_node = NULL; } + mutex_unlock(&context->context_mgr_node_lock); threads = 0; active_transactions = 0; @@ -3509,13 +3542,17 @@ static int binder_state_show(struct seq_file *m, void *unused) seq_puts(m, "binder state:\n"); + spin_lock(&binder_dead_nodes_lock); if (!hlist_empty(&binder_dead_nodes)) seq_puts(m, "dead nodes:\n"); hlist_for_each_entry(node, &binder_dead_nodes, dead_node) print_binder_node(m, node); + spin_unlock(&binder_dead_nodes_lock); + mutex_lock(&binder_procs_lock); hlist_for_each_entry(proc, &binder_procs, proc_node) print_binder_proc(m, proc, 1); + mutex_unlock(&binder_procs_lock); binder_unlock(__func__); return 0; } @@ -3530,8 +3567,10 @@ static int binder_stats_show(struct seq_file *m, void *unused) print_binder_stats(m, "", &binder_stats); + mutex_lock(&binder_procs_lock); hlist_for_each_entry(proc, &binder_procs, proc_node) print_binder_proc_stats(m, proc); + mutex_unlock(&binder_procs_lock); binder_unlock(__func__); return 0; } @@ -3543,8 +3582,10 @@ static int binder_transactions_show(struct seq_file *m, void *unused) binder_lock(__func__); seq_puts(m, "binder transactions:\n"); + mutex_lock(&binder_procs_lock); hlist_for_each_entry(proc, &binder_procs, proc_node) print_binder_proc(m, proc, 0); + mutex_unlock(&binder_procs_lock); binder_unlock(__func__); return 0; } @@ -3556,12 +3597,15 @@ static int binder_proc_show(struct seq_file *m, void *unused) binder_lock(__func__); + mutex_lock(&binder_procs_lock); hlist_for_each_entry(itr, &binder_procs, proc_node) { if (itr->pid == pid) { seq_puts(m, "binder proc state:\n"); print_binder_proc(m, itr, 1); } } + mutex_unlock(&binder_procs_lock); + binder_unlock(__func__); return 0; } @@ -3622,6 +3666,7 @@ static int __init init_binder_device(const char *name) binder_device->context.binder_context_mgr_uid = INVALID_UID; binder_device->context.name = name; + mutex_init(&binder_device->context.context_mgr_node_lock); ret = misc_register(&binder_device->miscdev); if (ret < 0) { -- cgit v1.2.3 From 0953c7976c36ce06a4e92b9a23cfb8f1bbe2321f Mon Sep 17 00:00:00 2001 From: Badhri Jagan Sridharan Date: Thu, 29 Jun 2017 12:01:44 -0700 Subject: binder: change binder_stats to atomics Use atomics for stats to avoid needing to lock for increments/decrements Signed-off-by: Todd Kjos Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 48 ++++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index fb484c6acd3e..cd4191d027e1 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -167,22 +167,22 @@ enum binder_stat_types { }; struct binder_stats { - int br[_IOC_NR(BR_FAILED_REPLY) + 1]; - int bc[_IOC_NR(BC_REPLY_SG) + 1]; - int obj_created[BINDER_STAT_COUNT]; - int obj_deleted[BINDER_STAT_COUNT]; + atomic_t br[_IOC_NR(BR_FAILED_REPLY) + 1]; + atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1]; + atomic_t obj_created[BINDER_STAT_COUNT]; + atomic_t obj_deleted[BINDER_STAT_COUNT]; }; static struct binder_stats binder_stats; static inline void binder_stats_deleted(enum binder_stat_types type) { - binder_stats.obj_deleted[type]++; + atomic_inc(&binder_stats.obj_deleted[type]); } static inline void binder_stats_created(enum binder_stat_types type) { - binder_stats.obj_created[type]++; + atomic_inc(&binder_stats.obj_created[type]); } struct binder_transaction_log_entry { @@ -1825,9 +1825,9 @@ static int binder_thread_write(struct binder_proc *proc, ptr += sizeof(uint32_t); trace_binder_command(cmd); if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.bc)) { - binder_stats.bc[_IOC_NR(cmd)]++; - proc->stats.bc[_IOC_NR(cmd)]++; - thread->stats.bc[_IOC_NR(cmd)]++; + atomic_inc(&binder_stats.bc[_IOC_NR(cmd)]); + atomic_inc(&proc->stats.bc[_IOC_NR(cmd)]); + atomic_inc(&thread->stats.bc[_IOC_NR(cmd)]); } switch (cmd) { case BC_INCREFS: @@ -2201,9 +2201,9 @@ static void binder_stat_br(struct binder_proc *proc, { trace_binder_return(cmd); if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.br)) { - binder_stats.br[_IOC_NR(cmd)]++; - proc->stats.br[_IOC_NR(cmd)]++; - thread->stats.br[_IOC_NR(cmd)]++; + atomic_inc(&binder_stats.br[_IOC_NR(cmd)]); + atomic_inc(&proc->stats.br[_IOC_NR(cmd)]); + atomic_inc(&thread->stats.br[_IOC_NR(cmd)]); } } @@ -3453,17 +3453,21 @@ static void print_binder_stats(struct seq_file *m, const char *prefix, BUILD_BUG_ON(ARRAY_SIZE(stats->bc) != ARRAY_SIZE(binder_command_strings)); for (i = 0; i < ARRAY_SIZE(stats->bc); i++) { - if (stats->bc[i]) + int temp = atomic_read(&stats->bc[i]); + + if (temp) seq_printf(m, "%s%s: %d\n", prefix, - binder_command_strings[i], stats->bc[i]); + binder_command_strings[i], temp); } BUILD_BUG_ON(ARRAY_SIZE(stats->br) != ARRAY_SIZE(binder_return_strings)); for (i = 0; i < ARRAY_SIZE(stats->br); i++) { - if (stats->br[i]) + int temp = atomic_read(&stats->br[i]); + + if (temp) seq_printf(m, "%s%s: %d\n", prefix, - binder_return_strings[i], stats->br[i]); + binder_return_strings[i], temp); } BUILD_BUG_ON(ARRAY_SIZE(stats->obj_created) != @@ -3471,11 +3475,15 @@ static void print_binder_stats(struct seq_file *m, const char *prefix, BUILD_BUG_ON(ARRAY_SIZE(stats->obj_created) != ARRAY_SIZE(stats->obj_deleted)); for (i = 0; i < ARRAY_SIZE(stats->obj_created); i++) { - if (stats->obj_created[i] || stats->obj_deleted[i]) - seq_printf(m, "%s%s: active %d total %d\n", prefix, + int created = atomic_read(&stats->obj_created[i]); + int deleted = atomic_read(&stats->obj_deleted[i]); + + if (created || deleted) + seq_printf(m, "%s%s: active %d total %d\n", + prefix, binder_objstat_strings[i], - stats->obj_created[i] - stats->obj_deleted[i], - stats->obj_created[i]); + created - deleted, + created); } } -- cgit v1.2.3 From 656a800aad6051ccc81b26c388a2a7a1c8cc8c81 Mon Sep 17 00:00:00 2001 From: Todd Kjos Date: Thu, 29 Jun 2017 12:01:45 -0700 Subject: binder: make binder_last_id an atomic Use an atomic for binder_last_id to avoid locking it Signed-off-by: Todd Kjos Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index cd4191d027e1..25f30d81c7d0 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -59,7 +59,7 @@ static DEFINE_SPINLOCK(binder_dead_nodes_lock); static struct dentry *binder_debugfs_dir_entry_root; static struct dentry *binder_debugfs_dir_entry_proc; -static int binder_last_id; +static atomic_t binder_last_id; #define BINDER_DEBUG_ENTRY(name) \ static int binder_##name##_open(struct inode *inode, struct file *file) \ @@ -496,7 +496,7 @@ static struct binder_node *binder_new_node(struct binder_proc *proc, binder_stats_created(BINDER_STAT_NODE); rb_link_node(&node->rb_node, parent, p); rb_insert_color(&node->rb_node, &proc->nodes); - node->debug_id = ++binder_last_id; + node->debug_id = atomic_inc_return(&binder_last_id); node->proc = proc; node->ptr = ptr; node->cookie = cookie; @@ -639,7 +639,7 @@ static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc, if (new_ref == NULL) return NULL; binder_stats_created(BINDER_STAT_REF); - new_ref->debug_id = ++binder_last_id; + new_ref->debug_id = atomic_inc_return(&binder_last_id); new_ref->proc = proc; new_ref->node = node; rb_link_node(&new_ref->rb_node_node, parent, p); @@ -1527,7 +1527,7 @@ static void binder_transaction(struct binder_proc *proc, } binder_stats_created(BINDER_STAT_TRANSACTION_COMPLETE); - t->debug_id = ++binder_last_id; + t->debug_id = atomic_inc_return(&binder_last_id); e->debug_id = t->debug_id; if (reply) -- cgit v1.2.3 From 57ada2fb2250eab5abe381353f12ada337d82808 Mon Sep 17 00:00:00 2001 From: Todd Kjos Date: Thu, 29 Jun 2017 12:01:46 -0700 Subject: binder: add log information for binder transaction failures Add additional information to determine the cause of binder failures. Adds the following to failed transaction log and kernel messages: return_error : value returned for transaction return_error_param : errno returned by binder allocator return_error_line : line number where error detected Also, return BR_DEAD_REPLY if an allocation error indicates a dead proc (-ESRCH) Signed-off-by: Todd Kjos Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 87 +++++++++++++++++++++++++++++++++++++----- drivers/android/binder_alloc.c | 20 +++++----- 2 files changed, 88 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 25f30d81c7d0..62ac0c41b8a6 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -196,6 +196,9 @@ struct binder_transaction_log_entry { int to_node; int data_size; int offsets_size; + int return_error_line; + uint32_t return_error; + uint32_t return_error_param; const char *context_name; }; struct binder_transaction_log { @@ -1142,7 +1145,7 @@ static int binder_translate_binder(struct flat_binder_object *fp, ref = binder_get_ref_for_node(target_proc, node); if (!ref) - return -EINVAL; + return -ENOMEM; if (fp->hdr.type == BINDER_TYPE_BINDER) fp->hdr.type = BINDER_TYPE_HANDLE; @@ -1199,7 +1202,7 @@ static int binder_translate_handle(struct flat_binder_object *fp, new_ref = binder_get_ref_for_node(target_proc, ref->node); if (!new_ref) - return -EINVAL; + return -ENOMEM; fp->binder = 0; fp->handle = new_ref->desc; @@ -1397,7 +1400,9 @@ static void binder_transaction(struct binder_proc *proc, wait_queue_head_t *target_wait; struct binder_transaction *in_reply_to = NULL; struct binder_transaction_log_entry *e; - uint32_t return_error; + uint32_t return_error = 0; + uint32_t return_error_param = 0; + uint32_t return_error_line = 0; struct binder_buffer_object *last_fixup_obj = NULL; binder_size_t last_fixup_min_off = 0; struct binder_context *context = proc->context; @@ -1417,6 +1422,8 @@ static void binder_transaction(struct binder_proc *proc, binder_user_error("%d:%d got reply transaction with no transaction stack\n", proc->pid, thread->pid); return_error = BR_FAILED_REPLY; + return_error_param = -EPROTO; + return_error_line = __LINE__; goto err_empty_call_stack; } binder_set_nice(in_reply_to->saved_priority); @@ -1428,6 +1435,8 @@ static void binder_transaction(struct binder_proc *proc, in_reply_to->to_thread ? in_reply_to->to_thread->pid : 0); return_error = BR_FAILED_REPLY; + return_error_param = -EPROTO; + return_error_line = __LINE__; in_reply_to = NULL; goto err_bad_call_stack; } @@ -1435,6 +1444,7 @@ static void binder_transaction(struct binder_proc *proc, target_thread = in_reply_to->from; if (target_thread == NULL) { return_error = BR_DEAD_REPLY; + return_error_line = __LINE__; goto err_dead_binder; } if (target_thread->transaction_stack != in_reply_to) { @@ -1444,6 +1454,8 @@ static void binder_transaction(struct binder_proc *proc, target_thread->transaction_stack->debug_id : 0, in_reply_to->debug_id); return_error = BR_FAILED_REPLY; + return_error_param = -EPROTO; + return_error_line = __LINE__; in_reply_to = NULL; target_thread = NULL; goto err_dead_binder; @@ -1458,6 +1470,8 @@ static void binder_transaction(struct binder_proc *proc, binder_user_error("%d:%d got transaction to invalid handle\n", proc->pid, thread->pid); return_error = BR_FAILED_REPLY; + return_error_param = -EINVAL; + return_error_line = __LINE__; goto err_invalid_target_handle; } target_node = ref->node; @@ -1467,6 +1481,7 @@ static void binder_transaction(struct binder_proc *proc, if (target_node == NULL) { return_error = BR_DEAD_REPLY; mutex_unlock(&context->context_mgr_node_lock); + return_error_line = __LINE__; goto err_no_context_mgr_node; } mutex_unlock(&context->context_mgr_node_lock); @@ -1475,11 +1490,14 @@ static void binder_transaction(struct binder_proc *proc, target_proc = target_node->proc; if (target_proc == NULL) { return_error = BR_DEAD_REPLY; + return_error_line = __LINE__; goto err_dead_binder; } if (security_binder_transaction(proc->tsk, target_proc->tsk) < 0) { return_error = BR_FAILED_REPLY; + return_error_param = -EPERM; + return_error_line = __LINE__; goto err_invalid_target_handle; } if (!(tr->flags & TF_ONE_WAY) && thread->transaction_stack) { @@ -1493,6 +1511,8 @@ static void binder_transaction(struct binder_proc *proc, tmp->to_thread ? tmp->to_thread->pid : 0); return_error = BR_FAILED_REPLY; + return_error_param = -EPROTO; + return_error_line = __LINE__; goto err_bad_call_stack; } while (tmp) { @@ -1516,6 +1536,8 @@ static void binder_transaction(struct binder_proc *proc, t = kzalloc(sizeof(*t), GFP_KERNEL); if (t == NULL) { return_error = BR_FAILED_REPLY; + return_error_param = -ENOMEM; + return_error_line = __LINE__; goto err_alloc_t_failed; } binder_stats_created(BINDER_STAT_TRANSACTION); @@ -1523,6 +1545,8 @@ static void binder_transaction(struct binder_proc *proc, tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL); if (tcomplete == NULL) { return_error = BR_FAILED_REPLY; + return_error_param = -ENOMEM; + return_error_line = __LINE__; goto err_alloc_tcomplete_failed; } binder_stats_created(BINDER_STAT_TRANSACTION_COMPLETE); @@ -1565,8 +1589,15 @@ static void binder_transaction(struct binder_proc *proc, t->buffer = binder_alloc_new_buf(&target_proc->alloc, tr->data_size, tr->offsets_size, extra_buffers_size, !reply && (t->flags & TF_ONE_WAY)); - if (t->buffer == NULL) { - return_error = BR_FAILED_REPLY; + if (IS_ERR(t->buffer)) { + /* + * -ESRCH indicates VMA cleared. The target is dying. + */ + return_error_param = PTR_ERR(t->buffer); + return_error = return_error_param == -ESRCH ? + BR_DEAD_REPLY : BR_FAILED_REPLY; + return_error_line = __LINE__; + t->buffer = NULL; goto err_binder_alloc_buf_failed; } t->buffer->allow_user_free = 0; @@ -1586,6 +1617,8 @@ static void binder_transaction(struct binder_proc *proc, binder_user_error("%d:%d got transaction with invalid data ptr\n", proc->pid, thread->pid); return_error = BR_FAILED_REPLY; + return_error_param = -EFAULT; + return_error_line = __LINE__; goto err_copy_data_failed; } if (copy_from_user(offp, (const void __user *)(uintptr_t) @@ -1593,12 +1626,16 @@ static void binder_transaction(struct binder_proc *proc, binder_user_error("%d:%d got transaction with invalid offsets ptr\n", proc->pid, thread->pid); return_error = BR_FAILED_REPLY; + return_error_param = -EFAULT; + return_error_line = __LINE__; goto err_copy_data_failed; } if (!IS_ALIGNED(tr->offsets_size, sizeof(binder_size_t))) { binder_user_error("%d:%d got transaction with invalid offsets size, %lld\n", proc->pid, thread->pid, (u64)tr->offsets_size); return_error = BR_FAILED_REPLY; + return_error_param = -EINVAL; + return_error_line = __LINE__; goto err_bad_offset; } if (!IS_ALIGNED(extra_buffers_size, sizeof(u64))) { @@ -1606,6 +1643,8 @@ static void binder_transaction(struct binder_proc *proc, proc->pid, thread->pid, (u64)extra_buffers_size); return_error = BR_FAILED_REPLY; + return_error_param = -EINVAL; + return_error_line = __LINE__; goto err_bad_offset; } off_end = (void *)off_start + tr->offsets_size; @@ -1622,6 +1661,8 @@ static void binder_transaction(struct binder_proc *proc, (u64)off_min, (u64)t->buffer->data_size); return_error = BR_FAILED_REPLY; + return_error_param = -EINVAL; + return_error_line = __LINE__; goto err_bad_offset; } @@ -1636,6 +1677,8 @@ static void binder_transaction(struct binder_proc *proc, ret = binder_translate_binder(fp, t, thread); if (ret < 0) { return_error = BR_FAILED_REPLY; + return_error_param = ret; + return_error_line = __LINE__; goto err_translate_failed; } } break; @@ -1647,6 +1690,8 @@ static void binder_transaction(struct binder_proc *proc, ret = binder_translate_handle(fp, t, thread); if (ret < 0) { return_error = BR_FAILED_REPLY; + return_error_param = ret; + return_error_line = __LINE__; goto err_translate_failed; } } break; @@ -1658,6 +1703,8 @@ static void binder_transaction(struct binder_proc *proc, if (target_fd < 0) { return_error = BR_FAILED_REPLY; + return_error_param = target_fd; + return_error_line = __LINE__; goto err_translate_failed; } fp->pad_binder = 0; @@ -1674,6 +1721,8 @@ static void binder_transaction(struct binder_proc *proc, binder_user_error("%d:%d got transaction with invalid parent offset or type\n", proc->pid, thread->pid); return_error = BR_FAILED_REPLY; + return_error_param = -EINVAL; + return_error_line = __LINE__; goto err_bad_parent; } if (!binder_validate_fixup(t->buffer, off_start, @@ -1683,12 +1732,16 @@ static void binder_transaction(struct binder_proc *proc, binder_user_error("%d:%d got transaction with out-of-order buffer fixup\n", proc->pid, thread->pid); return_error = BR_FAILED_REPLY; + return_error_param = -EINVAL; + return_error_line = __LINE__; goto err_bad_parent; } ret = binder_translate_fd_array(fda, parent, t, thread, in_reply_to); if (ret < 0) { return_error = BR_FAILED_REPLY; + return_error_param = ret; + return_error_line = __LINE__; goto err_translate_failed; } last_fixup_obj = parent; @@ -1704,6 +1757,8 @@ static void binder_transaction(struct binder_proc *proc, binder_user_error("%d:%d got transaction with too large buffer\n", proc->pid, thread->pid); return_error = BR_FAILED_REPLY; + return_error_param = -EINVAL; + return_error_line = __LINE__; goto err_bad_offset; } if (copy_from_user(sg_bufp, @@ -1711,7 +1766,9 @@ static void binder_transaction(struct binder_proc *proc, bp->buffer, bp->length)) { binder_user_error("%d:%d got transaction with invalid offsets ptr\n", proc->pid, thread->pid); + return_error_param = -EFAULT; return_error = BR_FAILED_REPLY; + return_error_line = __LINE__; goto err_copy_data_failed; } /* Fixup buffer pointer to target proc address space */ @@ -1726,6 +1783,8 @@ static void binder_transaction(struct binder_proc *proc, last_fixup_min_off); if (ret < 0) { return_error = BR_FAILED_REPLY; + return_error_param = ret; + return_error_line = __LINE__; goto err_translate_failed; } last_fixup_obj = bp; @@ -1735,6 +1794,8 @@ static void binder_transaction(struct binder_proc *proc, binder_user_error("%d:%d got transaction with invalid object type, %x\n", proc->pid, thread->pid, hdr->type); return_error = BR_FAILED_REPLY; + return_error_param = -EINVAL; + return_error_line = __LINE__; goto err_bad_object_type; } } @@ -1789,13 +1850,17 @@ err_dead_binder: err_invalid_target_handle: err_no_context_mgr_node: binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, - "%d:%d transaction failed %d, size %lld-%lld\n", - proc->pid, thread->pid, return_error, - (u64)tr->data_size, (u64)tr->offsets_size); + "%d:%d transaction failed %d/%d, size %lld-%lld line %d\n", + proc->pid, thread->pid, return_error, return_error_param, + (u64)tr->data_size, (u64)tr->offsets_size, + return_error_line); { struct binder_transaction_log_entry *fe; + e->return_error = return_error; + e->return_error_param = return_error_param; + e->return_error_line = return_error_line; fe = binder_transaction_log_add(&binder_transaction_log_failed); *fe = *e; } @@ -3622,11 +3687,13 @@ static void print_binder_transaction_log_entry(struct seq_file *m, struct binder_transaction_log_entry *e) { seq_printf(m, - "%d: %s from %d:%d to %d:%d context %s node %d handle %d size %d:%d\n", + "%d: %s from %d:%d to %d:%d context %s node %d handle %d size %d:%d ret %d/%d l=%d\n", e->debug_id, (e->call_type == 2) ? "reply" : ((e->call_type == 1) ? "async" : "call "), e->from_proc, e->from_thread, e->to_proc, e->to_thread, e->context_name, - e->to_node, e->target_handle, e->data_size, e->offsets_size); + e->to_node, e->target_handle, e->data_size, e->offsets_size, + e->return_error, e->return_error_param, + e->return_error_line); } static int binder_transaction_log_show(struct seq_file *m, void *unused) diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 198d04c5d958..a0af1419cc79 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -262,7 +262,7 @@ err_no_vma: up_write(&mm->mmap_sem); mmput(mm); } - return -ENOMEM; + return vma ? -ENOMEM : -ESRCH; } struct binder_buffer *binder_alloc_new_buf_locked(struct binder_alloc *alloc, @@ -278,11 +278,12 @@ struct binder_buffer *binder_alloc_new_buf_locked(struct binder_alloc *alloc, void *has_page_addr; void *end_page_addr; size_t size, data_offsets_size; + int ret; if (alloc->vma == NULL) { pr_err("%d: binder_alloc_buf, no vma\n", alloc->pid); - return NULL; + return ERR_PTR(-ESRCH); } data_offsets_size = ALIGN(data_size, sizeof(void *)) + @@ -292,21 +293,21 @@ struct binder_buffer *binder_alloc_new_buf_locked(struct binder_alloc *alloc, binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, "%d: got transaction with invalid size %zd-%zd\n", alloc->pid, data_size, offsets_size); - return NULL; + return ERR_PTR(-EINVAL); } size = data_offsets_size + ALIGN(extra_buffers_size, sizeof(void *)); if (size < data_offsets_size || size < extra_buffers_size) { binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, "%d: got transaction with invalid extra_buffers_size %zd\n", alloc->pid, extra_buffers_size); - return NULL; + return ERR_PTR(-EINVAL); } if (is_async && alloc->free_async_space < size + sizeof(struct binder_buffer)) { binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, "%d: binder_alloc_buf size %zd failed, no async space left\n", alloc->pid, size); - return NULL; + return ERR_PTR(-ENOSPC); } while (n) { @@ -327,7 +328,7 @@ struct binder_buffer *binder_alloc_new_buf_locked(struct binder_alloc *alloc, if (best_fit == NULL) { pr_err("%d: binder_alloc_buf size %zd failed, no address space\n", alloc->pid, size); - return NULL; + return ERR_PTR(-ENOSPC); } if (n == NULL) { buffer = rb_entry(best_fit, struct binder_buffer, rb_node); @@ -350,9 +351,10 @@ struct binder_buffer *binder_alloc_new_buf_locked(struct binder_alloc *alloc, (void *)PAGE_ALIGN((uintptr_t)buffer->data + buffer_size); if (end_page_addr > has_page_addr) end_page_addr = has_page_addr; - if (binder_update_page_range(alloc, 1, - (void *)PAGE_ALIGN((uintptr_t)buffer->data), end_page_addr, NULL)) - return NULL; + ret = binder_update_page_range(alloc, 1, + (void *)PAGE_ALIGN((uintptr_t)buffer->data), end_page_addr, NULL); + if (ret) + return ERR_PTR(ret); rb_erase(best_fit, &alloc->free_buffers); buffer->free = 0; -- cgit v1.2.3 From 26b47d8a16a72878228aeaed573786825b7ca204 Mon Sep 17 00:00:00 2001 From: Todd Kjos Date: Thu, 29 Jun 2017 12:01:47 -0700 Subject: binder: refactor queue management in binder_thread_read In binder_thread_read, the BINDER_WORK_NODE command is used to communicate the references on the node to userspace. It can take a couple of iterations in the loop to construct the list of commands for user space. When locking is added, the lock would need to be release on each iteration which means the state could change. The work item is not dequeued during this process which prevents a simpler queue management that can just dequeue up front and handle the work item. Fixed by changing the BINDER_WORK_NODE algorithm in binder_thread_read to determine which commands to send to userspace atomically in 1 pass so it stays consistent with the kernel view. The work item is now dequeued immediately since only 1 pass is needed. Signed-off-by: Todd Kjos Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 151 +++++++++++++++++++++++++++++------------------ 1 file changed, 94 insertions(+), 57 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 62ac0c41b8a6..f17d1dfa5b02 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -2285,6 +2285,37 @@ static int binder_has_thread_work(struct binder_thread *thread) (thread->looper & BINDER_LOOPER_STATE_NEED_RETURN); } +static int binder_put_node_cmd(struct binder_proc *proc, + struct binder_thread *thread, + void __user **ptrp, + binder_uintptr_t node_ptr, + binder_uintptr_t node_cookie, + int node_debug_id, + uint32_t cmd, const char *cmd_name) +{ + void __user *ptr = *ptrp; + + if (put_user(cmd, (uint32_t __user *)ptr)) + return -EFAULT; + ptr += sizeof(uint32_t); + + if (put_user(node_ptr, (binder_uintptr_t __user *)ptr)) + return -EFAULT; + ptr += sizeof(binder_uintptr_t); + + if (put_user(node_cookie, (binder_uintptr_t __user *)ptr)) + return -EFAULT; + ptr += sizeof(binder_uintptr_t); + + binder_stat_br(proc, thread, cmd); + binder_debug(BINDER_DEBUG_USER_REFS, "%d:%d %s %d u%016llx c%016llx\n", + proc->pid, thread->pid, cmd_name, node_debug_id, + (u64)node_ptr, (u64)node_cookie); + + *ptrp = ptr; + return 0; +} + static int binder_thread_read(struct binder_proc *proc, struct binder_thread *thread, binder_uintptr_t binder_buffer, size_t size, @@ -2410,72 +2441,78 @@ retry: } break; case BINDER_WORK_NODE: { struct binder_node *node = container_of(w, struct binder_node, work); - uint32_t cmd = BR_NOOP; - const char *cmd_name; - int strong = node->internal_strong_refs || node->local_strong_refs; - int weak = !hlist_empty(&node->refs) || node->local_weak_refs || strong; - - if (weak && !node->has_weak_ref) { - cmd = BR_INCREFS; - cmd_name = "BR_INCREFS"; + int strong, weak; + binder_uintptr_t node_ptr = node->ptr; + binder_uintptr_t node_cookie = node->cookie; + int node_debug_id = node->debug_id; + int has_weak_ref; + int has_strong_ref; + void __user *orig_ptr = ptr; + + BUG_ON(proc != node->proc); + strong = node->internal_strong_refs || + node->local_strong_refs; + weak = !hlist_empty(&node->refs) || + node->local_weak_refs || strong; + has_strong_ref = node->has_strong_ref; + has_weak_ref = node->has_weak_ref; + + if (weak && !has_weak_ref) { node->has_weak_ref = 1; node->pending_weak_ref = 1; node->local_weak_refs++; - } else if (strong && !node->has_strong_ref) { - cmd = BR_ACQUIRE; - cmd_name = "BR_ACQUIRE"; + } + if (strong && !has_strong_ref) { node->has_strong_ref = 1; node->pending_strong_ref = 1; node->local_strong_refs++; - } else if (!strong && node->has_strong_ref) { - cmd = BR_RELEASE; - cmd_name = "BR_RELEASE"; + } + if (!strong && has_strong_ref) node->has_strong_ref = 0; - } else if (!weak && node->has_weak_ref) { - cmd = BR_DECREFS; - cmd_name = "BR_DECREFS"; + if (!weak && has_weak_ref) node->has_weak_ref = 0; + list_del(&w->entry); + + if (!weak && !strong) { + binder_debug(BINDER_DEBUG_INTERNAL_REFS, + "%d:%d node %d u%016llx c%016llx deleted\n", + proc->pid, thread->pid, + node_debug_id, + (u64)node_ptr, + (u64)node_cookie); + rb_erase(&node->rb_node, &proc->nodes); + kfree(node); + binder_stats_deleted(BINDER_STAT_NODE); } - if (cmd != BR_NOOP) { - if (put_user(cmd, (uint32_t __user *)ptr)) - return -EFAULT; - ptr += sizeof(uint32_t); - if (put_user(node->ptr, - (binder_uintptr_t __user *)ptr)) - return -EFAULT; - ptr += sizeof(binder_uintptr_t); - if (put_user(node->cookie, - (binder_uintptr_t __user *)ptr)) - return -EFAULT; - ptr += sizeof(binder_uintptr_t); - - binder_stat_br(proc, thread, cmd); - binder_debug(BINDER_DEBUG_USER_REFS, - "%d:%d %s %d u%016llx c%016llx\n", - proc->pid, thread->pid, cmd_name, - node->debug_id, - (u64)node->ptr, (u64)node->cookie); - } else { - list_del_init(&w->entry); - if (!weak && !strong) { - binder_debug(BINDER_DEBUG_INTERNAL_REFS, - "%d:%d node %d u%016llx c%016llx deleted\n", - proc->pid, thread->pid, - node->debug_id, - (u64)node->ptr, - (u64)node->cookie); - rb_erase(&node->rb_node, &proc->nodes); - kfree(node); - binder_stats_deleted(BINDER_STAT_NODE); - } else { - binder_debug(BINDER_DEBUG_INTERNAL_REFS, - "%d:%d node %d u%016llx c%016llx state unchanged\n", - proc->pid, thread->pid, - node->debug_id, - (u64)node->ptr, - (u64)node->cookie); - } - } + if (weak && !has_weak_ref) + ret = binder_put_node_cmd( + proc, thread, &ptr, node_ptr, + node_cookie, node_debug_id, + BR_INCREFS, "BR_INCREFS"); + if (!ret && strong && !has_strong_ref) + ret = binder_put_node_cmd( + proc, thread, &ptr, node_ptr, + node_cookie, node_debug_id, + BR_ACQUIRE, "BR_ACQUIRE"); + if (!ret && !strong && has_strong_ref) + ret = binder_put_node_cmd( + proc, thread, &ptr, node_ptr, + node_cookie, node_debug_id, + BR_RELEASE, "BR_RELEASE"); + if (!ret && !weak && has_weak_ref) + ret = binder_put_node_cmd( + proc, thread, &ptr, node_ptr, + node_cookie, node_debug_id, + BR_DECREFS, "BR_DECREFS"); + if (orig_ptr == ptr) + binder_debug(BINDER_DEBUG_INTERNAL_REFS, + "%d:%d node %d u%016llx c%016llx state unchanged\n", + proc->pid, thread->pid, + node_debug_id, + (u64)node_ptr, + (u64)node_cookie); + if (ret) + return ret; } break; case BINDER_WORK_DEAD_BINDER: case BINDER_WORK_DEAD_BINDER_AND_CLEAR: -- cgit v1.2.3 From ccae6f676001d00efd1a4626773d1577e53188f7 Mon Sep 17 00:00:00 2001 From: Todd Kjos Date: Thu, 29 Jun 2017 12:01:48 -0700 Subject: binder: avoid race conditions when enqueuing txn Currently, the transaction complete work item is queued after the transaction. This means that it is possible for the transaction to be handled and a reply to be enqueued in the current thread before the transaction complete is enqueued, which violates the protocol with userspace who may not expect the transaction complete. Fixed by always enqueing the transaction complete first. Also, once the transaction is enqueued, it is unsafe to access since it might be freed. Currently, t->flags is accessed to determine whether a sync wake is needed. Changed to access tr->flags instead. Signed-off-by: Todd Kjos Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index f17d1dfa5b02..71faf548482d 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -1799,6 +1799,9 @@ static void binder_transaction(struct binder_proc *proc, goto err_bad_object_type; } } + tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE; + list_add_tail(&tcomplete->entry, &thread->todo); + if (reply) { BUG_ON(t->buffer->async_transaction != 0); binder_pop_transaction(target_thread, in_reply_to); @@ -1818,10 +1821,8 @@ static void binder_transaction(struct binder_proc *proc, } t->work.type = BINDER_WORK_TRANSACTION; list_add_tail(&t->work.entry, target_list); - tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE; - list_add_tail(&tcomplete->entry, &thread->todo); if (target_wait) { - if (reply || !(t->flags & TF_ONE_WAY)) + if (reply || !(tr->flags & TF_ONE_WAY)) wake_up_interruptible_sync(target_wait); else wake_up_interruptible(target_wait); -- cgit v1.2.3 From 08dabceefee0eddace493fc16da172c93402187f Mon Sep 17 00:00:00 2001 From: Todd Kjos Date: Thu, 29 Jun 2017 12:01:49 -0700 Subject: binder: don't modify thread->looper from other threads The looper member of struct binder_thread is a bitmask of control bits. All of the existing bits are modified by the affected thread except for BINDER_LOOPER_STATE_NEED_RETURN which can be modified in binder_deferred_flush() by another thread. To avoid adding a spinlock around all read-mod-writes to modify a bit, the BINDER_LOOPER_STATE_NEED_RETURN flag is replaced by a separate field in struct binder_thread. Signed-off-by: Todd Kjos Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 71faf548482d..3c1129d91825 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -334,14 +334,14 @@ enum { BINDER_LOOPER_STATE_EXITED = 0x04, BINDER_LOOPER_STATE_INVALID = 0x08, BINDER_LOOPER_STATE_WAITING = 0x10, - BINDER_LOOPER_STATE_NEED_RETURN = 0x20 }; struct binder_thread { struct binder_proc *proc; struct rb_node rb_node; int pid; - int looper; + int looper; /* only modified by this thread */ + bool looper_need_return; /* can be written by other thread */ struct binder_transaction *transaction_stack; struct list_head todo; uint32_t return_error; /* Write failed, return error code in read buf */ @@ -2276,14 +2276,13 @@ static void binder_stat_br(struct binder_proc *proc, static int binder_has_proc_work(struct binder_proc *proc, struct binder_thread *thread) { - return !list_empty(&proc->todo) || - (thread->looper & BINDER_LOOPER_STATE_NEED_RETURN); + return !list_empty(&proc->todo) || thread->looper_need_return; } static int binder_has_thread_work(struct binder_thread *thread) { return !list_empty(&thread->todo) || thread->return_error != BR_OK || - (thread->looper & BINDER_LOOPER_STATE_NEED_RETURN); + thread->looper_need_return; } static int binder_put_node_cmd(struct binder_proc *proc, @@ -2412,8 +2411,7 @@ retry: entry); } else { /* no data added */ - if (ptr - buffer == 4 && - !(thread->looper & BINDER_LOOPER_STATE_NEED_RETURN)) + if (ptr - buffer == 4 && !thread->looper_need_return) goto retry; break; } @@ -2727,7 +2725,7 @@ static struct binder_thread *binder_get_thread(struct binder_proc *proc) INIT_LIST_HEAD(&thread->todo); rb_link_node(&thread->rb_node, parent, p); rb_insert_color(&thread->rb_node, &proc->threads); - thread->looper |= BINDER_LOOPER_STATE_NEED_RETURN; + thread->looper_need_return = true; thread->return_error = BR_OK; thread->return_error2 = BR_OK; } @@ -2983,7 +2981,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ret = 0; err: if (thread) - thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN; + thread->looper_need_return = false; binder_unlock(__func__); wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2); if (ret && ret != -ERESTARTSYS) @@ -3138,7 +3136,7 @@ static void binder_deferred_flush(struct binder_proc *proc) for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) { struct binder_thread *thread = rb_entry(n, struct binder_thread, rb_node); - thread->looper |= BINDER_LOOPER_STATE_NEED_RETURN; + thread->looper_need_return = true; if (thread->looper & BINDER_LOOPER_STATE_WAITING) { wake_up_interruptible(&thread->wait); wake_count++; @@ -3399,7 +3397,9 @@ static void print_binder_thread(struct seq_file *m, size_t start_pos = m->count; size_t header_pos; - seq_printf(m, " thread %d: l %02x\n", thread->pid, thread->looper); + seq_printf(m, " thread %d: l %02x need_return %d\n", + thread->pid, thread->looper, + thread->looper_need_return); header_pos = m->count; t = thread->transaction_stack; while (t) { -- cgit v1.2.3 From e4cffcf4bf8b540e150c311e70559d735cc95358 Mon Sep 17 00:00:00 2001 From: Todd Kjos Date: Thu, 29 Jun 2017 12:01:50 -0700 Subject: binder: remove dead code in binder_get_ref_for_node node is always non-NULL in binder_get_ref_for_node so the conditional and else clause are not needed Signed-off-by: Todd Kjos Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 3c1129d91825..3bbfb2455b70 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -670,18 +670,12 @@ static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc, } rb_link_node(&new_ref->rb_node_desc, parent, p); rb_insert_color(&new_ref->rb_node_desc, &proc->refs_by_desc); - if (node) { - hlist_add_head(&new_ref->node_entry, &node->refs); + hlist_add_head(&new_ref->node_entry, &node->refs); - binder_debug(BINDER_DEBUG_INTERNAL_REFS, - "%d new ref %d desc %d for node %d\n", - proc->pid, new_ref->debug_id, new_ref->desc, - node->debug_id); - } else { - binder_debug(BINDER_DEBUG_INTERNAL_REFS, - "%d new ref %d desc %d for dead node\n", - proc->pid, new_ref->debug_id, new_ref->desc); - } + binder_debug(BINDER_DEBUG_INTERNAL_REFS, + "%d new ref %d desc %d for node %d\n", + proc->pid, new_ref->debug_id, new_ref->desc, + node->debug_id); return new_ref; } -- cgit v1.2.3 From 53d311cfa19ad35beba74d706effee02c86d198f Mon Sep 17 00:00:00 2001 From: Todd Kjos Date: Thu, 29 Jun 2017 12:01:51 -0700 Subject: binder: protect against two threads freeing buffer Adds protection against malicious user code freeing the same buffer at the same time which could cause a crash. Cannot happen under normal use. Signed-off-by: Todd Kjos Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 4 ++-- drivers/android/binder_alloc.c | 22 +++++++++++++++++----- drivers/android/binder_alloc.h | 7 ++++--- 3 files changed, 23 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 3bbfb2455b70..a1912a22c89c 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -2024,8 +2024,8 @@ static int binder_thread_write(struct binder_proc *proc, return -EFAULT; ptr += sizeof(binder_uintptr_t); - buffer = binder_alloc_buffer_lookup(&proc->alloc, - data_ptr); + buffer = binder_alloc_prepare_to_free(&proc->alloc, + data_ptr); if (buffer == NULL) { binder_user_error("%d:%d BC_FREE_BUFFER u%016llx no match\n", proc->pid, thread->pid, (u64)data_ptr); diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index a0af1419cc79..2a2e41b13de5 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -116,7 +116,7 @@ static void binder_insert_allocated_buffer_locked( rb_insert_color(&new_buffer->rb_node, &alloc->allocated_buffers); } -static struct binder_buffer *binder_alloc_buffer_lookup_locked( +static struct binder_buffer *binder_alloc_prepare_to_free_locked( struct binder_alloc *alloc, uintptr_t user_ptr) { @@ -135,8 +135,19 @@ static struct binder_buffer *binder_alloc_buffer_lookup_locked( n = n->rb_left; else if (kern_ptr > buffer) n = n->rb_right; - else + else { + /* + * Guard against user threads attempting to + * free the buffer twice + */ + if (buffer->free_in_progress) { + pr_err("%d:%d FREE_BUFFER u%016llx user freed buffer twice\n", + alloc->pid, current->pid, (u64)user_ptr); + return NULL; + } + buffer->free_in_progress = 1; return buffer; + } } return NULL; } @@ -152,13 +163,13 @@ static struct binder_buffer *binder_alloc_buffer_lookup_locked( * * Return: Pointer to buffer or NULL */ -struct binder_buffer *binder_alloc_buffer_lookup(struct binder_alloc *alloc, - uintptr_t user_ptr) +struct binder_buffer *binder_alloc_prepare_to_free(struct binder_alloc *alloc, + uintptr_t user_ptr) { struct binder_buffer *buffer; mutex_lock(&alloc->mutex); - buffer = binder_alloc_buffer_lookup_locked(alloc, user_ptr); + buffer = binder_alloc_prepare_to_free_locked(alloc, user_ptr); mutex_unlock(&alloc->mutex); return buffer; } @@ -358,6 +369,7 @@ struct binder_buffer *binder_alloc_new_buf_locked(struct binder_alloc *alloc, rb_erase(best_fit, &alloc->free_buffers); buffer->free = 0; + buffer->free_in_progress = 0; binder_insert_allocated_buffer_locked(alloc, buffer); if (buffer_size != size) { struct binder_buffer *new_buffer = (void *)buffer->data + size; diff --git a/drivers/android/binder_alloc.h b/drivers/android/binder_alloc.h index 721c511431f9..088e4ffc6230 100644 --- a/drivers/android/binder_alloc.h +++ b/drivers/android/binder_alloc.h @@ -48,7 +48,8 @@ struct binder_buffer { unsigned free:1; unsigned allow_user_free:1; unsigned async_transaction:1; - unsigned debug_id:29; + unsigned free_in_progress:1; + unsigned debug_id:28; struct binder_transaction *transaction; @@ -109,8 +110,8 @@ extern struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc, extern void binder_alloc_init(struct binder_alloc *alloc); extern void binder_alloc_vma_close(struct binder_alloc *alloc); extern struct binder_buffer * -binder_alloc_buffer_lookup(struct binder_alloc *alloc, - uintptr_t user_ptr); +binder_alloc_prepare_to_free(struct binder_alloc *alloc, + uintptr_t user_ptr); extern void binder_alloc_free_buf(struct binder_alloc *alloc, struct binder_buffer *buffer); extern int binder_alloc_mmap_handler(struct binder_alloc *alloc, -- cgit v1.2.3 From b05a68e94b97eae2ae671ed703416f8dd21e4257 Mon Sep 17 00:00:00 2001 From: Martijn Coenen Date: Thu, 29 Jun 2017 12:01:52 -0700 Subject: binder: add more debug info when allocation fails. Display information about allocated/free space whenever binder buffer allocation fails on synchronous transactions. Signed-off-by: Martijn Coenen Signed-off-by: Siqi Lin Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder_alloc.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 2a2e41b13de5..40f31df60580 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -337,8 +337,36 @@ struct binder_buffer *binder_alloc_new_buf_locked(struct binder_alloc *alloc, } } if (best_fit == NULL) { + size_t allocated_buffers = 0; + size_t largest_alloc_size = 0; + size_t total_alloc_size = 0; + size_t free_buffers = 0; + size_t largest_free_size = 0; + size_t total_free_size = 0; + + for (n = rb_first(&alloc->allocated_buffers); n != NULL; + n = rb_next(n)) { + buffer = rb_entry(n, struct binder_buffer, rb_node); + buffer_size = binder_alloc_buffer_size(alloc, buffer); + allocated_buffers++; + total_alloc_size += buffer_size; + if (buffer_size > largest_alloc_size) + largest_alloc_size = buffer_size; + } + for (n = rb_first(&alloc->free_buffers); n != NULL; + n = rb_next(n)) { + buffer = rb_entry(n, struct binder_buffer, rb_node); + buffer_size = binder_alloc_buffer_size(alloc, buffer); + free_buffers++; + total_free_size += buffer_size; + if (buffer_size > largest_free_size) + largest_free_size = buffer_size; + } pr_err("%d: binder_alloc_buf size %zd failed, no address space\n", alloc->pid, size); + pr_err("allocated: %zd (num: %zd largest: %zd), free: %zd (num: %zd largest: %zd)\n", + total_alloc_size, allocated_buffers, largest_alloc_size, + total_free_size, free_buffers, largest_free_size); return ERR_PTR(-ENOSPC); } if (n == NULL) { @@ -698,9 +726,10 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc) static void print_binder_buffer(struct seq_file *m, const char *prefix, struct binder_buffer *buffer) { - seq_printf(m, "%s %d: %pK size %zd:%zd %s\n", + seq_printf(m, "%s %d: %pK size %zd:%zd:%zd %s\n", prefix, buffer->debug_id, buffer->data, buffer->data_size, buffer->offsets_size, + buffer->extra_buffers_size, buffer->transaction ? "active" : "delivered"); } -- cgit v1.2.3 From d99c7333ab1c9d56e6f6e15c0b4398591465efc1 Mon Sep 17 00:00:00 2001 From: Todd Kjos Date: Thu, 29 Jun 2017 12:01:53 -0700 Subject: binder: use atomic for transaction_log index The log->next index for the transaction log was not protected when incremented. This led to a case where log->next++ resulted in an index larger than ARRAY_SIZE(log->entry) and eventually a bad access to memory. Fixed by making the log index an atomic64 and converting to an array by using "% ARRAY_SIZE(log->entry)" Also added "complete" field to the log entry which is written last to tell the print code whether the entry is complete Signed-off-by: Todd Kjos Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 75 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 59 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index a1912a22c89c..cb78a4e6872d 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -187,6 +187,7 @@ static inline void binder_stats_created(enum binder_stat_types type) struct binder_transaction_log_entry { int debug_id; + int debug_id_done; int call_type; int from_proc; int from_thread; @@ -202,8 +203,8 @@ struct binder_transaction_log_entry { const char *context_name; }; struct binder_transaction_log { - int next; - int full; + atomic_t cur; + bool full; struct binder_transaction_log_entry entry[32]; }; static struct binder_transaction_log binder_transaction_log; @@ -213,14 +214,19 @@ static struct binder_transaction_log_entry *binder_transaction_log_add( struct binder_transaction_log *log) { struct binder_transaction_log_entry *e; + unsigned int cur = atomic_inc_return(&log->cur); - e = &log->entry[log->next]; - memset(e, 0, sizeof(*e)); - log->next++; - if (log->next == ARRAY_SIZE(log->entry)) { - log->next = 0; + if (cur >= ARRAY_SIZE(log->entry)) log->full = 1; - } + e = &log->entry[cur % ARRAY_SIZE(log->entry)]; + WRITE_ONCE(e->debug_id_done, 0); + /* + * write-barrier to synchronize access to e->debug_id_done. + * We make sure the initialized 0 value is seen before + * memset() other fields are zeroed by memset. + */ + smp_wmb(); + memset(e, 0, sizeof(*e)); return e; } @@ -1400,8 +1406,10 @@ static void binder_transaction(struct binder_proc *proc, struct binder_buffer_object *last_fixup_obj = NULL; binder_size_t last_fixup_min_off = 0; struct binder_context *context = proc->context; + int t_debug_id = atomic_inc_return(&binder_last_id); e = binder_transaction_log_add(&binder_transaction_log); + e->debug_id = t_debug_id; e->call_type = reply ? 2 : !!(tr->flags & TF_ONE_WAY); e->from_proc = proc->pid; e->from_thread = thread->pid; @@ -1545,8 +1553,7 @@ static void binder_transaction(struct binder_proc *proc, } binder_stats_created(BINDER_STAT_TRANSACTION_COMPLETE); - t->debug_id = atomic_inc_return(&binder_last_id); - e->debug_id = t->debug_id; + t->debug_id = t_debug_id; if (reply) binder_debug(BINDER_DEBUG_TRANSACTION, @@ -1821,6 +1828,12 @@ static void binder_transaction(struct binder_proc *proc, else wake_up_interruptible(target_wait); } + /* + * write barrier to synchronize with initialization + * of log entry + */ + smp_wmb(); + WRITE_ONCE(e->debug_id_done, t_debug_id); return; err_translate_failed: @@ -1858,6 +1871,13 @@ err_no_context_mgr_node: e->return_error_line = return_error_line; fe = binder_transaction_log_add(&binder_transaction_log_failed); *fe = *e; + /* + * write barrier to synchronize with initialization + * of log entry + */ + smp_wmb(); + WRITE_ONCE(e->debug_id_done, t_debug_id); + WRITE_ONCE(fe->debug_id_done, t_debug_id); } BUG_ON(thread->return_error != BR_OK); @@ -3718,27 +3738,47 @@ static int binder_proc_show(struct seq_file *m, void *unused) static void print_binder_transaction_log_entry(struct seq_file *m, struct binder_transaction_log_entry *e) { + int debug_id = READ_ONCE(e->debug_id_done); + /* + * read barrier to guarantee debug_id_done read before + * we print the log values + */ + smp_rmb(); seq_printf(m, - "%d: %s from %d:%d to %d:%d context %s node %d handle %d size %d:%d ret %d/%d l=%d\n", + "%d: %s from %d:%d to %d:%d context %s node %d handle %d size %d:%d ret %d/%d l=%d", e->debug_id, (e->call_type == 2) ? "reply" : ((e->call_type == 1) ? "async" : "call "), e->from_proc, e->from_thread, e->to_proc, e->to_thread, e->context_name, e->to_node, e->target_handle, e->data_size, e->offsets_size, e->return_error, e->return_error_param, e->return_error_line); + /* + * read-barrier to guarantee read of debug_id_done after + * done printing the fields of the entry + */ + smp_rmb(); + seq_printf(m, debug_id && debug_id == READ_ONCE(e->debug_id_done) ? + "\n" : " (incomplete)\n"); } static int binder_transaction_log_show(struct seq_file *m, void *unused) { struct binder_transaction_log *log = m->private; + unsigned int log_cur = atomic_read(&log->cur); + unsigned int count; + unsigned int cur; int i; - if (log->full) { - for (i = log->next; i < ARRAY_SIZE(log->entry); i++) - print_binder_transaction_log_entry(m, &log->entry[i]); + count = log_cur + 1; + cur = count < ARRAY_SIZE(log->entry) && !log->full ? + 0 : count % ARRAY_SIZE(log->entry); + if (count > ARRAY_SIZE(log->entry) || log->full) + count = ARRAY_SIZE(log->entry); + for (i = 0; i < count; i++) { + unsigned int index = cur++ % ARRAY_SIZE(log->entry); + + print_binder_transaction_log_entry(m, &log->entry[index]); } - for (i = 0; i < log->next; i++) - print_binder_transaction_log_entry(m, &log->entry[i]); return 0; } @@ -3793,6 +3833,9 @@ static int __init binder_init(void) struct binder_device *device; struct hlist_node *tmp; + atomic_set(&binder_transaction_log.cur, ~0U); + atomic_set(&binder_transaction_log_failed.cur, ~0U); + binder_debugfs_dir_entry_root = debugfs_create_dir("binder", NULL); if (binder_debugfs_dir_entry_root) binder_debugfs_dir_entry_proc = debugfs_create_dir("proc", -- cgit v1.2.3 From b6d282cea3f3ed3a5b09d687443213547db39499 Mon Sep 17 00:00:00 2001 From: Todd Kjos Date: Thu, 29 Jun 2017 12:01:54 -0700 Subject: binder: refactor binder_pop_transaction binder_pop_transaction needs to be split into 2 pieces to to allow the proc lock to be held on entry to dequeue the transaction stack, but no lock when kfree'ing the transaction. Split into binder_pop_transaction_locked and binder_free_transaction (the actual locks are still to be added). Signed-off-by: Todd Kjos Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index cb78a4e6872d..d2fcf3cc29a6 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -768,14 +768,16 @@ static int binder_dec_ref(struct binder_ref *ref, int strong) static void binder_pop_transaction(struct binder_thread *target_thread, struct binder_transaction *t) { - if (target_thread) { - BUG_ON(target_thread->transaction_stack != t); - BUG_ON(target_thread->transaction_stack->from != target_thread); - target_thread->transaction_stack = - target_thread->transaction_stack->from_parent; - t->from = NULL; - } - t->need_reply = 0; + BUG_ON(!target_thread); + BUG_ON(target_thread->transaction_stack != t); + BUG_ON(target_thread->transaction_stack->from != target_thread); + target_thread->transaction_stack = + target_thread->transaction_stack->from_parent; + t->from = NULL; +} + +static void binder_free_transaction(struct binder_transaction *t) +{ if (t->buffer) t->buffer->transaction = NULL; kfree(t); @@ -808,6 +810,7 @@ static void binder_send_failed_reply(struct binder_transaction *t, binder_pop_transaction(target_thread, t); target_thread->return_error = error_code; wake_up_interruptible(&target_thread->wait); + binder_free_transaction(t); } else { pr_err("reply failed, target thread, %d:%d, has error code %d already\n", target_thread->proc->pid, @@ -822,7 +825,7 @@ static void binder_send_failed_reply(struct binder_transaction *t, "send failed reply for transaction %d, target dead\n", t->debug_id); - binder_pop_transaction(target_thread, t); + binder_free_transaction(t); if (next == NULL) { binder_debug(BINDER_DEBUG_DEAD_BINDER, "reply failed, no target thread at root\n"); @@ -1806,6 +1809,7 @@ static void binder_transaction(struct binder_proc *proc, if (reply) { BUG_ON(t->buffer->async_transaction != 0); binder_pop_transaction(target_thread, in_reply_to); + binder_free_transaction(in_reply_to); } else if (!(t->flags & TF_ONE_WAY)) { BUG_ON(t->buffer->async_transaction != 0); t->need_reply = 1; @@ -2635,9 +2639,7 @@ retry: t->to_thread = thread; thread->transaction_stack = t; } else { - t->buffer->transaction = NULL; - kfree(t); - binder_stats_deleted(BINDER_STAT_TRANSACTION); + binder_free_transaction(t); } break; } @@ -2680,9 +2682,7 @@ static void binder_release_work(struct list_head *list) binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, "undelivered transaction %d\n", t->debug_id); - t->buffer->transaction = NULL; - kfree(t); - binder_stats_deleted(BINDER_STAT_TRANSACTION); + binder_free_transaction(t); } } break; case BINDER_WORK_TRANSACTION_COMPLETE: { -- cgit v1.2.3 From 26549d17741035b604048770f354c8c6b5e25ac9 Mon Sep 17 00:00:00 2001 From: Todd Kjos Date: Thu, 29 Jun 2017 12:01:55 -0700 Subject: binder: guarantee txn complete / errors delivered in-order Since errors are tracked in the return_error/return_error2 fields of the binder_thread object and BR_TRANSACTION_COMPLETEs can be tracked either in those fields or via the thread todo work list, it is possible for errors to be reported ahead of the associated txn complete. Use the thread todo work list for errors to guarantee order. Also changed binder_send_failed_reply to pop the transaction even if it failed to send a reply. Signed-off-by: Todd Kjos Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 127 +++++++++++++++++++++++++++-------------------- 1 file changed, 73 insertions(+), 54 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index d2fcf3cc29a6..84a57dd7b973 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -249,6 +249,7 @@ struct binder_work { enum { BINDER_WORK_TRANSACTION = 1, BINDER_WORK_TRANSACTION_COMPLETE, + BINDER_WORK_RETURN_ERROR, BINDER_WORK_NODE, BINDER_WORK_DEAD_BINDER, BINDER_WORK_DEAD_BINDER_AND_CLEAR, @@ -256,6 +257,11 @@ struct binder_work { } type; }; +struct binder_error { + struct binder_work work; + uint32_t cmd; +}; + struct binder_node { int debug_id; struct binder_work work; @@ -350,10 +356,8 @@ struct binder_thread { bool looper_need_return; /* can be written by other thread */ struct binder_transaction *transaction_stack; struct list_head todo; - uint32_t return_error; /* Write failed, return error code in read buf */ - uint32_t return_error2; /* Write failed, return error code in read */ - /* buffer. Used when sending a reply to a dead process that */ - /* we are also waiting on */ + struct binder_error return_error; + struct binder_error reply_error; wait_queue_head_t wait; struct binder_stats stats; }; @@ -794,29 +798,24 @@ static void binder_send_failed_reply(struct binder_transaction *t, while (1) { target_thread = t->from; if (target_thread) { - if (target_thread->return_error != BR_OK && - target_thread->return_error2 == BR_OK) { - target_thread->return_error2 = - target_thread->return_error; - target_thread->return_error = BR_OK; - } - if (target_thread->return_error == BR_OK) { - binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, - "send failed reply for transaction %d to %d:%d\n", - t->debug_id, - target_thread->proc->pid, - target_thread->pid); - - binder_pop_transaction(target_thread, t); - target_thread->return_error = error_code; + binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, + "send failed reply for transaction %d to %d:%d\n", + t->debug_id, + target_thread->proc->pid, + target_thread->pid); + + binder_pop_transaction(target_thread, t); + if (target_thread->reply_error.cmd == BR_OK) { + target_thread->reply_error.cmd = error_code; + list_add_tail( + &target_thread->reply_error.work.entry, + &target_thread->todo); wake_up_interruptible(&target_thread->wait); - binder_free_transaction(t); } else { - pr_err("reply failed, target thread, %d:%d, has error code %d already\n", - target_thread->proc->pid, - target_thread->pid, - target_thread->return_error); + WARN(1, "Unexpected reply error: %u\n", + target_thread->reply_error.cmd); } + binder_free_transaction(t); return; } next = t->from_parent; @@ -1884,12 +1883,17 @@ err_no_context_mgr_node: WRITE_ONCE(fe->debug_id_done, t_debug_id); } - BUG_ON(thread->return_error != BR_OK); + BUG_ON(thread->return_error.cmd != BR_OK); if (in_reply_to) { - thread->return_error = BR_TRANSACTION_COMPLETE; + thread->return_error.cmd = BR_TRANSACTION_COMPLETE; + list_add_tail(&thread->return_error.work.entry, + &thread->todo); binder_send_failed_reply(in_reply_to, return_error); - } else - thread->return_error = return_error; + } else { + thread->return_error.cmd = return_error; + list_add_tail(&thread->return_error.work.entry, + &thread->todo); + } } static int binder_thread_write(struct binder_proc *proc, @@ -1903,7 +1907,7 @@ static int binder_thread_write(struct binder_proc *proc, void __user *ptr = buffer + *consumed; void __user *end = buffer + size; - while (ptr < end && thread->return_error == BR_OK) { + while (ptr < end && thread->return_error.cmd == BR_OK) { if (get_user(cmd, (uint32_t __user *)ptr)) return -EFAULT; ptr += sizeof(uint32_t); @@ -2183,7 +2187,12 @@ static int binder_thread_write(struct binder_proc *proc, } death = kzalloc(sizeof(*death), GFP_KERNEL); if (death == NULL) { - thread->return_error = BR_ERROR; + WARN_ON(thread->return_error.cmd != + BR_OK); + thread->return_error.cmd = BR_ERROR; + list_add_tail( + &thread->return_error.work.entry, + &thread->todo); binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, "%d:%d BC_REQUEST_DEATH_NOTIFICATION failed\n", proc->pid, thread->pid); @@ -2299,8 +2308,7 @@ static int binder_has_proc_work(struct binder_proc *proc, static int binder_has_thread_work(struct binder_thread *thread) { - return !list_empty(&thread->todo) || thread->return_error != BR_OK || - thread->looper_need_return; + return !list_empty(&thread->todo) || thread->looper_need_return; } static int binder_put_node_cmd(struct binder_proc *proc, @@ -2356,25 +2364,6 @@ retry: wait_for_proc_work = thread->transaction_stack == NULL && list_empty(&thread->todo); - if (thread->return_error != BR_OK && ptr < end) { - if (thread->return_error2 != BR_OK) { - if (put_user(thread->return_error2, (uint32_t __user *)ptr)) - return -EFAULT; - ptr += sizeof(uint32_t); - binder_stat_br(proc, thread, thread->return_error2); - if (ptr == end) - goto done; - thread->return_error2 = BR_OK; - } - if (put_user(thread->return_error, (uint32_t __user *)ptr)) - return -EFAULT; - ptr += sizeof(uint32_t); - binder_stat_br(proc, thread, thread->return_error); - thread->return_error = BR_OK; - goto done; - } - - thread->looper |= BINDER_LOOPER_STATE_WAITING; if (wait_for_proc_work) proc->ready_threads++; @@ -2441,6 +2430,19 @@ retry: case BINDER_WORK_TRANSACTION: { t = container_of(w, struct binder_transaction, work); } break; + case BINDER_WORK_RETURN_ERROR: { + struct binder_error *e = container_of( + w, struct binder_error, work); + + WARN_ON(e->cmd == BR_OK); + if (put_user(e->cmd, (uint32_t __user *)ptr)) + return -EFAULT; + e->cmd = BR_OK; + ptr += sizeof(uint32_t); + + binder_stat_br(proc, thread, cmd); + list_del(&w->entry); + } break; case BINDER_WORK_TRANSACTION_COMPLETE: { cmd = BR_TRANSACTION_COMPLETE; if (put_user(cmd, (uint32_t __user *)ptr)) @@ -2685,6 +2687,14 @@ static void binder_release_work(struct list_head *list) binder_free_transaction(t); } } break; + case BINDER_WORK_RETURN_ERROR: { + struct binder_error *e = container_of( + w, struct binder_error, work); + + binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, + "undelivered TRANSACTION_ERROR: %u\n", + e->cmd); + } break; case BINDER_WORK_TRANSACTION_COMPLETE: { binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, "undelivered TRANSACTION_COMPLETE\n"); @@ -2740,8 +2750,10 @@ static struct binder_thread *binder_get_thread(struct binder_proc *proc) rb_link_node(&thread->rb_node, parent, p); rb_insert_color(&thread->rb_node, &proc->threads); thread->looper_need_return = true; - thread->return_error = BR_OK; - thread->return_error2 = BR_OK; + thread->return_error.work.type = BINDER_WORK_RETURN_ERROR; + thread->return_error.cmd = BR_OK; + thread->reply_error.work.type = BINDER_WORK_RETURN_ERROR; + thread->reply_error.cmd = BR_OK; } return thread; } @@ -2799,7 +2811,7 @@ static unsigned int binder_poll(struct file *filp, thread = binder_get_thread(proc); wait_for_proc_work = thread->transaction_stack == NULL && - list_empty(&thread->todo) && thread->return_error == BR_OK; + list_empty(&thread->todo); binder_unlock(__func__); @@ -3378,6 +3390,13 @@ static void print_binder_work(struct seq_file *m, const char *prefix, t = container_of(w, struct binder_transaction, work); print_binder_transaction(m, transaction_prefix, t); break; + case BINDER_WORK_RETURN_ERROR: { + struct binder_error *e = container_of( + w, struct binder_error, work); + + seq_printf(m, "%stransaction error: %u\n", + prefix, e->cmd); + } break; case BINDER_WORK_TRANSACTION_COMPLETE: seq_printf(m, "%stransaction complete\n", prefix); break; -- cgit v1.2.3 From eb34983ba170f236b6801c7bee717da6abe4aff0 Mon Sep 17 00:00:00 2001 From: Todd Kjos Date: Thu, 29 Jun 2017 12:01:56 -0700 Subject: binder: make sure target_node has strong ref When initiating a transaction, the target_node must have a strong ref on it. Then we take a second strong ref to make sure the node survives until the transaction is complete. Signed-off-by: Todd Kjos Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 84a57dd7b973..fb79f40111eb 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -1469,8 +1469,19 @@ static void binder_transaction(struct binder_proc *proc, if (tr->target.handle) { struct binder_ref *ref; + /* + * There must already be a strong ref + * on this node. If so, do a strong + * increment on the node to ensure it + * stays alive until the transaction is + * done. + */ ref = binder_get_ref(proc, tr->target.handle, true); - if (ref == NULL) { + if (ref) { + binder_inc_node(ref->node, 1, 0, NULL); + target_node = ref->node; + } + if (target_node == NULL) { binder_user_error("%d:%d got transaction to invalid handle\n", proc->pid, thread->pid); return_error = BR_FAILED_REPLY; @@ -1478,7 +1489,6 @@ static void binder_transaction(struct binder_proc *proc, return_error_line = __LINE__; goto err_invalid_target_handle; } - target_node = ref->node; } else { mutex_lock(&context->context_mgr_node_lock); target_node = context->binder_context_mgr_node; @@ -1488,6 +1498,7 @@ static void binder_transaction(struct binder_proc *proc, return_error_line = __LINE__; goto err_no_context_mgr_node; } + binder_inc_node(target_node, 1, 0, NULL); mutex_unlock(&context->context_mgr_node_lock); } e->to_node = target_node->debug_id; @@ -1608,9 +1619,6 @@ static void binder_transaction(struct binder_proc *proc, t->buffer->transaction = t; t->buffer->target_node = target_node; trace_binder_transaction_alloc_buf(t->buffer); - if (target_node) - binder_inc_node(target_node, 1, 0, NULL); - off_start = (binder_size_t *)(t->buffer->data + ALIGN(tr->data_size, sizeof(void *))); offp = off_start; @@ -1846,6 +1854,7 @@ err_bad_parent: err_copy_data_failed: trace_binder_transaction_failed_buffer_release(t->buffer); binder_transaction_buffer_release(target_proc, t->buffer, offp); + target_node = NULL; t->buffer->transaction = NULL; binder_alloc_free_buf(&target_proc->alloc, t->buffer); err_binder_alloc_buf_failed: @@ -1860,6 +1869,9 @@ err_empty_call_stack: err_dead_binder: err_invalid_target_handle: err_no_context_mgr_node: + if (target_node) + binder_dec_node(target_node, 1, 0); + binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, "%d:%d transaction failed %d/%d, size %lld-%lld line %d\n", proc->pid, thread->pid, return_error, return_error_param, -- cgit v1.2.3 From 7a4408c6bd3eb1dafba67986259191be081e3efb Mon Sep 17 00:00:00 2001 From: Todd Kjos Date: Thu, 29 Jun 2017 12:01:57 -0700 Subject: binder: make sure accesses to proc/thread are safe binder_thread and binder_proc may be accessed by other threads when processing transaction. Therefore they must be prevented from being freed while a transaction is in progress that references them. This is done by introducing a temporary reference counter for threads and procs that indicates that the object is in use and must not be freed. binder_thread_dec_tmpref() and binder_proc_dec_tmpref() are used to decrement the temporary reference. It is safe to free a binder_thread if there is no reference and it has been released (indicated by thread->is_dead). It is safe to free a binder_proc if it has no remaining threads and no reference. A spinlock is added to the binder_transaction to safely access and set references for t->from and for debug code to safely access t->to_thread and t->to_proc. Signed-off-by: Todd Kjos Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 233 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 206 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index fb79f40111eb..ca7d866b89e8 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -325,6 +325,7 @@ struct binder_proc { struct files_struct *files; struct hlist_node deferred_work_node; int deferred_work; + bool is_dead; struct list_head todo; wait_queue_head_t wait; @@ -334,6 +335,7 @@ struct binder_proc { int requested_threads; int requested_threads_started; int ready_threads; + int tmp_ref; long default_priority; struct dentry *debugfs_entry; struct binder_alloc alloc; @@ -360,6 +362,8 @@ struct binder_thread { struct binder_error reply_error; wait_queue_head_t wait; struct binder_stats stats; + atomic_t tmp_ref; + bool is_dead; }; struct binder_transaction { @@ -379,10 +383,19 @@ struct binder_transaction { long priority; long saved_priority; kuid_t sender_euid; + /** + * @lock: protects @from, @to_proc, and @to_thread + * + * @from, @to_proc, and @to_thread can be set to NULL + * during thread teardown + */ + spinlock_t lock; }; static void binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer); +static void binder_free_thread(struct binder_thread *thread); +static void binder_free_proc(struct binder_proc *proc); static int task_get_unused_fd_flags(struct binder_proc *proc, int flags) { @@ -780,6 +793,79 @@ static void binder_pop_transaction(struct binder_thread *target_thread, t->from = NULL; } +/** + * binder_thread_dec_tmpref() - decrement thread->tmp_ref + * @thread: thread to decrement + * + * A thread needs to be kept alive while being used to create or + * handle a transaction. binder_get_txn_from() is used to safely + * extract t->from from a binder_transaction and keep the thread + * indicated by t->from from being freed. When done with that + * binder_thread, this function is called to decrement the + * tmp_ref and free if appropriate (thread has been released + * and no transaction being processed by the driver) + */ +static void binder_thread_dec_tmpref(struct binder_thread *thread) +{ + /* + * atomic is used to protect the counter value while + * it cannot reach zero or thread->is_dead is false + * + * TODO: future patch adds locking to ensure that the + * check of tmp_ref and is_dead is done with a lock held + */ + atomic_dec(&thread->tmp_ref); + if (thread->is_dead && !atomic_read(&thread->tmp_ref)) { + binder_free_thread(thread); + return; + } +} + +/** + * binder_proc_dec_tmpref() - decrement proc->tmp_ref + * @proc: proc to decrement + * + * A binder_proc needs to be kept alive while being used to create or + * handle a transaction. proc->tmp_ref is incremented when + * creating a new transaction or the binder_proc is currently in-use + * by threads that are being released. When done with the binder_proc, + * this function is called to decrement the counter and free the + * proc if appropriate (proc has been released, all threads have + * been released and not currenly in-use to process a transaction). + */ +static void binder_proc_dec_tmpref(struct binder_proc *proc) +{ + proc->tmp_ref--; + if (proc->is_dead && RB_EMPTY_ROOT(&proc->threads) && + !proc->tmp_ref) { + binder_free_proc(proc); + return; + } +} + +/** + * binder_get_txn_from() - safely extract the "from" thread in transaction + * @t: binder transaction for t->from + * + * Atomically return the "from" thread and increment the tmp_ref + * count for the thread to ensure it stays alive until + * binder_thread_dec_tmpref() is called. + * + * Return: the value of t->from + */ +static struct binder_thread *binder_get_txn_from( + struct binder_transaction *t) +{ + struct binder_thread *from; + + spin_lock(&t->lock); + from = t->from; + if (from) + atomic_inc(&from->tmp_ref); + spin_unlock(&t->lock); + return from; +} + static void binder_free_transaction(struct binder_transaction *t) { if (t->buffer) @@ -796,7 +882,7 @@ static void binder_send_failed_reply(struct binder_transaction *t, BUG_ON(t->flags & TF_ONE_WAY); while (1) { - target_thread = t->from; + target_thread = binder_get_txn_from(t); if (target_thread) { binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, "send failed reply for transaction %d to %d:%d\n", @@ -815,6 +901,7 @@ static void binder_send_failed_reply(struct binder_transaction *t, WARN(1, "Unexpected reply error: %u\n", target_thread->reply_error.cmd); } + binder_thread_dec_tmpref(target_thread); binder_free_transaction(t); return; } @@ -1395,7 +1482,7 @@ static void binder_transaction(struct binder_proc *proc, binder_size_t *offp, *off_end, *off_start; binder_size_t off_min; u8 *sg_bufp, *sg_buf_end; - struct binder_proc *target_proc; + struct binder_proc *target_proc = NULL; struct binder_thread *target_thread = NULL; struct binder_node *target_node = NULL; struct list_head *target_list; @@ -1432,12 +1519,14 @@ static void binder_transaction(struct binder_proc *proc, } binder_set_nice(in_reply_to->saved_priority); if (in_reply_to->to_thread != thread) { + spin_lock(&in_reply_to->lock); binder_user_error("%d:%d got reply transaction with bad transaction stack, transaction %d has target %d:%d\n", proc->pid, thread->pid, in_reply_to->debug_id, in_reply_to->to_proc ? in_reply_to->to_proc->pid : 0, in_reply_to->to_thread ? in_reply_to->to_thread->pid : 0); + spin_unlock(&in_reply_to->lock); return_error = BR_FAILED_REPLY; return_error_param = -EPROTO; return_error_line = __LINE__; @@ -1445,7 +1534,7 @@ static void binder_transaction(struct binder_proc *proc, goto err_bad_call_stack; } thread->transaction_stack = in_reply_to->to_parent; - target_thread = in_reply_to->from; + target_thread = binder_get_txn_from(in_reply_to); if (target_thread == NULL) { return_error = BR_DEAD_REPLY; return_error_line = __LINE__; @@ -1465,6 +1554,7 @@ static void binder_transaction(struct binder_proc *proc, goto err_dead_binder; } target_proc = target_thread->proc; + target_proc->tmp_ref++; } else { if (tr->target.handle) { struct binder_ref *ref; @@ -1508,6 +1598,7 @@ static void binder_transaction(struct binder_proc *proc, return_error_line = __LINE__; goto err_dead_binder; } + target_proc->tmp_ref++; if (security_binder_transaction(proc->tsk, target_proc->tsk) < 0) { return_error = BR_FAILED_REPLY; @@ -1520,19 +1611,30 @@ static void binder_transaction(struct binder_proc *proc, tmp = thread->transaction_stack; if (tmp->to_thread != thread) { + spin_lock(&tmp->lock); binder_user_error("%d:%d got new transaction with bad transaction stack, transaction %d has target %d:%d\n", proc->pid, thread->pid, tmp->debug_id, tmp->to_proc ? tmp->to_proc->pid : 0, tmp->to_thread ? tmp->to_thread->pid : 0); + spin_unlock(&tmp->lock); return_error = BR_FAILED_REPLY; return_error_param = -EPROTO; return_error_line = __LINE__; goto err_bad_call_stack; } while (tmp) { - if (tmp->from && tmp->from->proc == target_proc) - target_thread = tmp->from; + struct binder_thread *from; + + spin_lock(&tmp->lock); + from = tmp->from; + if (from && from->proc == target_proc) { + atomic_inc(&from->tmp_ref); + target_thread = from; + spin_unlock(&tmp->lock); + break; + } + spin_unlock(&tmp->lock); tmp = tmp->from_parent; } } @@ -1556,6 +1658,7 @@ static void binder_transaction(struct binder_proc *proc, goto err_alloc_t_failed; } binder_stats_created(BINDER_STAT_TRANSACTION); + spin_lock_init(&t->lock); tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL); if (tcomplete == NULL) { @@ -1814,6 +1917,8 @@ static void binder_transaction(struct binder_proc *proc, list_add_tail(&tcomplete->entry, &thread->todo); if (reply) { + if (target_thread->is_dead) + goto err_dead_proc_or_thread; BUG_ON(t->buffer->async_transaction != 0); binder_pop_transaction(target_thread, in_reply_to); binder_free_transaction(in_reply_to); @@ -1822,6 +1927,11 @@ static void binder_transaction(struct binder_proc *proc, t->need_reply = 1; t->from_parent = thread->transaction_stack; thread->transaction_stack = t; + if (target_proc->is_dead || + (target_thread && target_thread->is_dead)) { + binder_pop_transaction(thread, t); + goto err_dead_proc_or_thread; + } } else { BUG_ON(target_node == NULL); BUG_ON(t->buffer->async_transaction != 1); @@ -1830,6 +1940,9 @@ static void binder_transaction(struct binder_proc *proc, target_wait = NULL; } else target_node->has_async_transaction = 1; + if (target_proc->is_dead || + (target_thread && target_thread->is_dead)) + goto err_dead_proc_or_thread; } t->work.type = BINDER_WORK_TRANSACTION; list_add_tail(&t->work.entry, target_list); @@ -1839,6 +1952,9 @@ static void binder_transaction(struct binder_proc *proc, else wake_up_interruptible(target_wait); } + if (target_thread) + binder_thread_dec_tmpref(target_thread); + binder_proc_dec_tmpref(target_proc); /* * write barrier to synchronize with initialization * of log entry @@ -1847,6 +1963,9 @@ static void binder_transaction(struct binder_proc *proc, WRITE_ONCE(e->debug_id_done, t_debug_id); return; +err_dead_proc_or_thread: + return_error = BR_DEAD_REPLY; + return_error_line = __LINE__; err_translate_failed: err_bad_object_type: err_bad_offset: @@ -1869,6 +1988,10 @@ err_empty_call_stack: err_dead_binder: err_invalid_target_handle: err_no_context_mgr_node: + if (target_thread) + binder_thread_dec_tmpref(target_thread); + if (target_proc) + binder_proc_dec_tmpref(target_proc); if (target_node) binder_dec_node(target_node, 1, 0); @@ -2421,6 +2544,7 @@ retry: struct binder_transaction_data tr; struct binder_work *w; struct binder_transaction *t = NULL; + struct binder_thread *t_from; if (!list_empty(&thread->todo)) { w = list_first_entry(&thread->todo, struct binder_work, @@ -2609,8 +2733,9 @@ retry: tr.flags = t->flags; tr.sender_euid = from_kuid(current_user_ns(), t->sender_euid); - if (t->from) { - struct task_struct *sender = t->from->proc->tsk; + t_from = binder_get_txn_from(t); + if (t_from) { + struct task_struct *sender = t_from->proc->tsk; tr.sender_pid = task_tgid_nr_ns(sender, task_active_pid_ns(current)); @@ -2627,11 +2752,17 @@ retry: ALIGN(t->buffer->data_size, sizeof(void *)); - if (put_user(cmd, (uint32_t __user *)ptr)) + if (put_user(cmd, (uint32_t __user *)ptr)) { + if (t_from) + binder_thread_dec_tmpref(t_from); return -EFAULT; + } ptr += sizeof(uint32_t); - if (copy_to_user(ptr, &tr, sizeof(tr))) + if (copy_to_user(ptr, &tr, sizeof(tr))) { + if (t_from) + binder_thread_dec_tmpref(t_from); return -EFAULT; + } ptr += sizeof(tr); trace_binder_transaction_received(t); @@ -2641,11 +2772,13 @@ retry: proc->pid, thread->pid, (cmd == BR_TRANSACTION) ? "BR_TRANSACTION" : "BR_REPLY", - t->debug_id, t->from ? t->from->proc->pid : 0, - t->from ? t->from->pid : 0, cmd, + t->debug_id, t_from ? t_from->proc->pid : 0, + t_from ? t_from->pid : 0, cmd, t->buffer->data_size, t->buffer->offsets_size, (u64)tr.data.ptr.buffer, (u64)tr.data.ptr.offsets); + if (t_from) + binder_thread_dec_tmpref(t_from); list_del(&t->work.entry); t->buffer->allow_user_free = 1; if (cmd == BR_TRANSACTION && !(t->flags & TF_ONE_WAY)) { @@ -2757,6 +2890,7 @@ static struct binder_thread *binder_get_thread(struct binder_proc *proc) binder_stats_created(BINDER_STAT_THREAD); thread->proc = proc; thread->pid = current->pid; + atomic_set(&thread->tmp_ref, 0); init_waitqueue_head(&thread->wait); INIT_LIST_HEAD(&thread->todo); rb_link_node(&thread->rb_node, parent, p); @@ -2770,18 +2904,55 @@ static struct binder_thread *binder_get_thread(struct binder_proc *proc) return thread; } -static int binder_free_thread(struct binder_proc *proc, - struct binder_thread *thread) +static void binder_free_proc(struct binder_proc *proc) +{ + BUG_ON(!list_empty(&proc->todo)); + BUG_ON(!list_empty(&proc->delivered_death)); + binder_alloc_deferred_release(&proc->alloc); + put_task_struct(proc->tsk); + binder_stats_deleted(BINDER_STAT_PROC); + kfree(proc); +} + +static void binder_free_thread(struct binder_thread *thread) +{ + BUG_ON(!list_empty(&thread->todo)); + binder_stats_deleted(BINDER_STAT_THREAD); + binder_proc_dec_tmpref(thread->proc); + kfree(thread); +} + +static int binder_thread_release(struct binder_proc *proc, + struct binder_thread *thread) { struct binder_transaction *t; struct binder_transaction *send_reply = NULL; int active_transactions = 0; + struct binder_transaction *last_t = NULL; + /* + * take a ref on the proc so it survives + * after we remove this thread from proc->threads. + * The corresponding dec is when we actually + * free the thread in binder_free_thread() + */ + proc->tmp_ref++; + /* + * take a ref on this thread to ensure it + * survives while we are releasing it + */ + atomic_inc(&thread->tmp_ref); rb_erase(&thread->rb_node, &proc->threads); t = thread->transaction_stack; - if (t && t->to_thread == thread) - send_reply = t; + if (t) { + spin_lock(&t->lock); + if (t->to_thread == thread) + send_reply = t; + } + thread->is_dead = true; + while (t) { + last_t = t; active_transactions++; binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, "release %d:%d transaction %d %s, still active\n", @@ -2802,12 +2973,15 @@ static int binder_free_thread(struct binder_proc *proc, t = t->from_parent; } else BUG(); + spin_unlock(&last_t->lock); + if (t) + spin_lock(&t->lock); } + if (send_reply) binder_send_failed_reply(send_reply, BR_DEAD_REPLY); binder_release_work(&thread->todo); - kfree(thread); - binder_stats_deleted(BINDER_STAT_THREAD); + binder_thread_dec_tmpref(thread); return active_transactions; } @@ -2995,7 +3169,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) case BINDER_THREAD_EXIT: binder_debug(BINDER_DEBUG_THREADS, "%d:%d exit\n", proc->pid, thread->pid); - binder_free_thread(proc, thread); + binder_thread_release(proc, thread); thread = NULL; break; case BINDER_VERSION: { @@ -3265,7 +3439,13 @@ static void binder_deferred_release(struct binder_proc *proc) context->binder_context_mgr_node = NULL; } mutex_unlock(&context->context_mgr_node_lock); + /* + * Make sure proc stays alive after we + * remove all the threads + */ + proc->tmp_ref++; + proc->is_dead = true; threads = 0; active_transactions = 0; while ((n = rb_first(&proc->threads))) { @@ -3273,7 +3453,7 @@ static void binder_deferred_release(struct binder_proc *proc) thread = rb_entry(n, struct binder_thread, rb_node); threads++; - active_transactions += binder_free_thread(proc, thread); + active_transactions += binder_thread_release(proc, thread); } nodes = 0; @@ -3299,17 +3479,12 @@ static void binder_deferred_release(struct binder_proc *proc) binder_release_work(&proc->todo); binder_release_work(&proc->delivered_death); - binder_alloc_deferred_release(&proc->alloc); - binder_stats_deleted(BINDER_STAT_PROC); - - put_task_struct(proc->tsk); - binder_debug(BINDER_DEBUG_OPEN_CLOSE, "%s: %d threads %d, nodes %d (ref %d), refs %d, active transactions %d\n", __func__, proc->pid, threads, nodes, incoming_refs, outgoing_refs, active_transactions); - kfree(proc); + binder_proc_dec_tmpref(proc); } static void binder_deferred_func(struct work_struct *work) @@ -3370,6 +3545,7 @@ binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer) static void print_binder_transaction(struct seq_file *m, const char *prefix, struct binder_transaction *t) { + spin_lock(&t->lock); seq_printf(m, "%s %d: %p from %d:%d to %d:%d code %x flags %x pri %ld r%d", prefix, t->debug_id, t, @@ -3378,6 +3554,8 @@ static void print_binder_transaction(struct seq_file *m, const char *prefix, t->to_proc ? t->to_proc->pid : 0, t->to_thread ? t->to_thread->pid : 0, t->code, t->flags, t->priority, t->need_reply); + spin_unlock(&t->lock); + if (t->buffer == NULL) { seq_puts(m, " buffer free\n"); return; @@ -3442,9 +3620,10 @@ static void print_binder_thread(struct seq_file *m, size_t start_pos = m->count; size_t header_pos; - seq_printf(m, " thread %d: l %02x need_return %d\n", + seq_printf(m, " thread %d: l %02x need_return %d tr %d\n", thread->pid, thread->looper, - thread->looper_need_return); + thread->looper_need_return, + atomic_read(&thread->tmp_ref)); header_pos = m->count; t = thread->transaction_stack; while (t) { -- cgit v1.2.3 From 372e3147df7016ebeaa372939e8774a1292db558 Mon Sep 17 00:00:00 2001 From: Todd Kjos Date: Thu, 29 Jun 2017 12:01:58 -0700 Subject: binder: refactor binder ref inc/dec for thread safety Once locks are added, binder_ref's will only be accessed safely with the proc lock held. Refactor the inc/dec paths to make them atomic with the binder_get_ref* paths and node inc/dec. For example, instead of: ref = binder_get_ref(proc, handle, strong); ... binder_dec_ref(ref, strong); we now have: ret = binder_dec_ref_for_handle(proc, handle, strong, &rdata); Since the actual ref is no longer exposed to callers, a new struct binder_ref_data is introduced which can be used to return a copy of ref state. Signed-off-by: Todd Kjos Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 484 ++++++++++++++++++++++++++++++----------- drivers/android/binder_trace.h | 32 +-- 2 files changed, 379 insertions(+), 137 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index ca7d866b89e8..4d0b99862339 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -291,20 +291,51 @@ struct binder_ref_death { binder_uintptr_t cookie; }; +/** + * struct binder_ref_data - binder_ref counts and id + * @debug_id: unique ID for the ref + * @desc: unique userspace handle for ref + * @strong: strong ref count (debugging only if not locked) + * @weak: weak ref count (debugging only if not locked) + * + * Structure to hold ref count and ref id information. Since + * the actual ref can only be accessed with a lock, this structure + * is used to return information about the ref to callers of + * ref inc/dec functions. + */ +struct binder_ref_data { + int debug_id; + uint32_t desc; + int strong; + int weak; +}; + +/** + * struct binder_ref - struct to track references on nodes + * @data: binder_ref_data containing id, handle, and current refcounts + * @rb_node_desc: node for lookup by @data.desc in proc's rb_tree + * @rb_node_node: node for lookup by @node in proc's rb_tree + * @node_entry: list entry for node->refs list in target node + * @proc: binder_proc containing ref + * @node: binder_node of target node. When cleaning up a + * ref for deletion in binder_cleanup_ref, a non-NULL + * @node indicates the node must be freed + * @death: pointer to death notification (ref_death) if requested + * + * Structure to track references from procA to target node (on procB). This + * structure is unsafe to access without holding @proc->outer_lock. + */ struct binder_ref { /* Lookups needed: */ /* node + proc => ref (transaction) */ /* desc + proc => ref (transaction, inc/dec ref) */ /* node => refs + procs (proc exit) */ - int debug_id; + struct binder_ref_data data; struct rb_node rb_node_desc; struct rb_node rb_node_node; struct hlist_node node_entry; struct binder_proc *proc; struct binder_node *node; - uint32_t desc; - int strong; - int weak; struct binder_ref_death *death; }; @@ -627,11 +658,11 @@ static struct binder_ref *binder_get_ref(struct binder_proc *proc, while (n) { ref = rb_entry(n, struct binder_ref, rb_node_desc); - if (desc < ref->desc) { + if (desc < ref->data.desc) { n = n->rb_left; - } else if (desc > ref->desc) { + } else if (desc > ref->data.desc) { n = n->rb_right; - } else if (need_strong_ref && !ref->strong) { + } else if (need_strong_ref && !ref->data.strong) { binder_user_error("tried to use weak ref as strong ref\n"); return NULL; } else { @@ -641,14 +672,33 @@ static struct binder_ref *binder_get_ref(struct binder_proc *proc, return NULL; } +/** + * binder_get_ref_for_node() - get the ref associated with given node + * @proc: binder_proc that owns the ref + * @node: binder_node of target + * @new_ref: newly allocated binder_ref to be initialized or %NULL + * + * Look up the ref for the given node and return it if it exists + * + * If it doesn't exist and the caller provides a newly allocated + * ref, initialize the fields of the newly allocated ref and insert + * into the given proc rb_trees and node refs list. + * + * Return: the ref for node. It is possible that another thread + * allocated/initialized the ref first in which case the + * returned ref would be different than the passed-in + * new_ref. new_ref must be kfree'd by the caller in + * this case. + */ static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc, - struct binder_node *node) + struct binder_node *node, + struct binder_ref *new_ref) { - struct rb_node *n; + struct binder_context *context = proc->context; struct rb_node **p = &proc->refs_by_node.rb_node; struct rb_node *parent = NULL; - struct binder_ref *ref, *new_ref; - struct binder_context *context = proc->context; + struct binder_ref *ref; + struct rb_node *n; while (*p) { parent = *p; @@ -661,22 +711,22 @@ static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc, else return ref; } - new_ref = kzalloc(sizeof(*ref), GFP_KERNEL); - if (new_ref == NULL) + if (!new_ref) return NULL; + binder_stats_created(BINDER_STAT_REF); - new_ref->debug_id = atomic_inc_return(&binder_last_id); + new_ref->data.debug_id = atomic_inc_return(&binder_last_id); new_ref->proc = proc; new_ref->node = node; rb_link_node(&new_ref->rb_node_node, parent, p); rb_insert_color(&new_ref->rb_node_node, &proc->refs_by_node); - new_ref->desc = (node == context->binder_context_mgr_node) ? 0 : 1; + new_ref->data.desc = (node == context->binder_context_mgr_node) ? 0 : 1; for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) { ref = rb_entry(n, struct binder_ref, rb_node_desc); - if (ref->desc > new_ref->desc) + if (ref->data.desc > new_ref->data.desc) break; - new_ref->desc = ref->desc + 1; + new_ref->data.desc = ref->data.desc + 1; } p = &proc->refs_by_desc.rb_node; @@ -684,9 +734,9 @@ static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc, parent = *p; ref = rb_entry(parent, struct binder_ref, rb_node_desc); - if (new_ref->desc < ref->desc) + if (new_ref->data.desc < ref->data.desc) p = &(*p)->rb_left; - else if (new_ref->desc > ref->desc) + else if (new_ref->data.desc > ref->data.desc) p = &(*p)->rb_right; else BUG(); @@ -697,89 +747,267 @@ static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc, binder_debug(BINDER_DEBUG_INTERNAL_REFS, "%d new ref %d desc %d for node %d\n", - proc->pid, new_ref->debug_id, new_ref->desc, + proc->pid, new_ref->data.debug_id, new_ref->data.desc, node->debug_id); return new_ref; } -static void binder_delete_ref(struct binder_ref *ref) +static void binder_cleanup_ref(struct binder_ref *ref) { binder_debug(BINDER_DEBUG_INTERNAL_REFS, "%d delete ref %d desc %d for node %d\n", - ref->proc->pid, ref->debug_id, ref->desc, + ref->proc->pid, ref->data.debug_id, ref->data.desc, ref->node->debug_id); rb_erase(&ref->rb_node_desc, &ref->proc->refs_by_desc); rb_erase(&ref->rb_node_node, &ref->proc->refs_by_node); - if (ref->strong) + + if (ref->data.strong) binder_dec_node(ref->node, 1, 1); + hlist_del(&ref->node_entry); binder_dec_node(ref->node, 0, 1); + if (ref->death) { binder_debug(BINDER_DEBUG_DEAD_BINDER, "%d delete ref %d desc %d has death notification\n", - ref->proc->pid, ref->debug_id, ref->desc); + ref->proc->pid, ref->data.debug_id, + ref->data.desc); list_del(&ref->death->work.entry); - kfree(ref->death); binder_stats_deleted(BINDER_STAT_DEATH); } - kfree(ref); binder_stats_deleted(BINDER_STAT_REF); } +/** + * binder_inc_ref() - increment the ref for given handle + * @ref: ref to be incremented + * @strong: if true, strong increment, else weak + * @target_list: list to queue node work on + * + * Increment the ref. + * + * Return: 0, if successful, else errno + */ static int binder_inc_ref(struct binder_ref *ref, int strong, struct list_head *target_list) { int ret; if (strong) { - if (ref->strong == 0) { + if (ref->data.strong == 0) { ret = binder_inc_node(ref->node, 1, 1, target_list); if (ret) return ret; } - ref->strong++; + ref->data.strong++; } else { - if (ref->weak == 0) { + if (ref->data.weak == 0) { ret = binder_inc_node(ref->node, 0, 1, target_list); if (ret) return ret; } - ref->weak++; + ref->data.weak++; } return 0; } - -static int binder_dec_ref(struct binder_ref *ref, int strong) +/** + * binder_dec_ref() - dec the ref for given handle + * @ref: ref to be decremented + * @strong: if true, strong decrement, else weak + * + * Decrement the ref. + * + * TODO: kfree is avoided here since an upcoming patch + * will put this under a lock. + * + * Return: true if ref is cleaned up and ready to be freed + */ +static bool binder_dec_ref(struct binder_ref *ref, int strong) { if (strong) { - if (ref->strong == 0) { + if (ref->data.strong == 0) { binder_user_error("%d invalid dec strong, ref %d desc %d s %d w %d\n", - ref->proc->pid, ref->debug_id, - ref->desc, ref->strong, ref->weak); - return -EINVAL; + ref->proc->pid, ref->data.debug_id, + ref->data.desc, ref->data.strong, + ref->data.weak); + return false; } - ref->strong--; - if (ref->strong == 0) { + ref->data.strong--; + if (ref->data.strong == 0) { int ret; ret = binder_dec_node(ref->node, strong, 1); if (ret) - return ret; + return false; } } else { - if (ref->weak == 0) { + if (ref->data.weak == 0) { binder_user_error("%d invalid dec weak, ref %d desc %d s %d w %d\n", - ref->proc->pid, ref->debug_id, - ref->desc, ref->strong, ref->weak); - return -EINVAL; + ref->proc->pid, ref->data.debug_id, + ref->data.desc, ref->data.strong, + ref->data.weak); + return false; } - ref->weak--; + ref->data.weak--; } - if (ref->strong == 0 && ref->weak == 0) - binder_delete_ref(ref); - return 0; + if (ref->data.strong == 0 && ref->data.weak == 0) { + binder_cleanup_ref(ref); + /* + * TODO: we could kfree(ref) here, but an upcoming + * patch will call this with a lock held, so we + * return an indication that the ref should be + * freed. + */ + return true; + } + return false; +} + +/** + * binder_get_node_from_ref() - get the node from the given proc/desc + * @proc: proc containing the ref + * @desc: the handle associated with the ref + * @need_strong_ref: if true, only return node if ref is strong + * @rdata: the id/refcount data for the ref + * + * Given a proc and ref handle, return the associated binder_node + * + * Return: a binder_node or NULL if not found or not strong when strong required + */ +static struct binder_node *binder_get_node_from_ref( + struct binder_proc *proc, + u32 desc, bool need_strong_ref, + struct binder_ref_data *rdata) +{ + struct binder_node *node; + struct binder_ref *ref; + + ref = binder_get_ref(proc, desc, need_strong_ref); + if (!ref) + goto err_no_ref; + node = ref->node; + if (rdata) + *rdata = ref->data; + + return node; + +err_no_ref: + return NULL; +} + +/** + * binder_free_ref() - free the binder_ref + * @ref: ref to free + * + * Free the binder_ref and the binder_ref_death indicated by ref->death. + */ +static void binder_free_ref(struct binder_ref *ref) +{ + kfree(ref->death); + kfree(ref); +} + +/** + * binder_update_ref_for_handle() - inc/dec the ref for given handle + * @proc: proc containing the ref + * @desc: the handle associated with the ref + * @increment: true=inc reference, false=dec reference + * @strong: true=strong reference, false=weak reference + * @rdata: the id/refcount data for the ref + * + * Given a proc and ref handle, increment or decrement the ref + * according to "increment" arg. + * + * Return: 0 if successful, else errno + */ +static int binder_update_ref_for_handle(struct binder_proc *proc, + uint32_t desc, bool increment, bool strong, + struct binder_ref_data *rdata) +{ + int ret = 0; + struct binder_ref *ref; + bool delete_ref = false; + + ref = binder_get_ref(proc, desc, strong); + if (!ref) { + ret = -EINVAL; + goto err_no_ref; + } + if (increment) + ret = binder_inc_ref(ref, strong, NULL); + else + delete_ref = binder_dec_ref(ref, strong); + + if (rdata) + *rdata = ref->data; + + if (delete_ref) + binder_free_ref(ref); + return ret; + +err_no_ref: + return ret; +} + +/** + * binder_dec_ref_for_handle() - dec the ref for given handle + * @proc: proc containing the ref + * @desc: the handle associated with the ref + * @strong: true=strong reference, false=weak reference + * @rdata: the id/refcount data for the ref + * + * Just calls binder_update_ref_for_handle() to decrement the ref. + * + * Return: 0 if successful, else errno + */ +static int binder_dec_ref_for_handle(struct binder_proc *proc, + uint32_t desc, bool strong, struct binder_ref_data *rdata) +{ + return binder_update_ref_for_handle(proc, desc, false, strong, rdata); +} + + +/** + * binder_inc_ref_for_node() - increment the ref for given proc/node + * @proc: proc containing the ref + * @node: target node + * @strong: true=strong reference, false=weak reference + * @target_list: worklist to use if node is incremented + * @rdata: the id/refcount data for the ref + * + * Given a proc and node, increment the ref. Create the ref if it + * doesn't already exist + * + * Return: 0 if successful, else errno + */ +static int binder_inc_ref_for_node(struct binder_proc *proc, + struct binder_node *node, + bool strong, + struct list_head *target_list, + struct binder_ref_data *rdata) +{ + struct binder_ref *ref; + struct binder_ref *new_ref = NULL; + int ret = 0; + + ref = binder_get_ref_for_node(proc, node, NULL); + if (!ref) { + new_ref = kzalloc(sizeof(*ref), GFP_KERNEL); + if (!new_ref) + return -ENOMEM; + ref = binder_get_ref_for_node(proc, node, new_ref); + } + ret = binder_inc_ref(ref, strong, target_list); + *rdata = ref->data; + if (new_ref && ref != new_ref) + /* + * Another thread created the ref first so + * free the one we allocated + */ + kfree(new_ref); + return ret; } static void binder_pop_transaction(struct binder_thread *target_thread, @@ -1124,20 +1352,21 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, case BINDER_TYPE_HANDLE: case BINDER_TYPE_WEAK_HANDLE: { struct flat_binder_object *fp; - struct binder_ref *ref; + struct binder_ref_data rdata; + int ret; fp = to_flat_binder_object(hdr); - ref = binder_get_ref(proc, fp->handle, - hdr->type == BINDER_TYPE_HANDLE); - if (ref == NULL) { - pr_err("transaction release %d bad handle %d\n", - debug_id, fp->handle); + ret = binder_dec_ref_for_handle(proc, fp->handle, + hdr->type == BINDER_TYPE_HANDLE, &rdata); + + if (ret) { + pr_err("transaction release %d bad handle %d, ret = %d\n", + debug_id, fp->handle, ret); break; } binder_debug(BINDER_DEBUG_TRANSACTION, - " ref %d desc %d (node %d)\n", - ref->debug_id, ref->desc, ref->node->debug_id); - binder_dec_ref(ref, hdr->type == BINDER_TYPE_HANDLE); + " ref %d desc %d\n", + rdata.debug_id, rdata.desc); } break; case BINDER_TYPE_FD: { @@ -1209,9 +1438,10 @@ static int binder_translate_binder(struct flat_binder_object *fp, struct binder_thread *thread) { struct binder_node *node; - struct binder_ref *ref; struct binder_proc *proc = thread->proc; struct binder_proc *target_proc = t->to_proc; + struct binder_ref_data rdata; + int ret; node = binder_get_node(proc, fp->binder); if (!node) { @@ -1232,25 +1462,25 @@ static int binder_translate_binder(struct flat_binder_object *fp, if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) return -EPERM; - ref = binder_get_ref_for_node(target_proc, node); - if (!ref) - return -ENOMEM; + ret = binder_inc_ref_for_node(target_proc, node, + fp->hdr.type == BINDER_TYPE_BINDER, + &thread->todo, &rdata); + if (ret) + return ret; if (fp->hdr.type == BINDER_TYPE_BINDER) fp->hdr.type = BINDER_TYPE_HANDLE; else fp->hdr.type = BINDER_TYPE_WEAK_HANDLE; fp->binder = 0; - fp->handle = ref->desc; + fp->handle = rdata.desc; fp->cookie = 0; - binder_inc_ref(ref, fp->hdr.type == BINDER_TYPE_HANDLE, &thread->todo); - trace_binder_transaction_node_to_ref(t, node, ref); + trace_binder_transaction_node_to_ref(t, node, &rdata); binder_debug(BINDER_DEBUG_TRANSACTION, " node %d u%016llx -> ref %d desc %d\n", node->debug_id, (u64)node->ptr, - ref->debug_id, ref->desc); - + rdata.debug_id, rdata.desc); return 0; } @@ -1258,13 +1488,14 @@ static int binder_translate_handle(struct flat_binder_object *fp, struct binder_transaction *t, struct binder_thread *thread) { - struct binder_ref *ref; struct binder_proc *proc = thread->proc; struct binder_proc *target_proc = t->to_proc; + struct binder_node *node; + struct binder_ref_data src_rdata; - ref = binder_get_ref(proc, fp->handle, - fp->hdr.type == BINDER_TYPE_HANDLE); - if (!ref) { + node = binder_get_node_from_ref(proc, fp->handle, + fp->hdr.type == BINDER_TYPE_HANDLE, &src_rdata); + if (!node) { binder_user_error("%d:%d got transaction with invalid handle, %d\n", proc->pid, thread->pid, fp->handle); return -EINVAL; @@ -1272,37 +1503,41 @@ static int binder_translate_handle(struct flat_binder_object *fp, if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) return -EPERM; - if (ref->node->proc == target_proc) { + if (node->proc == target_proc) { if (fp->hdr.type == BINDER_TYPE_HANDLE) fp->hdr.type = BINDER_TYPE_BINDER; else fp->hdr.type = BINDER_TYPE_WEAK_BINDER; - fp->binder = ref->node->ptr; - fp->cookie = ref->node->cookie; - binder_inc_node(ref->node, fp->hdr.type == BINDER_TYPE_BINDER, + fp->binder = node->ptr; + fp->cookie = node->cookie; + binder_inc_node(node, + fp->hdr.type == BINDER_TYPE_BINDER, 0, NULL); - trace_binder_transaction_ref_to_node(t, ref); + trace_binder_transaction_ref_to_node(t, node, &src_rdata); binder_debug(BINDER_DEBUG_TRANSACTION, " ref %d desc %d -> node %d u%016llx\n", - ref->debug_id, ref->desc, ref->node->debug_id, - (u64)ref->node->ptr); + src_rdata.debug_id, src_rdata.desc, node->debug_id, + (u64)node->ptr); } else { - struct binder_ref *new_ref; + int ret; + struct binder_ref_data dest_rdata; - new_ref = binder_get_ref_for_node(target_proc, ref->node); - if (!new_ref) - return -ENOMEM; + ret = binder_inc_ref_for_node(target_proc, node, + fp->hdr.type == BINDER_TYPE_HANDLE, + NULL, &dest_rdata); + if (ret) + return ret; fp->binder = 0; - fp->handle = new_ref->desc; + fp->handle = dest_rdata.desc; fp->cookie = 0; - binder_inc_ref(new_ref, fp->hdr.type == BINDER_TYPE_HANDLE, - NULL); - trace_binder_transaction_ref_to_ref(t, ref, new_ref); + trace_binder_transaction_ref_to_ref(t, node, &src_rdata, + &dest_rdata); binder_debug(BINDER_DEBUG_TRANSACTION, " ref %d desc %d -> ref %d desc %d (node %d)\n", - ref->debug_id, ref->desc, new_ref->debug_id, - new_ref->desc, ref->node->debug_id); + src_rdata.debug_id, src_rdata.desc, + dest_rdata.debug_id, dest_rdata.desc, + node->debug_id); } return 0; } @@ -2043,6 +2278,8 @@ static int binder_thread_write(struct binder_proc *proc, void __user *end = buffer + size; while (ptr < end && thread->return_error.cmd == BR_OK) { + int ret; + if (get_user(cmd, (uint32_t __user *)ptr)) return -EFAULT; ptr += sizeof(uint32_t); @@ -2058,62 +2295,61 @@ static int binder_thread_write(struct binder_proc *proc, case BC_RELEASE: case BC_DECREFS: { uint32_t target; - struct binder_ref *ref = NULL; const char *debug_string; + bool strong = cmd == BC_ACQUIRE || cmd == BC_RELEASE; + bool increment = cmd == BC_INCREFS || cmd == BC_ACQUIRE; + struct binder_ref_data rdata; if (get_user(target, (uint32_t __user *)ptr)) return -EFAULT; ptr += sizeof(uint32_t); - if (target == 0 && - (cmd == BC_INCREFS || cmd == BC_ACQUIRE)) { + ret = -1; + if (increment && !target) { struct binder_node *ctx_mgr_node; - mutex_lock(&context->context_mgr_node_lock); ctx_mgr_node = context->binder_context_mgr_node; - if (ctx_mgr_node) { - ref = binder_get_ref_for_node(proc, - ctx_mgr_node); - if (ref && ref->desc != target) { - binder_user_error("%d:%d tried to acquire reference to desc 0, got %d instead\n", - proc->pid, thread->pid, - ref->desc); - } - } + if (ctx_mgr_node) + ret = binder_inc_ref_for_node( + proc, ctx_mgr_node, + strong, NULL, &rdata); mutex_unlock(&context->context_mgr_node_lock); } - if (ref == NULL) - ref = binder_get_ref(proc, target, - cmd == BC_ACQUIRE || - cmd == BC_RELEASE); - if (ref == NULL) { - binder_user_error("%d:%d refcount change on invalid ref %d\n", - proc->pid, thread->pid, target); - break; + if (ret) + ret = binder_update_ref_for_handle( + proc, target, increment, strong, + &rdata); + if (!ret && rdata.desc != target) { + binder_user_error("%d:%d tried to acquire reference to desc %d, got %d instead\n", + proc->pid, thread->pid, + target, rdata.desc); } switch (cmd) { case BC_INCREFS: debug_string = "IncRefs"; - binder_inc_ref(ref, 0, NULL); break; case BC_ACQUIRE: debug_string = "Acquire"; - binder_inc_ref(ref, 1, NULL); break; case BC_RELEASE: debug_string = "Release"; - binder_dec_ref(ref, 1); break; case BC_DECREFS: default: debug_string = "DecRefs"; - binder_dec_ref(ref, 0); + break; + } + if (ret) { + binder_user_error("%d:%d %s %d refcount change on invalid ref %d ret %d\n", + proc->pid, thread->pid, debug_string, + strong, target, ret); break; } binder_debug(BINDER_DEBUG_USER_REFS, - "%d:%d %s ref %d desc %d s %d w %d for node %d\n", - proc->pid, thread->pid, debug_string, ref->debug_id, - ref->desc, ref->strong, ref->weak, ref->node->debug_id); + "%d:%d %s ref %d desc %d s %d w %d\n", + proc->pid, thread->pid, debug_string, + rdata.debug_id, rdata.desc, rdata.strong, + rdata.weak); break; } case BC_INCREFS_DONE: @@ -2311,8 +2547,9 @@ static int binder_thread_write(struct binder_proc *proc, cmd == BC_REQUEST_DEATH_NOTIFICATION ? "BC_REQUEST_DEATH_NOTIFICATION" : "BC_CLEAR_DEATH_NOTIFICATION", - (u64)cookie, ref->debug_id, ref->desc, - ref->strong, ref->weak, ref->node->debug_id); + (u64)cookie, ref->data.debug_id, + ref->data.desc, ref->data.strong, + ref->data.weak, ref->node->debug_id); if (cmd == BC_REQUEST_DEATH_NOTIFICATION) { if (ref->death) { @@ -3473,7 +3710,8 @@ static void binder_deferred_release(struct binder_proc *proc) ref = rb_entry(n, struct binder_ref, rb_node_desc); outgoing_refs++; - binder_delete_ref(ref); + binder_cleanup_ref(ref); + binder_free_ref(ref); } binder_release_work(&proc->todo); @@ -3675,9 +3913,11 @@ static void print_binder_node(struct seq_file *m, struct binder_node *node) static void print_binder_ref(struct seq_file *m, struct binder_ref *ref) { - seq_printf(m, " ref %d: desc %d %snode %d s %d w %d d %p\n", - ref->debug_id, ref->desc, ref->node->proc ? "" : "dead ", - ref->node->debug_id, ref->strong, ref->weak, ref->death); + seq_printf(m, " ref %d: desc %d %snode %d s %d w %d d %pK\n", + ref->data.debug_id, ref->data.desc, + ref->node->proc ? "" : "dead ", + ref->node->debug_id, ref->data.strong, + ref->data.weak, ref->death); } static void print_binder_proc(struct seq_file *m, @@ -3844,8 +4084,8 @@ static void print_binder_proc_stats(struct seq_file *m, struct binder_ref *ref = rb_entry(n, struct binder_ref, rb_node_desc); count++; - strong += ref->strong; - weak += ref->weak; + strong += ref->data.strong; + weak += ref->data.weak; } seq_printf(m, " refs: %d s %d w %d\n", count, strong, weak); diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h index 50b0d21f42cf..7967db16ba5a 100644 --- a/drivers/android/binder_trace.h +++ b/drivers/android/binder_trace.h @@ -24,7 +24,7 @@ struct binder_buffer; struct binder_node; struct binder_proc; struct binder_alloc; -struct binder_ref; +struct binder_ref_data; struct binder_thread; struct binder_transaction; @@ -147,8 +147,8 @@ TRACE_EVENT(binder_transaction_received, TRACE_EVENT(binder_transaction_node_to_ref, TP_PROTO(struct binder_transaction *t, struct binder_node *node, - struct binder_ref *ref), - TP_ARGS(t, node, ref), + struct binder_ref_data *rdata), + TP_ARGS(t, node, rdata), TP_STRUCT__entry( __field(int, debug_id) @@ -161,8 +161,8 @@ TRACE_EVENT(binder_transaction_node_to_ref, __entry->debug_id = t->debug_id; __entry->node_debug_id = node->debug_id; __entry->node_ptr = node->ptr; - __entry->ref_debug_id = ref->debug_id; - __entry->ref_desc = ref->desc; + __entry->ref_debug_id = rdata->debug_id; + __entry->ref_desc = rdata->desc; ), TP_printk("transaction=%d node=%d src_ptr=0x%016llx ==> dest_ref=%d dest_desc=%d", __entry->debug_id, __entry->node_debug_id, @@ -171,8 +171,9 @@ TRACE_EVENT(binder_transaction_node_to_ref, ); TRACE_EVENT(binder_transaction_ref_to_node, - TP_PROTO(struct binder_transaction *t, struct binder_ref *ref), - TP_ARGS(t, ref), + TP_PROTO(struct binder_transaction *t, struct binder_node *node, + struct binder_ref_data *rdata), + TP_ARGS(t, node, rdata), TP_STRUCT__entry( __field(int, debug_id) @@ -183,10 +184,10 @@ TRACE_EVENT(binder_transaction_ref_to_node, ), TP_fast_assign( __entry->debug_id = t->debug_id; - __entry->ref_debug_id = ref->debug_id; - __entry->ref_desc = ref->desc; - __entry->node_debug_id = ref->node->debug_id; - __entry->node_ptr = ref->node->ptr; + __entry->ref_debug_id = rdata->debug_id; + __entry->ref_desc = rdata->desc; + __entry->node_debug_id = node->debug_id; + __entry->node_ptr = node->ptr; ), TP_printk("transaction=%d node=%d src_ref=%d src_desc=%d ==> dest_ptr=0x%016llx", __entry->debug_id, __entry->node_debug_id, @@ -195,9 +196,10 @@ TRACE_EVENT(binder_transaction_ref_to_node, ); TRACE_EVENT(binder_transaction_ref_to_ref, - TP_PROTO(struct binder_transaction *t, struct binder_ref *src_ref, - struct binder_ref *dest_ref), - TP_ARGS(t, src_ref, dest_ref), + TP_PROTO(struct binder_transaction *t, struct binder_node *node, + struct binder_ref_data *src_ref, + struct binder_ref_data *dest_ref), + TP_ARGS(t, node, src_ref, dest_ref), TP_STRUCT__entry( __field(int, debug_id) @@ -209,7 +211,7 @@ TRACE_EVENT(binder_transaction_ref_to_ref, ), TP_fast_assign( __entry->debug_id = t->debug_id; - __entry->node_debug_id = src_ref->node->debug_id; + __entry->node_debug_id = node->debug_id; __entry->src_ref_debug_id = src_ref->debug_id; __entry->src_ref_desc = src_ref->desc; __entry->dest_ref_debug_id = dest_ref->debug_id; -- cgit v1.2.3 From adc1884222276df6eb018f78bccacbcd78a0b9f6 Mon Sep 17 00:00:00 2001 From: Todd Kjos Date: Thu, 29 Jun 2017 12:01:59 -0700 Subject: binder: use node->tmp_refs to ensure node safety When obtaining a node via binder_get_node(), binder_get_node_from_ref() or binder_new_node(), increment node->tmp_refs to take a temporary reference on the node to ensure the node persists while being used. binder_put_node() must be called to remove the temporary reference. Signed-off-by: Todd Kjos Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 124 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 104 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 4d0b99862339..ec050c6d1192 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -274,6 +274,7 @@ struct binder_node { int internal_strong_refs; int local_weak_refs; int local_strong_refs; + int tmp_refs; binder_uintptr_t ptr; binder_uintptr_t cookie; unsigned has_strong_ref:1; @@ -427,6 +428,7 @@ static void binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer); static void binder_free_thread(struct binder_thread *thread); static void binder_free_proc(struct binder_proc *proc); +static void binder_inc_node_tmpref(struct binder_node *node); static int task_get_unused_fd_flags(struct binder_proc *proc, int flags) { @@ -521,8 +523,15 @@ static struct binder_node *binder_get_node(struct binder_proc *proc, n = n->rb_left; else if (ptr > node->ptr) n = n->rb_right; - else + else { + /* + * take an implicit weak reference + * to ensure node stays alive until + * call to binder_put_node() + */ + binder_inc_node_tmpref(node); return node; + } } return NULL; } @@ -551,6 +560,7 @@ static struct binder_node *binder_new_node(struct binder_proc *proc, if (node == NULL) return NULL; binder_stats_created(BINDER_STAT_NODE); + node->tmp_refs++; rb_link_node(&node->rb_node, parent, p); rb_insert_color(&node->rb_node, &proc->nodes); node->debug_id = atomic_inc_return(&binder_last_id); @@ -615,7 +625,8 @@ static int binder_dec_node(struct binder_node *node, int strong, int internal) } else { if (!internal) node->local_weak_refs--; - if (node->local_weak_refs || !hlist_empty(&node->refs)) + if (node->local_weak_refs || node->tmp_refs || + !hlist_empty(&node->refs)) return 0; } if (node->proc && (node->has_strong_ref || node->has_weak_ref)) { @@ -625,7 +636,7 @@ static int binder_dec_node(struct binder_node *node, int strong, int internal) } } else { if (hlist_empty(&node->refs) && !node->local_strong_refs && - !node->local_weak_refs) { + !node->local_weak_refs && !node->tmp_refs) { list_del_init(&node->work.entry); if (node->proc) { rb_erase(&node->rb_node, &node->proc->nodes); @@ -648,6 +659,46 @@ static int binder_dec_node(struct binder_node *node, int strong, int internal) return 0; } +/** + * binder_inc_node_tmpref() - take a temporary reference on node + * @node: node to reference + * + * Take reference on node to prevent the node from being freed + * while referenced only by a local variable + */ +static void binder_inc_node_tmpref(struct binder_node *node) +{ + /* + * No call to binder_inc_node() is needed since we + * don't need to inform userspace of any changes to + * tmp_refs + */ + node->tmp_refs++; +} + +/** + * binder_dec_node_tmpref() - remove a temporary reference on node + * @node: node to reference + * + * Release temporary reference on node taken via binder_inc_node_tmpref() + */ +static void binder_dec_node_tmpref(struct binder_node *node) +{ + node->tmp_refs--; + BUG_ON(node->tmp_refs < 0); + /* + * Call binder_dec_node() to check if all refcounts are 0 + * and cleanup is needed. Calling with strong=0 and internal=1 + * causes no actual reference to be released in binder_dec_node(). + * If that changes, a change is needed here too. + */ + binder_dec_node(node, 0, 1); +} + +static void binder_put_node(struct binder_node *node) +{ + binder_dec_node_tmpref(node); +} static struct binder_ref *binder_get_ref(struct binder_proc *proc, u32 desc, bool need_strong_ref) @@ -888,6 +939,11 @@ static struct binder_node *binder_get_node_from_ref( if (!ref) goto err_no_ref; node = ref->node; + /* + * Take an implicit reference on the node to ensure + * it stays alive until the call to binder_put_node() + */ + binder_inc_node_tmpref(node); if (rdata) *rdata = ref->data; @@ -1348,6 +1404,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, node->debug_id, (u64)node->ptr); binder_dec_node(node, hdr->type == BINDER_TYPE_BINDER, 0); + binder_put_node(node); } break; case BINDER_TYPE_HANDLE: case BINDER_TYPE_WEAK_HANDLE: { @@ -1441,7 +1498,7 @@ static int binder_translate_binder(struct flat_binder_object *fp, struct binder_proc *proc = thread->proc; struct binder_proc *target_proc = t->to_proc; struct binder_ref_data rdata; - int ret; + int ret = 0; node = binder_get_node(proc, fp->binder); if (!node) { @@ -1457,16 +1514,19 @@ static int binder_translate_binder(struct flat_binder_object *fp, proc->pid, thread->pid, (u64)fp->binder, node->debug_id, (u64)fp->cookie, (u64)node->cookie); - return -EINVAL; + ret = -EINVAL; + goto done; + } + if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) { + ret = -EPERM; + goto done; } - if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) - return -EPERM; ret = binder_inc_ref_for_node(target_proc, node, fp->hdr.type == BINDER_TYPE_BINDER, &thread->todo, &rdata); if (ret) - return ret; + goto done; if (fp->hdr.type == BINDER_TYPE_BINDER) fp->hdr.type = BINDER_TYPE_HANDLE; @@ -1481,7 +1541,9 @@ static int binder_translate_binder(struct flat_binder_object *fp, " node %d u%016llx -> ref %d desc %d\n", node->debug_id, (u64)node->ptr, rdata.debug_id, rdata.desc); - return 0; +done: + binder_put_node(node); + return ret; } static int binder_translate_handle(struct flat_binder_object *fp, @@ -1492,6 +1554,7 @@ static int binder_translate_handle(struct flat_binder_object *fp, struct binder_proc *target_proc = t->to_proc; struct binder_node *node; struct binder_ref_data src_rdata; + int ret = 0; node = binder_get_node_from_ref(proc, fp->handle, fp->hdr.type == BINDER_TYPE_HANDLE, &src_rdata); @@ -1500,8 +1563,10 @@ static int binder_translate_handle(struct flat_binder_object *fp, proc->pid, thread->pid, fp->handle); return -EINVAL; } - if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) - return -EPERM; + if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) { + ret = -EPERM; + goto done; + } if (node->proc == target_proc) { if (fp->hdr.type == BINDER_TYPE_HANDLE) @@ -1526,7 +1591,7 @@ static int binder_translate_handle(struct flat_binder_object *fp, fp->hdr.type == BINDER_TYPE_HANDLE, NULL, &dest_rdata); if (ret) - return ret; + goto done; fp->binder = 0; fp->handle = dest_rdata.desc; @@ -1539,7 +1604,9 @@ static int binder_translate_handle(struct flat_binder_object *fp, dest_rdata.debug_id, dest_rdata.desc, node->debug_id); } - return 0; +done: + binder_put_node(node); + return ret; } static int binder_translate_fd(int fd, @@ -2381,6 +2448,7 @@ static int binder_thread_write(struct binder_proc *proc, "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE", (u64)node_ptr, node->debug_id, (u64)cookie, (u64)node->cookie); + binder_put_node(node); break; } if (cmd == BC_ACQUIRE_DONE) { @@ -2388,6 +2456,7 @@ static int binder_thread_write(struct binder_proc *proc, binder_user_error("%d:%d BC_ACQUIRE_DONE node %d has no pending acquire request\n", proc->pid, thread->pid, node->debug_id); + binder_put_node(node); break; } node->pending_strong_ref = 0; @@ -2396,16 +2465,19 @@ static int binder_thread_write(struct binder_proc *proc, binder_user_error("%d:%d BC_INCREFS_DONE node %d has no pending increfs request\n", proc->pid, thread->pid, node->debug_id); + binder_put_node(node); break; } node->pending_weak_ref = 0; } binder_dec_node(node, cmd == BC_ACQUIRE_DONE, 0); binder_debug(BINDER_DEBUG_USER_REFS, - "%d:%d %s node %d ls %d lw %d\n", + "%d:%d %s node %d ls %d lw %d tr %d\n", proc->pid, thread->pid, cmd == BC_INCREFS_DONE ? "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE", - node->debug_id, node->local_strong_refs, node->local_weak_refs); + node->debug_id, node->local_strong_refs, + node->local_weak_refs, node->tmp_refs); + binder_put_node(node); break; } case BC_ATTEMPT_ACQUIRE: @@ -2845,7 +2917,8 @@ retry: strong = node->internal_strong_refs || node->local_strong_refs; weak = !hlist_empty(&node->refs) || - node->local_weak_refs || strong; + node->local_weak_refs || + node->tmp_refs || strong; has_strong_ref = node->has_strong_ref; has_weak_ref = node->has_weak_ref; @@ -3357,6 +3430,7 @@ static int binder_ioctl_set_ctx_mgr(struct file *filp) new_node->has_strong_ref = 1; new_node->has_weak_ref = 1; context->binder_context_mgr_node = new_node; + binder_put_node(new_node); out: mutex_unlock(&context->context_mgr_node_lock); return ret; @@ -3615,8 +3689,11 @@ static int binder_node_release(struct binder_node *node, int refs) list_del_init(&node->work.entry); binder_release_work(&node->async_todo); - - if (hlist_empty(&node->refs)) { + /* + * The caller must have taken a temporary ref on the node, + */ + BUG_ON(!node->tmp_refs); + if (hlist_empty(&node->refs) && node->tmp_refs == 1) { kfree(node); binder_stats_deleted(BINDER_STAT_NODE); @@ -3651,6 +3728,7 @@ static int binder_node_release(struct binder_node *node, int refs) binder_debug(BINDER_DEBUG_DEAD_BINDER, "node %d now dead, refs %d, death %d\n", node->debug_id, refs, death); + binder_put_node(node); return refs; } @@ -3700,6 +3778,12 @@ static void binder_deferred_release(struct binder_proc *proc) node = rb_entry(n, struct binder_node, rb_node); nodes++; + /* + * take a temporary ref on the node before + * calling binder_node_release() which will either + * kfree() the node or call binder_put_node() + */ + binder_inc_node_tmpref(node); rb_erase(&node->rb_node, &proc->nodes); incoming_refs = binder_node_release(node, incoming_refs); } @@ -3895,11 +3979,11 @@ static void print_binder_node(struct seq_file *m, struct binder_node *node) hlist_for_each_entry(ref, &node->refs, node_entry) count++; - seq_printf(m, " node %d: u%016llx c%016llx hs %d hw %d ls %d lw %d is %d iw %d", + seq_printf(m, " node %d: u%016llx c%016llx hs %d hw %d ls %d lw %d is %d iw %d tr %d", node->debug_id, (u64)node->ptr, (u64)node->cookie, node->has_strong_ref, node->has_weak_ref, node->local_strong_refs, node->local_weak_refs, - node->internal_strong_refs, count); + node->internal_strong_refs, count, node->tmp_refs); if (count) { seq_puts(m, " proc"); hlist_for_each_entry(ref, &node->refs, node_entry) -- cgit v1.2.3 From 9630fe8839baf3f47df9187ca720cfa1c10b132e Mon Sep 17 00:00:00 2001 From: Todd Kjos Date: Thu, 29 Jun 2017 12:02:00 -0700 Subject: binder: introduce locking helper functions There are 3 main spinlocks which must be acquired in this order: 1) proc->outer_lock : protects most fields of binder_proc, binder_thread, and binder_ref structures. binder_proc_lock() and binder_proc_unlock() are used to acq/rel. 2) node->lock : protects most fields of binder_node. binder_node_lock() and binder_node_unlock() are used to acq/rel 3) proc->inner_lock : protects the thread and node lists (proc->threads, proc->nodes) and all todo lists associated with the binder_proc (proc->todo, thread->todo, proc->delivered_death and node->async_todo). binder_inner_proc_lock() and binder_inner_proc_unlock() are used to acq/rel Any lock under procA must never be nested under any lock at the same level or below on procB. Functions that require a lock held on entry indicate which lock in the suffix of the function name: foo_olocked() : requires node->outer_lock foo_nlocked() : requires node->lock foo_ilocked() : requires proc->inner_lock foo_iolocked(): requires proc->outer_lock and proc->inner_lock foo_nilocked(): requires node->lock and proc->inner_lock Signed-off-by: Todd Kjos Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 238 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 238 insertions(+) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index ec050c6d1192..91fece5c067f 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -15,6 +15,39 @@ * */ +/* + * Locking overview + * + * There are 3 main spinlocks which must be acquired in the + * order shown: + * + * 1) proc->outer_lock : protects binder_ref + * binder_proc_lock() and binder_proc_unlock() are + * used to acq/rel. + * 2) node->lock : protects most fields of binder_node. + * binder_node_lock() and binder_node_unlock() are + * used to acq/rel + * 3) proc->inner_lock : protects the thread and node lists + * (proc->threads, proc->nodes) and all todo lists associated + * with the binder_proc (proc->todo, thread->todo, + * proc->delivered_death and node->async_todo). + * binder_inner_proc_lock() and binder_inner_proc_unlock() + * are used to acq/rel + * + * Any lock under procA must never be nested under any lock at the same + * level or below on procB. + * + * Functions that require a lock held on entry indicate which lock + * in the suffix of the function name: + * + * foo_olocked() : requires node->outer_lock + * foo_nlocked() : requires node->lock + * foo_ilocked() : requires proc->inner_lock + * foo_oilocked(): requires proc->outer_lock and proc->inner_lock + * foo_nilocked(): requires node->lock and proc->inner_lock + * ... + */ + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include @@ -36,6 +69,7 @@ #include #include #include +#include #ifdef CONFIG_ANDROID_BINDER_IPC_32BIT #define BINDER_IPC_32BIT 1 @@ -106,6 +140,7 @@ enum { BINDER_DEBUG_FREE_BUFFER = 1U << 11, BINDER_DEBUG_INTERNAL_REFS = 1U << 12, BINDER_DEBUG_PRIORITY_CAP = 1U << 13, + BINDER_DEBUG_SPINLOCKS = 1U << 14, }; static uint32_t binder_debug_mask = BINDER_DEBUG_USER_ERROR | BINDER_DEBUG_FAILED_TRANSACTION | BINDER_DEBUG_DEAD_TRANSACTION; @@ -262,8 +297,43 @@ struct binder_error { uint32_t cmd; }; +/** + * struct binder_node - binder node bookkeeping + * @debug_id: unique ID for debugging + * (invariant after initialized) + * @lock: lock for node fields + * @work: worklist element for node work + * @rb_node: element for proc->nodes tree + * @dead_node: element for binder_dead_nodes list + * (protected by binder_dead_nodes_lock) + * @proc: binder_proc that owns this node + * (invariant after initialized) + * @refs: list of references on this node + * @internal_strong_refs: used to take strong references when + * initiating a transaction + * @local_weak_refs: weak user refs from local process + * @local_strong_refs: strong user refs from local process + * @tmp_refs: temporary kernel refs + * @ptr: userspace pointer for node + * (invariant, no lock needed) + * @cookie: userspace cookie for node + * (invariant, no lock needed) + * @has_strong_ref: userspace notified of strong ref + * @pending_strong_ref: userspace has acked notification of strong ref + * @has_weak_ref: userspace notified of weak ref + * @pending_weak_ref: userspace has acked notification of weak ref + * @has_async_transaction: async transaction to node in progress + * @accept_fds: file descriptor operations supported for node + * (invariant after initialized) + * @min_priority: minimum scheduling priority + * (invariant after initialized) + * @async_todo: list of async work items + * + * Bookkeeping structure for binder nodes. + */ struct binder_node { int debug_id; + spinlock_t lock; struct binder_work work; union { struct rb_node rb_node; @@ -346,6 +416,51 @@ enum binder_deferred_state { BINDER_DEFERRED_RELEASE = 0x04, }; +/** + * struct binder_proc - binder process bookkeeping + * @proc_node: element for binder_procs list + * @threads: rbtree of binder_threads in this proc + * @nodes: rbtree of binder nodes associated with + * this proc ordered by node->ptr + * @refs_by_desc: rbtree of refs ordered by ref->desc + * @refs_by_node: rbtree of refs ordered by ref->node + * @pid PID of group_leader of process + * (invariant after initialized) + * @tsk task_struct for group_leader of process + * (invariant after initialized) + * @files files_struct for process + * (invariant after initialized) + * @deferred_work_node: element for binder_deferred_list + * (protected by binder_deferred_lock) + * @deferred_work: bitmap of deferred work to perform + * (protected by binder_deferred_lock) + * @is_dead: process is dead and awaiting free + * when outstanding transactions are cleaned up + * @todo: list of work for this process + * @wait: wait queue head to wait for proc work + * (invariant after initialized) + * @stats: per-process binder statistics + * (atomics, no lock needed) + * @delivered_death: list of delivered death notification + * @max_threads: cap on number of binder threads + * @requested_threads: number of binder threads requested but not + * yet started. In current implementation, can + * only be 0 or 1. + * @requested_threads_started: number binder threads started + * @ready_threads: number of threads waiting for proc work + * @tmp_ref: temporary reference to indicate proc is in use + * @default_priority: default scheduler priority + * (invariant after initialized) + * @debugfs_entry: debugfs node + * @alloc: binder allocator bookkeeping + * @context: binder_context for this proc + * (invariant after initialized) + * @inner_lock: can nest under outer_lock and/or node lock + * @outer_lock: no nesting under innor or node lock + * Lock order: 1) outer, 2) node, 3) inner + * + * Bookkeeping structure for binder processes + */ struct binder_proc { struct hlist_node proc_node; struct rb_root threads; @@ -372,6 +487,8 @@ struct binder_proc { struct dentry *debugfs_entry; struct binder_alloc alloc; struct binder_context *context; + spinlock_t inner_lock; + spinlock_t outer_lock; }; enum { @@ -382,6 +499,33 @@ enum { BINDER_LOOPER_STATE_WAITING = 0x10, }; +/** + * struct binder_thread - binder thread bookkeeping + * @proc: binder process for this thread + * (invariant after initialization) + * @rb_node: element for proc->threads rbtree + * @pid: PID for this thread + * (invariant after initialization) + * @looper: bitmap of looping state + * (only accessed by this thread) + * @looper_needs_return: looping thread needs to exit driver + * (no lock needed) + * @transaction_stack: stack of in-progress transactions for this thread + * @todo: list of work to do for this thread + * @return_error: transaction errors reported by this thread + * (only accessed by this thread) + * @reply_error: transaction errors reported by target thread + * @wait: wait queue for thread work + * @stats: per-thread statistics + * (atomics, no lock needed) + * @tmp_ref: temporary reference to indicate thread is in use + * (atomic since @proc->inner_lock cannot + * always be acquired) + * @is_dead: thread is dead and awaiting free + * when outstanding transactions are cleaned up + * + * Bookkeeping structure for binder threads. + */ struct binder_thread { struct binder_proc *proc; struct rb_node rb_node; @@ -424,6 +568,97 @@ struct binder_transaction { spinlock_t lock; }; +/** + * binder_proc_lock() - Acquire outer lock for given binder_proc + * @proc: struct binder_proc to acquire + * + * Acquires proc->outer_lock. Used to protect binder_ref + * structures associated with the given proc. + */ +#define binder_proc_lock(proc) _binder_proc_lock(proc, __LINE__) +static void +_binder_proc_lock(struct binder_proc *proc, int line) +{ + binder_debug(BINDER_DEBUG_SPINLOCKS, + "%s: line=%d\n", __func__, line); + spin_lock(&proc->outer_lock); +} + +/** + * binder_proc_unlock() - Release spinlock for given binder_proc + * @proc: struct binder_proc to acquire + * + * Release lock acquired via binder_proc_lock() + */ +#define binder_proc_unlock(_proc) _binder_proc_unlock(_proc, __LINE__) +static void +_binder_proc_unlock(struct binder_proc *proc, int line) +{ + binder_debug(BINDER_DEBUG_SPINLOCKS, + "%s: line=%d\n", __func__, line); + spin_unlock(&proc->outer_lock); +} + +/** + * binder_inner_proc_lock() - Acquire inner lock for given binder_proc + * @proc: struct binder_proc to acquire + * + * Acquires proc->inner_lock. Used to protect todo lists + */ +#define binder_inner_proc_lock(proc) _binder_inner_proc_lock(proc, __LINE__) +static void +_binder_inner_proc_lock(struct binder_proc *proc, int line) +{ + binder_debug(BINDER_DEBUG_SPINLOCKS, + "%s: line=%d\n", __func__, line); + spin_lock(&proc->inner_lock); +} + +/** + * binder_inner_proc_unlock() - Release inner lock for given binder_proc + * @proc: struct binder_proc to acquire + * + * Release lock acquired via binder_inner_proc_lock() + */ +#define binder_inner_proc_unlock(proc) _binder_inner_proc_unlock(proc, __LINE__) +static void +_binder_inner_proc_unlock(struct binder_proc *proc, int line) +{ + binder_debug(BINDER_DEBUG_SPINLOCKS, + "%s: line=%d\n", __func__, line); + spin_unlock(&proc->inner_lock); +} + +/** + * binder_node_lock() - Acquire spinlock for given binder_node + * @node: struct binder_node to acquire + * + * Acquires node->lock. Used to protect binder_node fields + */ +#define binder_node_lock(node) _binder_node_lock(node, __LINE__) +static void +_binder_node_lock(struct binder_node *node, int line) +{ + binder_debug(BINDER_DEBUG_SPINLOCKS, + "%s: line=%d\n", __func__, line); + spin_lock(&node->lock); +} + +/** + * binder_node_unlock() - Release spinlock for given binder_proc + * @node: struct binder_node to acquire + * + * Release lock acquired via binder_node_lock() + */ +#define binder_node_unlock(node) _binder_node_unlock(node, __LINE__) +static void +_binder_node_unlock(struct binder_node *node, int line) +{ + binder_debug(BINDER_DEBUG_SPINLOCKS, + "%s: line=%d\n", __func__, line); + spin_unlock(&node->lock); +} + static void binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer); static void binder_free_thread(struct binder_thread *thread); @@ -568,6 +803,7 @@ static struct binder_node *binder_new_node(struct binder_proc *proc, node->ptr = ptr; node->cookie = cookie; node->work.type = BINDER_WORK_NODE; + spin_lock_init(&node->lock); INIT_LIST_HEAD(&node->work.entry); INIT_LIST_HEAD(&node->async_todo); binder_debug(BINDER_DEBUG_INTERNAL_REFS, @@ -3599,6 +3835,8 @@ static int binder_open(struct inode *nodp, struct file *filp) proc = kzalloc(sizeof(*proc), GFP_KERNEL); if (proc == NULL) return -ENOMEM; + spin_lock_init(&proc->inner_lock); + spin_lock_init(&proc->outer_lock); get_task_struct(current->group_leader); proc->tsk = current->group_leader; INIT_LIST_HEAD(&proc->todo); -- cgit v1.2.3 From ed29721e22e30939f417a2f734c0bfb3a980647d Mon Sep 17 00:00:00 2001 From: Todd Kjos Date: Thu, 29 Jun 2017 12:02:01 -0700 Subject: binder: use inner lock to sync work dq and node counts For correct behavior we need to hold the inner lock when dequeuing and processing node work in binder_thread_read. We now hold the inner lock when we enter the switch statement and release it after processing anything that might be affected by other threads. We also need to hold the inner lock to protect the node weak/strong ref tracking fields as long as node->proc is non-NULL (if it is NULL then we are guaranteed that we don't have any node work queued). This means that other functions that manipulate these fields must hold the inner lock. Refactored these functions to use the inner lock. Signed-off-by: Todd Kjos Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 249 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 198 insertions(+), 51 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 91fece5c067f..6c741416fa00 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -311,17 +311,36 @@ struct binder_error { * @refs: list of references on this node * @internal_strong_refs: used to take strong references when * initiating a transaction + * (protected by @proc->inner_lock if @proc + * and by @lock) * @local_weak_refs: weak user refs from local process + * (protected by @proc->inner_lock if @proc + * and by @lock) * @local_strong_refs: strong user refs from local process + * (protected by @proc->inner_lock if @proc + * and by @lock) * @tmp_refs: temporary kernel refs + * (protected by @proc->inner_lock while @proc + * is valid, and by binder_dead_nodes_lock + * if @proc is NULL. During inc/dec and node release + * it is also protected by @lock to provide safety + * as the node dies and @proc becomes NULL) * @ptr: userspace pointer for node * (invariant, no lock needed) * @cookie: userspace cookie for node * (invariant, no lock needed) * @has_strong_ref: userspace notified of strong ref + * (protected by @proc->inner_lock if @proc + * and by @lock) * @pending_strong_ref: userspace has acked notification of strong ref + * (protected by @proc->inner_lock if @proc + * and by @lock) * @has_weak_ref: userspace notified of weak ref + * (protected by @proc->inner_lock if @proc + * and by @lock) * @pending_weak_ref: userspace has acked notification of weak ref + * (protected by @proc->inner_lock if @proc + * and by @lock) * @has_async_transaction: async transaction to node in progress * @accept_fds: file descriptor operations supported for node * (invariant after initialized) @@ -347,13 +366,24 @@ struct binder_node { int tmp_refs; binder_uintptr_t ptr; binder_uintptr_t cookie; - unsigned has_strong_ref:1; - unsigned pending_strong_ref:1; - unsigned has_weak_ref:1; - unsigned pending_weak_ref:1; - unsigned has_async_transaction:1; - unsigned accept_fds:1; - unsigned min_priority:8; + struct { + /* + * bitfield elements protected by + * proc inner_lock + */ + u8 has_strong_ref:1; + u8 pending_strong_ref:1; + u8 has_weak_ref:1; + u8 pending_weak_ref:1; + }; + struct { + /* + * invariant after initialization + */ + u8 accept_fds:1; + u8 min_priority; + }; + bool has_async_transaction; struct list_head async_todo; }; @@ -813,9 +843,18 @@ static struct binder_node *binder_new_node(struct binder_proc *proc, return node; } -static int binder_inc_node(struct binder_node *node, int strong, int internal, - struct list_head *target_list) +static void binder_free_node(struct binder_node *node) { + kfree(node); + binder_stats_deleted(BINDER_STAT_NODE); +} + +static int binder_inc_node_ilocked(struct binder_node *node, int strong, + int internal, + struct list_head *target_list) +{ + if (node->proc) + BUG_ON(!spin_is_locked(&node->proc->inner_lock)); if (strong) { if (internal) { if (target_list == NULL && @@ -849,23 +888,43 @@ static int binder_inc_node(struct binder_node *node, int strong, int internal, return 0; } -static int binder_dec_node(struct binder_node *node, int strong, int internal) +static int binder_inc_node(struct binder_node *node, int strong, int internal, + struct list_head *target_list) +{ + int ret; + + if (node->proc) + binder_inner_proc_lock(node->proc); + ret = binder_inc_node_ilocked(node, strong, internal, target_list); + if (node->proc) + binder_inner_proc_unlock(node->proc); + + return ret; +} + +static bool binder_dec_node_ilocked(struct binder_node *node, + int strong, int internal) { + struct binder_proc *proc = node->proc; + + if (proc) + BUG_ON(!spin_is_locked(&proc->inner_lock)); if (strong) { if (internal) node->internal_strong_refs--; else node->local_strong_refs--; if (node->local_strong_refs || node->internal_strong_refs) - return 0; + return false; } else { if (!internal) node->local_weak_refs--; if (node->local_weak_refs || node->tmp_refs || !hlist_empty(&node->refs)) - return 0; + return false; } - if (node->proc && (node->has_strong_ref || node->has_weak_ref)) { + + if (proc && (node->has_strong_ref || node->has_weak_ref)) { if (list_empty(&node->work.entry)) { list_add_tail(&node->work.entry, &node->proc->todo); wake_up_interruptible(&node->proc->wait); @@ -874,25 +933,55 @@ static int binder_dec_node(struct binder_node *node, int strong, int internal) if (hlist_empty(&node->refs) && !node->local_strong_refs && !node->local_weak_refs && !node->tmp_refs) { list_del_init(&node->work.entry); - if (node->proc) { + if (proc) { rb_erase(&node->rb_node, &node->proc->nodes); binder_debug(BINDER_DEBUG_INTERNAL_REFS, "refless node %d deleted\n", node->debug_id); } else { spin_lock(&binder_dead_nodes_lock); + /* + * tmp_refs could have changed so + * check it again + */ + if (node->tmp_refs) { + spin_unlock(&binder_dead_nodes_lock); + return false; + } hlist_del(&node->dead_node); spin_unlock(&binder_dead_nodes_lock); binder_debug(BINDER_DEBUG_INTERNAL_REFS, "dead node %d deleted\n", node->debug_id); } - kfree(node); - binder_stats_deleted(BINDER_STAT_NODE); + return true; } } + return false; +} - return 0; +static void binder_dec_node(struct binder_node *node, int strong, int internal) +{ + bool free_node; + + if (node->proc) + binder_inner_proc_lock(node->proc); + free_node = binder_dec_node_ilocked(node, strong, internal); + if (node->proc) + binder_inner_proc_unlock(node->proc); + + if (free_node) + binder_free_node(node); +} + +static void binder_inc_node_tmpref_ilocked(struct binder_node *node) +{ + /* + * No call to binder_inc_node() is needed since we + * don't need to inform userspace of any changes to + * tmp_refs + */ + node->tmp_refs++; } /** @@ -900,16 +989,25 @@ static int binder_dec_node(struct binder_node *node, int strong, int internal) * @node: node to reference * * Take reference on node to prevent the node from being freed - * while referenced only by a local variable + * while referenced only by a local variable. The inner lock is + * needed to serialize with the node work on the queue (which + * isn't needed after the node is dead). If the node is dead + * (node->proc is NULL), use binder_dead_nodes_lock to protect + * node->tmp_refs against dead-node-only cases where the node + * lock cannot be acquired (eg traversing the dead node list to + * print nodes) */ static void binder_inc_node_tmpref(struct binder_node *node) { - /* - * No call to binder_inc_node() is needed since we - * don't need to inform userspace of any changes to - * tmp_refs - */ - node->tmp_refs++; + if (node->proc) + binder_inner_proc_lock(node->proc); + else + spin_lock(&binder_dead_nodes_lock); + binder_inc_node_tmpref_ilocked(node); + if (node->proc) + binder_inner_proc_unlock(node->proc); + else + spin_unlock(&binder_dead_nodes_lock); } /** @@ -920,15 +1018,27 @@ static void binder_inc_node_tmpref(struct binder_node *node) */ static void binder_dec_node_tmpref(struct binder_node *node) { + bool free_node; + + if (node->proc) + binder_inner_proc_lock(node->proc); + else + spin_lock(&binder_dead_nodes_lock); node->tmp_refs--; BUG_ON(node->tmp_refs < 0); + if (!node->proc) + spin_unlock(&binder_dead_nodes_lock); /* * Call binder_dec_node() to check if all refcounts are 0 * and cleanup is needed. Calling with strong=0 and internal=1 * causes no actual reference to be released in binder_dec_node(). * If that changes, a change is needed here too. */ - binder_dec_node(node, 0, 1); + free_node = binder_dec_node_ilocked(node, 0, 1); + if (node->proc) + binder_inner_proc_unlock(node->proc); + if (free_node) + binder_free_node(node); } static void binder_put_node(struct binder_node *node) @@ -1041,6 +1151,9 @@ static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc, static void binder_cleanup_ref(struct binder_ref *ref) { + bool delete_node = false; + struct binder_proc *node_proc = ref->node->proc; + binder_debug(BINDER_DEBUG_INTERNAL_REFS, "%d delete ref %d desc %d for node %d\n", ref->proc->pid, ref->data.debug_id, ref->data.desc, @@ -1049,11 +1162,26 @@ static void binder_cleanup_ref(struct binder_ref *ref) rb_erase(&ref->rb_node_desc, &ref->proc->refs_by_desc); rb_erase(&ref->rb_node_node, &ref->proc->refs_by_node); + if (node_proc) + binder_inner_proc_lock(node_proc); if (ref->data.strong) - binder_dec_node(ref->node, 1, 1); + binder_dec_node_ilocked(ref->node, 1, 1); hlist_del(&ref->node_entry); - binder_dec_node(ref->node, 0, 1); + delete_node = binder_dec_node_ilocked(ref->node, 0, 1); + if (node_proc) + binder_inner_proc_unlock(node_proc); + /* + * Clear ref->node unless we want the caller to free the node + */ + if (!delete_node) { + /* + * The caller uses ref->node to determine + * whether the node needs to be freed. Clear + * it since the node is still alive. + */ + ref->node = NULL; + } if (ref->death) { binder_debug(BINDER_DEBUG_DEAD_BINDER, @@ -1122,13 +1250,8 @@ static bool binder_dec_ref(struct binder_ref *ref, int strong) return false; } ref->data.strong--; - if (ref->data.strong == 0) { - int ret; - - ret = binder_dec_node(ref->node, strong, 1); - if (ret) - return false; - } + if (ref->data.strong == 0) + binder_dec_node(ref->node, strong, 1); } else { if (ref->data.weak == 0) { binder_user_error("%d invalid dec weak, ref %d desc %d s %d w %d\n", @@ -1193,10 +1316,13 @@ err_no_ref: * binder_free_ref() - free the binder_ref * @ref: ref to free * - * Free the binder_ref and the binder_ref_death indicated by ref->death. + * Free the binder_ref. Free the binder_node indicated by ref->node + * (if non-NULL) and the binder_ref_death indicated by ref->death. */ static void binder_free_ref(struct binder_ref *ref) { + if (ref->node) + binder_free_node(ref->node); kfree(ref->death); kfree(ref); } @@ -2687,11 +2813,13 @@ static int binder_thread_write(struct binder_proc *proc, binder_put_node(node); break; } + binder_inner_proc_lock(proc); if (cmd == BC_ACQUIRE_DONE) { if (node->pending_strong_ref == 0) { binder_user_error("%d:%d BC_ACQUIRE_DONE node %d has no pending acquire request\n", proc->pid, thread->pid, node->debug_id); + binder_inner_proc_unlock(proc); binder_put_node(node); break; } @@ -2701,11 +2829,13 @@ static int binder_thread_write(struct binder_proc *proc, binder_user_error("%d:%d BC_INCREFS_DONE node %d has no pending increfs request\n", proc->pid, thread->pid, node->debug_id); + binder_inner_proc_unlock(proc); binder_put_node(node); break; } node->pending_weak_ref = 0; } + binder_inner_proc_unlock(proc); binder_dec_node(node, cmd == BC_ACQUIRE_DONE, 0); binder_debug(BINDER_DEBUG_USER_REFS, "%d:%d %s node %d ls %d lw %d tr %d\n", @@ -3091,6 +3221,7 @@ retry: struct binder_transaction *t = NULL; struct binder_thread *t_from; + binder_inner_proc_lock(proc); if (!list_empty(&thread->todo)) { w = list_first_entry(&thread->todo, struct binder_work, entry); @@ -3104,11 +3235,15 @@ retry: break; } - if (end - ptr < sizeof(tr) + 4) + if (end - ptr < sizeof(tr) + 4) { + binder_inner_proc_unlock(proc); break; + } + list_del_init(&w->entry); switch (w->type) { case BINDER_WORK_TRANSACTION: { + binder_inner_proc_unlock(proc); t = container_of(w, struct binder_transaction, work); } break; case BINDER_WORK_RETURN_ERROR: { @@ -3116,15 +3251,16 @@ retry: w, struct binder_error, work); WARN_ON(e->cmd == BR_OK); + binder_inner_proc_unlock(proc); if (put_user(e->cmd, (uint32_t __user *)ptr)) return -EFAULT; e->cmd = BR_OK; ptr += sizeof(uint32_t); binder_stat_br(proc, thread, cmd); - list_del(&w->entry); } break; case BINDER_WORK_TRANSACTION_COMPLETE: { + binder_inner_proc_unlock(proc); cmd = BR_TRANSACTION_COMPLETE; if (put_user(cmd, (uint32_t __user *)ptr)) return -EFAULT; @@ -3134,8 +3270,6 @@ retry: binder_debug(BINDER_DEBUG_TRANSACTION_COMPLETE, "%d:%d BR_TRANSACTION_COMPLETE\n", proc->pid, thread->pid); - - list_del(&w->entry); kfree(w); binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE); } break; @@ -3172,8 +3306,6 @@ retry: node->has_strong_ref = 0; if (!weak && has_weak_ref) node->has_weak_ref = 0; - list_del(&w->entry); - if (!weak && !strong) { binder_debug(BINDER_DEBUG_INTERNAL_REFS, "%d:%d node %d u%016llx c%016llx deleted\n", @@ -3182,9 +3314,11 @@ retry: (u64)node_ptr, (u64)node_cookie); rb_erase(&node->rb_node, &proc->nodes); - kfree(node); - binder_stats_deleted(BINDER_STAT_NODE); - } + binder_inner_proc_unlock(proc); + binder_free_node(node); + } else + binder_inner_proc_unlock(proc); + if (weak && !has_weak_ref) ret = binder_put_node_cmd( proc, thread, &ptr, node_ptr, @@ -3226,6 +3360,13 @@ retry: cmd = BR_CLEAR_DEATH_NOTIFICATION_DONE; else cmd = BR_DEAD_BINDER; + /* + * TODO: there is a race condition between + * death notification requests and delivery + * of the notifications. This will be handled + * in a later patch. + */ + binder_inner_proc_unlock(proc); if (put_user(cmd, (uint32_t __user *)ptr)) return -EFAULT; ptr += sizeof(uint32_t); @@ -3243,11 +3384,14 @@ retry: (u64)death->cookie); if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION) { - list_del(&w->entry); kfree(death); binder_stats_deleted(BINDER_STAT_DEATH); - } else - list_move(&w->entry, &proc->delivered_death); + } else { + binder_inner_proc_lock(proc); + list_add_tail(&w->entry, + &proc->delivered_death); + binder_inner_proc_unlock(proc); + } if (cmd == BR_DEAD_BINDER) goto done; /* DEAD_BINDER notifications can cause transactions */ } break; @@ -3325,7 +3469,6 @@ retry: if (t_from) binder_thread_dec_tmpref(t_from); - list_del(&t->work.entry); t->buffer->allow_user_free = 1; if (cmd == BR_TRANSACTION && !(t->flags & TF_ONE_WAY)) { t->to_parent = thread->transaction_stack; @@ -3924,16 +4067,19 @@ static int binder_node_release(struct binder_node *node, int refs) { struct binder_ref *ref; int death = 0; + struct binder_proc *proc = node->proc; - list_del_init(&node->work.entry); binder_release_work(&node->async_todo); + + binder_inner_proc_lock(proc); + list_del_init(&node->work.entry); /* * The caller must have taken a temporary ref on the node, */ BUG_ON(!node->tmp_refs); if (hlist_empty(&node->refs) && node->tmp_refs == 1) { - kfree(node); - binder_stats_deleted(BINDER_STAT_NODE); + binder_inner_proc_unlock(proc); + binder_free_node(node); return refs; } @@ -3941,6 +4087,7 @@ static int binder_node_release(struct binder_node *node, int refs) node->proc = NULL; node->local_strong_refs = 0; node->local_weak_refs = 0; + binder_inner_proc_unlock(proc); spin_lock(&binder_dead_nodes_lock); hlist_add_head(&node->dead_node, &binder_dead_nodes); -- cgit v1.2.3 From 72196393a5e3d28c21679e3b745c06dd4a5b24c9 Mon Sep 17 00:00:00 2001 From: Todd Kjos Date: Thu, 29 Jun 2017 12:02:02 -0700 Subject: binder: add spinlocks to protect todo lists The todo lists in the proc, thread, and node structures are accessed by other procs/threads to place work items on the queue. The todo lists are protected by the new proc->inner_lock. No locks should ever be nested under these locks. As the name suggests, an outer lock will be introduced in a later patch. Signed-off-by: Todd Kjos Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 355 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 269 insertions(+), 86 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 6c741416fa00..5a0389767843 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -279,8 +279,16 @@ struct binder_device { struct binder_context context; }; +/** + * struct binder_work - work enqueued on a worklist + * @entry: node enqueued on list + * @type: type of work to be performed + * + * There are separate work lists for proc, thread, and node (async). + */ struct binder_work { struct list_head entry; + enum { BINDER_WORK_TRANSACTION = 1, BINDER_WORK_TRANSACTION_COMPLETE, @@ -303,6 +311,7 @@ struct binder_error { * (invariant after initialized) * @lock: lock for node fields * @work: worklist element for node work + * (protected by @proc->inner_lock) * @rb_node: element for proc->nodes tree * @dead_node: element for binder_dead_nodes list * (protected by binder_dead_nodes_lock) @@ -347,6 +356,7 @@ struct binder_error { * @min_priority: minimum scheduling priority * (invariant after initialized) * @async_todo: list of async work items + * (protected by @proc->inner_lock) * * Bookkeeping structure for binder nodes. */ @@ -388,6 +398,11 @@ struct binder_node { }; struct binder_ref_death { + /** + * @work: worklist element for death notifications + * (protected by inner_lock of the proc that + * this ref belongs to) + */ struct binder_work work; binder_uintptr_t cookie; }; @@ -467,11 +482,13 @@ enum binder_deferred_state { * @is_dead: process is dead and awaiting free * when outstanding transactions are cleaned up * @todo: list of work for this process + * (protected by @inner_lock) * @wait: wait queue head to wait for proc work * (invariant after initialized) * @stats: per-process binder statistics * (atomics, no lock needed) * @delivered_death: list of delivered death notification + * (protected by @inner_lock) * @max_threads: cap on number of binder threads * @requested_threads: number of binder threads requested but not * yet started. In current implementation, can @@ -542,6 +559,7 @@ enum { * (no lock needed) * @transaction_stack: stack of in-progress transactions for this thread * @todo: list of work to do for this thread + * (protected by @proc->inner_lock) * @return_error: transaction errors reported by this thread * (only accessed by this thread) * @reply_error: transaction errors reported by target thread @@ -689,6 +707,111 @@ _binder_node_unlock(struct binder_node *node, int line) spin_unlock(&node->lock); } +static bool binder_worklist_empty_ilocked(struct list_head *list) +{ + return list_empty(list); +} + +/** + * binder_worklist_empty() - Check if no items on the work list + * @proc: binder_proc associated with list + * @list: list to check + * + * Return: true if there are no items on list, else false + */ +static bool binder_worklist_empty(struct binder_proc *proc, + struct list_head *list) +{ + bool ret; + + binder_inner_proc_lock(proc); + ret = binder_worklist_empty_ilocked(list); + binder_inner_proc_unlock(proc); + return ret; +} + +static void +binder_enqueue_work_ilocked(struct binder_work *work, + struct list_head *target_list) +{ + BUG_ON(target_list == NULL); + BUG_ON(work->entry.next && !list_empty(&work->entry)); + list_add_tail(&work->entry, target_list); +} + +/** + * binder_enqueue_work() - Add an item to the work list + * @proc: binder_proc associated with list + * @work: struct binder_work to add to list + * @target_list: list to add work to + * + * Adds the work to the specified list. Asserts that work + * is not already on a list. + */ +static void +binder_enqueue_work(struct binder_proc *proc, + struct binder_work *work, + struct list_head *target_list) +{ + binder_inner_proc_lock(proc); + binder_enqueue_work_ilocked(work, target_list); + binder_inner_proc_unlock(proc); +} + +static void +binder_dequeue_work_ilocked(struct binder_work *work) +{ + list_del_init(&work->entry); +} + +/** + * binder_dequeue_work() - Removes an item from the work list + * @proc: binder_proc associated with list + * @work: struct binder_work to remove from list + * + * Removes the specified work item from whatever list it is on. + * Can safely be called if work is not on any list. + */ +static void +binder_dequeue_work(struct binder_proc *proc, struct binder_work *work) +{ + binder_inner_proc_lock(proc); + binder_dequeue_work_ilocked(work); + binder_inner_proc_unlock(proc); +} + +static struct binder_work *binder_dequeue_work_head_ilocked( + struct list_head *list) +{ + struct binder_work *w; + + w = list_first_entry_or_null(list, struct binder_work, entry); + if (w) + list_del_init(&w->entry); + return w; +} + +/** + * binder_dequeue_work_head() - Dequeues the item at head of list + * @proc: binder_proc associated with list + * @list: list to dequeue head + * + * Removes the head of the list if there are items on the list + * + * Return: pointer dequeued binder_work, NULL if list was empty + */ +static struct binder_work *binder_dequeue_work_head( + struct binder_proc *proc, + struct list_head *list) +{ + struct binder_work *w; + + binder_inner_proc_lock(proc); + w = binder_dequeue_work_head_ilocked(list); + binder_inner_proc_unlock(proc); + return w; +} + static void binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer); static void binder_free_thread(struct binder_thread *thread); @@ -870,8 +993,8 @@ static int binder_inc_node_ilocked(struct binder_node *node, int strong, } else node->local_strong_refs++; if (!node->has_strong_ref && target_list) { - list_del_init(&node->work.entry); - list_add_tail(&node->work.entry, target_list); + binder_dequeue_work_ilocked(&node->work); + binder_enqueue_work_ilocked(&node->work, target_list); } } else { if (!internal) @@ -882,7 +1005,7 @@ static int binder_inc_node_ilocked(struct binder_node *node, int strong, node->debug_id); return -EINVAL; } - list_add_tail(&node->work.entry, target_list); + binder_enqueue_work_ilocked(&node->work, target_list); } } return 0; @@ -926,19 +1049,20 @@ static bool binder_dec_node_ilocked(struct binder_node *node, if (proc && (node->has_strong_ref || node->has_weak_ref)) { if (list_empty(&node->work.entry)) { - list_add_tail(&node->work.entry, &node->proc->todo); + binder_enqueue_work_ilocked(&node->work, &proc->todo); wake_up_interruptible(&node->proc->wait); } } else { if (hlist_empty(&node->refs) && !node->local_strong_refs && !node->local_weak_refs && !node->tmp_refs) { - list_del_init(&node->work.entry); if (proc) { - rb_erase(&node->rb_node, &node->proc->nodes); + binder_dequeue_work_ilocked(&node->work); + rb_erase(&node->rb_node, &proc->nodes); binder_debug(BINDER_DEBUG_INTERNAL_REFS, "refless node %d deleted\n", node->debug_id); } else { + BUG_ON(!list_empty(&node->work.entry)); spin_lock(&binder_dead_nodes_lock); /* * tmp_refs could have changed so @@ -1188,7 +1312,7 @@ static void binder_cleanup_ref(struct binder_ref *ref) "%d delete ref %d desc %d has death notification\n", ref->proc->pid, ref->data.debug_id, ref->data.desc); - list_del(&ref->death->work.entry); + binder_dequeue_work(ref->proc, &ref->death->work); binder_stats_deleted(BINDER_STAT_DEATH); } binder_stats_deleted(BINDER_STAT_REF); @@ -1539,8 +1663,9 @@ static void binder_send_failed_reply(struct binder_transaction *t, binder_pop_transaction(target_thread, t); if (target_thread->reply_error.cmd == BR_OK) { target_thread->reply_error.cmd = error_code; - list_add_tail( - &target_thread->reply_error.work.entry, + binder_enqueue_work( + target_thread->proc, + &target_thread->reply_error.work, &target_thread->todo); wake_up_interruptible(&target_thread->wait); } else { @@ -2578,7 +2703,7 @@ static void binder_transaction(struct binder_proc *proc, } } tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE; - list_add_tail(&tcomplete->entry, &thread->todo); + binder_enqueue_work(proc, tcomplete, &thread->todo); if (reply) { if (target_thread->is_dead) @@ -2609,7 +2734,7 @@ static void binder_transaction(struct binder_proc *proc, goto err_dead_proc_or_thread; } t->work.type = BINDER_WORK_TRANSACTION; - list_add_tail(&t->work.entry, target_list); + binder_enqueue_work(target_proc, &t->work, target_list); if (target_wait) { if (reply || !(tr->flags & TF_ONE_WAY)) wake_up_interruptible_sync(target_wait); @@ -2685,13 +2810,15 @@ err_no_context_mgr_node: BUG_ON(thread->return_error.cmd != BR_OK); if (in_reply_to) { thread->return_error.cmd = BR_TRANSACTION_COMPLETE; - list_add_tail(&thread->return_error.work.entry, - &thread->todo); + binder_enqueue_work(thread->proc, + &thread->return_error.work, + &thread->todo); binder_send_failed_reply(in_reply_to, return_error); } else { thread->return_error.cmd = return_error; - list_add_tail(&thread->return_error.work.entry, - &thread->todo); + binder_enqueue_work(thread->proc, + &thread->return_error.work, + &thread->todo); } } @@ -2884,11 +3011,21 @@ static int binder_thread_write(struct binder_proc *proc, buffer->transaction = NULL; } if (buffer->async_transaction && buffer->target_node) { - BUG_ON(!buffer->target_node->has_async_transaction); - if (list_empty(&buffer->target_node->async_todo)) - buffer->target_node->has_async_transaction = 0; + struct binder_node *buf_node; + struct binder_work *w; + + buf_node = buffer->target_node; + BUG_ON(!buf_node->has_async_transaction); + BUG_ON(buf_node->proc != proc); + binder_inner_proc_lock(proc); + w = binder_dequeue_work_head_ilocked( + &buf_node->async_todo); + if (!w) + buf_node->has_async_transaction = 0; else - list_move_tail(buffer->target_node->async_todo.next, &thread->todo); + binder_enqueue_work_ilocked( + w, &thread->todo); + binder_inner_proc_unlock(proc); } trace_binder_transaction_buffer_release(buffer); binder_transaction_buffer_release(proc, buffer, NULL); @@ -3000,9 +3137,10 @@ static int binder_thread_write(struct binder_proc *proc, WARN_ON(thread->return_error.cmd != BR_OK); thread->return_error.cmd = BR_ERROR; - list_add_tail( - &thread->return_error.work.entry, - &thread->todo); + binder_enqueue_work( + thread->proc, + &thread->return_error.work, + &thread->todo); binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, "%d:%d BC_REQUEST_DEATH_NOTIFICATION failed\n", proc->pid, thread->pid); @@ -3014,11 +3152,20 @@ static int binder_thread_write(struct binder_proc *proc, ref->death = death; if (ref->node->proc == NULL) { ref->death->work.type = BINDER_WORK_DEAD_BINDER; - if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) { - list_add_tail(&ref->death->work.entry, &thread->todo); - } else { - list_add_tail(&ref->death->work.entry, &proc->todo); - wake_up_interruptible(&proc->wait); + if (thread->looper & + (BINDER_LOOPER_STATE_REGISTERED | + BINDER_LOOPER_STATE_ENTERED)) + binder_enqueue_work( + proc, + &ref->death->work, + &thread->todo); + else { + binder_enqueue_work( + proc, + &ref->death->work, + &proc->todo); + wake_up_interruptible( + &proc->wait); } } } else { @@ -3036,18 +3183,27 @@ static int binder_thread_write(struct binder_proc *proc, break; } ref->death = NULL; + binder_inner_proc_lock(proc); if (list_empty(&death->work.entry)) { death->work.type = BINDER_WORK_CLEAR_DEATH_NOTIFICATION; - if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) { - list_add_tail(&death->work.entry, &thread->todo); - } else { - list_add_tail(&death->work.entry, &proc->todo); - wake_up_interruptible(&proc->wait); + if (thread->looper & + (BINDER_LOOPER_STATE_REGISTERED | + BINDER_LOOPER_STATE_ENTERED)) + binder_enqueue_work_ilocked( + &death->work, + &thread->todo); + else { + binder_enqueue_work_ilocked( + &death->work, + &proc->todo); + wake_up_interruptible( + &proc->wait); } } else { BUG_ON(death->work.type != BINDER_WORK_DEAD_BINDER); death->work.type = BINDER_WORK_DEAD_BINDER_AND_CLEAR; } + binder_inner_proc_unlock(proc); } } break; case BC_DEAD_BINDER_DONE: { @@ -3059,8 +3215,13 @@ static int binder_thread_write(struct binder_proc *proc, return -EFAULT; ptr += sizeof(cookie); - list_for_each_entry(w, &proc->delivered_death, entry) { - struct binder_ref_death *tmp_death = container_of(w, struct binder_ref_death, work); + binder_inner_proc_lock(proc); + list_for_each_entry(w, &proc->delivered_death, + entry) { + struct binder_ref_death *tmp_death = + container_of(w, + struct binder_ref_death, + work); if (tmp_death->cookie == cookie) { death = tmp_death; @@ -3074,19 +3235,25 @@ static int binder_thread_write(struct binder_proc *proc, if (death == NULL) { binder_user_error("%d:%d BC_DEAD_BINDER_DONE %016llx not found\n", proc->pid, thread->pid, (u64)cookie); + binder_inner_proc_unlock(proc); break; } - - list_del_init(&death->work.entry); + binder_dequeue_work_ilocked(&death->work); if (death->work.type == BINDER_WORK_DEAD_BINDER_AND_CLEAR) { death->work.type = BINDER_WORK_CLEAR_DEATH_NOTIFICATION; - if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) { - list_add_tail(&death->work.entry, &thread->todo); - } else { - list_add_tail(&death->work.entry, &proc->todo); + if (thread->looper & + (BINDER_LOOPER_STATE_REGISTERED | + BINDER_LOOPER_STATE_ENTERED)) + binder_enqueue_work_ilocked( + &death->work, &thread->todo); + else { + binder_enqueue_work_ilocked( + &death->work, + &proc->todo); wake_up_interruptible(&proc->wait); } } + binder_inner_proc_unlock(proc); } break; default: @@ -3113,12 +3280,14 @@ static void binder_stat_br(struct binder_proc *proc, static int binder_has_proc_work(struct binder_proc *proc, struct binder_thread *thread) { - return !list_empty(&proc->todo) || thread->looper_need_return; + return !binder_worklist_empty(proc, &proc->todo) || + thread->looper_need_return; } static int binder_has_thread_work(struct binder_thread *thread) { - return !list_empty(&thread->todo) || thread->looper_need_return; + return !binder_worklist_empty(thread->proc, &thread->todo) || + thread->looper_need_return; } static int binder_put_node_cmd(struct binder_proc *proc, @@ -3172,7 +3341,7 @@ static int binder_thread_read(struct binder_proc *proc, retry: wait_for_proc_work = thread->transaction_stack == NULL && - list_empty(&thread->todo); + binder_worklist_empty(proc, &thread->todo); thread->looper |= BINDER_LOOPER_STATE_WAITING; if (wait_for_proc_work) @@ -3182,7 +3351,7 @@ retry: trace_binder_wait_for_work(wait_for_proc_work, !!thread->transaction_stack, - !list_empty(&thread->todo)); + !binder_worklist_empty(proc, &thread->todo)); if (wait_for_proc_work) { if (!(thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED))) { @@ -3217,18 +3386,20 @@ retry: while (1) { uint32_t cmd; struct binder_transaction_data tr; - struct binder_work *w; + struct binder_work *w = NULL; + struct list_head *list = NULL; struct binder_transaction *t = NULL; struct binder_thread *t_from; binder_inner_proc_lock(proc); - if (!list_empty(&thread->todo)) { - w = list_first_entry(&thread->todo, struct binder_work, - entry); - } else if (!list_empty(&proc->todo) && wait_for_proc_work) { - w = list_first_entry(&proc->todo, struct binder_work, - entry); - } else { + if (!binder_worklist_empty_ilocked(&thread->todo)) + list = &thread->todo; + else if (!binder_worklist_empty_ilocked(&proc->todo) && + wait_for_proc_work) + list = &proc->todo; + else { + binder_inner_proc_unlock(proc); + /* no data added */ if (ptr - buffer == 4 && !thread->looper_need_return) goto retry; @@ -3239,7 +3410,7 @@ retry: binder_inner_proc_unlock(proc); break; } - list_del_init(&w->entry); + w = binder_dequeue_work_head_ilocked(list); switch (w->type) { case BINDER_WORK_TRANSACTION: { @@ -3388,8 +3559,8 @@ retry: binder_stats_deleted(BINDER_STAT_DEATH); } else { binder_inner_proc_lock(proc); - list_add_tail(&w->entry, - &proc->delivered_death); + binder_enqueue_work_ilocked( + w, &proc->delivered_death); binder_inner_proc_unlock(proc); } if (cmd == BR_DEAD_BINDER) @@ -3499,13 +3670,16 @@ done: return 0; } -static void binder_release_work(struct list_head *list) +static void binder_release_work(struct binder_proc *proc, + struct list_head *list) { struct binder_work *w; - while (!list_empty(list)) { - w = list_first_entry(list, struct binder_work, entry); - list_del_init(&w->entry); + while (1) { + w = binder_dequeue_work_head(proc, list); + if (!w) + return; + switch (w->type) { case BINDER_WORK_TRANSACTION: { struct binder_transaction *t; @@ -3669,7 +3843,7 @@ static int binder_thread_release(struct binder_proc *proc, if (send_reply) binder_send_failed_reply(send_reply, BR_DEAD_REPLY); - binder_release_work(&thread->todo); + binder_release_work(proc, &thread->todo); binder_thread_dec_tmpref(thread); return active_transactions; } @@ -3686,7 +3860,7 @@ static unsigned int binder_poll(struct file *filp, thread = binder_get_thread(proc); wait_for_proc_work = thread->transaction_stack == NULL && - list_empty(&thread->todo); + binder_worklist_empty(proc, &thread->todo); binder_unlock(__func__); @@ -3749,7 +3923,7 @@ static int binder_ioctl_write_read(struct file *filp, &bwr.read_consumed, filp->f_flags & O_NONBLOCK); trace_binder_read_done(ret); - if (!list_empty(&proc->todo)) + if (!binder_worklist_empty(proc, &proc->todo)) wake_up_interruptible(&proc->wait); if (ret < 0) { if (copy_to_user(ubuf, &bwr, sizeof(bwr))) @@ -4069,10 +4243,10 @@ static int binder_node_release(struct binder_node *node, int refs) int death = 0; struct binder_proc *proc = node->proc; - binder_release_work(&node->async_todo); + binder_release_work(proc, &node->async_todo); binder_inner_proc_lock(proc); - list_del_init(&node->work.entry); + binder_dequeue_work_ilocked(&node->work); /* * The caller must have taken a temporary ref on the node, */ @@ -4101,13 +4275,15 @@ static int binder_node_release(struct binder_node *node, int refs) death++; + binder_inner_proc_lock(ref->proc); if (list_empty(&ref->death->work.entry)) { ref->death->work.type = BINDER_WORK_DEAD_BINDER; - list_add_tail(&ref->death->work.entry, - &ref->proc->todo); + binder_enqueue_work_ilocked(&ref->death->work, + &ref->proc->todo); wake_up_interruptible(&ref->proc->wait); } else BUG(); + binder_inner_proc_unlock(ref->proc); } binder_debug(BINDER_DEBUG_DEAD_BINDER, @@ -4183,8 +4359,8 @@ static void binder_deferred_release(struct binder_proc *proc) binder_free_ref(ref); } - binder_release_work(&proc->todo); - binder_release_work(&proc->delivered_death); + binder_release_work(proc, &proc->todo); + binder_release_work(proc, &proc->delivered_death); binder_debug(BINDER_DEBUG_OPEN_CLOSE, "%s: %d threads %d, nodes %d (ref %d), refs %d, active transactions %d\n", @@ -4275,9 +4451,9 @@ static void print_binder_transaction(struct seq_file *m, const char *prefix, t->buffer->data); } -static void print_binder_work(struct seq_file *m, const char *prefix, - const char *transaction_prefix, - struct binder_work *w) +static void print_binder_work_ilocked(struct seq_file *m, const char *prefix, + const char *transaction_prefix, + struct binder_work *w) { struct binder_node *node; struct binder_transaction *t; @@ -4318,15 +4494,16 @@ static void print_binder_work(struct seq_file *m, const char *prefix, } } -static void print_binder_thread(struct seq_file *m, - struct binder_thread *thread, - int print_always) +static void print_binder_thread_ilocked(struct seq_file *m, + struct binder_thread *thread, + int print_always) { struct binder_transaction *t; struct binder_work *w; size_t start_pos = m->count; size_t header_pos; + WARN_ON(!spin_is_locked(&thread->proc->inner_lock)); seq_printf(m, " thread %d: l %02x need_return %d tr %d\n", thread->pid, thread->looper, thread->looper_need_return, @@ -4348,7 +4525,8 @@ static void print_binder_thread(struct seq_file *m, } } list_for_each_entry(w, &thread->todo, entry) { - print_binder_work(m, " ", " pending transaction", w); + print_binder_work_ilocked(m, " ", + " pending transaction", w); } if (!print_always && m->count == header_pos) m->count = start_pos; @@ -4375,9 +4553,13 @@ static void print_binder_node(struct seq_file *m, struct binder_node *node) seq_printf(m, " %d", ref->proc->pid); } seq_puts(m, "\n"); - list_for_each_entry(w, &node->async_todo, entry) - print_binder_work(m, " ", - " pending async transaction", w); + if (node->proc) { + binder_inner_proc_lock(node->proc); + list_for_each_entry(w, &node->async_todo, entry) + print_binder_work_ilocked(m, " ", + " pending async transaction", w); + binder_inner_proc_unlock(node->proc); + } } static void print_binder_ref(struct seq_file *m, struct binder_ref *ref) @@ -4401,9 +4583,11 @@ static void print_binder_proc(struct seq_file *m, seq_printf(m, "context %s\n", proc->context->name); header_pos = m->count; + binder_inner_proc_lock(proc); for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) - print_binder_thread(m, rb_entry(n, struct binder_thread, + print_binder_thread_ilocked(m, rb_entry(n, struct binder_thread, rb_node), print_all); + binder_inner_proc_unlock(proc); for (n = rb_first(&proc->nodes); n != NULL; n = rb_next(n)) { struct binder_node *node = rb_entry(n, struct binder_node, rb_node); @@ -4418,12 +4602,14 @@ static void print_binder_proc(struct seq_file *m, rb_node_desc)); } binder_alloc_print_allocated(m, &proc->alloc); + binder_inner_proc_lock(proc); list_for_each_entry(w, &proc->todo, entry) - print_binder_work(m, " ", " pending transaction", w); + print_binder_work_ilocked(m, " ", " pending transaction", w); list_for_each_entry(w, &proc->delivered_death, entry) { seq_puts(m, " has delivered dead binder\n"); break; } + binder_inner_proc_unlock(proc); if (!print_all && m->count == header_pos) m->count = start_pos; } @@ -4562,15 +4748,12 @@ static void print_binder_proc_stats(struct seq_file *m, seq_printf(m, " buffers: %d\n", count); count = 0; + binder_inner_proc_lock(proc); list_for_each_entry(w, &proc->todo, entry) { - switch (w->type) { - case BINDER_WORK_TRANSACTION: + if (w->type == BINDER_WORK_TRANSACTION) count++; - break; - default: - break; - } } + binder_inner_proc_unlock(proc); seq_printf(m, " pending transactions: %d\n", count); print_binder_stats(m, " ", &proc->stats); -- cgit v1.2.3 From 673068eee8560d57e0b37bbb52157811b7f5b563 Mon Sep 17 00:00:00 2001 From: Todd Kjos Date: Thu, 29 Jun 2017 12:02:03 -0700 Subject: binder: add spinlock to protect binder_node node->node_lock is used to protect elements of node. No need to acquire for fields that are invariant: debug_id, ptr, cookie. Signed-off-by: Todd Kjos Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 220 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 165 insertions(+), 55 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 5a0389767843..5654187555be 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -318,6 +318,7 @@ struct binder_error { * @proc: binder_proc that owns this node * (invariant after initialized) * @refs: list of references on this node + * (protected by @lock) * @internal_strong_refs: used to take strong references when * initiating a transaction * (protected by @proc->inner_lock if @proc @@ -351,6 +352,7 @@ struct binder_error { * (protected by @proc->inner_lock if @proc * and by @lock) * @has_async_transaction: async transaction to node in progress + * (protected by @lock) * @accept_fds: file descriptor operations supported for node * (invariant after initialized) * @min_priority: minimum scheduling priority @@ -432,6 +434,7 @@ struct binder_ref_data { * @rb_node_desc: node for lookup by @data.desc in proc's rb_tree * @rb_node_node: node for lookup by @node in proc's rb_tree * @node_entry: list entry for node->refs list in target node + * (protected by @node->lock) * @proc: binder_proc containing ref * @node: binder_node of target node. When cleaning up a * ref for deletion in binder_cleanup_ref, a non-NULL @@ -707,6 +710,43 @@ _binder_node_unlock(struct binder_node *node, int line) spin_unlock(&node->lock); } +/** + * binder_node_inner_lock() - Acquire node and inner locks + * @node: struct binder_node to acquire + * + * Acquires node->lock. If node->proc also acquires + * proc->inner_lock. Used to protect binder_node fields + */ +#define binder_node_inner_lock(node) _binder_node_inner_lock(node, __LINE__) +static void +_binder_node_inner_lock(struct binder_node *node, int line) +{ + binder_debug(BINDER_DEBUG_SPINLOCKS, + "%s: line=%d\n", __func__, line); + spin_lock(&node->lock); + if (node->proc) + binder_inner_proc_lock(node->proc); +} + +/** + * binder_node_unlock() - Release node and inner locks + * @node: struct binder_node to acquire + * + * Release lock acquired via binder_node_lock() + */ +#define binder_node_inner_unlock(node) _binder_node_inner_unlock(node, __LINE__) +static void +_binder_node_inner_unlock(struct binder_node *node, int line) +{ + struct binder_proc *proc = node->proc; + + binder_debug(BINDER_DEBUG_SPINLOCKS, + "%s: line=%d\n", __func__, line); + if (proc) + binder_inner_proc_unlock(proc); + spin_unlock(&node->lock); +} + static bool binder_worklist_empty_ilocked(struct list_head *list) { return list_empty(list); @@ -925,12 +965,14 @@ static struct binder_node *binder_get_node(struct binder_proc *proc, } static struct binder_node *binder_new_node(struct binder_proc *proc, - binder_uintptr_t ptr, - binder_uintptr_t cookie) + struct flat_binder_object *fp) { struct rb_node **p = &proc->nodes.rb_node; struct rb_node *parent = NULL; struct binder_node *node; + binder_uintptr_t ptr = fp ? fp->binder : 0; + binder_uintptr_t cookie = fp ? fp->cookie : 0; + __u32 flags = fp ? fp->flags : 0; while (*p) { parent = *p; @@ -956,6 +998,8 @@ static struct binder_node *binder_new_node(struct binder_proc *proc, node->ptr = ptr; node->cookie = cookie; node->work.type = BINDER_WORK_NODE; + node->min_priority = flags & FLAT_BINDER_FLAG_PRIORITY_MASK; + node->accept_fds = !!(flags & FLAT_BINDER_FLAG_ACCEPTS_FDS); spin_lock_init(&node->lock); INIT_LIST_HEAD(&node->work.entry); INIT_LIST_HEAD(&node->async_todo); @@ -972,12 +1016,15 @@ static void binder_free_node(struct binder_node *node) binder_stats_deleted(BINDER_STAT_NODE); } -static int binder_inc_node_ilocked(struct binder_node *node, int strong, - int internal, - struct list_head *target_list) +static int binder_inc_node_nilocked(struct binder_node *node, int strong, + int internal, + struct list_head *target_list) { - if (node->proc) - BUG_ON(!spin_is_locked(&node->proc->inner_lock)); + struct binder_proc *proc = node->proc; + + BUG_ON(!spin_is_locked(&node->lock)); + if (proc) + BUG_ON(!spin_is_locked(&proc->inner_lock)); if (strong) { if (internal) { if (target_list == NULL && @@ -1016,20 +1063,19 @@ static int binder_inc_node(struct binder_node *node, int strong, int internal, { int ret; - if (node->proc) - binder_inner_proc_lock(node->proc); - ret = binder_inc_node_ilocked(node, strong, internal, target_list); - if (node->proc) - binder_inner_proc_unlock(node->proc); + binder_node_inner_lock(node); + ret = binder_inc_node_nilocked(node, strong, internal, target_list); + binder_node_inner_unlock(node); return ret; } -static bool binder_dec_node_ilocked(struct binder_node *node, - int strong, int internal) +static bool binder_dec_node_nilocked(struct binder_node *node, + int strong, int internal) { struct binder_proc *proc = node->proc; + BUG_ON(!spin_is_locked(&node->lock)); if (proc) BUG_ON(!spin_is_locked(&proc->inner_lock)); if (strong) { @@ -1088,12 +1134,9 @@ static void binder_dec_node(struct binder_node *node, int strong, int internal) { bool free_node; - if (node->proc) - binder_inner_proc_lock(node->proc); - free_node = binder_dec_node_ilocked(node, strong, internal); - if (node->proc) - binder_inner_proc_unlock(node->proc); - + binder_node_inner_lock(node); + free_node = binder_dec_node_nilocked(node, strong, internal); + binder_node_inner_unlock(node); if (free_node) binder_free_node(node); } @@ -1123,6 +1166,7 @@ static void binder_inc_node_tmpref_ilocked(struct binder_node *node) */ static void binder_inc_node_tmpref(struct binder_node *node) { + binder_node_lock(node); if (node->proc) binder_inner_proc_lock(node->proc); else @@ -1132,6 +1176,7 @@ static void binder_inc_node_tmpref(struct binder_node *node) binder_inner_proc_unlock(node->proc); else spin_unlock(&binder_dead_nodes_lock); + binder_node_unlock(node); } /** @@ -1144,9 +1189,8 @@ static void binder_dec_node_tmpref(struct binder_node *node) { bool free_node; - if (node->proc) - binder_inner_proc_lock(node->proc); - else + binder_node_inner_lock(node); + if (!node->proc) spin_lock(&binder_dead_nodes_lock); node->tmp_refs--; BUG_ON(node->tmp_refs < 0); @@ -1158,9 +1202,8 @@ static void binder_dec_node_tmpref(struct binder_node *node) * causes no actual reference to be released in binder_dec_node(). * If that changes, a change is needed here too. */ - free_node = binder_dec_node_ilocked(node, 0, 1); - if (node->proc) - binder_inner_proc_unlock(node->proc); + free_node = binder_dec_node_nilocked(node, 0, 1); + binder_node_inner_unlock(node); if (free_node) binder_free_node(node); } @@ -1264,19 +1307,21 @@ static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc, } rb_link_node(&new_ref->rb_node_desc, parent, p); rb_insert_color(&new_ref->rb_node_desc, &proc->refs_by_desc); + + binder_node_lock(node); hlist_add_head(&new_ref->node_entry, &node->refs); binder_debug(BINDER_DEBUG_INTERNAL_REFS, "%d new ref %d desc %d for node %d\n", proc->pid, new_ref->data.debug_id, new_ref->data.desc, node->debug_id); + binder_node_unlock(node); return new_ref; } static void binder_cleanup_ref(struct binder_ref *ref) { bool delete_node = false; - struct binder_proc *node_proc = ref->node->proc; binder_debug(BINDER_DEBUG_INTERNAL_REFS, "%d delete ref %d desc %d for node %d\n", @@ -1286,15 +1331,13 @@ static void binder_cleanup_ref(struct binder_ref *ref) rb_erase(&ref->rb_node_desc, &ref->proc->refs_by_desc); rb_erase(&ref->rb_node_node, &ref->proc->refs_by_node); - if (node_proc) - binder_inner_proc_lock(node_proc); + binder_node_inner_lock(ref->node); if (ref->data.strong) - binder_dec_node_ilocked(ref->node, 1, 1); + binder_dec_node_nilocked(ref->node, 1, 1); hlist_del(&ref->node_entry); - delete_node = binder_dec_node_ilocked(ref->node, 0, 1); - if (node_proc) - binder_inner_proc_unlock(node_proc); + delete_node = binder_dec_node_nilocked(ref->node, 0, 1); + binder_node_inner_unlock(ref->node); /* * Clear ref->node unless we want the caller to free the node */ @@ -1989,12 +2032,9 @@ static int binder_translate_binder(struct flat_binder_object *fp, node = binder_get_node(proc, fp->binder); if (!node) { - node = binder_new_node(proc, fp->binder, fp->cookie); + node = binder_new_node(proc, fp); if (!node) return -ENOMEM; - - node->min_priority = fp->flags & FLAT_BINDER_FLAG_PRIORITY_MASK; - node->accept_fds = !!(fp->flags & FLAT_BINDER_FLAG_ACCEPTS_FDS); } if (fp->cookie != node->cookie) { binder_user_error("%d:%d sending u%016llx node %d, cookie mismatch %016llx != %016llx\n", @@ -2055,6 +2095,7 @@ static int binder_translate_handle(struct flat_binder_object *fp, goto done; } + binder_node_lock(node); if (node->proc == target_proc) { if (fp->hdr.type == BINDER_TYPE_HANDLE) fp->hdr.type = BINDER_TYPE_BINDER; @@ -2062,18 +2103,24 @@ static int binder_translate_handle(struct flat_binder_object *fp, fp->hdr.type = BINDER_TYPE_WEAK_BINDER; fp->binder = node->ptr; fp->cookie = node->cookie; - binder_inc_node(node, - fp->hdr.type == BINDER_TYPE_BINDER, - 0, NULL); + if (node->proc) + binder_inner_proc_lock(node->proc); + binder_inc_node_nilocked(node, + fp->hdr.type == BINDER_TYPE_BINDER, + 0, NULL); + if (node->proc) + binder_inner_proc_unlock(node->proc); trace_binder_transaction_ref_to_node(t, node, &src_rdata); binder_debug(BINDER_DEBUG_TRANSACTION, " ref %d desc %d -> node %d u%016llx\n", src_rdata.debug_id, src_rdata.desc, node->debug_id, (u64)node->ptr); + binder_node_unlock(node); } else { int ret; struct binder_ref_data dest_rdata; + binder_node_unlock(node); ret = binder_inc_ref_for_node(target_proc, node, fp->hdr.type == BINDER_TYPE_HANDLE, NULL, &dest_rdata); @@ -2381,13 +2428,16 @@ static void binder_transaction(struct binder_proc *proc, mutex_unlock(&context->context_mgr_node_lock); } e->to_node = target_node->debug_id; + binder_node_lock(target_node); target_proc = target_node->proc; if (target_proc == NULL) { + binder_node_unlock(target_node); return_error = BR_DEAD_REPLY; return_error_line = __LINE__; goto err_dead_binder; } target_proc->tmp_ref++; + binder_node_unlock(target_node); if (security_binder_transaction(proc->tsk, target_proc->tsk) < 0) { return_error = BR_FAILED_REPLY; @@ -2704,6 +2754,7 @@ static void binder_transaction(struct binder_proc *proc, } tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE; binder_enqueue_work(proc, tcomplete, &thread->todo); + t->work.type = BINDER_WORK_TRANSACTION; if (reply) { if (target_thread->is_dead) @@ -2711,6 +2762,7 @@ static void binder_transaction(struct binder_proc *proc, BUG_ON(t->buffer->async_transaction != 0); binder_pop_transaction(target_thread, in_reply_to); binder_free_transaction(in_reply_to); + binder_enqueue_work(target_proc, &t->work, target_list); } else if (!(t->flags & TF_ONE_WAY)) { BUG_ON(t->buffer->async_transaction != 0); t->need_reply = 1; @@ -2721,20 +2773,29 @@ static void binder_transaction(struct binder_proc *proc, binder_pop_transaction(thread, t); goto err_dead_proc_or_thread; } + binder_enqueue_work(target_proc, &t->work, target_list); } else { BUG_ON(target_node == NULL); BUG_ON(t->buffer->async_transaction != 1); + binder_node_lock(target_node); if (target_node->has_async_transaction) { target_list = &target_node->async_todo; target_wait = NULL; } else target_node->has_async_transaction = 1; + /* + * Test/set of has_async_transaction + * must be atomic with enqueue on + * async_todo + */ if (target_proc->is_dead || - (target_thread && target_thread->is_dead)) + (target_thread && target_thread->is_dead)) { + binder_node_unlock(target_node); goto err_dead_proc_or_thread; + } + binder_enqueue_work(target_proc, &t->work, target_list); + binder_node_unlock(target_node); } - t->work.type = BINDER_WORK_TRANSACTION; - binder_enqueue_work(target_proc, &t->work, target_list); if (target_wait) { if (reply || !(tr->flags & TF_ONE_WAY)) wake_up_interruptible_sync(target_wait); @@ -2913,6 +2974,7 @@ static int binder_thread_write(struct binder_proc *proc, binder_uintptr_t node_ptr; binder_uintptr_t cookie; struct binder_node *node; + bool free_node; if (get_user(node_ptr, (binder_uintptr_t __user *)ptr)) return -EFAULT; @@ -2940,13 +3002,13 @@ static int binder_thread_write(struct binder_proc *proc, binder_put_node(node); break; } - binder_inner_proc_lock(proc); + binder_node_inner_lock(node); if (cmd == BC_ACQUIRE_DONE) { if (node->pending_strong_ref == 0) { binder_user_error("%d:%d BC_ACQUIRE_DONE node %d has no pending acquire request\n", proc->pid, thread->pid, node->debug_id); - binder_inner_proc_unlock(proc); + binder_node_inner_unlock(node); binder_put_node(node); break; } @@ -2956,20 +3018,22 @@ static int binder_thread_write(struct binder_proc *proc, binder_user_error("%d:%d BC_INCREFS_DONE node %d has no pending increfs request\n", proc->pid, thread->pid, node->debug_id); - binder_inner_proc_unlock(proc); + binder_node_inner_unlock(node); binder_put_node(node); break; } node->pending_weak_ref = 0; } - binder_inner_proc_unlock(proc); - binder_dec_node(node, cmd == BC_ACQUIRE_DONE, 0); + free_node = binder_dec_node_nilocked(node, + cmd == BC_ACQUIRE_DONE, 0); + WARN_ON(free_node); binder_debug(BINDER_DEBUG_USER_REFS, "%d:%d %s node %d ls %d lw %d tr %d\n", proc->pid, thread->pid, cmd == BC_INCREFS_DONE ? "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE", node->debug_id, node->local_strong_refs, node->local_weak_refs, node->tmp_refs); + binder_node_inner_unlock(node); binder_put_node(node); break; } @@ -3015,9 +3079,9 @@ static int binder_thread_write(struct binder_proc *proc, struct binder_work *w; buf_node = buffer->target_node; + binder_node_inner_lock(buf_node); BUG_ON(!buf_node->has_async_transaction); BUG_ON(buf_node->proc != proc); - binder_inner_proc_lock(proc); w = binder_dequeue_work_head_ilocked( &buf_node->async_todo); if (!w) @@ -3025,7 +3089,7 @@ static int binder_thread_write(struct binder_proc *proc, else binder_enqueue_work_ilocked( w, &thread->todo); - binder_inner_proc_unlock(proc); + binder_node_inner_unlock(buf_node); } trace_binder_transaction_buffer_release(buffer); binder_transaction_buffer_release(proc, buffer, NULL); @@ -3150,6 +3214,7 @@ static int binder_thread_write(struct binder_proc *proc, INIT_LIST_HEAD(&death->work.entry); death->cookie = cookie; ref->death = death; + binder_node_lock(ref->node); if (ref->node->proc == NULL) { ref->death->work.type = BINDER_WORK_DEAD_BINDER; if (thread->looper & @@ -3168,10 +3233,13 @@ static int binder_thread_write(struct binder_proc *proc, &proc->wait); } } + binder_node_unlock(ref->node); } else { + binder_node_lock(ref->node); if (ref->death == NULL) { binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification not active\n", proc->pid, thread->pid); + binder_node_unlock(ref->node); break; } death = ref->death; @@ -3180,6 +3248,7 @@ static int binder_thread_write(struct binder_proc *proc, proc->pid, thread->pid, (u64)death->cookie, (u64)cookie); + binder_node_unlock(ref->node); break; } ref->death = NULL; @@ -3204,6 +3273,7 @@ static int binder_thread_write(struct binder_proc *proc, death->work.type = BINDER_WORK_DEAD_BINDER_AND_CLEAR; } binder_inner_proc_unlock(proc); + binder_node_unlock(ref->node); } } break; case BC_DEAD_BINDER_DONE: { @@ -3486,6 +3556,17 @@ retry: (u64)node_cookie); rb_erase(&node->rb_node, &proc->nodes); binder_inner_proc_unlock(proc); + binder_node_lock(node); + /* + * Acquire the node lock before freeing the + * node to serialize with other threads that + * may have been holding the node lock while + * decrementing this node (avoids race where + * this thread frees while the other thread + * is unlocking the node after the final + * decrement) + */ + binder_node_unlock(node); binder_free_node(node); } else binder_inner_proc_unlock(proc); @@ -3973,16 +4054,18 @@ static int binder_ioctl_set_ctx_mgr(struct file *filp) } else { context->binder_context_mgr_uid = curr_euid; } - new_node = binder_new_node(proc, 0, 0); + new_node = binder_new_node(proc, NULL); if (!new_node) { ret = -ENOMEM; goto out; } + binder_node_lock(new_node); new_node->local_weak_refs++; new_node->local_strong_refs++; new_node->has_strong_ref = 1; new_node->has_weak_ref = 1; context->binder_context_mgr_node = new_node; + binder_node_unlock(new_node); binder_put_node(new_node); out: mutex_unlock(&context->context_mgr_node_lock); @@ -4245,6 +4328,7 @@ static int binder_node_release(struct binder_node *node, int refs) binder_release_work(proc, &node->async_todo); + binder_node_lock(node); binder_inner_proc_lock(proc); binder_dequeue_work_ilocked(&node->work); /* @@ -4253,6 +4337,7 @@ static int binder_node_release(struct binder_node *node, int refs) BUG_ON(!node->tmp_refs); if (hlist_empty(&node->refs) && node->tmp_refs == 1) { binder_inner_proc_unlock(proc); + binder_node_unlock(node); binder_free_node(node); return refs; @@ -4289,6 +4374,7 @@ static int binder_node_release(struct binder_node *node, int refs) binder_debug(BINDER_DEBUG_DEAD_BINDER, "node %d now dead, refs %d, death %d\n", node->debug_id, refs, death); + binder_node_unlock(node); binder_put_node(node); return refs; @@ -4532,12 +4618,15 @@ static void print_binder_thread_ilocked(struct seq_file *m, m->count = start_pos; } -static void print_binder_node(struct seq_file *m, struct binder_node *node) +static void print_binder_node_nlocked(struct seq_file *m, + struct binder_node *node) { struct binder_ref *ref; struct binder_work *w; int count; + WARN_ON(!spin_is_locked(&node->lock)); + count = 0; hlist_for_each_entry(ref, &node->refs, node_entry) count++; @@ -4564,11 +4653,13 @@ static void print_binder_node(struct seq_file *m, struct binder_node *node) static void print_binder_ref(struct seq_file *m, struct binder_ref *ref) { + binder_node_lock(ref->node); seq_printf(m, " ref %d: desc %d %snode %d s %d w %d d %pK\n", ref->data.debug_id, ref->data.desc, ref->node->proc ? "" : "dead ", ref->node->debug_id, ref->data.strong, ref->data.weak, ref->death); + binder_node_unlock(ref->node); } static void print_binder_proc(struct seq_file *m, @@ -4591,8 +4682,10 @@ static void print_binder_proc(struct seq_file *m, for (n = rb_first(&proc->nodes); n != NULL; n = rb_next(n)) { struct binder_node *node = rb_entry(n, struct binder_node, rb_node); + binder_node_lock(node); if (print_all || node->has_async_transaction) - print_binder_node(m, node); + print_binder_node_nlocked(m, node); + binder_node_unlock(node); } if (print_all) { for (n = rb_first(&proc->refs_by_desc); @@ -4764,6 +4857,7 @@ static int binder_state_show(struct seq_file *m, void *unused) { struct binder_proc *proc; struct binder_node *node; + struct binder_node *last_node = NULL; binder_lock(__func__); @@ -4772,9 +4866,25 @@ static int binder_state_show(struct seq_file *m, void *unused) spin_lock(&binder_dead_nodes_lock); if (!hlist_empty(&binder_dead_nodes)) seq_puts(m, "dead nodes:\n"); - hlist_for_each_entry(node, &binder_dead_nodes, dead_node) - print_binder_node(m, node); + hlist_for_each_entry(node, &binder_dead_nodes, dead_node) { + /* + * take a temporary reference on the node so it + * survives and isn't removed from the list + * while we print it. + */ + node->tmp_refs++; + spin_unlock(&binder_dead_nodes_lock); + if (last_node) + binder_put_node(last_node); + binder_node_lock(node); + print_binder_node_nlocked(m, node); + binder_node_unlock(node); + last_node = node; + spin_lock(&binder_dead_nodes_lock); + } spin_unlock(&binder_dead_nodes_lock); + if (last_node) + binder_put_node(last_node); mutex_lock(&binder_procs_lock); hlist_for_each_entry(proc, &binder_procs, proc_node) -- cgit v1.2.3 From da0fa9e4e8c5aac7cafa6cbb14d908ab8bbffd2f Mon Sep 17 00:00:00 2001 From: Todd Kjos Date: Thu, 29 Jun 2017 12:02:04 -0700 Subject: binder: protect proc->nodes with inner lock When locks for binder_ref handling are added, proc->nodes will need to be modified while holding the outer lock Signed-off-by: Todd Kjos Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 112 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 89 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 5654187555be..4d08b5141b01 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -313,6 +313,7 @@ struct binder_error { * @work: worklist element for node work * (protected by @proc->inner_lock) * @rb_node: element for proc->nodes tree + * (protected by @proc->inner_lock) * @dead_node: element for binder_dead_nodes list * (protected by binder_dead_nodes_lock) * @proc: binder_proc that owns this node @@ -470,6 +471,7 @@ enum binder_deferred_state { * @threads: rbtree of binder_threads in this proc * @nodes: rbtree of binder nodes associated with * this proc ordered by node->ptr + * (protected by @inner_lock) * @refs_by_desc: rbtree of refs ordered by ref->desc * @refs_by_node: rbtree of refs ordered by ref->node * @pid PID of group_leader of process @@ -856,7 +858,7 @@ static void binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer); static void binder_free_thread(struct binder_thread *thread); static void binder_free_proc(struct binder_proc *proc); -static void binder_inc_node_tmpref(struct binder_node *node); +static void binder_inc_node_tmpref_ilocked(struct binder_node *node); static int task_get_unused_fd_flags(struct binder_proc *proc, int flags) { @@ -938,12 +940,14 @@ static void binder_set_nice(long nice) binder_user_error("%d RLIMIT_NICE not set\n", current->pid); } -static struct binder_node *binder_get_node(struct binder_proc *proc, - binder_uintptr_t ptr) +static struct binder_node *binder_get_node_ilocked(struct binder_proc *proc, + binder_uintptr_t ptr) { struct rb_node *n = proc->nodes.rb_node; struct binder_node *node; + BUG_ON(!spin_is_locked(&proc->inner_lock)); + while (n) { node = rb_entry(n, struct binder_node, rb_node); @@ -957,15 +961,28 @@ static struct binder_node *binder_get_node(struct binder_proc *proc, * to ensure node stays alive until * call to binder_put_node() */ - binder_inc_node_tmpref(node); + binder_inc_node_tmpref_ilocked(node); return node; } } return NULL; } -static struct binder_node *binder_new_node(struct binder_proc *proc, - struct flat_binder_object *fp) +static struct binder_node *binder_get_node(struct binder_proc *proc, + binder_uintptr_t ptr) +{ + struct binder_node *node; + + binder_inner_proc_lock(proc); + node = binder_get_node_ilocked(proc, ptr); + binder_inner_proc_unlock(proc); + return node; +} + +static struct binder_node *binder_init_node_ilocked( + struct binder_proc *proc, + struct binder_node *new_node, + struct flat_binder_object *fp) { struct rb_node **p = &proc->nodes.rb_node; struct rb_node *parent = NULL; @@ -974,7 +991,9 @@ static struct binder_node *binder_new_node(struct binder_proc *proc, binder_uintptr_t cookie = fp ? fp->cookie : 0; __u32 flags = fp ? fp->flags : 0; + BUG_ON(!spin_is_locked(&proc->inner_lock)); while (*p) { + parent = *p; node = rb_entry(parent, struct binder_node, rb_node); @@ -982,13 +1001,17 @@ static struct binder_node *binder_new_node(struct binder_proc *proc, p = &(*p)->rb_left; else if (ptr > node->ptr) p = &(*p)->rb_right; - else - return NULL; + else { + /* + * A matching node is already in + * the rb tree. Abandon the init + * and return it. + */ + binder_inc_node_tmpref_ilocked(node); + return node; + } } - - node = kzalloc(sizeof(*node), GFP_KERNEL); - if (node == NULL) - return NULL; + node = new_node; binder_stats_created(BINDER_STAT_NODE); node->tmp_refs++; rb_link_node(&node->rb_node, parent, p); @@ -1007,6 +1030,27 @@ static struct binder_node *binder_new_node(struct binder_proc *proc, "%d:%d node %d u%016llx c%016llx created\n", proc->pid, current->pid, node->debug_id, (u64)node->ptr, (u64)node->cookie); + + return node; +} + +static struct binder_node *binder_new_node(struct binder_proc *proc, + struct flat_binder_object *fp) +{ + struct binder_node *node; + struct binder_node *new_node = kzalloc(sizeof(*node), GFP_KERNEL); + + if (!new_node) + return NULL; + binder_inner_proc_lock(proc); + node = binder_init_node_ilocked(proc, new_node, fp); + binder_inner_proc_unlock(proc); + if (node != new_node) + /* + * The node was already added by another thread + */ + kfree(new_node); + return node; } @@ -4420,6 +4464,7 @@ static void binder_deferred_release(struct binder_proc *proc) nodes = 0; incoming_refs = 0; + binder_inner_proc_lock(proc); while ((n = rb_first(&proc->nodes))) { struct binder_node *node; @@ -4430,10 +4475,13 @@ static void binder_deferred_release(struct binder_proc *proc) * calling binder_node_release() which will either * kfree() the node or call binder_put_node() */ - binder_inc_node_tmpref(node); + binder_inc_node_tmpref_ilocked(node); rb_erase(&node->rb_node, &proc->nodes); + binder_inner_proc_unlock(proc); incoming_refs = binder_node_release(node, incoming_refs); + binder_inner_proc_lock(proc); } + binder_inner_proc_unlock(proc); outgoing_refs = 0; while ((n = rb_first(&proc->refs_by_desc))) { @@ -4618,14 +4666,16 @@ static void print_binder_thread_ilocked(struct seq_file *m, m->count = start_pos; } -static void print_binder_node_nlocked(struct seq_file *m, - struct binder_node *node) +static void print_binder_node_nilocked(struct seq_file *m, + struct binder_node *node) { struct binder_ref *ref; struct binder_work *w; int count; WARN_ON(!spin_is_locked(&node->lock)); + if (node->proc) + WARN_ON(!spin_is_locked(&node->proc->inner_lock)); count = 0; hlist_for_each_entry(ref, &node->refs, node_entry) @@ -4643,11 +4693,9 @@ static void print_binder_node_nlocked(struct seq_file *m, } seq_puts(m, "\n"); if (node->proc) { - binder_inner_proc_lock(node->proc); list_for_each_entry(w, &node->async_todo, entry) print_binder_work_ilocked(m, " ", " pending async transaction", w); - binder_inner_proc_unlock(node->proc); } } @@ -4669,6 +4717,7 @@ static void print_binder_proc(struct seq_file *m, struct rb_node *n; size_t start_pos = m->count; size_t header_pos; + struct binder_node *last_node = NULL; seq_printf(m, "proc %d\n", proc->pid); seq_printf(m, "context %s\n", proc->context->name); @@ -4678,15 +4727,30 @@ static void print_binder_proc(struct seq_file *m, for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) print_binder_thread_ilocked(m, rb_entry(n, struct binder_thread, rb_node), print_all); - binder_inner_proc_unlock(proc); + for (n = rb_first(&proc->nodes); n != NULL; n = rb_next(n)) { struct binder_node *node = rb_entry(n, struct binder_node, rb_node); - binder_node_lock(node); - if (print_all || node->has_async_transaction) - print_binder_node_nlocked(m, node); - binder_node_unlock(node); + /* + * take a temporary reference on the node so it + * survives and isn't removed from the tree + * while we print it. + */ + binder_inc_node_tmpref_ilocked(node); + /* Need to drop inner lock to take node lock */ + binder_inner_proc_unlock(proc); + if (last_node) + binder_put_node(last_node); + binder_node_inner_lock(node); + print_binder_node_nilocked(m, node); + binder_node_inner_unlock(node); + last_node = node; + binder_inner_proc_lock(proc); } + binder_inner_proc_unlock(proc); + if (last_node) + binder_put_node(last_node); + if (print_all) { for (n = rb_first(&proc->refs_by_desc); n != NULL; @@ -4822,8 +4886,10 @@ static void print_binder_proc_stats(struct seq_file *m, proc->ready_threads, binder_alloc_get_free_async_space(&proc->alloc)); count = 0; + binder_inner_proc_lock(proc); for (n = rb_first(&proc->nodes); n != NULL; n = rb_next(n)) count++; + binder_inner_proc_unlock(proc); seq_printf(m, " nodes: %d\n", count); count = 0; strong = 0; @@ -4877,7 +4943,7 @@ static int binder_state_show(struct seq_file *m, void *unused) if (last_node) binder_put_node(last_node); binder_node_lock(node); - print_binder_node_nlocked(m, node); + print_binder_node_nilocked(m, node); binder_node_unlock(node); last_node = node; spin_lock(&binder_dead_nodes_lock); -- cgit v1.2.3 From 7bd7b0e639afb847a14ca994795fb5c64d2a7bf4 Mon Sep 17 00:00:00 2001 From: Todd Kjos Date: Thu, 29 Jun 2017 12:02:05 -0700 Subject: binder: protect proc->threads with inner_lock proc->threads will need to be accessed with higher locks of other processes held so use proc->inner_lock to protect it. proc->tmp_ref now needs to be protected by proc->inner_lock. Signed-off-by: Todd Kjos Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 87 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 63 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 4d08b5141b01..5deb9453dee4 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -469,6 +469,7 @@ enum binder_deferred_state { * struct binder_proc - binder process bookkeeping * @proc_node: element for binder_procs list * @threads: rbtree of binder_threads in this proc + * (protected by @inner_lock) * @nodes: rbtree of binder nodes associated with * this proc ordered by node->ptr * (protected by @inner_lock) @@ -486,6 +487,7 @@ enum binder_deferred_state { * (protected by binder_deferred_lock) * @is_dead: process is dead and awaiting free * when outstanding transactions are cleaned up + * (protected by @inner_lock) * @todo: list of work for this process * (protected by @inner_lock) * @wait: wait queue head to wait for proc work @@ -501,6 +503,7 @@ enum binder_deferred_state { * @requested_threads_started: number binder threads started * @ready_threads: number of threads waiting for proc work * @tmp_ref: temporary reference to indicate proc is in use + * (protected by @inner_lock) * @default_priority: default scheduler priority * (invariant after initialized) * @debugfs_entry: debugfs node @@ -556,6 +559,7 @@ enum { * @proc: binder process for this thread * (invariant after initialization) * @rb_node: element for proc->threads rbtree + * (protected by @proc->inner_lock) * @pid: PID for this thread * (invariant after initialization) * @looper: bitmap of looping state @@ -576,6 +580,7 @@ enum { * always be acquired) * @is_dead: thread is dead and awaiting free * when outstanding transactions are cleaned up + * (protected by @proc->inner_lock) * * Bookkeeping structure for binder threads. */ @@ -1667,15 +1672,15 @@ static void binder_thread_dec_tmpref(struct binder_thread *thread) /* * atomic is used to protect the counter value while * it cannot reach zero or thread->is_dead is false - * - * TODO: future patch adds locking to ensure that the - * check of tmp_ref and is_dead is done with a lock held */ + binder_inner_proc_lock(thread->proc); atomic_dec(&thread->tmp_ref); if (thread->is_dead && !atomic_read(&thread->tmp_ref)) { + binder_inner_proc_unlock(thread->proc); binder_free_thread(thread); return; } + binder_inner_proc_unlock(thread->proc); } /** @@ -1692,12 +1697,15 @@ static void binder_thread_dec_tmpref(struct binder_thread *thread) */ static void binder_proc_dec_tmpref(struct binder_proc *proc) { + binder_inner_proc_lock(proc); proc->tmp_ref--; if (proc->is_dead && RB_EMPTY_ROOT(&proc->threads) && !proc->tmp_ref) { + binder_inner_proc_unlock(proc); binder_free_proc(proc); return; } + binder_inner_proc_unlock(proc); } /** @@ -2480,7 +2488,9 @@ static void binder_transaction(struct binder_proc *proc, return_error_line = __LINE__; goto err_dead_binder; } + binder_inner_proc_lock(target_proc); target_proc->tmp_ref++; + binder_inner_proc_unlock(target_proc); binder_node_unlock(target_node); if (security_binder_transaction(proc->tsk, target_proc->tsk) < 0) { @@ -3854,7 +3864,8 @@ static void binder_release_work(struct binder_proc *proc, } -static struct binder_thread *binder_get_thread(struct binder_proc *proc) +static struct binder_thread *binder_get_thread_ilocked( + struct binder_proc *proc, struct binder_thread *new_thread) { struct binder_thread *thread = NULL; struct rb_node *parent = NULL; @@ -3869,25 +3880,45 @@ static struct binder_thread *binder_get_thread(struct binder_proc *proc) else if (current->pid > thread->pid) p = &(*p)->rb_right; else - break; + return thread; } - if (*p == NULL) { - thread = kzalloc(sizeof(*thread), GFP_KERNEL); - if (thread == NULL) + if (!new_thread) + return NULL; + thread = new_thread; + binder_stats_created(BINDER_STAT_THREAD); + thread->proc = proc; + thread->pid = current->pid; + atomic_set(&thread->tmp_ref, 0); + init_waitqueue_head(&thread->wait); + INIT_LIST_HEAD(&thread->todo); + rb_link_node(&thread->rb_node, parent, p); + rb_insert_color(&thread->rb_node, &proc->threads); + thread->looper_need_return = true; + thread->return_error.work.type = BINDER_WORK_RETURN_ERROR; + thread->return_error.cmd = BR_OK; + thread->reply_error.work.type = BINDER_WORK_RETURN_ERROR; + thread->reply_error.cmd = BR_OK; + + return thread; +} + +static struct binder_thread *binder_get_thread(struct binder_proc *proc) +{ + struct binder_thread *thread; + struct binder_thread *new_thread; + + binder_inner_proc_lock(proc); + thread = binder_get_thread_ilocked(proc, NULL); + binder_inner_proc_unlock(proc); + if (!thread) { + new_thread = kzalloc(sizeof(*thread), GFP_KERNEL); + if (new_thread == NULL) return NULL; - binder_stats_created(BINDER_STAT_THREAD); - thread->proc = proc; - thread->pid = current->pid; - atomic_set(&thread->tmp_ref, 0); - init_waitqueue_head(&thread->wait); - INIT_LIST_HEAD(&thread->todo); - rb_link_node(&thread->rb_node, parent, p); - rb_insert_color(&thread->rb_node, &proc->threads); - thread->looper_need_return = true; - thread->return_error.work.type = BINDER_WORK_RETURN_ERROR; - thread->return_error.cmd = BR_OK; - thread->reply_error.work.type = BINDER_WORK_RETURN_ERROR; - thread->reply_error.cmd = BR_OK; + binder_inner_proc_lock(proc); + thread = binder_get_thread_ilocked(proc, new_thread); + binder_inner_proc_unlock(proc); + if (thread != new_thread) + kfree(new_thread); } return thread; } @@ -3918,6 +3949,7 @@ static int binder_thread_release(struct binder_proc *proc, int active_transactions = 0; struct binder_transaction *last_t = NULL; + binder_inner_proc_lock(thread->proc); /* * take a ref on the proc so it survives * after we remove this thread from proc->threads. @@ -3965,6 +3997,7 @@ static int binder_thread_release(struct binder_proc *proc, if (t) spin_lock(&t->lock); } + binder_inner_proc_unlock(thread->proc); if (send_reply) binder_send_failed_reply(send_reply, BR_DEAD_REPLY); @@ -4338,6 +4371,7 @@ static void binder_deferred_flush(struct binder_proc *proc) struct rb_node *n; int wake_count = 0; + binder_inner_proc_lock(proc); for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) { struct binder_thread *thread = rb_entry(n, struct binder_thread, rb_node); @@ -4347,6 +4381,7 @@ static void binder_deferred_flush(struct binder_proc *proc) wake_count++; } } + binder_inner_proc_unlock(proc); wake_up_interruptible_all(&proc->wait); binder_debug(BINDER_DEBUG_OPEN_CLOSE, @@ -4445,6 +4480,7 @@ static void binder_deferred_release(struct binder_proc *proc) context->binder_context_mgr_node = NULL; } mutex_unlock(&context->context_mgr_node_lock); + binder_inner_proc_lock(proc); /* * Make sure proc stays alive after we * remove all the threads @@ -4458,13 +4494,14 @@ static void binder_deferred_release(struct binder_proc *proc) struct binder_thread *thread; thread = rb_entry(n, struct binder_thread, rb_node); + binder_inner_proc_unlock(proc); threads++; active_transactions += binder_thread_release(proc, thread); + binder_inner_proc_lock(proc); } nodes = 0; incoming_refs = 0; - binder_inner_proc_lock(proc); while ((n = rb_first(&proc->nodes))) { struct binder_node *node; @@ -4872,10 +4909,13 @@ static void print_binder_proc_stats(struct seq_file *m, struct binder_work *w; struct rb_node *n; int count, strong, weak; + size_t free_async_space = + binder_alloc_get_free_async_space(&proc->alloc); seq_printf(m, "proc %d\n", proc->pid); seq_printf(m, "context %s\n", proc->context->name); count = 0; + binder_inner_proc_lock(proc); for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) count++; seq_printf(m, " threads: %d\n", count); @@ -4884,9 +4924,8 @@ static void print_binder_proc_stats(struct seq_file *m, " free async space %zd\n", proc->requested_threads, proc->requested_threads_started, proc->max_threads, proc->ready_threads, - binder_alloc_get_free_async_space(&proc->alloc)); + free_async_space); count = 0; - binder_inner_proc_lock(proc); for (n = rb_first(&proc->nodes); n != NULL; n = rb_next(n)) count++; binder_inner_proc_unlock(proc); -- cgit v1.2.3 From 0b89d69a96258810ce2cb8892c95214f4bbe4b25 Mon Sep 17 00:00:00 2001 From: Martijn Coenen Date: Thu, 29 Jun 2017 12:02:06 -0700 Subject: binder: protect transaction_stack with inner lock. This makes future changes to priority inheritance easier, since we want to be able to look at a thread's transaction stack when selecting a thread to inherit priority for. It also allows us to take just a single lock in a few paths, where we used to take two in succession. Signed-off-by: Martijn Coenen Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 96 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 79 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 5deb9453dee4..9d18ca1f7dcc 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -30,7 +30,8 @@ * 3) proc->inner_lock : protects the thread and node lists * (proc->threads, proc->nodes) and all todo lists associated * with the binder_proc (proc->todo, thread->todo, - * proc->delivered_death and node->async_todo). + * proc->delivered_death and node->async_todo), as well as + * thread->transaction_stack * binder_inner_proc_lock() and binder_inner_proc_unlock() * are used to acq/rel * @@ -567,11 +568,13 @@ enum { * @looper_needs_return: looping thread needs to exit driver * (no lock needed) * @transaction_stack: stack of in-progress transactions for this thread + * (protected by @proc->inner_lock) * @todo: list of work to do for this thread * (protected by @proc->inner_lock) * @return_error: transaction errors reported by this thread * (only accessed by this thread) * @reply_error: transaction errors reported by target thread + * (protected by @proc->inner_lock) * @wait: wait queue for thread work * @stats: per-thread statistics * (atomics, no lock needed) @@ -1644,10 +1647,11 @@ static int binder_inc_ref_for_node(struct binder_proc *proc, return ret; } -static void binder_pop_transaction(struct binder_thread *target_thread, - struct binder_transaction *t) +static void binder_pop_transaction_ilocked(struct binder_thread *target_thread, + struct binder_transaction *t) { BUG_ON(!target_thread); + BUG_ON(!spin_is_locked(&target_thread->proc->inner_lock)); BUG_ON(target_thread->transaction_stack != t); BUG_ON(target_thread->transaction_stack->from != target_thread); target_thread->transaction_stack = @@ -1731,6 +1735,35 @@ static struct binder_thread *binder_get_txn_from( return from; } +/** + * binder_get_txn_from_and_acq_inner() - get t->from and acquire inner lock + * @t: binder transaction for t->from + * + * Same as binder_get_txn_from() except it also acquires the proc->inner_lock + * to guarantee that the thread cannot be released while operating on it. + * The caller must call binder_inner_proc_unlock() to release the inner lock + * as well as call binder_dec_thread_txn() to release the reference. + * + * Return: the value of t->from + */ +static struct binder_thread *binder_get_txn_from_and_acq_inner( + struct binder_transaction *t) +{ + struct binder_thread *from; + + from = binder_get_txn_from(t); + if (!from) + return NULL; + binder_inner_proc_lock(from->proc); + if (t->from) { + BUG_ON(from != t->from); + return from; + } + binder_inner_proc_unlock(from->proc); + binder_thread_dec_tmpref(from); + return NULL; +} + static void binder_free_transaction(struct binder_transaction *t) { if (t->buffer) @@ -1747,7 +1780,7 @@ static void binder_send_failed_reply(struct binder_transaction *t, BUG_ON(t->flags & TF_ONE_WAY); while (1) { - target_thread = binder_get_txn_from(t); + target_thread = binder_get_txn_from_and_acq_inner(t); if (target_thread) { binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, "send failed reply for transaction %d to %d:%d\n", @@ -1755,11 +1788,10 @@ static void binder_send_failed_reply(struct binder_transaction *t, target_thread->proc->pid, target_thread->pid); - binder_pop_transaction(target_thread, t); + binder_pop_transaction_ilocked(target_thread, t); if (target_thread->reply_error.cmd == BR_OK) { target_thread->reply_error.cmd = error_code; - binder_enqueue_work( - target_thread->proc, + binder_enqueue_work_ilocked( &target_thread->reply_error.work, &target_thread->todo); wake_up_interruptible(&target_thread->wait); @@ -1767,6 +1799,7 @@ static void binder_send_failed_reply(struct binder_transaction *t, WARN(1, "Unexpected reply error: %u\n", target_thread->reply_error.cmd); } + binder_inner_proc_unlock(target_thread->proc); binder_thread_dec_tmpref(target_thread); binder_free_transaction(t); return; @@ -2396,8 +2429,10 @@ static void binder_transaction(struct binder_proc *proc, e->context_name = proc->context->name; if (reply) { + binder_inner_proc_lock(proc); in_reply_to = thread->transaction_stack; if (in_reply_to == NULL) { + binder_inner_proc_unlock(proc); binder_user_error("%d:%d got reply transaction with no transaction stack\n", proc->pid, thread->pid); return_error = BR_FAILED_REPLY; @@ -2405,7 +2440,6 @@ static void binder_transaction(struct binder_proc *proc, return_error_line = __LINE__; goto err_empty_call_stack; } - binder_set_nice(in_reply_to->saved_priority); if (in_reply_to->to_thread != thread) { spin_lock(&in_reply_to->lock); binder_user_error("%d:%d got reply transaction with bad transaction stack, transaction %d has target %d:%d\n", @@ -2415,6 +2449,7 @@ static void binder_transaction(struct binder_proc *proc, in_reply_to->to_thread ? in_reply_to->to_thread->pid : 0); spin_unlock(&in_reply_to->lock); + binder_inner_proc_unlock(proc); return_error = BR_FAILED_REPLY; return_error_param = -EPROTO; return_error_line = __LINE__; @@ -2422,7 +2457,9 @@ static void binder_transaction(struct binder_proc *proc, goto err_bad_call_stack; } thread->transaction_stack = in_reply_to->to_parent; - target_thread = binder_get_txn_from(in_reply_to); + binder_inner_proc_unlock(proc); + binder_set_nice(in_reply_to->saved_priority); + target_thread = binder_get_txn_from_and_acq_inner(in_reply_to); if (target_thread == NULL) { return_error = BR_DEAD_REPLY; return_error_line = __LINE__; @@ -2434,6 +2471,7 @@ static void binder_transaction(struct binder_proc *proc, target_thread->transaction_stack ? target_thread->transaction_stack->debug_id : 0, in_reply_to->debug_id); + binder_inner_proc_unlock(target_thread->proc); return_error = BR_FAILED_REPLY; return_error_param = -EPROTO; return_error_line = __LINE__; @@ -2443,6 +2481,7 @@ static void binder_transaction(struct binder_proc *proc, } target_proc = target_thread->proc; target_proc->tmp_ref++; + binder_inner_proc_unlock(target_thread->proc); } else { if (tr->target.handle) { struct binder_ref *ref; @@ -2499,6 +2538,7 @@ static void binder_transaction(struct binder_proc *proc, return_error_line = __LINE__; goto err_invalid_target_handle; } + binder_inner_proc_lock(proc); if (!(tr->flags & TF_ONE_WAY) && thread->transaction_stack) { struct binder_transaction *tmp; @@ -2511,6 +2551,7 @@ static void binder_transaction(struct binder_proc *proc, tmp->to_thread ? tmp->to_thread->pid : 0); spin_unlock(&tmp->lock); + binder_inner_proc_unlock(proc); return_error = BR_FAILED_REPLY; return_error_param = -EPROTO; return_error_line = __LINE__; @@ -2531,6 +2572,7 @@ static void binder_transaction(struct binder_proc *proc, tmp = tmp->from_parent; } } + binder_inner_proc_unlock(proc); } if (target_thread) { e->to_thread = target_thread->pid; @@ -2811,23 +2853,34 @@ static void binder_transaction(struct binder_proc *proc, t->work.type = BINDER_WORK_TRANSACTION; if (reply) { - if (target_thread->is_dead) + binder_inner_proc_lock(target_proc); + if (target_thread->is_dead) { + binder_inner_proc_unlock(target_proc); goto err_dead_proc_or_thread; + } BUG_ON(t->buffer->async_transaction != 0); - binder_pop_transaction(target_thread, in_reply_to); + binder_pop_transaction_ilocked(target_thread, in_reply_to); + binder_enqueue_work_ilocked(&t->work, target_list); + binder_inner_proc_unlock(target_proc); binder_free_transaction(in_reply_to); - binder_enqueue_work(target_proc, &t->work, target_list); } else if (!(t->flags & TF_ONE_WAY)) { BUG_ON(t->buffer->async_transaction != 0); + binder_inner_proc_lock(proc); t->need_reply = 1; t->from_parent = thread->transaction_stack; thread->transaction_stack = t; + binder_inner_proc_unlock(proc); + binder_inner_proc_lock(target_proc); if (target_proc->is_dead || (target_thread && target_thread->is_dead)) { - binder_pop_transaction(thread, t); + binder_inner_proc_unlock(target_proc); + binder_inner_proc_lock(proc); + binder_pop_transaction_ilocked(thread, t); + binder_inner_proc_unlock(proc); goto err_dead_proc_or_thread; } - binder_enqueue_work(target_proc, &t->work, target_list); + binder_enqueue_work_ilocked(&t->work, target_list); + binder_inner_proc_unlock(target_proc); } else { BUG_ON(target_node == NULL); BUG_ON(t->buffer->async_transaction != 1); @@ -2842,12 +2895,15 @@ static void binder_transaction(struct binder_proc *proc, * must be atomic with enqueue on * async_todo */ + binder_inner_proc_lock(target_proc); if (target_proc->is_dead || (target_thread && target_thread->is_dead)) { + binder_inner_proc_unlock(target_proc); binder_node_unlock(target_node); goto err_dead_proc_or_thread; } - binder_enqueue_work(target_proc, &t->work, target_list); + binder_enqueue_work_ilocked(&t->work, target_list); + binder_inner_proc_unlock(target_proc); binder_node_unlock(target_node); } if (target_wait) { @@ -3464,8 +3520,10 @@ static int binder_thread_read(struct binder_proc *proc, } retry: + binder_inner_proc_lock(proc); wait_for_proc_work = thread->transaction_stack == NULL && - binder_worklist_empty(proc, &thread->todo); + binder_worklist_empty_ilocked(&thread->todo); + binder_inner_proc_unlock(proc); thread->looper |= BINDER_LOOPER_STATE_WAITING; if (wait_for_proc_work) @@ -3777,9 +3835,11 @@ retry: binder_thread_dec_tmpref(t_from); t->buffer->allow_user_free = 1; if (cmd == BR_TRANSACTION && !(t->flags & TF_ONE_WAY)) { + binder_inner_proc_lock(thread->proc); t->to_parent = thread->transaction_stack; t->to_thread = thread; thread->transaction_stack = t; + binder_inner_proc_unlock(thread->proc); } else { binder_free_transaction(t); } @@ -4017,8 +4077,10 @@ static unsigned int binder_poll(struct file *filp, thread = binder_get_thread(proc); + binder_inner_proc_lock(thread->proc); wait_for_proc_work = thread->transaction_stack == NULL && - binder_worklist_empty(proc, &thread->todo); + binder_worklist_empty_ilocked(&thread->todo); + binder_inner_proc_unlock(thread->proc); binder_unlock(__func__); -- cgit v1.2.3 From b3e6861283790d78f298f2a1bc3ef5fd81b381f4 Mon Sep 17 00:00:00 2001 From: Todd Kjos Date: Thu, 29 Jun 2017 12:02:07 -0700 Subject: binder: use inner lock to protect thread accounting Use the inner lock to protect thread accounting fields in proc structure: max_threads, requested_threads, requested_threads_started and ready_threads. Signed-off-by: Todd Kjos Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 9d18ca1f7dcc..704540ea3e12 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -498,11 +498,15 @@ enum binder_deferred_state { * @delivered_death: list of delivered death notification * (protected by @inner_lock) * @max_threads: cap on number of binder threads + * (protected by @inner_lock) * @requested_threads: number of binder threads requested but not * yet started. In current implementation, can * only be 0 or 1. + * (protected by @inner_lock) * @requested_threads_started: number binder threads started + * (protected by @inner_lock) * @ready_threads: number of threads waiting for proc work + * (protected by @inner_lock) * @tmp_ref: temporary reference to indicate proc is in use * (protected by @inner_lock) * @default_priority: default scheduler priority @@ -3234,6 +3238,7 @@ static int binder_thread_write(struct binder_proc *proc, binder_debug(BINDER_DEBUG_THREADS, "%d:%d BC_REGISTER_LOOPER\n", proc->pid, thread->pid); + binder_inner_proc_lock(proc); if (thread->looper & BINDER_LOOPER_STATE_ENTERED) { thread->looper |= BINDER_LOOPER_STATE_INVALID; binder_user_error("%d:%d ERROR: BC_REGISTER_LOOPER called after BC_ENTER_LOOPER\n", @@ -3247,6 +3252,7 @@ static int binder_thread_write(struct binder_proc *proc, proc->requested_threads_started++; } thread->looper |= BINDER_LOOPER_STATE_REGISTERED; + binder_inner_proc_unlock(proc); break; case BC_ENTER_LOOPER: binder_debug(BINDER_DEBUG_THREADS, @@ -3523,11 +3529,11 @@ retry: binder_inner_proc_lock(proc); wait_for_proc_work = thread->transaction_stack == NULL && binder_worklist_empty_ilocked(&thread->todo); + if (wait_for_proc_work) + proc->ready_threads++; binder_inner_proc_unlock(proc); thread->looper |= BINDER_LOOPER_STATE_WAITING; - if (wait_for_proc_work) - proc->ready_threads++; binder_unlock(__func__); @@ -3558,8 +3564,10 @@ retry: binder_lock(__func__); + binder_inner_proc_lock(proc); if (wait_for_proc_work) proc->ready_threads--; + binder_inner_proc_unlock(proc); thread->looper &= ~BINDER_LOOPER_STATE_WAITING; if (ret) @@ -3849,19 +3857,22 @@ retry: done: *consumed = ptr - buffer; + binder_inner_proc_lock(proc); if (proc->requested_threads + proc->ready_threads == 0 && proc->requested_threads_started < proc->max_threads && (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) /* the user-space code fails to */ /*spawn a new thread if we leave this out */) { proc->requested_threads++; + binder_inner_proc_unlock(proc); binder_debug(BINDER_DEBUG_THREADS, "%d:%d BR_SPAWN_LOOPER\n", proc->pid, thread->pid); if (put_user(BR_SPAWN_LOOPER, (uint32_t __user *)buffer)) return -EFAULT; binder_stat_br(proc, thread, BR_SPAWN_LOOPER); - } + } else + binder_inner_proc_unlock(proc); return 0; } @@ -4241,12 +4252,19 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (ret) goto err; break; - case BINDER_SET_MAX_THREADS: - if (copy_from_user(&proc->max_threads, ubuf, sizeof(proc->max_threads))) { + case BINDER_SET_MAX_THREADS: { + int max_threads; + + if (copy_from_user(&max_threads, ubuf, + sizeof(max_threads))) { ret = -EINVAL; goto err; } + binder_inner_proc_lock(proc); + proc->max_threads = max_threads; + binder_inner_proc_unlock(proc); break; + } case BINDER_SET_CONTEXT_MGR: ret = binder_ioctl_set_ctx_mgr(filp); if (ret) -- cgit v1.2.3 From 2c1838dc6817dd28cf24ba0c57cc8693be9bbfc5 Mon Sep 17 00:00:00 2001 From: Todd Kjos Date: Thu, 29 Jun 2017 12:02:08 -0700 Subject: binder: protect binder_ref with outer lock Use proc->outer_lock to protect the binder_ref structure. The outer lock allows functions operating on the binder_ref to do nested acquires of node and inner locks as necessary to attach refs to nodes atomically. Binder refs must never be accesssed without holding the outer lock. Signed-off-by: Todd Kjos Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 133 +++++++++++++++++++++++++++++------------------ 1 file changed, 83 insertions(+), 50 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 704540ea3e12..f07f0d488aa4 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -475,7 +475,9 @@ enum binder_deferred_state { * this proc ordered by node->ptr * (protected by @inner_lock) * @refs_by_desc: rbtree of refs ordered by ref->desc + * (protected by @outer_lock) * @refs_by_node: rbtree of refs ordered by ref->node + * (protected by @outer_lock) * @pid PID of group_leader of process * (invariant after initialized) * @tsk task_struct for group_leader of process @@ -1269,8 +1271,8 @@ static void binder_put_node(struct binder_node *node) binder_dec_node_tmpref(node); } -static struct binder_ref *binder_get_ref(struct binder_proc *proc, - u32 desc, bool need_strong_ref) +static struct binder_ref *binder_get_ref_olocked(struct binder_proc *proc, + u32 desc, bool need_strong_ref) { struct rb_node *n = proc->refs_by_desc.rb_node; struct binder_ref *ref; @@ -1293,7 +1295,7 @@ static struct binder_ref *binder_get_ref(struct binder_proc *proc, } /** - * binder_get_ref_for_node() - get the ref associated with given node + * binder_get_ref_for_node_olocked() - get the ref associated with given node * @proc: binder_proc that owns the ref * @node: binder_node of target * @new_ref: newly allocated binder_ref to be initialized or %NULL @@ -1310,9 +1312,10 @@ static struct binder_ref *binder_get_ref(struct binder_proc *proc, * new_ref. new_ref must be kfree'd by the caller in * this case. */ -static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc, - struct binder_node *node, - struct binder_ref *new_ref) +static struct binder_ref *binder_get_ref_for_node_olocked( + struct binder_proc *proc, + struct binder_node *node, + struct binder_ref *new_ref) { struct binder_context *context = proc->context; struct rb_node **p = &proc->refs_by_node.rb_node; @@ -1375,7 +1378,7 @@ static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc, return new_ref; } -static void binder_cleanup_ref(struct binder_ref *ref) +static void binder_cleanup_ref_olocked(struct binder_ref *ref) { bool delete_node = false; @@ -1418,17 +1421,17 @@ static void binder_cleanup_ref(struct binder_ref *ref) } /** - * binder_inc_ref() - increment the ref for given handle + * binder_inc_ref_olocked() - increment the ref for given handle * @ref: ref to be incremented * @strong: if true, strong increment, else weak * @target_list: list to queue node work on * - * Increment the ref. + * Increment the ref. @ref->proc->outer_lock must be held on entry * * Return: 0, if successful, else errno */ -static int binder_inc_ref(struct binder_ref *ref, int strong, - struct list_head *target_list) +static int binder_inc_ref_olocked(struct binder_ref *ref, int strong, + struct list_head *target_list) { int ret; @@ -1457,12 +1460,9 @@ static int binder_inc_ref(struct binder_ref *ref, int strong, * * Decrement the ref. * - * TODO: kfree is avoided here since an upcoming patch - * will put this under a lock. - * * Return: true if ref is cleaned up and ready to be freed */ -static bool binder_dec_ref(struct binder_ref *ref, int strong) +static bool binder_dec_ref_olocked(struct binder_ref *ref, int strong) { if (strong) { if (ref->data.strong == 0) { @@ -1486,13 +1486,7 @@ static bool binder_dec_ref(struct binder_ref *ref, int strong) ref->data.weak--; } if (ref->data.strong == 0 && ref->data.weak == 0) { - binder_cleanup_ref(ref); - /* - * TODO: we could kfree(ref) here, but an upcoming - * patch will call this with a lock held, so we - * return an indication that the ref should be - * freed. - */ + binder_cleanup_ref_olocked(ref); return true; } return false; @@ -1517,7 +1511,8 @@ static struct binder_node *binder_get_node_from_ref( struct binder_node *node; struct binder_ref *ref; - ref = binder_get_ref(proc, desc, need_strong_ref); + binder_proc_lock(proc); + ref = binder_get_ref_olocked(proc, desc, need_strong_ref); if (!ref) goto err_no_ref; node = ref->node; @@ -1528,10 +1523,12 @@ static struct binder_node *binder_get_node_from_ref( binder_inc_node_tmpref(node); if (rdata) *rdata = ref->data; + binder_proc_unlock(proc); return node; err_no_ref: + binder_proc_unlock(proc); return NULL; } @@ -1571,24 +1568,27 @@ static int binder_update_ref_for_handle(struct binder_proc *proc, struct binder_ref *ref; bool delete_ref = false; - ref = binder_get_ref(proc, desc, strong); + binder_proc_lock(proc); + ref = binder_get_ref_olocked(proc, desc, strong); if (!ref) { ret = -EINVAL; goto err_no_ref; } if (increment) - ret = binder_inc_ref(ref, strong, NULL); + ret = binder_inc_ref_olocked(ref, strong, NULL); else - delete_ref = binder_dec_ref(ref, strong); + delete_ref = binder_dec_ref_olocked(ref, strong); if (rdata) *rdata = ref->data; + binder_proc_unlock(proc); if (delete_ref) binder_free_ref(ref); return ret; err_no_ref: + binder_proc_unlock(proc); return ret; } @@ -1633,15 +1633,19 @@ static int binder_inc_ref_for_node(struct binder_proc *proc, struct binder_ref *new_ref = NULL; int ret = 0; - ref = binder_get_ref_for_node(proc, node, NULL); + binder_proc_lock(proc); + ref = binder_get_ref_for_node_olocked(proc, node, NULL); if (!ref) { + binder_proc_unlock(proc); new_ref = kzalloc(sizeof(*ref), GFP_KERNEL); if (!new_ref) return -ENOMEM; - ref = binder_get_ref_for_node(proc, node, new_ref); + binder_proc_lock(proc); + ref = binder_get_ref_for_node_olocked(proc, node, new_ref); } - ret = binder_inc_ref(ref, strong, target_list); + ret = binder_inc_ref_olocked(ref, strong, target_list); *rdata = ref->data; + binder_proc_unlock(proc); if (new_ref && ref != new_ref) /* * Another thread created the ref first so @@ -2497,11 +2501,14 @@ static void binder_transaction(struct binder_proc *proc, * stays alive until the transaction is * done. */ - ref = binder_get_ref(proc, tr->target.handle, true); + binder_proc_lock(proc); + ref = binder_get_ref_olocked(proc, tr->target.handle, + true); if (ref) { binder_inc_node(ref->node, 1, 0, NULL); target_node = ref->node; } + binder_proc_unlock(proc); if (target_node == NULL) { binder_user_error("%d:%d got transaction to invalid handle\n", proc->pid, thread->pid); @@ -3277,7 +3284,7 @@ static int binder_thread_write(struct binder_proc *proc, uint32_t target; binder_uintptr_t cookie; struct binder_ref *ref; - struct binder_ref_death *death; + struct binder_ref_death *death = NULL; if (get_user(target, (uint32_t __user *)ptr)) return -EFAULT; @@ -3285,7 +3292,29 @@ static int binder_thread_write(struct binder_proc *proc, if (get_user(cookie, (binder_uintptr_t __user *)ptr)) return -EFAULT; ptr += sizeof(binder_uintptr_t); - ref = binder_get_ref(proc, target, false); + if (cmd == BC_REQUEST_DEATH_NOTIFICATION) { + /* + * Allocate memory for death notification + * before taking lock + */ + death = kzalloc(sizeof(*death), GFP_KERNEL); + if (death == NULL) { + WARN_ON(thread->return_error.cmd != + BR_OK); + thread->return_error.cmd = BR_ERROR; + binder_enqueue_work( + thread->proc, + &thread->return_error.work, + &thread->todo); + binder_debug( + BINDER_DEBUG_FAILED_TRANSACTION, + "%d:%d BC_REQUEST_DEATH_NOTIFICATION failed\n", + proc->pid, thread->pid); + break; + } + } + binder_proc_lock(proc); + ref = binder_get_ref_olocked(proc, target, false); if (ref == NULL) { binder_user_error("%d:%d %s invalid ref %d\n", proc->pid, thread->pid, @@ -3293,6 +3322,8 @@ static int binder_thread_write(struct binder_proc *proc, "BC_REQUEST_DEATH_NOTIFICATION" : "BC_CLEAR_DEATH_NOTIFICATION", target); + binder_proc_unlock(proc); + kfree(death); break; } @@ -3310,20 +3341,8 @@ static int binder_thread_write(struct binder_proc *proc, if (ref->death) { binder_user_error("%d:%d BC_REQUEST_DEATH_NOTIFICATION death notification already set\n", proc->pid, thread->pid); - break; - } - death = kzalloc(sizeof(*death), GFP_KERNEL); - if (death == NULL) { - WARN_ON(thread->return_error.cmd != - BR_OK); - thread->return_error.cmd = BR_ERROR; - binder_enqueue_work( - thread->proc, - &thread->return_error.work, - &thread->todo); - binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, - "%d:%d BC_REQUEST_DEATH_NOTIFICATION failed\n", - proc->pid, thread->pid); + binder_proc_unlock(proc); + kfree(death); break; } binder_stats_created(BINDER_STAT_DEATH); @@ -3356,6 +3375,7 @@ static int binder_thread_write(struct binder_proc *proc, binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification not active\n", proc->pid, thread->pid); binder_node_unlock(ref->node); + binder_proc_unlock(proc); break; } death = ref->death; @@ -3365,6 +3385,7 @@ static int binder_thread_write(struct binder_proc *proc, (u64)death->cookie, (u64)cookie); binder_node_unlock(ref->node); + binder_proc_unlock(proc); break; } ref->death = NULL; @@ -3391,6 +3412,7 @@ static int binder_thread_write(struct binder_proc *proc, binder_inner_proc_unlock(proc); binder_node_unlock(ref->node); } + binder_proc_unlock(proc); } break; case BC_DEAD_BINDER_DONE: { struct binder_work *w; @@ -4601,14 +4623,18 @@ static void binder_deferred_release(struct binder_proc *proc) binder_inner_proc_unlock(proc); outgoing_refs = 0; + binder_proc_lock(proc); while ((n = rb_first(&proc->refs_by_desc))) { struct binder_ref *ref; ref = rb_entry(n, struct binder_ref, rb_node_desc); outgoing_refs++; - binder_cleanup_ref(ref); + binder_cleanup_ref_olocked(ref); + binder_proc_unlock(proc); binder_free_ref(ref); + binder_proc_lock(proc); } + binder_proc_unlock(proc); binder_release_work(proc, &proc->todo); binder_release_work(proc, &proc->delivered_death); @@ -4816,8 +4842,10 @@ static void print_binder_node_nilocked(struct seq_file *m, } } -static void print_binder_ref(struct seq_file *m, struct binder_ref *ref) +static void print_binder_ref_olocked(struct seq_file *m, + struct binder_ref *ref) { + WARN_ON(!spin_is_locked(&ref->proc->outer_lock)); binder_node_lock(ref->node); seq_printf(m, " ref %d: desc %d %snode %d s %d w %d d %pK\n", ref->data.debug_id, ref->data.desc, @@ -4869,11 +4897,14 @@ static void print_binder_proc(struct seq_file *m, binder_put_node(last_node); if (print_all) { + binder_proc_lock(proc); for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) - print_binder_ref(m, rb_entry(n, struct binder_ref, - rb_node_desc)); + print_binder_ref_olocked(m, rb_entry(n, + struct binder_ref, + rb_node_desc)); + binder_proc_unlock(proc); } binder_alloc_print_allocated(m, &proc->alloc); binder_inner_proc_lock(proc); @@ -5013,6 +5044,7 @@ static void print_binder_proc_stats(struct seq_file *m, count = 0; strong = 0; weak = 0; + binder_proc_lock(proc); for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) { struct binder_ref *ref = rb_entry(n, struct binder_ref, rb_node_desc); @@ -5020,6 +5052,7 @@ static void print_binder_proc_stats(struct seq_file *m, strong += ref->data.strong; weak += ref->data.weak; } + binder_proc_unlock(proc); seq_printf(m, " refs: %d s %d w %d\n", count, strong, weak); count = binder_alloc_get_allocated_count(&proc->alloc); -- cgit v1.2.3 From 5f2f63696c552081bc90fb0ef80c94def33ba421 Mon Sep 17 00:00:00 2001 From: Todd Kjos Date: Thu, 29 Jun 2017 12:02:09 -0700 Subject: binder: protect against stale pointers in print_binder_transaction When printing transactions there were several race conditions that could cause a stale pointer to be deferenced. Fixed by reading the pointer once and using it if valid (which is safe). The transaction buffer also needed protection via proc lock, so it is only printed if we are holding the correct lock. Signed-off-by: Todd Kjos Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 60 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index f07f0d488aa4..36ef88d10631 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -4702,35 +4702,52 @@ binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer) mutex_unlock(&binder_deferred_lock); } -static void print_binder_transaction(struct seq_file *m, const char *prefix, - struct binder_transaction *t) +static void print_binder_transaction_ilocked(struct seq_file *m, + struct binder_proc *proc, + const char *prefix, + struct binder_transaction *t) { + struct binder_proc *to_proc; + struct binder_buffer *buffer = t->buffer; + + WARN_ON(!spin_is_locked(&proc->inner_lock)); spin_lock(&t->lock); + to_proc = t->to_proc; seq_printf(m, "%s %d: %p from %d:%d to %d:%d code %x flags %x pri %ld r%d", prefix, t->debug_id, t, t->from ? t->from->proc->pid : 0, t->from ? t->from->pid : 0, - t->to_proc ? t->to_proc->pid : 0, + to_proc ? to_proc->pid : 0, t->to_thread ? t->to_thread->pid : 0, t->code, t->flags, t->priority, t->need_reply); spin_unlock(&t->lock); - if (t->buffer == NULL) { + if (proc != to_proc) { + /* + * Can only safely deref buffer if we are holding the + * correct proc inner lock for this node + */ + seq_puts(m, "\n"); + return; + } + + if (buffer == NULL) { seq_puts(m, " buffer free\n"); return; } - if (t->buffer->target_node) - seq_printf(m, " node %d", - t->buffer->target_node->debug_id); + if (buffer->target_node) + seq_printf(m, " node %d", buffer->target_node->debug_id); seq_printf(m, " size %zd:%zd data %p\n", - t->buffer->data_size, t->buffer->offsets_size, - t->buffer->data); + buffer->data_size, buffer->offsets_size, + buffer->data); } -static void print_binder_work_ilocked(struct seq_file *m, const char *prefix, - const char *transaction_prefix, - struct binder_work *w) +static void print_binder_work_ilocked(struct seq_file *m, + struct binder_proc *proc, + const char *prefix, + const char *transaction_prefix, + struct binder_work *w) { struct binder_node *node; struct binder_transaction *t; @@ -4738,7 +4755,8 @@ static void print_binder_work_ilocked(struct seq_file *m, const char *prefix, switch (w->type) { case BINDER_WORK_TRANSACTION: t = container_of(w, struct binder_transaction, work); - print_binder_transaction(m, transaction_prefix, t); + print_binder_transaction_ilocked( + m, proc, transaction_prefix, t); break; case BINDER_WORK_RETURN_ERROR: { struct binder_error *e = container_of( @@ -4789,20 +4807,21 @@ static void print_binder_thread_ilocked(struct seq_file *m, t = thread->transaction_stack; while (t) { if (t->from == thread) { - print_binder_transaction(m, - " outgoing transaction", t); + print_binder_transaction_ilocked(m, thread->proc, + " outgoing transaction", t); t = t->from_parent; } else if (t->to_thread == thread) { - print_binder_transaction(m, + print_binder_transaction_ilocked(m, thread->proc, " incoming transaction", t); t = t->to_parent; } else { - print_binder_transaction(m, " bad transaction", t); + print_binder_transaction_ilocked(m, thread->proc, + " bad transaction", t); t = NULL; } } list_for_each_entry(w, &thread->todo, entry) { - print_binder_work_ilocked(m, " ", + print_binder_work_ilocked(m, thread->proc, " ", " pending transaction", w); } if (!print_always && m->count == header_pos) @@ -4837,7 +4856,7 @@ static void print_binder_node_nilocked(struct seq_file *m, seq_puts(m, "\n"); if (node->proc) { list_for_each_entry(w, &node->async_todo, entry) - print_binder_work_ilocked(m, " ", + print_binder_work_ilocked(m, node->proc, " ", " pending async transaction", w); } } @@ -4909,7 +4928,8 @@ static void print_binder_proc(struct seq_file *m, binder_alloc_print_allocated(m, &proc->alloc); binder_inner_proc_lock(proc); list_for_each_entry(w, &proc->todo, entry) - print_binder_work_ilocked(m, " ", " pending transaction", w); + print_binder_work_ilocked(m, proc, " ", + " pending transaction", w); list_for_each_entry(w, &proc->delivered_death, entry) { seq_puts(m, " has delivered dead binder\n"); break; -- cgit v1.2.3 From ab51ec6bdf0b7afc087470a62f273ad35f6ee506 Mon Sep 17 00:00:00 2001 From: Martijn Coenen Date: Thu, 29 Jun 2017 12:02:10 -0700 Subject: binder: fix death race conditions A race existed where one thread could register a death notification for a node, while another thread was cleaning up that node and sending out death notifications for its references, causing simultaneous access to ref->death because different locks were held. Signed-off-by: Martijn Coenen Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 64 ++++++++++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 36ef88d10631..1e50b034d49a 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -442,6 +442,7 @@ struct binder_ref_data { * ref for deletion in binder_cleanup_ref, a non-NULL * @node indicates the node must be freed * @death: pointer to death notification (ref_death) if requested + * (protected by @node->lock) * * Structure to track references from procA to target node (on procB). This * structure is unsafe to access without holding @proc->outer_lock. @@ -3337,10 +3338,12 @@ static int binder_thread_write(struct binder_proc *proc, ref->data.desc, ref->data.strong, ref->data.weak, ref->node->debug_id); + binder_node_lock(ref->node); if (cmd == BC_REQUEST_DEATH_NOTIFICATION) { if (ref->death) { binder_user_error("%d:%d BC_REQUEST_DEATH_NOTIFICATION death notification already set\n", proc->pid, thread->pid); + binder_node_unlock(ref->node); binder_proc_unlock(proc); kfree(death); break; @@ -3349,7 +3352,6 @@ static int binder_thread_write(struct binder_proc *proc, INIT_LIST_HEAD(&death->work.entry); death->cookie = cookie; ref->death = death; - binder_node_lock(ref->node); if (ref->node->proc == NULL) { ref->death->work.type = BINDER_WORK_DEAD_BINDER; if (thread->looper & @@ -3368,9 +3370,7 @@ static int binder_thread_write(struct binder_proc *proc, &proc->wait); } } - binder_node_unlock(ref->node); } else { - binder_node_lock(ref->node); if (ref->death == NULL) { binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification not active\n", proc->pid, thread->pid); @@ -3410,8 +3410,8 @@ static int binder_thread_write(struct binder_proc *proc, death->work.type = BINDER_WORK_DEAD_BINDER_AND_CLEAR; } binder_inner_proc_unlock(proc); - binder_node_unlock(ref->node); } + binder_node_unlock(ref->node); binder_proc_unlock(proc); } break; case BC_DEAD_BINDER_DONE: { @@ -3748,44 +3748,39 @@ retry: case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: { struct binder_ref_death *death; uint32_t cmd; + binder_uintptr_t cookie; death = container_of(w, struct binder_ref_death, work); if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION) cmd = BR_CLEAR_DEATH_NOTIFICATION_DONE; else cmd = BR_DEAD_BINDER; - /* - * TODO: there is a race condition between - * death notification requests and delivery - * of the notifications. This will be handled - * in a later patch. - */ - binder_inner_proc_unlock(proc); - if (put_user(cmd, (uint32_t __user *)ptr)) - return -EFAULT; - ptr += sizeof(uint32_t); - if (put_user(death->cookie, - (binder_uintptr_t __user *)ptr)) - return -EFAULT; - ptr += sizeof(binder_uintptr_t); - binder_stat_br(proc, thread, cmd); + cookie = death->cookie; + binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION, "%d:%d %s %016llx\n", proc->pid, thread->pid, cmd == BR_DEAD_BINDER ? "BR_DEAD_BINDER" : "BR_CLEAR_DEATH_NOTIFICATION_DONE", - (u64)death->cookie); - + (u64)cookie); if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION) { + binder_inner_proc_unlock(proc); kfree(death); binder_stats_deleted(BINDER_STAT_DEATH); } else { - binder_inner_proc_lock(proc); binder_enqueue_work_ilocked( w, &proc->delivered_death); binder_inner_proc_unlock(proc); } + if (put_user(cmd, (uint32_t __user *)ptr)) + return -EFAULT; + ptr += sizeof(uint32_t); + if (put_user(cookie, + (binder_uintptr_t __user *)ptr)) + return -EFAULT; + ptr += sizeof(binder_uintptr_t); + binder_stat_br(proc, thread, cmd); if (cmd == BR_DEAD_BINDER) goto done; /* DEAD_BINDER notifications can cause transactions */ } break; @@ -4535,20 +4530,25 @@ static int binder_node_release(struct binder_node *node, int refs) hlist_for_each_entry(ref, &node->refs, node_entry) { refs++; - - if (!ref->death) + /* + * Need the node lock to synchronize + * with new notification requests and the + * inner lock to synchronize with queued + * death notifications. + */ + binder_inner_proc_lock(ref->proc); + if (!ref->death) { + binder_inner_proc_unlock(ref->proc); continue; + } death++; - binder_inner_proc_lock(ref->proc); - if (list_empty(&ref->death->work.entry)) { - ref->death->work.type = BINDER_WORK_DEAD_BINDER; - binder_enqueue_work_ilocked(&ref->death->work, - &ref->proc->todo); - wake_up_interruptible(&ref->proc->wait); - } else - BUG(); + BUG_ON(!list_empty(&ref->death->work.entry)); + ref->death->work.type = BINDER_WORK_DEAD_BINDER; + binder_enqueue_work_ilocked(&ref->death->work, + &ref->proc->todo); + wake_up_interruptible(&ref->proc->wait); binder_inner_proc_unlock(ref->proc); } -- cgit v1.2.3 From a60b890f607dc6d7806afc0dc8666577faf40bb4 Mon Sep 17 00:00:00 2001 From: Todd Kjos Date: Thu, 29 Jun 2017 12:02:11 -0700 Subject: binder: remove global binder lock Remove global mutex and rely on fine-grained locking Signed-off-by: Todd Kjos Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 46 +++------------------------------------------- 1 file changed, 3 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 1e50b034d49a..c8e9d5dfcd86 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -80,8 +80,6 @@ #include "binder_alloc.h" #include "binder_trace.h" -static DEFINE_MUTEX(binder_main_lock); - static HLIST_HEAD(binder_deferred_list); static DEFINE_MUTEX(binder_deferred_lock); @@ -924,19 +922,6 @@ static long task_close_fd(struct binder_proc *proc, unsigned int fd) return retval; } -static inline void binder_lock(const char *tag) -{ - trace_binder_lock(tag); - mutex_lock(&binder_main_lock); - trace_binder_locked(tag); -} - -static inline void binder_unlock(const char *tag) -{ - trace_binder_unlock(tag); - mutex_unlock(&binder_main_lock); -} - static void binder_set_nice(long nice) { long min_nice; @@ -3557,8 +3542,6 @@ retry: thread->looper |= BINDER_LOOPER_STATE_WAITING; - binder_unlock(__func__); - trace_binder_wait_for_work(wait_for_proc_work, !!thread->transaction_stack, !binder_worklist_empty(proc, &thread->todo)); @@ -3584,8 +3567,6 @@ retry: ret = wait_event_freezable(thread->wait, binder_has_thread_work(thread)); } - binder_lock(__func__); - binder_inner_proc_lock(proc); if (wait_for_proc_work) proc->ready_threads--; @@ -4101,8 +4082,6 @@ static unsigned int binder_poll(struct file *filp, struct binder_thread *thread = NULL; int wait_for_proc_work; - binder_lock(__func__); - thread = binder_get_thread(proc); binder_inner_proc_lock(thread->proc); @@ -4110,8 +4089,6 @@ static unsigned int binder_poll(struct file *filp, binder_worklist_empty_ilocked(&thread->todo); binder_inner_proc_unlock(thread->proc); - binder_unlock(__func__); - if (wait_for_proc_work) { if (binder_has_proc_work(proc, thread)) return POLLIN; @@ -4256,7 +4233,6 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (ret) goto err_unlocked; - binder_lock(__func__); thread = binder_get_thread(proc); if (thread == NULL) { ret = -ENOMEM; @@ -4315,7 +4291,6 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) err: if (thread) thread->looper_need_return = false; - binder_unlock(__func__); wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2); if (ret && ret != -ERESTARTSYS) pr_info("%d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret); @@ -4421,15 +4396,11 @@ static int binder_open(struct inode *nodp, struct file *filp) proc->context = &binder_dev->context; binder_alloc_init(&proc->alloc); - binder_lock(__func__); - binder_stats_created(BINDER_STAT_PROC); proc->pid = current->group_leader->pid; INIT_LIST_HEAD(&proc->delivered_death); filp->private_data = proc; - binder_unlock(__func__); - mutex_lock(&binder_procs_lock); hlist_add_head(&proc->proc_node, &binder_procs); mutex_unlock(&binder_procs_lock); @@ -4655,7 +4626,6 @@ static void binder_deferred_func(struct work_struct *work) int defer; do { - binder_lock(__func__); mutex_lock(&binder_deferred_lock); if (!hlist_empty(&binder_deferred_list)) { proc = hlist_entry(binder_deferred_list.first, @@ -4682,7 +4652,6 @@ static void binder_deferred_func(struct work_struct *work) if (defer & BINDER_DEFERRED_RELEASE) binder_deferred_release(proc); /* frees proc */ - binder_unlock(__func__); if (files) put_files_struct(files); } while (proc); @@ -5097,8 +5066,6 @@ static int binder_state_show(struct seq_file *m, void *unused) struct binder_node *node; struct binder_node *last_node = NULL; - binder_lock(__func__); - seq_puts(m, "binder state:\n"); spin_lock(&binder_dead_nodes_lock); @@ -5128,7 +5095,7 @@ static int binder_state_show(struct seq_file *m, void *unused) hlist_for_each_entry(proc, &binder_procs, proc_node) print_binder_proc(m, proc, 1); mutex_unlock(&binder_procs_lock); - binder_unlock(__func__); + return 0; } @@ -5136,8 +5103,6 @@ static int binder_stats_show(struct seq_file *m, void *unused) { struct binder_proc *proc; - binder_lock(__func__); - seq_puts(m, "binder stats:\n"); print_binder_stats(m, "", &binder_stats); @@ -5146,7 +5111,7 @@ static int binder_stats_show(struct seq_file *m, void *unused) hlist_for_each_entry(proc, &binder_procs, proc_node) print_binder_proc_stats(m, proc); mutex_unlock(&binder_procs_lock); - binder_unlock(__func__); + return 0; } @@ -5154,14 +5119,12 @@ static int binder_transactions_show(struct seq_file *m, void *unused) { struct binder_proc *proc; - binder_lock(__func__); - seq_puts(m, "binder transactions:\n"); mutex_lock(&binder_procs_lock); hlist_for_each_entry(proc, &binder_procs, proc_node) print_binder_proc(m, proc, 0); mutex_unlock(&binder_procs_lock); - binder_unlock(__func__); + return 0; } @@ -5170,8 +5133,6 @@ static int binder_proc_show(struct seq_file *m, void *unused) struct binder_proc *itr; int pid = (unsigned long)m->private; - binder_lock(__func__); - mutex_lock(&binder_procs_lock); hlist_for_each_entry(itr, &binder_procs, proc_node) { if (itr->pid == pid) { @@ -5181,7 +5142,6 @@ static int binder_proc_show(struct seq_file *m, void *unused) } mutex_unlock(&binder_procs_lock); - binder_unlock(__func__); return 0; } -- cgit v1.2.3 From c3643b699fa22178dca307e4aca077ca338616cd Mon Sep 17 00:00:00 2001 From: Krzysztof Opasiak Date: Wed, 5 Jul 2017 19:24:44 +0200 Subject: android: binder: Use dedicated helper to access rlimit value Use rlimit() helper instead of manually writing whole chain from current task to rlim_cur Signed-off-by: Krzysztof Opasiak Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index c8e9d5dfcd86..fdbde8ce5804 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -930,7 +930,7 @@ static void binder_set_nice(long nice) set_user_nice(current, nice); return; } - min_nice = rlimit_to_nice(current->signal->rlim[RLIMIT_NICE].rlim_cur); + min_nice = rlimit_to_nice(rlimit(RLIMIT_NICE)); binder_debug(BINDER_DEBUG_PRIORITY_CAP, "%d: nice value %ld not allowed use %ld instead\n", current->pid, nice, min_nice); -- cgit v1.2.3 From 5b7d40cdcd15f8058de956046f751d22a464394b Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Wed, 24 May 2017 22:55:21 +0300 Subject: binder: remove unused BINDER_SMALL_BUF_SIZE define MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It was never used since addition of binder to linux mainstream tree. Cc: Greg Kroah-Hartman Cc: "Arve Hjønnevåg" Cc: Riley Andrews Cc: devel@driverdev.osuosl.org Signed-off-by: Dmitry Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index fdbde8ce5804..9f95d7093f32 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -122,8 +122,6 @@ BINDER_DEBUG_ENTRY(proc); #define FORBIDDEN_MMAP_FLAGS (VM_WRITE) -#define BINDER_SMALL_BUF_SIZE (PAGE_SIZE * 64) - enum { BINDER_DEBUG_USER_ERROR = 1U << 0, BINDER_DEBUG_FAILED_TRANSACTION = 1U << 1, -- cgit v1.2.3 From 67de6bf1e4f869a490656448f471fdc4a0a405ad Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Thu, 29 Jun 2017 09:40:02 +0300 Subject: mei: me: enable asynchronous probing On some platforms, currently Broxton, Apollo Lake and Kaby Lake, ME FW may be busy with internal bookkeeping and answering late to the start message. As a mitigation, the driver requests for a synchronous probing to prevent stalling of the overall boot process. For example, on a Apollo Lake platform the overall boot time has reduced from ~0.9 to ~0.6 seconds on average. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/pci-me.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c index 8621a198a2ce..8bf9a3d9792d 100644 --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c @@ -485,6 +485,7 @@ static struct pci_driver mei_me_driver = { .remove = mei_me_remove, .shutdown = mei_me_shutdown, .driver.pm = MEI_ME_PM_OPS, + .driver.probe_type = PROBE_PREFER_ASYNCHRONOUS, }; module_pci_driver(mei_me_driver); -- cgit v1.2.3 From f5ac3c49ff0b36d9b6a804b4b86efcaf27ba044b Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 14 Jun 2017 10:03:15 +0300 Subject: mei: me: use an index instead of a pointer for private data Device 'new_id' interface is useful for testing of not yet published hardware on older kernels and for internally used device ids on simulation platforms. However currently with the device configuration held in device_id driver data as a pointer to mei_cfg structure it is hard, as one need to locate the address of the correct structure. A recommended way of doing that is to use and index instead of a pointer. This patch adds a new list of configuration mei_cfg_list[] indexed via enum mei_cfg_idx. In addition it cleanups ich platform naming, renames legacy generation to ich and what was ich to ich10. Signed-off-by: Tomas Winkler Signed-off-by: Alexander Usyskin Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hw-me.c | 45 ++++++++++++++----- drivers/misc/mei/hw-me.h | 39 +++++++++++++---- drivers/misc/mei/pci-me.c | 108 ++++++++++++++++++++++++---------------------- 3 files changed, 121 insertions(+), 71 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index 71216affcab1..10dcf4ff99a5 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c @@ -1354,10 +1354,10 @@ static bool mei_me_fw_type_sps(struct pci_dev *pdev) .quirk_probe = mei_me_fw_type_sps -#define MEI_CFG_LEGACY_HFS \ +#define MEI_CFG_ICH_HFS \ .fw_status.count = 0 -#define MEI_CFG_ICH_HFS \ +#define MEI_CFG_ICH10_HFS \ .fw_status.count = 1, \ .fw_status.status[0] = PCI_CFG_HFS_1 @@ -1376,38 +1376,61 @@ static bool mei_me_fw_type_sps(struct pci_dev *pdev) .fw_status.status[5] = PCI_CFG_HFS_6 /* ICH Legacy devices */ -const struct mei_cfg mei_me_legacy_cfg = { - MEI_CFG_LEGACY_HFS, +static const struct mei_cfg mei_me_ich_cfg = { + MEI_CFG_ICH_HFS, }; /* ICH devices */ -const struct mei_cfg mei_me_ich_cfg = { - MEI_CFG_ICH_HFS, +static const struct mei_cfg mei_me_ich10_cfg = { + MEI_CFG_ICH10_HFS, }; /* PCH devices */ -const struct mei_cfg mei_me_pch_cfg = { +static const struct mei_cfg mei_me_pch_cfg = { MEI_CFG_PCH_HFS, }; - /* PCH Cougar Point and Patsburg with quirk for Node Manager exclusion */ -const struct mei_cfg mei_me_pch_cpt_pbg_cfg = { +static const struct mei_cfg mei_me_pch_cpt_pbg_cfg = { MEI_CFG_PCH_HFS, MEI_CFG_FW_NM, }; /* PCH8 Lynx Point and newer devices */ -const struct mei_cfg mei_me_pch8_cfg = { +static const struct mei_cfg mei_me_pch8_cfg = { MEI_CFG_PCH8_HFS, }; /* PCH8 Lynx Point with quirk for SPS Firmware exclusion */ -const struct mei_cfg mei_me_pch8_sps_cfg = { +static const struct mei_cfg mei_me_pch8_sps_cfg = { MEI_CFG_PCH8_HFS, MEI_CFG_FW_SPS, }; +/* + * mei_cfg_list - A list of platform platform specific configurations. + * Note: has to be synchronized with enum mei_cfg_idx. + */ +static const struct mei_cfg *const mei_cfg_list[] = { + [MEI_ME_UNDEF_CFG] = NULL, + [MEI_ME_ICH_CFG] = &mei_me_ich_cfg, + [MEI_ME_ICH10_CFG] = &mei_me_ich10_cfg, + [MEI_ME_PCH_CFG] = &mei_me_pch_cfg, + [MEI_ME_PCH_CPT_PBG_CFG] = &mei_me_pch_cpt_pbg_cfg, + [MEI_ME_PCH8_CFG] = &mei_me_pch8_cfg, + [MEI_ME_PCH8_SPS_CFG] = &mei_me_pch8_sps_cfg, +}; + +const struct mei_cfg *mei_me_get_cfg(kernel_ulong_t idx) +{ + BUILD_BUG_ON(ARRAY_SIZE(mei_cfg_list) != MEI_ME_NUM_CFG); + + if (idx >= MEI_ME_NUM_CFG) + return NULL; + + return mei_cfg_list[idx]; +}; + /** * mei_me_dev_init - allocates and initializes the mei device structure * diff --git a/drivers/misc/mei/hw-me.h b/drivers/misc/mei/hw-me.h index cf64847a35b9..67892533576e 100644 --- a/drivers/misc/mei/hw-me.h +++ b/drivers/misc/mei/hw-me.h @@ -41,8 +41,7 @@ struct mei_cfg { #define MEI_PCI_DEVICE(dev, cfg) \ .vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \ .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, \ - .driver_data = (kernel_ulong_t)&(cfg) - + .driver_data = (kernel_ulong_t)(cfg), #define MEI_ME_RPM_TIMEOUT 500 /* ms */ @@ -63,12 +62,36 @@ struct mei_me_hw { #define to_me_hw(dev) (struct mei_me_hw *)((dev)->hw) -extern const struct mei_cfg mei_me_legacy_cfg; -extern const struct mei_cfg mei_me_ich_cfg; -extern const struct mei_cfg mei_me_pch_cfg; -extern const struct mei_cfg mei_me_pch_cpt_pbg_cfg; -extern const struct mei_cfg mei_me_pch8_cfg; -extern const struct mei_cfg mei_me_pch8_sps_cfg; +/** + * enum mei_cfg_idx - indices to platform specific configurations. + * + * Note: has to be synchronized with mei_cfg_list[] + * + * @MEI_ME_UNDEF_CFG: Lower sentinel. + * @MEI_ME_ICH_CFG: I/O Controller Hub legacy devices. + * @MEI_ME_ICH10_CFG: I/O Controller Hub platforms Gen10 + * @MEI_ME_PCH_CFG: Platform Controller Hub platforms (Up to Gen8). + * @MEI_ME_PCH_CPT_PBG_CFG:Platform Controller Hub workstations + * with quirk for Node Manager exclusion. + * @MEI_ME_PCH8_CFG: Platform Controller Hub Gen8 and newer + * client platforms. + * @MEI_ME_PCH8_SPS_CFG: Platform Controller Hub Gen8 and newer + * servers platforms with quirk for + * SPS firmware exclusion. + * @MEI_ME_NUM_CFG: Upper Sentinel. + */ +enum mei_cfg_idx { + MEI_ME_UNDEF_CFG, + MEI_ME_ICH_CFG, + MEI_ME_ICH10_CFG, + MEI_ME_PCH_CFG, + MEI_ME_PCH_CPT_PBG_CFG, + MEI_ME_PCH8_CFG, + MEI_ME_PCH8_SPS_CFG, + MEI_ME_NUM_CFG, +}; + +const struct mei_cfg *mei_me_get_cfg(kernel_ulong_t idx); struct mei_device *mei_me_dev_init(struct pci_dev *pdev, const struct mei_cfg *cfg); diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c index 8bf9a3d9792d..3f4e36b8892f 100644 --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c @@ -43,57 +43,58 @@ /* mei_pci_tbl - PCI Device ID Table */ static const struct pci_device_id mei_me_pci_tbl[] = { - {MEI_PCI_DEVICE(MEI_DEV_ID_82946GZ, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_82G35, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_82Q965, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_82G965, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_82GM965, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_82GME965, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_82Q35, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_82G33, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_82Q33, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_82X38, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_3200, mei_me_legacy_cfg)}, - - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_6, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_7, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_8, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_9, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_10, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9M_1, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9M_2, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9M_3, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9M_4, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH10_1, mei_me_ich_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH10_2, mei_me_ich_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH10_3, mei_me_ich_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH10_4, mei_me_ich_cfg)}, - - {MEI_PCI_DEVICE(MEI_DEV_ID_IBXPK_1, mei_me_pch_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_IBXPK_2, mei_me_pch_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_CPT_1, mei_me_pch_cpt_pbg_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_PBG_1, mei_me_pch_cpt_pbg_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_PPT_1, mei_me_pch_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_PPT_2, mei_me_pch_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_PPT_3, mei_me_pch_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_H, mei_me_pch8_sps_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_W, mei_me_pch8_sps_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_LP, mei_me_pch8_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_HR, mei_me_pch8_sps_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_WPT_LP, mei_me_pch8_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_WPT_LP_2, mei_me_pch8_cfg)}, - - {MEI_PCI_DEVICE(MEI_DEV_ID_SPT, mei_me_pch8_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_2, mei_me_pch8_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H, mei_me_pch8_sps_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H_2, mei_me_pch8_sps_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_LBG, mei_me_pch8_cfg)}, - - {MEI_PCI_DEVICE(MEI_DEV_ID_BXT_M, mei_me_pch8_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_APL_I, mei_me_pch8_cfg)}, - - {MEI_PCI_DEVICE(MEI_DEV_ID_KBP, mei_me_pch8_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_KBP_2, mei_me_pch8_cfg)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_82946GZ, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_82G35, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_82Q965, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_82G965, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_82GM965, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_82GME965, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_82Q35, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_82G33, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_82Q33, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_82X38, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_3200, MEI_ME_ICH_CFG)}, + + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_6, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_7, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_8, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_9, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_10, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9M_1, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9M_2, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9M_3, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9M_4, MEI_ME_ICH_CFG)}, + + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH10_1, MEI_ME_ICH10_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH10_2, MEI_ME_ICH10_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH10_3, MEI_ME_ICH10_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH10_4, MEI_ME_ICH10_CFG)}, + + {MEI_PCI_DEVICE(MEI_DEV_ID_IBXPK_1, MEI_ME_PCH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_IBXPK_2, MEI_ME_PCH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_CPT_1, MEI_ME_PCH_CPT_PBG_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_PBG_1, MEI_ME_PCH_CPT_PBG_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_PPT_1, MEI_ME_PCH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_PPT_2, MEI_ME_PCH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_PPT_3, MEI_ME_PCH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_H, MEI_ME_PCH8_SPS_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_W, MEI_ME_PCH8_SPS_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_LP, MEI_ME_PCH8_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_HR, MEI_ME_PCH8_SPS_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_WPT_LP, MEI_ME_PCH8_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_WPT_LP_2, MEI_ME_PCH8_CFG)}, + + {MEI_PCI_DEVICE(MEI_DEV_ID_SPT, MEI_ME_PCH8_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_2, MEI_ME_PCH8_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H, MEI_ME_PCH8_SPS_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H_2, MEI_ME_PCH8_SPS_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_LBG, MEI_ME_PCH8_CFG)}, + + {MEI_PCI_DEVICE(MEI_DEV_ID_BXT_M, MEI_ME_PCH8_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_APL_I, MEI_ME_PCH8_CFG)}, + + {MEI_PCI_DEVICE(MEI_DEV_ID_KBP, MEI_ME_PCH8_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_KBP_2, MEI_ME_PCH8_CFG)}, /* required last entry */ {0, } @@ -138,12 +139,15 @@ static bool mei_me_quirk_probe(struct pci_dev *pdev, */ static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - const struct mei_cfg *cfg = (struct mei_cfg *)(ent->driver_data); + const struct mei_cfg *cfg; struct mei_device *dev; struct mei_me_hw *hw; unsigned int irqflags; int err; + cfg = mei_me_get_cfg(ent->driver_data); + if (!cfg) + return -ENODEV; if (!mei_me_quirk_probe(pdev, cfg)) return -ENODEV; -- cgit v1.2.3 From f12a616e0cdee71440b72f7602825db424d37879 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Fri, 14 Jul 2017 11:42:46 +0200 Subject: spi: loopback-test: provide loop_req option. Provide a module parameter to request internal loop by the SPI master controller. This should make loop testing easier without extra HW modification. For test automation a logic analyzer is recommended for host controller-independent verification. An example test rig configuration and procedure: i.MX6S RIoRBoard Logic Analyzer ----------------------------------------- (J13 4) GND ------------- GND (J13 6) CSPI3-CLK ------> PIN 3 (J13 8) CSPI3-MOSI <----- PIN 2 ^ - internal loop configured by SPI_LOOP | or can be user external jamper. (J13 10) CSPI3-MISO -----> PIN 1 grab some data and decode it: sigrok-cli -d fx2lafw --time 160000 --config samplerate=10m \ --channels 0-2 -o dump.sr sigrok-cli -i dump.sr -P spi:mosi=1:clk=2 > result_for_regression_tests Signed-off-by: Oleksij Rempel Signed-off-by: Mark Brown --- drivers/spi/spi-loopback-test.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/spi/spi-loopback-test.c b/drivers/spi/spi-loopback-test.c index 3459965004f8..0d3c56e2526c 100644 --- a/drivers/spi/spi-loopback-test.c +++ b/drivers/spi/spi-loopback-test.c @@ -51,6 +51,12 @@ MODULE_PARM_DESC(loopback, "is checked to match tx_buf after the spi_message " \ "is executed"); +int loop_req; +module_param(loop_req, int, 0); +MODULE_PARM_DESC(loop_req, + "if set controller will be asked to enable test loop mode. " \ + "If controller supported it, MISO and MOSI will be connected"); + /* run only a specific test */ int run_only_test = -1; module_param(run_only_test, int, 0); @@ -313,6 +319,16 @@ static int spi_loopback_test_probe(struct spi_device *spi) { int ret; + if (loop_req) { + spi->mode = SPI_LOOP | spi->mode; + ret = spi_setup(spi); + if (ret) { + dev_err(&spi->dev, "SPI setup with SPI_LOOP failed (%d)\n", + ret); + return ret; + } + } + dev_info(&spi->dev, "Executing spi-loopback-tests\n"); ret = spi_test_run_tests(spi, spi_tests); -- cgit v1.2.3 From eb42ea6d0b8ed9ca8e73cc24fa801f0d8ab28905 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 21 Jun 2017 13:00:07 +0200 Subject: drm/crc: Handle opening and closing crc better When I was doing a grep . -r /sys/kernel/debug/dri/0 I noticed a WARN appearing when I aborted the grep with ^C. After investigating I've also noticed that the error handling was lacking and there are race conditions involving multiple calls to open/close simultaneously. Fix this by setting the opened flag first and using crc->entries to decide when crc can be collected. Also call unset crc source before cleaning up, this way there is no race with a future open(). This patch has been tested with all the tests in igt with CRC in their name. Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/20170621110007.11674-1-maarten.lankhorst@linux.intel.com Reviewed-by: Tomeu Vizoso [mlankhorst: Add description that this patch has been tested with IGT, based on tomeu's feedback] --- drivers/gpu/drm/drm_debugfs_crc.c | 46 ++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_debugfs_crc.c b/drivers/gpu/drm/drm_debugfs_crc.c index 1722d8f21449..d0ea4627a093 100644 --- a/drivers/gpu/drm/drm_debugfs_crc.c +++ b/drivers/gpu/drm/drm_debugfs_crc.c @@ -136,21 +136,38 @@ static int crtc_crc_data_count(struct drm_crtc_crc *crc) return CIRC_CNT(crc->head, crc->tail, DRM_CRC_ENTRIES_NR); } +static void crtc_crc_cleanup(struct drm_crtc_crc *crc) +{ + kfree(crc->entries); + crc->entries = NULL; + crc->head = 0; + crc->tail = 0; + crc->values_cnt = 0; + crc->opened = false; +} + static int crtc_crc_open(struct inode *inode, struct file *filep) { struct drm_crtc *crtc = inode->i_private; struct drm_crtc_crc *crc = &crtc->crc; struct drm_crtc_crc_entry *entries = NULL; size_t values_cnt; - int ret; + int ret = 0; - if (crc->opened) - return -EBUSY; + spin_lock_irq(&crc->lock); + if (!crc->opened) + crc->opened = true; + else + ret = -EBUSY; + spin_unlock_irq(&crc->lock); - ret = crtc->funcs->set_crc_source(crtc, crc->source, &values_cnt); if (ret) return ret; + ret = crtc->funcs->set_crc_source(crtc, crc->source, &values_cnt); + if (ret) + goto err; + if (WARN_ON(values_cnt > DRM_MAX_CRC_NR)) { ret = -EINVAL; goto err_disable; @@ -170,7 +187,6 @@ static int crtc_crc_open(struct inode *inode, struct file *filep) spin_lock_irq(&crc->lock); crc->entries = entries; crc->values_cnt = values_cnt; - crc->opened = true; /* * Only return once we got a first frame, so userspace doesn't have to @@ -182,12 +198,17 @@ static int crtc_crc_open(struct inode *inode, struct file *filep) crc->lock); spin_unlock_irq(&crc->lock); - WARN_ON(ret); + if (ret) + goto err_disable; return 0; err_disable: crtc->funcs->set_crc_source(crtc, NULL, &values_cnt); +err: + spin_lock_irq(&crc->lock); + crtc_crc_cleanup(crc); + spin_unlock_irq(&crc->lock); return ret; } @@ -197,17 +218,12 @@ static int crtc_crc_release(struct inode *inode, struct file *filep) struct drm_crtc_crc *crc = &crtc->crc; size_t values_cnt; + crtc->funcs->set_crc_source(crtc, NULL, &values_cnt); + spin_lock_irq(&crc->lock); - kfree(crc->entries); - crc->entries = NULL; - crc->head = 0; - crc->tail = 0; - crc->values_cnt = 0; - crc->opened = false; + crtc_crc_cleanup(crc); spin_unlock_irq(&crc->lock); - crtc->funcs->set_crc_source(crtc, NULL, &values_cnt); - return 0; } @@ -334,7 +350,7 @@ int drm_crtc_add_crc_entry(struct drm_crtc *crtc, bool has_frame, spin_lock(&crc->lock); /* Caller may not have noticed yet that userspace has stopped reading */ - if (!crc->opened) { + if (!crc->entries) { spin_unlock(&crc->lock); return -EINVAL; } -- cgit v1.2.3 From 8038e09be5a3ac061118bd80c7a505829920b50f Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 6 Jul 2017 15:03:15 +0200 Subject: drm/crc: Only open CRC on atomic drivers when the CRTC is active. Commit e8fa5671183c ("drm: crc: Wait for a frame before returning from open()") adds a wait for CRC frame, but with the CRTC off this will never be generated. For atomic drivers we know if a CRTC is active through crtc_state->active, so when inactive reject the open with -EIO. Just like with the previous patch changing debugfs opening semantics, this patch has been tested against igt. Signed-off-by: Maarten Lankhorst Fixes: e8fa5671183c ("drm: crc: Wait for a frame before returning from open()") Testcase: debugfs_test.read_all_entries Link: http://patchwork.freedesktop.org/patch/msgid/15f9d300-65d3-63aa-00e3-e83f5e4d5a7a@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/drm_debugfs_crc.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_debugfs_crc.c b/drivers/gpu/drm/drm_debugfs_crc.c index d0ea4627a093..f9e26dda56d6 100644 --- a/drivers/gpu/drm/drm_debugfs_crc.c +++ b/drivers/gpu/drm/drm_debugfs_crc.c @@ -154,6 +154,19 @@ static int crtc_crc_open(struct inode *inode, struct file *filep) size_t values_cnt; int ret = 0; + if (drm_drv_uses_atomic_modeset(crtc->dev)) { + ret = drm_modeset_lock_interruptible(&crtc->mutex, NULL); + if (ret) + return ret; + + if (!crtc->state->active) + ret = -EIO; + drm_modeset_unlock(&crtc->mutex); + + if (ret) + return ret; + } + spin_lock_irq(&crc->lock); if (!crc->opened) crc->opened = true; -- cgit v1.2.3 From 4226ff69a3dff78bead7d9a270423cd21f8d40b8 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sun, 25 Jun 2017 12:30:24 -0700 Subject: vmbus: simplify hv_ringbuffer_read With new iterator functions (and the double mapping) the ring buffer read function can be greatly simplified. Signed-off-by: Stephen Hemminger Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/hv/ring_buffer.c | 118 +++++++---------------------------------------- 1 file changed, 17 insertions(+), 101 deletions(-) (limited to 'drivers') diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c index 1f450c39a9b0..f29981764653 100644 --- a/drivers/hv/ring_buffer.c +++ b/drivers/hv/ring_buffer.c @@ -94,30 +94,6 @@ hv_set_next_write_location(struct hv_ring_buffer_info *ring_info, ring_info->ring_buffer->write_index = next_write_location; } -/* Get the next read location for the specified ring buffer. */ -static inline u32 -hv_get_next_read_location(const struct hv_ring_buffer_info *ring_info) -{ - return ring_info->ring_buffer->read_index; -} - -/* - * Get the next read location + offset for the specified ring buffer. - * This allows the caller to skip. - */ -static inline u32 -hv_get_next_readlocation_withoffset(const struct hv_ring_buffer_info *ring_info, - u32 offset) -{ - u32 next = ring_info->ring_buffer->read_index; - - next += offset; - if (next >= ring_info->ring_datasize) - next -= ring_info->ring_datasize; - - return next; -} - /* Set the next read location for the specified ring buffer. */ static inline void hv_set_next_read_location(struct hv_ring_buffer_info *ring_info, @@ -141,29 +117,6 @@ hv_get_ring_bufferindices(struct hv_ring_buffer_info *ring_info) return (u64)ring_info->ring_buffer->write_index << 32; } -/* - * Helper routine to copy to source from ring buffer. - * Assume there is enough room. Handles wrap-around in src case only!! - */ -static u32 hv_copyfrom_ringbuffer( - const struct hv_ring_buffer_info *ring_info, - void *dest, - u32 destlen, - u32 start_read_offset) -{ - void *ring_buffer = hv_get_ring_buffer(ring_info); - u32 ring_buffer_size = hv_get_ring_buffersize(ring_info); - - memcpy(dest, ring_buffer + start_read_offset, destlen); - - start_read_offset += destlen; - if (start_read_offset >= ring_buffer_size) - start_read_offset -= ring_buffer_size; - - return start_read_offset; -} - - /* * Helper routine to copy from source to ring buffer. * Assume there is enough room. Handles wrap-around in dest case only!! @@ -334,33 +287,22 @@ int hv_ringbuffer_write(struct vmbus_channel *channel, return 0; } -static inline void -init_cached_read_index(struct hv_ring_buffer_info *rbi) -{ - rbi->cached_read_index = rbi->ring_buffer->read_index; -} - int hv_ringbuffer_read(struct vmbus_channel *channel, void *buffer, u32 buflen, u32 *buffer_actual_len, u64 *requestid, bool raw) { - u32 bytes_avail_toread; - u32 next_read_location; - u64 prev_indices = 0; - struct vmpacket_descriptor desc; - u32 offset; - u32 packetlen; - struct hv_ring_buffer_info *inring_info = &channel->inbound; - - if (buflen <= 0) + struct vmpacket_descriptor *desc; + u32 packetlen, offset; + + if (unlikely(buflen == 0)) return -EINVAL; *buffer_actual_len = 0; *requestid = 0; - bytes_avail_toread = hv_get_bytes_to_read(inring_info); /* Make sure there is something to read */ - if (bytes_avail_toread < sizeof(desc)) { + desc = hv_pkt_iter_first(channel); + if (desc == NULL) { /* * No error is set when there is even no header, drivers are * supposed to analyze buffer_actual_len. @@ -368,48 +310,22 @@ int hv_ringbuffer_read(struct vmbus_channel *channel, return 0; } - init_cached_read_index(inring_info); - - next_read_location = hv_get_next_read_location(inring_info); - next_read_location = hv_copyfrom_ringbuffer(inring_info, &desc, - sizeof(desc), - next_read_location); - - offset = raw ? 0 : (desc.offset8 << 3); - packetlen = (desc.len8 << 3) - offset; + offset = raw ? 0 : (desc->offset8 << 3); + packetlen = (desc->len8 << 3) - offset; *buffer_actual_len = packetlen; - *requestid = desc.trans_id; - - if (bytes_avail_toread < packetlen + offset) - return -EAGAIN; + *requestid = desc->trans_id; - if (packetlen > buflen) + if (unlikely(packetlen > buflen)) return -ENOBUFS; - next_read_location = - hv_get_next_readlocation_withoffset(inring_info, offset); + /* since ring is double mapped, only one copy is necessary */ + memcpy(buffer, (const char *)desc + offset, packetlen); - next_read_location = hv_copyfrom_ringbuffer(inring_info, - buffer, - packetlen, - next_read_location); + /* Advance ring index to next packet descriptor */ + __hv_pkt_iter_next(channel, desc); - next_read_location = hv_copyfrom_ringbuffer(inring_info, - &prev_indices, - sizeof(u64), - next_read_location); - - /* - * Make sure all reads are done before we update the read index since - * the writer may start writing to the read area once the read index - * is updated. - */ - virt_mb(); - - /* Update the read index */ - hv_set_next_read_location(inring_info, next_read_location); - - hv_signal_on_read(channel); + /* Notify host of update */ + hv_pkt_iter_close(channel); return 0; } @@ -442,7 +358,7 @@ struct vmpacket_descriptor *hv_pkt_iter_first(struct vmbus_channel *channel) struct hv_ring_buffer_info *rbi = &channel->inbound; /* set state for later hv_signal_on_read() */ - init_cached_read_index(rbi); + rbi->cached_read_index = rbi->ring_buffer->read_index; if (hv_pkt_iter_avail(rbi) < sizeof(struct vmpacket_descriptor)) return NULL; -- cgit v1.2.3 From 8dd45f2ab005a1f3301296059b23b03ec3dbf79b Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sun, 25 Jun 2017 12:30:26 -0700 Subject: vmbus: refactor hv_signal_on_read The function hv_signal_on_read was defined in hyperv.h and only used in one place in ring_buffer code. Clearer to just move it inline there. Signed-off-by: Stephen Hemminger Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/hv/ring_buffer.c | 32 +++++++++++++++++++++++++++++-- include/linux/hyperv.h | 49 ------------------------------------------------ 2 files changed, 30 insertions(+), 51 deletions(-) (limited to 'drivers') diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c index f29981764653..a9021f13379f 100644 --- a/drivers/hv/ring_buffer.c +++ b/drivers/hv/ring_buffer.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "hyperv_vmbus.h" @@ -357,7 +358,7 @@ struct vmpacket_descriptor *hv_pkt_iter_first(struct vmbus_channel *channel) { struct hv_ring_buffer_info *rbi = &channel->inbound; - /* set state for later hv_signal_on_read() */ + /* set state for later hv_pkt_iter_close */ rbi->cached_read_index = rbi->ring_buffer->read_index; if (hv_pkt_iter_avail(rbi) < sizeof(struct vmpacket_descriptor)) @@ -400,6 +401,8 @@ EXPORT_SYMBOL_GPL(__hv_pkt_iter_next); void hv_pkt_iter_close(struct vmbus_channel *channel) { struct hv_ring_buffer_info *rbi = &channel->inbound; + u32 cur_write_sz, cached_write_sz; + u32 pending_sz; /* * Make sure all reads are done before we update the read index since @@ -409,6 +412,31 @@ void hv_pkt_iter_close(struct vmbus_channel *channel) virt_rmb(); rbi->ring_buffer->read_index = rbi->priv_read_index; - hv_signal_on_read(channel); + /* + * Issue a full memory barrier before making the signaling decision. + * Here is the reason for having this barrier: + * If the reading of the pend_sz (in this function) + * were to be reordered and read before we commit the new read + * index (in the calling function) we could + * have a problem. If the host were to set the pending_sz after we + * have sampled pending_sz and go to sleep before we commit the + * read index, we could miss sending the interrupt. Issue a full + * memory barrier to address this. + */ + virt_mb(); + + pending_sz = READ_ONCE(rbi->ring_buffer->pending_send_sz); + /* If the other end is not blocked on write don't bother. */ + if (pending_sz == 0) + return; + + cur_write_sz = hv_get_bytes_to_write(rbi); + + if (cur_write_sz < pending_sz) + return; + + cached_write_sz = hv_get_cached_bytes_to_write(rbi); + if (cached_write_sz < pending_sz) + vmbus_setevent(channel); } EXPORT_SYMBOL_GPL(hv_pkt_iter_close); diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 5e5f966bf37f..308e1f9706bb 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -1471,55 +1471,6 @@ hv_get_ring_buffer(const struct hv_ring_buffer_info *ring_info) return ring_info->ring_buffer->buffer; } -/* - * To optimize the flow management on the send-side, - * when the sender is blocked because of lack of - * sufficient space in the ring buffer, potential the - * consumer of the ring buffer can signal the producer. - * This is controlled by the following parameters: - * - * 1. pending_send_sz: This is the size in bytes that the - * producer is trying to send. - * 2. The feature bit feat_pending_send_sz set to indicate if - * the consumer of the ring will signal when the ring - * state transitions from being full to a state where - * there is room for the producer to send the pending packet. - */ - -static inline void hv_signal_on_read(struct vmbus_channel *channel) -{ - u32 cur_write_sz, cached_write_sz; - u32 pending_sz; - struct hv_ring_buffer_info *rbi = &channel->inbound; - - /* - * Issue a full memory barrier before making the signaling decision. - * Here is the reason for having this barrier: - * If the reading of the pend_sz (in this function) - * were to be reordered and read before we commit the new read - * index (in the calling function) we could - * have a problem. If the host were to set the pending_sz after we - * have sampled pending_sz and go to sleep before we commit the - * read index, we could miss sending the interrupt. Issue a full - * memory barrier to address this. - */ - virt_mb(); - - pending_sz = READ_ONCE(rbi->ring_buffer->pending_send_sz); - /* If the other end is not blocked on write don't bother. */ - if (pending_sz == 0) - return; - - cur_write_sz = hv_get_bytes_to_write(rbi); - - if (cur_write_sz < pending_sz) - return; - - cached_write_sz = hv_get_cached_bytes_to_write(rbi); - if (cached_write_sz < pending_sz) - vmbus_setevent(channel); -} - /* * Mask off host interrupt callback notifications */ -- cgit v1.2.3 From 05d00bc94ac27d220d8a78e365d7fa3a26dcca17 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sun, 25 Jun 2017 12:30:27 -0700 Subject: vmbus: eliminate duplicate cached index Don't need cached read index anymore now that packet iterator is used. The iterator has the original read index until the visible read_index is updated. Signed-off-by: Stephen Hemminger Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/hv/ring_buffer.c | 17 ++++------------- include/linux/hyperv.h | 14 -------------- 2 files changed, 4 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c index a9021f13379f..b0f79526b86a 100644 --- a/drivers/hv/ring_buffer.c +++ b/drivers/hv/ring_buffer.c @@ -358,9 +358,6 @@ struct vmpacket_descriptor *hv_pkt_iter_first(struct vmbus_channel *channel) { struct hv_ring_buffer_info *rbi = &channel->inbound; - /* set state for later hv_pkt_iter_close */ - rbi->cached_read_index = rbi->ring_buffer->read_index; - if (hv_pkt_iter_avail(rbi) < sizeof(struct vmpacket_descriptor)) return NULL; @@ -388,10 +385,7 @@ __hv_pkt_iter_next(struct vmbus_channel *channel, rbi->priv_read_index -= dsize; /* more data? */ - if (hv_pkt_iter_avail(rbi) < sizeof(struct vmpacket_descriptor)) - return NULL; - else - return hv_get_ring_buffer(rbi) + rbi->priv_read_index; + return hv_pkt_iter_first(channel); } EXPORT_SYMBOL_GPL(__hv_pkt_iter_next); @@ -401,7 +395,7 @@ EXPORT_SYMBOL_GPL(__hv_pkt_iter_next); void hv_pkt_iter_close(struct vmbus_channel *channel) { struct hv_ring_buffer_info *rbi = &channel->inbound; - u32 cur_write_sz, cached_write_sz; + u32 orig_write_sz = hv_get_bytes_to_write(rbi); u32 pending_sz; /* @@ -430,13 +424,10 @@ void hv_pkt_iter_close(struct vmbus_channel *channel) if (pending_sz == 0) return; - cur_write_sz = hv_get_bytes_to_write(rbi); - - if (cur_write_sz < pending_sz) + if (hv_get_bytes_to_write(rbi) < pending_sz) return; - cached_write_sz = hv_get_cached_bytes_to_write(rbi); - if (cached_write_sz < pending_sz) + if (orig_write_sz < pending_sz) vmbus_setevent(channel); } EXPORT_SYMBOL_GPL(hv_pkt_iter_close); diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 308e1f9706bb..27db4e650b8c 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -125,7 +125,6 @@ struct hv_ring_buffer_info { u32 ring_datasize; /* < ring_size */ u32 priv_read_index; - u32 cached_read_index; }; /* @@ -178,19 +177,6 @@ static inline u32 hv_get_bytes_to_write(const struct hv_ring_buffer_info *rbi) return write; } -static inline u32 hv_get_cached_bytes_to_write( - const struct hv_ring_buffer_info *rbi) -{ - u32 read_loc, write_loc, dsize, write; - - dsize = rbi->ring_datasize; - read_loc = rbi->cached_read_index; - write_loc = rbi->ring_buffer->write_index; - - write = write_loc >= read_loc ? dsize - (write_loc - read_loc) : - read_loc - write_loc; - return write; -} /* * VMBUS version is 32 bit entity broken up into * two 16 bit quantities: major_number. minor_number. -- cgit v1.2.3 From 03bad714a1619c0074eb44d6f217c505fe27030f Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sun, 25 Jun 2017 12:30:28 -0700 Subject: vmbus: more host signalling avoidance Don't signal host if it has disabled interrupts for that ring buffer. Check the feature bit to see if host supports pending send size flag. Signed-off-by: Stephen Hemminger Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/hv/ring_buffer.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c index b0f79526b86a..741daa6e2fc7 100644 --- a/drivers/hv/ring_buffer.c +++ b/drivers/hv/ring_buffer.c @@ -396,7 +396,6 @@ void hv_pkt_iter_close(struct vmbus_channel *channel) { struct hv_ring_buffer_info *rbi = &channel->inbound; u32 orig_write_sz = hv_get_bytes_to_write(rbi); - u32 pending_sz; /* * Make sure all reads are done before we update the read index since @@ -419,15 +418,27 @@ void hv_pkt_iter_close(struct vmbus_channel *channel) */ virt_mb(); - pending_sz = READ_ONCE(rbi->ring_buffer->pending_send_sz); - /* If the other end is not blocked on write don't bother. */ - if (pending_sz == 0) + /* If host has disabled notifications then skip */ + if (rbi->ring_buffer->interrupt_mask) return; - if (hv_get_bytes_to_write(rbi) < pending_sz) - return; + if (rbi->ring_buffer->feature_bits.feat_pending_send_sz) { + u32 pending_sz = READ_ONCE(rbi->ring_buffer->pending_send_sz); - if (orig_write_sz < pending_sz) - vmbus_setevent(channel); + /* + * If there was space before we began iteration, + * then host was not blocked. Also handles case where + * pending_sz is zero then host has nothing pending + * and does not need to be signaled. + */ + if (orig_write_sz > pending_sz) + return; + + /* If pending write will not fit, don't give false hope. */ + if (hv_get_bytes_to_write(rbi) < pending_sz) + return; + } + + vmbus_setevent(channel); } EXPORT_SYMBOL_GPL(hv_pkt_iter_close); -- cgit v1.2.3 From 15e1674de747d58c5a6154ba6e85bc61e5009b08 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sun, 25 Jun 2017 12:30:29 -0700 Subject: vmbus: add prefetch to ring buffer iterator When iterating over incoming ring elements from the host, prefetch the next descriptor so that it is cache hot. Signed-off-by: Stephen Hemminger Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/hv/ring_buffer.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c index 741daa6e2fc7..12eb8caa4263 100644 --- a/drivers/hv/ring_buffer.c +++ b/drivers/hv/ring_buffer.c @@ -357,11 +357,16 @@ static u32 hv_pkt_iter_avail(const struct hv_ring_buffer_info *rbi) struct vmpacket_descriptor *hv_pkt_iter_first(struct vmbus_channel *channel) { struct hv_ring_buffer_info *rbi = &channel->inbound; + struct vmpacket_descriptor *desc; if (hv_pkt_iter_avail(rbi) < sizeof(struct vmpacket_descriptor)) return NULL; - return hv_get_ring_buffer(rbi) + rbi->priv_read_index; + desc = hv_get_ring_buffer(rbi) + rbi->priv_read_index; + if (desc) + prefetch((char *)desc + (desc->len8 << 3)); + + return desc; } EXPORT_SYMBOL_GPL(hv_pkt_iter_first); -- cgit v1.2.3 From 2dee584bc9e3c75afc2c85f107e516c58a8efaf3 Mon Sep 17 00:00:00 2001 From: Patrick Venture Date: Thu, 6 Jul 2017 10:03:46 -0700 Subject: drivers/misc: (aspeed-lpc-snoop): Add ast2400 to compat This driver can be used on the aspeed ast2400 with minor modifications. Tested: ast2400 on quanta-q71l Signed-off-by: Patrick Venture Signed-off-by: Greg Kroah-Hartman --- drivers/misc/aspeed-lpc-snoop.c | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/aspeed-lpc-snoop.c b/drivers/misc/aspeed-lpc-snoop.c index 593905565b74..cb78c98bc78d 100644 --- a/drivers/misc/aspeed-lpc-snoop.c +++ b/drivers/misc/aspeed-lpc-snoop.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -51,6 +52,13 @@ #define HICRB_ENSNP0D BIT(14) #define HICRB_ENSNP1D BIT(15) +struct aspeed_lpc_snoop_model_data { + /* The ast2400 has bits 14 and 15 as reserved, whereas the ast2500 + * can use them. + */ + unsigned int has_hicrb_ensnp; +}; + struct aspeed_lpc_snoop { struct regmap *regmap; int irq; @@ -123,10 +131,13 @@ static int aspeed_lpc_snoop_config_irq(struct aspeed_lpc_snoop *lpc_snoop, } static int aspeed_lpc_enable_snoop(struct aspeed_lpc_snoop *lpc_snoop, - int channel, u16 lpc_port) + struct device *dev, + int channel, u16 lpc_port) { int rc = 0; u32 hicr5_en, snpwadr_mask, snpwadr_shift, hicrb_en; + const struct aspeed_lpc_snoop_model_data *model_data = + of_device_get_match_data(dev); /* Create FIFO datastructure */ rc = kfifo_alloc(&lpc_snoop->snoop_fifo[channel], @@ -155,7 +166,9 @@ static int aspeed_lpc_enable_snoop(struct aspeed_lpc_snoop *lpc_snoop, regmap_update_bits(lpc_snoop->regmap, HICR5, hicr5_en, hicr5_en); regmap_update_bits(lpc_snoop->regmap, SNPWADR, snpwadr_mask, lpc_port << snpwadr_shift); - regmap_update_bits(lpc_snoop->regmap, HICRB, hicrb_en, hicrb_en); + if (model_data->has_hicrb_ensnp) + regmap_update_bits(lpc_snoop->regmap, HICRB, + hicrb_en, hicrb_en); return rc; } @@ -213,14 +226,14 @@ static int aspeed_lpc_snoop_probe(struct platform_device *pdev) if (rc) return rc; - rc = aspeed_lpc_enable_snoop(lpc_snoop, 0, port); + rc = aspeed_lpc_enable_snoop(lpc_snoop, dev, 0, port); if (rc) return rc; /* Configuration of 2nd snoop channel port is optional */ if (of_property_read_u32_index(dev->of_node, "snoop-ports", 1, &port) == 0) { - rc = aspeed_lpc_enable_snoop(lpc_snoop, 1, port); + rc = aspeed_lpc_enable_snoop(lpc_snoop, dev, 1, port); if (rc) aspeed_lpc_disable_snoop(lpc_snoop, 0); } @@ -239,8 +252,19 @@ static int aspeed_lpc_snoop_remove(struct platform_device *pdev) return 0; } +static const struct aspeed_lpc_snoop_model_data ast2400_model_data = { + .has_hicrb_ensnp = 0, +}; + +static const struct aspeed_lpc_snoop_model_data ast2500_model_data = { + .has_hicrb_ensnp = 1, +}; + static const struct of_device_id aspeed_lpc_snoop_match[] = { - { .compatible = "aspeed,ast2500-lpc-snoop" }, + { .compatible = "aspeed,ast2400-lpc-snoop", + .data = &ast2400_model_data }, + { .compatible = "aspeed,ast2500-lpc-snoop", + .data = &ast2500_model_data }, { }, }; -- cgit v1.2.3 From caa97be1a2052f2dfc026c3fe5ef62f620782f24 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 10 Jul 2017 16:08:32 +0100 Subject: char/mwave: make some arrays static const to make object code smaller Don't populate arrays on the stack but make them static. Makes the object code smaller. Also remove temporary variables that have hard coded array sizes and just use ARRAY_SIZE instead and wrap some lines that are wider than 80 chars to clean up some checkpatch warnings. Before: text data bss dec hex filename 11141 2008 64 13213 339d drivers/char/mwave/smapi.o After: text data bss dec hex filename 10697 2352 64 13113 3339 drivers/char/mwave/smapi.o Signed-off-by: Colin Ian King Acked-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/char/mwave/smapi.c | 48 ++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/char/mwave/smapi.c b/drivers/char/mwave/smapi.c index 8c5411a8f33f..691f5898bb32 100644 --- a/drivers/char/mwave/smapi.c +++ b/drivers/char/mwave/smapi.c @@ -128,10 +128,11 @@ int smapi_query_DSP_cfg(SMAPI_DSP_SETTINGS * pSettings) { int bRC = -EIO; unsigned short usAX, usBX, usCX, usDX, usDI, usSI; - unsigned short ausDspBases[] = { 0x0030, 0x4E30, 0x8E30, 0xCE30, 0x0130, 0x0350, 0x0070, 0x0DB0 }; - unsigned short ausUartBases[] = { 0x03F8, 0x02F8, 0x03E8, 0x02E8 }; - unsigned short numDspBases = 8; - unsigned short numUartBases = 4; + static const unsigned short ausDspBases[] = { + 0x0030, 0x4E30, 0x8E30, 0xCE30, + 0x0130, 0x0350, 0x0070, 0x0DB0 }; + static const unsigned short ausUartBases[] = { + 0x03F8, 0x02F8, 0x03E8, 0x02E8 }; PRINTK_1(TRACE_SMAPI, "smapi::smapi_query_DSP_cfg entry\n"); @@ -148,7 +149,7 @@ int smapi_query_DSP_cfg(SMAPI_DSP_SETTINGS * pSettings) pSettings->bDSPEnabled = ((usCX & 0x0001) != 0); pSettings->usDspIRQ = usSI & 0x00FF; pSettings->usDspDMA = (usSI & 0xFF00) >> 8; - if ((usDI & 0x00FF) < numDspBases) { + if ((usDI & 0x00FF) < ARRAY_SIZE(ausDspBases)) { pSettings->usDspBaseIO = ausDspBases[usDI & 0x00FF]; } else { pSettings->usDspBaseIO = 0; @@ -176,7 +177,7 @@ int smapi_query_DSP_cfg(SMAPI_DSP_SETTINGS * pSettings) pSettings->bModemEnabled = ((usCX & 0x0001) != 0); pSettings->usUartIRQ = usSI & 0x000F; - if (((usSI & 0xFF00) >> 8) < numUartBases) { + if (((usSI & 0xFF00) >> 8) < ARRAY_SIZE(ausUartBases)) { pSettings->usUartBaseIO = ausUartBases[(usSI & 0xFF00) >> 8]; } else { pSettings->usUartBaseIO = 0; @@ -205,15 +206,16 @@ int smapi_set_DSP_cfg(void) int bRC = -EIO; int i; unsigned short usAX, usBX, usCX, usDX, usDI, usSI; - unsigned short ausDspBases[] = { 0x0030, 0x4E30, 0x8E30, 0xCE30, 0x0130, 0x0350, 0x0070, 0x0DB0 }; - unsigned short ausUartBases[] = { 0x03F8, 0x02F8, 0x03E8, 0x02E8 }; - unsigned short ausDspIrqs[] = { 5, 7, 10, 11, 15 }; - unsigned short ausUartIrqs[] = { 3, 4 }; - - unsigned short numDspBases = 8; - unsigned short numUartBases = 4; - unsigned short numDspIrqs = 5; - unsigned short numUartIrqs = 2; + static const unsigned short ausDspBases[] = { + 0x0030, 0x4E30, 0x8E30, 0xCE30, + 0x0130, 0x0350, 0x0070, 0x0DB0 }; + static const unsigned short ausUartBases[] = { + 0x03F8, 0x02F8, 0x03E8, 0x02E8 }; + static const unsigned short ausDspIrqs[] = { + 5, 7, 10, 11, 15 }; + static const unsigned short ausUartIrqs[] = { + 3, 4 }; + unsigned short dspio_index = 0, uartio_index = 0; PRINTK_5(TRACE_SMAPI, @@ -221,11 +223,11 @@ int smapi_set_DSP_cfg(void) mwave_3780i_irq, mwave_3780i_io, mwave_uart_irq, mwave_uart_io); if (mwave_3780i_io) { - for (i = 0; i < numDspBases; i++) { + for (i = 0; i < ARRAY_SIZE(ausDspBases); i++) { if (mwave_3780i_io == ausDspBases[i]) break; } - if (i == numDspBases) { + if (i == ARRAY_SIZE(ausDspBases)) { PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_set_DSP_cfg: Error: Invalid mwave_3780i_io address %x. Aborting.\n", mwave_3780i_io); return bRC; } @@ -233,22 +235,22 @@ int smapi_set_DSP_cfg(void) } if (mwave_3780i_irq) { - for (i = 0; i < numDspIrqs; i++) { + for (i = 0; i < ARRAY_SIZE(ausDspIrqs); i++) { if (mwave_3780i_irq == ausDspIrqs[i]) break; } - if (i == numDspIrqs) { + if (i == ARRAY_SIZE(ausDspIrqs)) { PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_set_DSP_cfg: Error: Invalid mwave_3780i_irq %x. Aborting.\n", mwave_3780i_irq); return bRC; } } if (mwave_uart_io) { - for (i = 0; i < numUartBases; i++) { + for (i = 0; i < ARRAY_SIZE(ausUartBases); i++) { if (mwave_uart_io == ausUartBases[i]) break; } - if (i == numUartBases) { + if (i == ARRAY_SIZE(ausUartBases)) { PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_set_DSP_cfg: Error: Invalid mwave_uart_io address %x. Aborting.\n", mwave_uart_io); return bRC; } @@ -257,11 +259,11 @@ int smapi_set_DSP_cfg(void) if (mwave_uart_irq) { - for (i = 0; i < numUartIrqs; i++) { + for (i = 0; i < ARRAY_SIZE(ausUartIrqs); i++) { if (mwave_uart_irq == ausUartIrqs[i]) break; } - if (i == numUartIrqs) { + if (i == ARRAY_SIZE(ausUartIrqs)) { PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_set_DSP_cfg: Error: Invalid mwave_uart_irq %x. Aborting.\n", mwave_uart_irq); return bRC; } -- cgit v1.2.3 From 7b948f1377322b0b95feee62e307b6889a09e4ea Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Fri, 14 Jul 2017 22:04:49 +0530 Subject: auxdisplay: constify charlcd_ops. charlcd_ops are not supposed to change at runtime. All functions working with charlcd_ops provided by work with const charlcd_ops. So mark the non-const structs as const. File size before: text data bss dec hex filename 12750 560 362 13672 3568 drivers/auxdisplay/panel.o File size After adding 'const': text data bss dec hex filename 12942 368 362 13672 3568 drivers/auxdisplay/panel.o Signed-off-by: Arvind Yadav Reviewed-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/auxdisplay/panel.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c index 7a8b8fb2f572..df126dcdaf18 100644 --- a/drivers/auxdisplay/panel.c +++ b/drivers/auxdisplay/panel.c @@ -877,21 +877,21 @@ static void lcd_clear_fast_tilcd(struct charlcd *charlcd) spin_unlock_irq(&pprt_lock); } -static struct charlcd_ops charlcd_serial_ops = { +static const struct charlcd_ops charlcd_serial_ops = { .write_cmd = lcd_write_cmd_s, .write_data = lcd_write_data_s, .clear_fast = lcd_clear_fast_s, .backlight = lcd_backlight, }; -static struct charlcd_ops charlcd_parallel_ops = { +static const struct charlcd_ops charlcd_parallel_ops = { .write_cmd = lcd_write_cmd_p8, .write_data = lcd_write_data_p8, .clear_fast = lcd_clear_fast_p8, .backlight = lcd_backlight, }; -static struct charlcd_ops charlcd_tilcd_ops = { +static const struct charlcd_ops charlcd_tilcd_ops = { .write_cmd = lcd_write_cmd_tilcd, .write_data = lcd_write_data_tilcd, .clear_fast = lcd_clear_fast_tilcd, -- cgit v1.2.3 From ba8848d415c92cfc7bbc56e2c9d4cac4e92a4a90 Mon Sep 17 00:00:00 2001 From: Guoqing Jiang Date: Fri, 14 Jul 2017 17:06:15 +0800 Subject: ppdev: remove unused ROUND_UP macro This macro is not used after commit 3b9ab374a1e6 ("ppdev: convert to y2038 safe"), so let's remove it. Signed-off-by: Guoqing Jiang Signed-off-by: Greg Kroah-Hartman --- drivers/char/ppdev.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index 3e73bcdf9e65..d256110ba672 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -101,9 +101,6 @@ static DEFINE_IDA(ida_index); #define PP_BUFFER_SIZE 1024 #define PARDEVICE_MAX 8 -/* ROUND_UP macro from fs/select.c */ -#define ROUND_UP(x,y) (((x)+(y)-1)/(y)) - static DEFINE_MUTEX(pp_do_mutex); /* define fixed sized ioctl cmd for y2038 migration */ -- cgit v1.2.3 From 50fa0285955899c1678c5ee47fc69dc56d17b107 Mon Sep 17 00:00:00 2001 From: Vincent Legoll Date: Wed, 14 Jun 2017 10:36:26 -0500 Subject: Make FPGA a menuconfig to ease disabling it all No need to get into the submenu to disable all FPGA-related config entries Signed-off-by: Vincent Legoll Acked-by: Moritz Fischer Signed-off-by: Alan Tull Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/Kconfig | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index 161ba9dccede..10361902c830 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -2,9 +2,7 @@ # FPGA framework configuration # -menu "FPGA Configuration Support" - -config FPGA +menuconfig FPGA tristate "FPGA Configuration Framework" help Say Y here if you want support for configuring FPGAs from the @@ -106,5 +104,3 @@ config XILINX_PR_DECOUPLER being reprogrammed during partial reconfig. endif # FPGA - -endmenu -- cgit v1.2.3 From 5692fae0742df7587189174b1cba364d22846c85 Mon Sep 17 00:00:00 2001 From: Joshua Clayton Date: Wed, 14 Jun 2017 10:36:29 -0500 Subject: fpga manager: Add altera-ps-spi driver for Altera FPGAs altera-ps-spi loads FPGA firmware over SPI, using the "passive serial" interface on Altera Arria 10, Cyclone V or Stratix V FPGAs. This is one of the simpler ways to set up an FPGA at runtime. The signal interface is close to unidirectional SPI with lsb first. Signed-off-by: Joshua Clayton Signed-off-by: Anatolij Gustschin Signed-off-by: Alan Tull Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/Kconfig | 7 + drivers/fpga/Makefile | 1 + drivers/fpga/altera-ps-spi.c | 297 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 305 insertions(+) create mode 100644 drivers/fpga/altera-ps-spi.c (limited to 'drivers') diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index 10361902c830..e0e2d6db669f 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -24,6 +24,13 @@ config FPGA_MGR_ICE40_SPI help FPGA manager driver support for Lattice iCE40 FPGAs over SPI. +config FPGA_MGR_ALTERA_PS_SPI + tristate "Altera FPGA Passive Serial over SPI" + depends on SPI + help + FPGA manager driver support for Altera Arria/Cyclone/Stratix + using the passive serial interface over SPI. + config FPGA_MGR_SOCFPGA tristate "Altera SOCFPGA FPGA Manager" depends on ARCH_SOCFPGA || COMPILE_TEST diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile index 2a4f0218145c..e75d3570e26a 100644 --- a/drivers/fpga/Makefile +++ b/drivers/fpga/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_FPGA) += fpga-mgr.o # FPGA Manager Drivers +obj-$(CONFIG_FPGA_MGR_ALTERA_PS_SPI) += altera-ps-spi.o obj-$(CONFIG_FPGA_MGR_ICE40_SPI) += ice40-spi.o obj-$(CONFIG_FPGA_MGR_SOCFPGA) += socfpga.o obj-$(CONFIG_FPGA_MGR_SOCFPGA_A10) += socfpga-a10.o diff --git a/drivers/fpga/altera-ps-spi.c b/drivers/fpga/altera-ps-spi.c new file mode 100644 index 000000000000..0db8def668ed --- /dev/null +++ b/drivers/fpga/altera-ps-spi.c @@ -0,0 +1,297 @@ +/* + * Altera Passive Serial SPI Driver + * + * Copyright (c) 2017 United Western Technologies, Corporation + * + * Joshua Clayton + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * Manage Altera FPGA firmware that is loaded over SPI using the passive + * serial configuration method. + * Firmware must be in binary "rbf" format. + * Works on Arria 10, Cyclone V and Stratix V. Should work on Cyclone series. + * May work on other Altera FPGAs. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum altera_ps_devtype { + CYCLONE5, + ARRIA10, +}; + +struct altera_ps_data { + enum altera_ps_devtype devtype; + int status_wait_min_us; + int status_wait_max_us; + int t_cfg_us; + int t_st2ck_us; +}; + +struct altera_ps_conf { + struct gpio_desc *config; + struct gpio_desc *confd; + struct gpio_desc *status; + struct spi_device *spi; + const struct altera_ps_data *data; + u32 info_flags; + char mgr_name[64]; +}; + +/* | Arria 10 | Cyclone5 | Stratix5 | + * t_CF2ST0 | [; 600] | [; 600] | [; 600] |ns + * t_CFG | [2;] | [2;] | [2;] |µs + * t_STATUS | [268; 3000] | [268; 1506] | [268; 1506] |µs + * t_CF2ST1 | [; 3000] | [; 1506] | [; 1506] |µs + * t_CF2CK | [3010;] | [1506;] | [1506;] |µs + * t_ST2CK | [10;] | [2;] | [2;] |µs + * t_CD2UM | [175; 830] | [175; 437] | [175; 437] |µs + */ +static struct altera_ps_data c5_data = { + /* these values for Cyclone5 are compatible with Stratix5 */ + .devtype = CYCLONE5, + .status_wait_min_us = 268, + .status_wait_max_us = 1506, + .t_cfg_us = 2, + .t_st2ck_us = 2, +}; + +static struct altera_ps_data a10_data = { + .devtype = ARRIA10, + .status_wait_min_us = 268, /* min(t_STATUS) */ + .status_wait_max_us = 3000, /* max(t_CF2ST1) */ + .t_cfg_us = 2, /* max { min(t_CFG), max(tCF2ST0) } */ + .t_st2ck_us = 10, /* min(t_ST2CK) */ +}; + +static const struct of_device_id of_ef_match[] = { + { .compatible = "altr,fpga-passive-serial", .data = &c5_data }, + { .compatible = "altr,fpga-arria10-passive-serial", .data = &a10_data }, + {} +}; +MODULE_DEVICE_TABLE(of, of_ef_match); + +static enum fpga_mgr_states altera_ps_state(struct fpga_manager *mgr) +{ + struct altera_ps_conf *conf = mgr->priv; + + if (gpiod_get_value_cansleep(conf->status)) + return FPGA_MGR_STATE_RESET; + + return FPGA_MGR_STATE_UNKNOWN; +} + +static inline void altera_ps_delay(int delay_us) +{ + if (delay_us > 10) + usleep_range(delay_us, delay_us + 5); + else + udelay(delay_us); +} + +static int altera_ps_write_init(struct fpga_manager *mgr, + struct fpga_image_info *info, + const char *buf, size_t count) +{ + struct altera_ps_conf *conf = mgr->priv; + int min, max, waits; + int i; + + conf->info_flags = info->flags; + + if (info->flags & FPGA_MGR_PARTIAL_RECONFIG) { + dev_err(&mgr->dev, "Partial reconfiguration not supported.\n"); + return -EINVAL; + } + + gpiod_set_value_cansleep(conf->config, 1); + + /* wait min reset pulse time */ + altera_ps_delay(conf->data->t_cfg_us); + + if (!gpiod_get_value_cansleep(conf->status)) { + dev_err(&mgr->dev, "Status pin failed to show a reset\n"); + return -EIO; + } + + gpiod_set_value_cansleep(conf->config, 0); + + min = conf->data->status_wait_min_us; + max = conf->data->status_wait_max_us; + waits = max / min; + if (max % min) + waits++; + + /* wait for max { max(t_STATUS), max(t_CF2ST1) } */ + for (i = 0; i < waits; i++) { + usleep_range(min, min + 10); + if (!gpiod_get_value_cansleep(conf->status)) { + /* wait for min(t_ST2CK)*/ + altera_ps_delay(conf->data->t_st2ck_us); + return 0; + } + } + + dev_err(&mgr->dev, "Status pin not ready.\n"); + return -EIO; +} + +static void rev_buf(char *buf, size_t len) +{ + const char *fw_end = (buf + len); + + /* set buffer to lsb first */ + while (buf < fw_end) { + *buf = bitrev8(*buf); + buf++; + } +} + +static int altera_ps_write(struct fpga_manager *mgr, const char *buf, + size_t count) +{ + struct altera_ps_conf *conf = mgr->priv; + const char *fw_data = buf; + const char *fw_data_end = fw_data + count; + + while (fw_data < fw_data_end) { + int ret; + size_t stride = min_t(size_t, fw_data_end - fw_data, SZ_4K); + + if (!(conf->info_flags & FPGA_MGR_BITSTREAM_LSB_FIRST)) + rev_buf((char *)fw_data, stride); + + ret = spi_write(conf->spi, fw_data, stride); + if (ret) { + dev_err(&mgr->dev, "spi error in firmware write: %d\n", + ret); + return ret; + } + fw_data += stride; + } + + return 0; +} + +static int altera_ps_write_complete(struct fpga_manager *mgr, + struct fpga_image_info *info) +{ + struct altera_ps_conf *conf = mgr->priv; + const char dummy[] = {0}; + int ret; + + if (gpiod_get_value_cansleep(conf->status)) { + dev_err(&mgr->dev, "Error during configuration.\n"); + return -EIO; + } + + if (!IS_ERR(conf->confd)) { + if (!gpiod_get_raw_value_cansleep(conf->confd)) { + dev_err(&mgr->dev, "CONF_DONE is inactive!\n"); + return -EIO; + } + } + + /* + * After CONF_DONE goes high, send two additional falling edges on DCLK + * to begin initialization and enter user mode + */ + ret = spi_write(conf->spi, dummy, 1); + if (ret) { + dev_err(&mgr->dev, "spi error during end sequence: %d\n", ret); + return ret; + } + + return 0; +} + +static const struct fpga_manager_ops altera_ps_ops = { + .state = altera_ps_state, + .write_init = altera_ps_write_init, + .write = altera_ps_write, + .write_complete = altera_ps_write_complete, +}; + +static int altera_ps_probe(struct spi_device *spi) +{ + struct altera_ps_conf *conf; + const struct of_device_id *of_id; + + conf = devm_kzalloc(&spi->dev, sizeof(*conf), GFP_KERNEL); + if (!conf) + return -ENOMEM; + + of_id = of_match_device(of_ef_match, &spi->dev); + if (!of_id) + return -ENODEV; + + conf->data = of_id->data; + conf->spi = spi; + conf->config = devm_gpiod_get(&spi->dev, "nconfig", GPIOD_OUT_HIGH); + if (IS_ERR(conf->config)) { + dev_err(&spi->dev, "Failed to get config gpio: %ld\n", + PTR_ERR(conf->config)); + return PTR_ERR(conf->config); + } + + conf->status = devm_gpiod_get(&spi->dev, "nstat", GPIOD_IN); + if (IS_ERR(conf->status)) { + dev_err(&spi->dev, "Failed to get status gpio: %ld\n", + PTR_ERR(conf->status)); + return PTR_ERR(conf->status); + } + + conf->confd = devm_gpiod_get(&spi->dev, "confd", GPIOD_IN); + if (IS_ERR(conf->confd)) { + dev_warn(&spi->dev, "Not using confd gpio: %ld\n", + PTR_ERR(conf->confd)); + } + + /* Register manager with unique name */ + snprintf(conf->mgr_name, sizeof(conf->mgr_name), "%s %s", + dev_driver_string(&spi->dev), dev_name(&spi->dev)); + + return fpga_mgr_register(&spi->dev, conf->mgr_name, + &altera_ps_ops, conf); +} + +static int altera_ps_remove(struct spi_device *spi) +{ + fpga_mgr_unregister(&spi->dev); + + return 0; +} + +static const struct spi_device_id altera_ps_spi_ids[] = { + {"cyclone-ps-spi", 0}, + {} +}; +MODULE_DEVICE_TABLE(spi, altera_ps_spi_ids); + +static struct spi_driver altera_ps_driver = { + .driver = { + .name = "altera-ps-spi", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(of_ef_match), + }, + .id_table = altera_ps_spi_ids, + .probe = altera_ps_probe, + .remove = altera_ps_remove, +}; + +module_spi_driver(altera_ps_driver) + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Joshua Clayton "); +MODULE_DESCRIPTION("Module to load Altera FPGA firmware over SPI"); -- cgit v1.2.3 From fcfe18f885f6a2a7e906546fe709fccfda73a4b1 Mon Sep 17 00:00:00 2001 From: Joshua Clayton Date: Wed, 14 Jun 2017 10:36:32 -0500 Subject: fpga-manager: altera-ps-spi: use bitrev8x4 Speed up bit reversal by using hardware bit reversal Add extra code to handle less than 4byte remnants, if any Signed-off-by: Joshua Clayton Signed-off-by: Alan Tull Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/altera-ps-spi.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/fpga/altera-ps-spi.c b/drivers/fpga/altera-ps-spi.c index 0db8def668ed..14f14efdf0d5 100644 --- a/drivers/fpga/altera-ps-spi.c +++ b/drivers/fpga/altera-ps-spi.c @@ -149,12 +149,23 @@ static int altera_ps_write_init(struct fpga_manager *mgr, static void rev_buf(char *buf, size_t len) { - const char *fw_end = (buf + len); + u32 *fw32 = (u32 *)buf; + size_t extra_bytes = (len & 0x03); + const u32 *fw_end = (u32 *)(buf + len - extra_bytes); /* set buffer to lsb first */ - while (buf < fw_end) { - *buf = bitrev8(*buf); - buf++; + while (fw32 < fw_end) { + *fw32 = bitrev8x4(*fw32); + fw32++; + } + + if (extra_bytes) { + buf = (char *)fw_end; + while (extra_bytes) { + *buf = bitrev8(*buf); + buf++; + extra_bytes--; + } } } -- cgit v1.2.3 From 34d1dc17ce978ae76e676d401b48fe9d004aa948 Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Wed, 14 Jun 2017 10:36:35 -0500 Subject: fpga manager: Add Altera CvP driver Add FPGA manager driver for loading Arria-V/Cyclone-V/Stratix-V and Arria-10 FPGAs via CvP. Signed-off-by: Anatolij Gustschin Reviewed-by: Andy Shevchenko Signed-off-by: Alan Tull Signed-off-by: Greg Kroah-Hartman --- Documentation/ABI/testing/sysfs-driver-altera-cvp | 8 + drivers/fpga/Kconfig | 7 + drivers/fpga/Makefile | 1 + drivers/fpga/altera-cvp.c | 500 ++++++++++++++++++++++ 4 files changed, 516 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-driver-altera-cvp create mode 100644 drivers/fpga/altera-cvp.c (limited to 'drivers') diff --git a/Documentation/ABI/testing/sysfs-driver-altera-cvp b/Documentation/ABI/testing/sysfs-driver-altera-cvp new file mode 100644 index 000000000000..8cde64a71edb --- /dev/null +++ b/Documentation/ABI/testing/sysfs-driver-altera-cvp @@ -0,0 +1,8 @@ +What: /sys/bus/pci/drivers/altera-cvp/chkcfg +Date: May 2017 +Kernel Version: 4.13 +Contact: Anatolij Gustschin +Description: + Contains either 1 or 0 and controls if configuration + error checking in altera-cvp driver is turned on or + off. diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index e0e2d6db669f..ad5448f718b3 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -24,6 +24,13 @@ config FPGA_MGR_ICE40_SPI help FPGA manager driver support for Lattice iCE40 FPGAs over SPI. +config FPGA_MGR_ALTERA_CVP + tristate "Altera Arria-V/Cyclone-V/Stratix-V CvP FPGA Manager" + depends on PCI + help + FPGA manager driver support for Arria-V, Cyclone-V, Stratix-V + and Arria 10 Altera FPGAs using the CvP interface over PCIe. + config FPGA_MGR_ALTERA_PS_SPI tristate "Altera FPGA Passive Serial over SPI" depends on SPI diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile index e75d3570e26a..e09895f0525b 100644 --- a/drivers/fpga/Makefile +++ b/drivers/fpga/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_FPGA) += fpga-mgr.o # FPGA Manager Drivers +obj-$(CONFIG_FPGA_MGR_ALTERA_CVP) += altera-cvp.o obj-$(CONFIG_FPGA_MGR_ALTERA_PS_SPI) += altera-ps-spi.o obj-$(CONFIG_FPGA_MGR_ICE40_SPI) += ice40-spi.o obj-$(CONFIG_FPGA_MGR_SOCFPGA) += socfpga.o diff --git a/drivers/fpga/altera-cvp.c b/drivers/fpga/altera-cvp.c new file mode 100644 index 000000000000..08629ee69d11 --- /dev/null +++ b/drivers/fpga/altera-cvp.c @@ -0,0 +1,500 @@ +/* + * FPGA Manager Driver for Altera Arria/Cyclone/Stratix CvP + * + * Copyright (C) 2017 DENX Software Engineering + * + * Anatolij Gustschin + * + * 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; version 2 of the License. + * + * 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. + * + * Manage Altera FPGA firmware using PCIe CvP. + * Firmware must be in binary "rbf" format. + */ + +#include +#include +#include +#include +#include +#include + +#define CVP_BAR 0 /* BAR used for data transfer in memory mode */ +#define CVP_DUMMY_WR 244 /* dummy writes to clear CvP state machine */ +#define TIMEOUT_US 2000 /* CVP STATUS timeout for USERMODE polling */ + +/* Vendor Specific Extended Capability Registers */ +#define VSE_PCIE_EXT_CAP_ID 0x200 +#define VSE_PCIE_EXT_CAP_ID_VAL 0x000b /* 16bit */ + +#define VSE_CVP_STATUS 0x21c /* 32bit */ +#define VSE_CVP_STATUS_CFG_RDY BIT(18) /* CVP_CONFIG_READY */ +#define VSE_CVP_STATUS_CFG_ERR BIT(19) /* CVP_CONFIG_ERROR */ +#define VSE_CVP_STATUS_CVP_EN BIT(20) /* ctrl block is enabling CVP */ +#define VSE_CVP_STATUS_USERMODE BIT(21) /* USERMODE */ +#define VSE_CVP_STATUS_CFG_DONE BIT(23) /* CVP_CONFIG_DONE */ +#define VSE_CVP_STATUS_PLD_CLK_IN_USE BIT(24) /* PLD_CLK_IN_USE */ + +#define VSE_CVP_MODE_CTRL 0x220 /* 32bit */ +#define VSE_CVP_MODE_CTRL_CVP_MODE BIT(0) /* CVP (1) or normal mode (0) */ +#define VSE_CVP_MODE_CTRL_HIP_CLK_SEL BIT(1) /* PMA (1) or fabric clock (0) */ +#define VSE_CVP_MODE_CTRL_NUMCLKS_OFF 8 /* NUMCLKS bits offset */ +#define VSE_CVP_MODE_CTRL_NUMCLKS_MASK GENMASK(15, 8) + +#define VSE_CVP_DATA 0x228 /* 32bit */ +#define VSE_CVP_PROG_CTRL 0x22c /* 32bit */ +#define VSE_CVP_PROG_CTRL_CONFIG BIT(0) +#define VSE_CVP_PROG_CTRL_START_XFER BIT(1) + +#define VSE_UNCOR_ERR_STATUS 0x234 /* 32bit */ +#define VSE_UNCOR_ERR_CVP_CFG_ERR BIT(5) /* CVP_CONFIG_ERROR_LATCHED */ + +#define DRV_NAME "altera-cvp" +#define ALTERA_CVP_MGR_NAME "Altera CvP FPGA Manager" + +/* Optional CvP config error status check for debugging */ +static bool altera_cvp_chkcfg; + +struct altera_cvp_conf { + struct fpga_manager *mgr; + struct pci_dev *pci_dev; + void __iomem *map; + void (*write_data)(struct altera_cvp_conf *, u32); + char mgr_name[64]; + u8 numclks; +}; + +static enum fpga_mgr_states altera_cvp_state(struct fpga_manager *mgr) +{ + struct altera_cvp_conf *conf = mgr->priv; + u32 status; + + pci_read_config_dword(conf->pci_dev, VSE_CVP_STATUS, &status); + + if (status & VSE_CVP_STATUS_CFG_DONE) + return FPGA_MGR_STATE_OPERATING; + + if (status & VSE_CVP_STATUS_CVP_EN) + return FPGA_MGR_STATE_POWER_UP; + + return FPGA_MGR_STATE_UNKNOWN; +} + +static void altera_cvp_write_data_iomem(struct altera_cvp_conf *conf, u32 val) +{ + writel(val, conf->map); +} + +static void altera_cvp_write_data_config(struct altera_cvp_conf *conf, u32 val) +{ + pci_write_config_dword(conf->pci_dev, VSE_CVP_DATA, val); +} + +/* switches between CvP clock and internal clock */ +static void altera_cvp_dummy_write(struct altera_cvp_conf *conf) +{ + unsigned int i; + u32 val; + + /* set 1 CVP clock cycle for every CVP Data Register Write */ + pci_read_config_dword(conf->pci_dev, VSE_CVP_MODE_CTRL, &val); + val &= ~VSE_CVP_MODE_CTRL_NUMCLKS_MASK; + val |= 1 << VSE_CVP_MODE_CTRL_NUMCLKS_OFF; + pci_write_config_dword(conf->pci_dev, VSE_CVP_MODE_CTRL, val); + + for (i = 0; i < CVP_DUMMY_WR; i++) + conf->write_data(conf, 0); /* dummy data, could be any value */ +} + +static int altera_cvp_wait_status(struct altera_cvp_conf *conf, u32 status_mask, + u32 status_val, int timeout_us) +{ + unsigned int retries; + u32 val; + + retries = timeout_us / 10; + if (timeout_us % 10) + retries++; + + do { + pci_read_config_dword(conf->pci_dev, VSE_CVP_STATUS, &val); + if ((val & status_mask) == status_val) + return 0; + + /* use small usleep value to re-check and break early */ + usleep_range(10, 11); + } while (--retries); + + return -ETIMEDOUT; +} + +static int altera_cvp_teardown(struct fpga_manager *mgr, + struct fpga_image_info *info) +{ + struct altera_cvp_conf *conf = mgr->priv; + struct pci_dev *pdev = conf->pci_dev; + int ret; + u32 val; + + /* STEP 12 - reset START_XFER bit */ + pci_read_config_dword(pdev, VSE_CVP_PROG_CTRL, &val); + val &= ~VSE_CVP_PROG_CTRL_START_XFER; + pci_write_config_dword(pdev, VSE_CVP_PROG_CTRL, val); + + /* STEP 13 - reset CVP_CONFIG bit */ + val &= ~VSE_CVP_PROG_CTRL_CONFIG; + pci_write_config_dword(pdev, VSE_CVP_PROG_CTRL, val); + + /* + * STEP 14 + * - set CVP_NUMCLKS to 1 and then issue CVP_DUMMY_WR dummy + * writes to the HIP + */ + altera_cvp_dummy_write(conf); /* from CVP clock to internal clock */ + + /* STEP 15 - poll CVP_CONFIG_READY bit for 0 with 10us timeout */ + ret = altera_cvp_wait_status(conf, VSE_CVP_STATUS_CFG_RDY, 0, 10); + if (ret) + dev_err(&mgr->dev, "CFG_RDY == 0 timeout\n"); + + return ret; +} + +static int altera_cvp_write_init(struct fpga_manager *mgr, + struct fpga_image_info *info, + const char *buf, size_t count) +{ + struct altera_cvp_conf *conf = mgr->priv; + struct pci_dev *pdev = conf->pci_dev; + u32 iflags, val; + int ret; + + iflags = info ? info->flags : 0; + + if (iflags & FPGA_MGR_PARTIAL_RECONFIG) { + dev_err(&mgr->dev, "Partial reconfiguration not supported.\n"); + return -EINVAL; + } + + /* Determine allowed clock to data ratio */ + if (iflags & FPGA_MGR_COMPRESSED_BITSTREAM) + conf->numclks = 8; /* ratio for all compressed images */ + else if (iflags & FPGA_MGR_ENCRYPTED_BITSTREAM) + conf->numclks = 4; /* for uncompressed and encrypted images */ + else + conf->numclks = 1; /* for uncompressed and unencrypted images */ + + /* STEP 1 - read CVP status and check CVP_EN flag */ + pci_read_config_dword(pdev, VSE_CVP_STATUS, &val); + if (!(val & VSE_CVP_STATUS_CVP_EN)) { + dev_err(&mgr->dev, "CVP mode off: 0x%04x\n", val); + return -ENODEV; + } + + if (val & VSE_CVP_STATUS_CFG_RDY) { + dev_warn(&mgr->dev, "CvP already started, teardown first\n"); + ret = altera_cvp_teardown(mgr, info); + if (ret) + return ret; + } + + /* + * STEP 2 + * - set HIP_CLK_SEL and CVP_MODE (must be set in the order mentioned) + */ + /* switch from fabric to PMA clock */ + pci_read_config_dword(pdev, VSE_CVP_MODE_CTRL, &val); + val |= VSE_CVP_MODE_CTRL_HIP_CLK_SEL; + pci_write_config_dword(pdev, VSE_CVP_MODE_CTRL, val); + + /* set CVP mode */ + pci_read_config_dword(pdev, VSE_CVP_MODE_CTRL, &val); + val |= VSE_CVP_MODE_CTRL_CVP_MODE; + pci_write_config_dword(pdev, VSE_CVP_MODE_CTRL, val); + + /* + * STEP 3 + * - set CVP_NUMCLKS to 1 and issue CVP_DUMMY_WR dummy writes to the HIP + */ + altera_cvp_dummy_write(conf); + + /* STEP 4 - set CVP_CONFIG bit */ + pci_read_config_dword(pdev, VSE_CVP_PROG_CTRL, &val); + /* request control block to begin transfer using CVP */ + val |= VSE_CVP_PROG_CTRL_CONFIG; + pci_write_config_dword(pdev, VSE_CVP_PROG_CTRL, val); + + /* STEP 5 - poll CVP_CONFIG READY for 1 with 10us timeout */ + ret = altera_cvp_wait_status(conf, VSE_CVP_STATUS_CFG_RDY, + VSE_CVP_STATUS_CFG_RDY, 10); + if (ret) { + dev_warn(&mgr->dev, "CFG_RDY == 1 timeout\n"); + return ret; + } + + /* + * STEP 6 + * - set CVP_NUMCLKS to 1 and issue CVP_DUMMY_WR dummy writes to the HIP + */ + altera_cvp_dummy_write(conf); + + /* STEP 7 - set START_XFER */ + pci_read_config_dword(pdev, VSE_CVP_PROG_CTRL, &val); + val |= VSE_CVP_PROG_CTRL_START_XFER; + pci_write_config_dword(pdev, VSE_CVP_PROG_CTRL, val); + + /* STEP 8 - start transfer (set CVP_NUMCLKS for bitstream) */ + pci_read_config_dword(pdev, VSE_CVP_MODE_CTRL, &val); + val &= ~VSE_CVP_MODE_CTRL_NUMCLKS_MASK; + val |= conf->numclks << VSE_CVP_MODE_CTRL_NUMCLKS_OFF; + pci_write_config_dword(pdev, VSE_CVP_MODE_CTRL, val); + + return 0; +} + +static inline int altera_cvp_chk_error(struct fpga_manager *mgr, size_t bytes) +{ + struct altera_cvp_conf *conf = mgr->priv; + u32 val; + + /* STEP 10 (optional) - check CVP_CONFIG_ERROR flag */ + pci_read_config_dword(conf->pci_dev, VSE_CVP_STATUS, &val); + if (val & VSE_CVP_STATUS_CFG_ERR) { + dev_err(&mgr->dev, "CVP_CONFIG_ERROR after %zu bytes!\n", + bytes); + return -EPROTO; + } + return 0; +} + +static int altera_cvp_write(struct fpga_manager *mgr, const char *buf, + size_t count) +{ + struct altera_cvp_conf *conf = mgr->priv; + const u32 *data; + size_t done, remaining; + int status = 0; + u32 mask; + + /* STEP 9 - write 32-bit data from RBF file to CVP data register */ + data = (u32 *)buf; + remaining = count; + done = 0; + + while (remaining >= 4) { + conf->write_data(conf, *data++); + done += 4; + remaining -= 4; + + /* + * STEP 10 (optional) and STEP 11 + * - check error flag + * - loop until data transfer completed + * Config images can be huge (more than 40 MiB), so + * only check after a new 4k data block has been written. + * This reduces the number of checks and speeds up the + * configuration process. + */ + if (altera_cvp_chkcfg && !(done % SZ_4K)) { + status = altera_cvp_chk_error(mgr, done); + if (status < 0) + return status; + } + } + + /* write up to 3 trailing bytes, if any */ + mask = BIT(remaining * 8) - 1; + if (mask) + conf->write_data(conf, *data & mask); + + if (altera_cvp_chkcfg) + status = altera_cvp_chk_error(mgr, count); + + return status; +} + +static int altera_cvp_write_complete(struct fpga_manager *mgr, + struct fpga_image_info *info) +{ + struct altera_cvp_conf *conf = mgr->priv; + struct pci_dev *pdev = conf->pci_dev; + int ret; + u32 mask; + u32 val; + + ret = altera_cvp_teardown(mgr, info); + if (ret) + return ret; + + /* STEP 16 - check CVP_CONFIG_ERROR_LATCHED bit */ + pci_read_config_dword(pdev, VSE_UNCOR_ERR_STATUS, &val); + if (val & VSE_UNCOR_ERR_CVP_CFG_ERR) { + dev_err(&mgr->dev, "detected CVP_CONFIG_ERROR_LATCHED!\n"); + return -EPROTO; + } + + /* STEP 17 - reset CVP_MODE and HIP_CLK_SEL bit */ + pci_read_config_dword(pdev, VSE_CVP_MODE_CTRL, &val); + val &= ~VSE_CVP_MODE_CTRL_HIP_CLK_SEL; + val &= ~VSE_CVP_MODE_CTRL_CVP_MODE; + pci_write_config_dword(pdev, VSE_CVP_MODE_CTRL, val); + + /* STEP 18 - poll PLD_CLK_IN_USE and USER_MODE bits */ + mask = VSE_CVP_STATUS_PLD_CLK_IN_USE | VSE_CVP_STATUS_USERMODE; + ret = altera_cvp_wait_status(conf, mask, mask, TIMEOUT_US); + if (ret) + dev_err(&mgr->dev, "PLD_CLK_IN_USE|USERMODE timeout\n"); + + return ret; +} + +static const struct fpga_manager_ops altera_cvp_ops = { + .state = altera_cvp_state, + .write_init = altera_cvp_write_init, + .write = altera_cvp_write, + .write_complete = altera_cvp_write_complete, +}; + +static ssize_t show_chkcfg(struct device_driver *dev, char *buf) +{ + return snprintf(buf, 3, "%d\n", altera_cvp_chkcfg); +} + +static ssize_t store_chkcfg(struct device_driver *drv, const char *buf, + size_t count) +{ + int ret; + + ret = kstrtobool(buf, &altera_cvp_chkcfg); + if (ret) + return ret; + + return count; +} + +static DRIVER_ATTR(chkcfg, 0600, show_chkcfg, store_chkcfg); + +static int altera_cvp_probe(struct pci_dev *pdev, + const struct pci_device_id *dev_id); +static void altera_cvp_remove(struct pci_dev *pdev); + +#define PCI_VENDOR_ID_ALTERA 0x1172 + +static struct pci_device_id altera_cvp_id_tbl[] = { + { PCI_VDEVICE(ALTERA, PCI_ANY_ID) }, + { } +}; +MODULE_DEVICE_TABLE(pci, altera_cvp_id_tbl); + +static struct pci_driver altera_cvp_driver = { + .name = DRV_NAME, + .id_table = altera_cvp_id_tbl, + .probe = altera_cvp_probe, + .remove = altera_cvp_remove, +}; + +static int altera_cvp_probe(struct pci_dev *pdev, + const struct pci_device_id *dev_id) +{ + struct altera_cvp_conf *conf; + u16 cmd, val; + int ret; + + /* + * First check if this is the expected FPGA device. PCI config + * space access works without enabling the PCI device, memory + * space access is enabled further down. + */ + pci_read_config_word(pdev, VSE_PCIE_EXT_CAP_ID, &val); + if (val != VSE_PCIE_EXT_CAP_ID_VAL) { + dev_err(&pdev->dev, "Wrong EXT_CAP_ID value 0x%x\n", val); + return -ENODEV; + } + + conf = devm_kzalloc(&pdev->dev, sizeof(*conf), GFP_KERNEL); + if (!conf) + return -ENOMEM; + + /* + * Enable memory BAR access. We cannot use pci_enable_device() here + * because it will make the driver unusable with FPGA devices that + * have additional big IOMEM resources (e.g. 4GiB BARs) on 32-bit + * platform. Such BARs will not have an assigned address range and + * pci_enable_device() will fail, complaining about not claimed BAR, + * even if the concerned BAR is not needed for FPGA configuration + * at all. Thus, enable the device via PCI config space command. + */ + pci_read_config_word(pdev, PCI_COMMAND, &cmd); + if (!(cmd & PCI_COMMAND_MEMORY)) { + cmd |= PCI_COMMAND_MEMORY; + pci_write_config_word(pdev, PCI_COMMAND, cmd); + } + + ret = pci_request_region(pdev, CVP_BAR, "CVP"); + if (ret) { + dev_err(&pdev->dev, "Requesting CVP BAR region failed\n"); + goto err_disable; + } + + conf->pci_dev = pdev; + conf->write_data = altera_cvp_write_data_iomem; + + conf->map = pci_iomap(pdev, CVP_BAR, 0); + if (!conf->map) { + dev_warn(&pdev->dev, "Mapping CVP BAR failed\n"); + conf->write_data = altera_cvp_write_data_config; + } + + snprintf(conf->mgr_name, sizeof(conf->mgr_name), "%s @%s", + ALTERA_CVP_MGR_NAME, pci_name(pdev)); + + ret = fpga_mgr_register(&pdev->dev, conf->mgr_name, + &altera_cvp_ops, conf); + if (ret) + goto err_unmap; + + ret = driver_create_file(&altera_cvp_driver.driver, + &driver_attr_chkcfg); + if (ret) { + dev_err(&pdev->dev, "Can't create sysfs chkcfg file\n"); + fpga_mgr_unregister(&pdev->dev); + goto err_unmap; + } + + return 0; + +err_unmap: + pci_iounmap(pdev, conf->map); + pci_release_region(pdev, CVP_BAR); +err_disable: + cmd &= ~PCI_COMMAND_MEMORY; + pci_write_config_word(pdev, PCI_COMMAND, cmd); + return ret; +} + +static void altera_cvp_remove(struct pci_dev *pdev) +{ + struct fpga_manager *mgr = pci_get_drvdata(pdev); + struct altera_cvp_conf *conf = mgr->priv; + u16 cmd; + + driver_remove_file(&altera_cvp_driver.driver, &driver_attr_chkcfg); + fpga_mgr_unregister(&pdev->dev); + pci_iounmap(pdev, conf->map); + pci_release_region(pdev, CVP_BAR); + pci_read_config_word(pdev, PCI_COMMAND, &cmd); + cmd &= ~PCI_COMMAND_MEMORY; + pci_write_config_word(pdev, PCI_COMMAND, cmd); +} + +module_pci_driver(altera_cvp_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Anatolij Gustschin "); +MODULE_DESCRIPTION("Module to load Altera FPGA over CvP"); -- cgit v1.2.3 From 3eeba1a28e0df150adec37d67b567de653cf285c Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 23 Jun 2017 14:55:30 +0530 Subject: arch_topology: Don't break lines unnecessarily There is no need of line break at few places, avoid them. Signed-off-by: Viresh Kumar Reviewed-by: Juri Lelli Tested-by: Juri Lelli Signed-off-by: Greg Kroah-Hartman --- drivers/base/arch_topology.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index d1c33a85059e..0ad79b5cd56d 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -41,8 +41,7 @@ static ssize_t cpu_capacity_show(struct device *dev, { struct cpu *cpu = container_of(dev, struct cpu, dev); - return sprintf(buf, "%lu\n", - topology_get_cpu_scale(NULL, cpu->dev.id)); + return sprintf(buf, "%lu\n", topology_get_cpu_scale(NULL, cpu->dev.id)); } static ssize_t cpu_capacity_store(struct device *dev, @@ -128,8 +127,7 @@ int __init topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu) if (cap_parsing_failed) return !ret; - ret = of_property_read_u32(cpu_node, - "capacity-dmips-mhz", + ret = of_property_read_u32(cpu_node, "capacity-dmips-mhz", &cpu_capacity); if (!ret) { if (!raw_capacity) { @@ -181,8 +179,7 @@ init_cpu_capacity_callback(struct notifier_block *nb, pr_debug("cpu_capacity: init cpu capacity for CPUs [%*pbl] (to_visit=%*pbl)\n", cpumask_pr_args(policy->related_cpus), cpumask_pr_args(cpus_to_visit)); - cpumask_andnot(cpus_to_visit, - cpus_to_visit, + cpumask_andnot(cpus_to_visit, cpus_to_visit, policy->related_cpus); for_each_cpu(cpu, policy->related_cpus) { raw_capacity[cpu] = topology_get_cpu_scale(NULL, cpu) * -- cgit v1.2.3 From 93a57081d20c1f93c209fec0f247f5bed936cc34 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 23 Jun 2017 14:55:31 +0530 Subject: arch_topology: Convert switch block to if block We only need to take care of one case here (CPUFREQ_NOTIFY) and there is no need to add an extra level of indentation to the case specific code by using a switch block. Use an if block instead. Also add some blank lines to make the code look better. Signed-off-by: Viresh Kumar Reviewed-by: Juri Lelli Tested-by: Juri Lelli Signed-off-by: Greg Kroah-Hartman --- drivers/base/arch_topology.c | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index 0ad79b5cd56d..a3cd7c869c3e 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -174,26 +174,29 @@ init_cpu_capacity_callback(struct notifier_block *nb, if (cap_parsing_failed || cap_parsing_done) return 0; - switch (val) { - case CPUFREQ_NOTIFY: - pr_debug("cpu_capacity: init cpu capacity for CPUs [%*pbl] (to_visit=%*pbl)\n", - cpumask_pr_args(policy->related_cpus), - cpumask_pr_args(cpus_to_visit)); - cpumask_andnot(cpus_to_visit, cpus_to_visit, - policy->related_cpus); - for_each_cpu(cpu, policy->related_cpus) { - raw_capacity[cpu] = topology_get_cpu_scale(NULL, cpu) * - policy->cpuinfo.max_freq / 1000UL; - capacity_scale = max(raw_capacity[cpu], capacity_scale); - } - if (cpumask_empty(cpus_to_visit)) { - topology_normalize_cpu_scale(); - kfree(raw_capacity); - pr_debug("cpu_capacity: parsing done\n"); - cap_parsing_done = true; - schedule_work(&parsing_done_work); - } + if (val != CPUFREQ_NOTIFY) + return 0; + + pr_debug("cpu_capacity: init cpu capacity for CPUs [%*pbl] (to_visit=%*pbl)\n", + cpumask_pr_args(policy->related_cpus), + cpumask_pr_args(cpus_to_visit)); + + cpumask_andnot(cpus_to_visit, cpus_to_visit, policy->related_cpus); + + for_each_cpu(cpu, policy->related_cpus) { + raw_capacity[cpu] = topology_get_cpu_scale(NULL, cpu) * + policy->cpuinfo.max_freq / 1000UL; + capacity_scale = max(raw_capacity[cpu], capacity_scale); } + + if (cpumask_empty(cpus_to_visit)) { + topology_normalize_cpu_scale(); + kfree(raw_capacity); + pr_debug("cpu_capacity: parsing done\n"); + cap_parsing_done = true; + schedule_work(&parsing_done_work); + } + return 0; } -- cgit v1.2.3 From 805df2966f67a6b1a228c8e580e230b6c849b41e Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 23 Jun 2017 14:55:32 +0530 Subject: arch_topology: Change return type of topology_parse_cpu_capacity() to bool topology_parse_cpu_capacity() returns 1 on success and 0 on errors. Make it return bool instead of int as that suits the purpose better. Signed-off-by: Viresh Kumar Reviewed-by: Juri Lelli Tested-by: Juri Lelli Signed-off-by: Greg Kroah-Hartman --- drivers/base/arch_topology.c | 8 ++++---- include/linux/arch_topology.h | 4 +++- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index a3cd7c869c3e..5728e2fbb765 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -119,13 +119,13 @@ void topology_normalize_cpu_scale(void) mutex_unlock(&cpu_scale_mutex); } -int __init topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu) +bool __init topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu) { - int ret = 1; + int ret; u32 cpu_capacity; if (cap_parsing_failed) - return !ret; + return false; ret = of_property_read_u32(cpu_node, "capacity-dmips-mhz", &cpu_capacity); @@ -137,7 +137,7 @@ int __init topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu) if (!raw_capacity) { pr_err("cpu_capacity: failed to allocate memory for raw capacities\n"); cap_parsing_failed = true; - return 0; + return false; } } capacity_scale = max(cpu_capacity, capacity_scale); diff --git a/include/linux/arch_topology.h b/include/linux/arch_topology.h index 9af3c174c03a..716ce587247e 100644 --- a/include/linux/arch_topology.h +++ b/include/linux/arch_topology.h @@ -4,10 +4,12 @@ #ifndef _LINUX_ARCH_TOPOLOGY_H_ #define _LINUX_ARCH_TOPOLOGY_H_ +#include + void topology_normalize_cpu_scale(void); struct device_node; -int topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu); +bool topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu); struct sched_domain; unsigned long topology_get_cpu_scale(struct sched_domain *sd, int cpu); -- cgit v1.2.3 From 62de1161e220bc6ded7806ef0d149560f06152b3 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 23 Jun 2017 14:55:33 +0530 Subject: arch_topology: Localize cap_parsing_failed to topology_parse_cpu_capacity() cap_parsing_failed is only required in topology_parse_cpu_capacity() to know if we have already tried to allocate raw_capacity and failed, or if at least one of the cpu_node didn't had the required "capacity-dmips-mhz" property. All other users can use raw_capacity instead of cap_parsing_failed. Make sure we set raw_capacity to NULL after we free it. Signed-off-by: Viresh Kumar Reviewed-by: Juri Lelli Tested-by: Juri Lelli Signed-off-by: Greg Kroah-Hartman --- drivers/base/arch_topology.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index 5728e2fbb765..9e4d2107f4fa 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -95,14 +95,21 @@ subsys_initcall(register_cpu_capacity_sysctl); static u32 capacity_scale; static u32 *raw_capacity; -static bool cap_parsing_failed; + +static int __init free_raw_capacity(void) +{ + kfree(raw_capacity); + raw_capacity = NULL; + + return 0; +} void topology_normalize_cpu_scale(void) { u64 capacity; int cpu; - if (!raw_capacity || cap_parsing_failed) + if (!raw_capacity) return; pr_debug("cpu_capacity: capacity_scale=%u\n", capacity_scale); @@ -121,6 +128,7 @@ void topology_normalize_cpu_scale(void) bool __init topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu) { + static bool cap_parsing_failed; int ret; u32 cpu_capacity; @@ -151,7 +159,7 @@ bool __init topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu) pr_err("cpu_capacity: partial information: fallback to 1024 for all CPUs\n"); } cap_parsing_failed = true; - kfree(raw_capacity); + free_raw_capacity(); } return !ret; @@ -171,7 +179,7 @@ init_cpu_capacity_callback(struct notifier_block *nb, struct cpufreq_policy *policy = data; int cpu; - if (cap_parsing_failed || cap_parsing_done) + if (!raw_capacity || cap_parsing_done) return 0; if (val != CPUFREQ_NOTIFY) @@ -191,7 +199,7 @@ init_cpu_capacity_callback(struct notifier_block *nb, if (cpumask_empty(cpus_to_visit)) { topology_normalize_cpu_scale(); - kfree(raw_capacity); + free_raw_capacity(); pr_debug("cpu_capacity: parsing done\n"); cap_parsing_done = true; schedule_work(&parsing_done_work); @@ -233,11 +241,5 @@ static void parsing_done_workfn(struct work_struct *work) } #else -static int __init free_raw_capacity(void) -{ - kfree(raw_capacity); - - return 0; -} core_initcall(free_raw_capacity); #endif -- cgit v1.2.3 From d8bcf4db9244e2b85597c680f4e1c3a837b067fe Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 23 Jun 2017 14:55:34 +0530 Subject: arch_topology: Get rid of cap_parsing_done There is no need to check for cap_parsing_done flag anymore as !raw_capacity flag alone is enough for us. Remove the (now) useless flag cap_parsing_done. Signed-off-by: Viresh Kumar Reviewed-by: Juri Lelli Tested-by: Juri Lelli Signed-off-by: Greg Kroah-Hartman --- drivers/base/arch_topology.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index 9e4d2107f4fa..74043ead9da1 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -167,7 +167,6 @@ bool __init topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu) #ifdef CONFIG_CPU_FREQ static cpumask_var_t cpus_to_visit; -static bool cap_parsing_done; static void parsing_done_workfn(struct work_struct *work); static DECLARE_WORK(parsing_done_work, parsing_done_workfn); @@ -179,7 +178,7 @@ init_cpu_capacity_callback(struct notifier_block *nb, struct cpufreq_policy *policy = data; int cpu; - if (!raw_capacity || cap_parsing_done) + if (!raw_capacity) return 0; if (val != CPUFREQ_NOTIFY) @@ -201,7 +200,6 @@ init_cpu_capacity_callback(struct notifier_block *nb, topology_normalize_cpu_scale(); free_raw_capacity(); pr_debug("cpu_capacity: parsing done\n"); - cap_parsing_done = true; schedule_work(&parsing_done_work); } -- cgit v1.2.3 From ee06b1728b95643668e40fc58ae118aeb7c1753e Mon Sep 17 00:00:00 2001 From: "Alvaro G. M" Date: Mon, 17 Jul 2017 09:12:28 +0200 Subject: net: axienet: add support for standard phy-mode binding Keep supporting proprietary "xlnx,phy-type" attribute and add support for MII connectivity to the PHY. Reviewed-by: Andrew Lunn Signed-off-by: Alvaro Gamez Machado Signed-off-by: David S. Miller --- .../devicetree/bindings/net/xilinx_axienet.txt | 55 ++++++++++++++++++++++ drivers/net/ethernet/xilinx/xilinx_axienet.h | 4 +- drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 48 ++++++++++++++----- 3 files changed, 93 insertions(+), 14 deletions(-) create mode 100644 Documentation/devicetree/bindings/net/xilinx_axienet.txt (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/net/xilinx_axienet.txt b/Documentation/devicetree/bindings/net/xilinx_axienet.txt new file mode 100644 index 000000000000..38f9ec076743 --- /dev/null +++ b/Documentation/devicetree/bindings/net/xilinx_axienet.txt @@ -0,0 +1,55 @@ +XILINX AXI ETHERNET Device Tree Bindings +-------------------------------------------------------- + +Also called AXI 1G/2.5G Ethernet Subsystem, the xilinx axi ethernet IP core +provides connectivity to an external ethernet PHY supporting different +interfaces: MII, GMII, RGMII, SGMII, 1000BaseX. It also includes two +segments of memory for buffering TX and RX, as well as the capability of +offloading TX/RX checksum calculation off the processor. + +Management configuration is done through the AXI interface, while payload is +sent and received through means of an AXI DMA controller. This driver +includes the DMA driver code, so this driver is incompatible with AXI DMA +driver. + +For more details about mdio please refer phy.txt file in the same directory. + +Required properties: +- compatible : Must be one of "xlnx,axi-ethernet-1.00.a", + "xlnx,axi-ethernet-1.01.a", "xlnx,axi-ethernet-2.01.a" +- reg : Address and length of the IO space. +- interrupts : Should be a list of two interrupt, TX and RX. +- phy-handle : Should point to the external phy device. + See ethernet.txt file in the same directory. +- xlnx,rxmem : Set to allocated memory buffer for Rx/Tx in the hardware + +Optional properties: +- phy-mode : See ethernet.txt +- xlnx,phy-type : Deprecated, do not use, but still accepted in preference + to phy-mode. +- xlnx,txcsum : 0 or empty for disabling TX checksum offload, + 1 to enable partial TX checksum offload, + 2 to enable full TX checksum offload +- xlnx,rxcsum : Same values as xlnx,txcsum but for RX checksum offload + +Example: + axi_ethernet_eth: ethernet@40c00000 { + compatible = "xlnx,axi-ethernet-1.00.a"; + device_type = "network"; + interrupt-parent = <µblaze_0_axi_intc>; + interrupts = <2 0>; + phy-mode = "mii"; + reg = <0x40c00000 0x40000>; + xlnx,rxcsum = <0x2>; + xlnx,rxmem = <0x800>; + xlnx,txcsum = <0x2>; + phy-handle = <&phy0>; + axi_ethernetlite_0_mdio: mdio { + #address-cells = <1>; + #size-cells = <0>; + phy0: phy@0 { + device_type = "ethernet-phy"; + reg = <1>; + }; + }; + }; diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/ethernet/xilinx/xilinx_axienet.h index af27f7d1cbf3..5ef626331f85 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h @@ -389,7 +389,7 @@ struct axidma_bd { * @dma_err_tasklet: Tasklet structure to process Axi DMA errors * @tx_irq: Axidma TX IRQ number * @rx_irq: Axidma RX IRQ number - * @phy_type: Phy type to identify between MII/GMII/RGMII/SGMII/1000 Base-X + * @phy_mode: Phy type to identify between MII/GMII/RGMII/SGMII/1000 Base-X * @options: AxiEthernet option word * @last_link: Phy link state in which the PHY was negotiated earlier * @features: Stores the extended features supported by the axienet hw @@ -432,7 +432,7 @@ struct axienet_local { int tx_irq; int rx_irq; - u32 phy_type; + phy_interface_t phy_mode; u32 options; /* Current options word */ u32 last_link; diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index 33c595f4691d..e74e1e897864 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -531,11 +531,11 @@ static void axienet_adjust_link(struct net_device *ndev) link_state = phy->speed | (phy->duplex << 1) | phy->link; if (lp->last_link != link_state) { if ((phy->speed == SPEED_10) || (phy->speed == SPEED_100)) { - if (lp->phy_type == XAE_PHY_TYPE_1000BASE_X) + if (lp->phy_mode == PHY_INTERFACE_MODE_1000BASEX) setspeed = 0; } else { if ((phy->speed == SPEED_1000) && - (lp->phy_type == XAE_PHY_TYPE_MII)) + (lp->phy_mode == PHY_INTERFACE_MODE_MII)) setspeed = 0; } @@ -935,15 +935,8 @@ static int axienet_open(struct net_device *ndev) return ret; if (lp->phy_node) { - if (lp->phy_type == XAE_PHY_TYPE_GMII) { - phydev = of_phy_connect(lp->ndev, lp->phy_node, - axienet_adjust_link, 0, - PHY_INTERFACE_MODE_GMII); - } else if (lp->phy_type == XAE_PHY_TYPE_RGMII_2_0) { - phydev = of_phy_connect(lp->ndev, lp->phy_node, - axienet_adjust_link, 0, - PHY_INTERFACE_MODE_RGMII_ID); - } + phydev = of_phy_connect(lp->ndev, lp->phy_node, + axienet_adjust_link, 0, lp->phy_mode); if (!phydev) dev_err(lp->dev, "of_phy_connect() failed\n"); @@ -1539,7 +1532,38 @@ static int axienet_probe(struct platform_device *pdev) * the device-tree and accordingly set flags. */ of_property_read_u32(pdev->dev.of_node, "xlnx,rxmem", &lp->rxmem); - of_property_read_u32(pdev->dev.of_node, "xlnx,phy-type", &lp->phy_type); + + /* Start with the proprietary, and broken phy_type */ + ret = of_property_read_u32(pdev->dev.of_node, "xlnx,phy-type", &value); + if (!ret) { + netdev_warn(ndev, "Please upgrade your device tree binary blob to use phy-mode"); + switch (value) { + case XAE_PHY_TYPE_MII: + lp->phy_mode = PHY_INTERFACE_MODE_MII; + break; + case XAE_PHY_TYPE_GMII: + lp->phy_mode = PHY_INTERFACE_MODE_GMII; + break; + case XAE_PHY_TYPE_RGMII_2_0: + lp->phy_mode = PHY_INTERFACE_MODE_RGMII_ID; + break; + case XAE_PHY_TYPE_SGMII: + lp->phy_mode = PHY_INTERFACE_MODE_SGMII; + break; + case XAE_PHY_TYPE_1000BASE_X: + lp->phy_mode = PHY_INTERFACE_MODE_1000BASEX; + break; + default: + ret = -EINVAL; + goto free_netdev; + } + } else { + lp->phy_mode = of_get_phy_mode(pdev->dev.of_node); + if (lp->phy_mode < 0) { + ret = -EINVAL; + goto free_netdev; + } + } /* Find the DMA node, map the DMA registers, and decode the DMA IRQs */ np = of_parse_phandle(pdev->dev.of_node, "axistream-connected", 0); -- cgit v1.2.3 From 5f57e0909136f912b1a8ed677ef6eed8cbb3ec4f Mon Sep 17 00:00:00 2001 From: Or Gerlitz Date: Mon, 17 Jul 2017 14:07:26 +0200 Subject: mlxsw: acl: Add ip ttl acl element Define new element for ip ttl and place it into scratch area. Signed-off-by: Or Gerlitz Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h index 9807ef814e42..789ebb31f4e5 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h @@ -57,6 +57,7 @@ enum mlxsw_afk_element { MLXSW_AFK_ELEMENT_VID, MLXSW_AFK_ELEMENT_PCP, MLXSW_AFK_ELEMENT_TCP_FLAGS, + MLXSW_AFK_ELEMENT_IP_TTL_, MLXSW_AFK_ELEMENT_MAX, }; @@ -104,6 +105,7 @@ static const struct mlxsw_afk_element_info mlxsw_afk_element_infos[] = { MLXSW_AFK_ELEMENT_INFO_U32(VID, 0x10, 8, 12), MLXSW_AFK_ELEMENT_INFO_U32(PCP, 0x10, 20, 3), MLXSW_AFK_ELEMENT_INFO_U32(TCP_FLAGS, 0x10, 23, 9), + MLXSW_AFK_ELEMENT_INFO_U32(IP_TTL_, 0x14, 0, 8), MLXSW_AFK_ELEMENT_INFO_U32(SRC_IP4, 0x18, 0, 32), MLXSW_AFK_ELEMENT_INFO_U32(DST_IP4, 0x1C, 0, 32), MLXSW_AFK_ELEMENT_INFO_BUF(SRC_IP6_HI, 0x18, 8), -- cgit v1.2.3 From 046759a6cf36118f5f4468f5a3998aada040ca5d Mon Sep 17 00:00:00 2001 From: Or Gerlitz Date: Mon, 17 Jul 2017 14:07:27 +0200 Subject: mlxsw: spectrum: Add ttl to the ipv4 acl block Add ttl field to the ipv4 acl block. Signed-off-by: Or Gerlitz Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.h | 1 + drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.h index 85d5001a5818..8a4767ca6909 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.h @@ -70,6 +70,7 @@ static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_dip[] = { static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4[] = { MLXSW_AFK_ELEMENT_INST_U32(SRC_IP4, 0x00, 0, 32), + MLXSW_AFK_ELEMENT_INST_U32(IP_TTL_, 0x04, 24, 8), MLXSW_AFK_ELEMENT_INST_U32(TCP_FLAGS, 0x08, 8, 9), /* TCP_CONTROL+TCP_ECN */ }; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index 61a10f166f97..2c57be7a8399 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -984,6 +984,7 @@ static const enum mlxsw_afk_element mlxsw_sp_acl_tcam_pattern_ipv4[] = { MLXSW_AFK_ELEMENT_VID, MLXSW_AFK_ELEMENT_PCP, MLXSW_AFK_ELEMENT_TCP_FLAGS, + MLXSW_AFK_ELEMENT_IP_TTL_, }; static const enum mlxsw_afk_element mlxsw_sp_acl_tcam_pattern_ipv6[] = { -- cgit v1.2.3 From fcbca8217d62405e91b14953cfb005f83cfa90f1 Mon Sep 17 00:00:00 2001 From: Or Gerlitz Date: Mon, 17 Jul 2017 14:07:28 +0200 Subject: mlxsw: spectrum_flower: Add support for ip ttl Support offloading rules that match on ip ttl. Signed-off-by: Or Gerlitz Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum_flower.c | 37 ++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c index 21bb2bf62d3e..84fe33cf1e95 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c @@ -212,11 +212,39 @@ static int mlxsw_sp_flower_parse_tcp(struct mlxsw_sp *mlxsw_sp, return 0; } +static int mlxsw_sp_flower_parse_ip(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_rule_info *rulei, + struct tc_cls_flower_offload *f, + u16 n_proto) +{ + struct flow_dissector_key_ip *key, *mask; + + if (!dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_IP)) + return 0; + + if (n_proto != ETH_P_IP && n_proto != ETH_P_IPV6) { + dev_err(mlxsw_sp->bus_info->dev, "IP keys supported only for IPv4/6\n"); + return -EINVAL; + } + + key = skb_flow_dissector_target(f->dissector, + FLOW_DISSECTOR_KEY_IP, + f->key); + mask = skb_flow_dissector_target(f->dissector, + FLOW_DISSECTOR_KEY_IP, + f->mask); + mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_IP_TTL_, + key->ttl, mask->ttl); + return 0; +} + static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp, struct net_device *dev, struct mlxsw_sp_acl_rule_info *rulei, struct tc_cls_flower_offload *f) { + u16 n_proto_mask = 0; + u16 n_proto_key = 0; u16 addr_type = 0; u8 ip_proto = 0; int err; @@ -229,6 +257,7 @@ static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp, BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | BIT(FLOW_DISSECTOR_KEY_PORTS) | BIT(FLOW_DISSECTOR_KEY_TCP) | + BIT(FLOW_DISSECTOR_KEY_IP) | BIT(FLOW_DISSECTOR_KEY_VLAN))) { dev_err(mlxsw_sp->bus_info->dev, "Unsupported key\n"); return -EOPNOTSUPP; @@ -253,8 +282,8 @@ static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp, skb_flow_dissector_target(f->dissector, FLOW_DISSECTOR_KEY_BASIC, f->mask); - u16 n_proto_key = ntohs(key->n_proto); - u16 n_proto_mask = ntohs(mask->n_proto); + n_proto_key = ntohs(key->n_proto); + n_proto_mask = ntohs(mask->n_proto); if (n_proto_key == ETH_P_ALL) { n_proto_key = 0; @@ -324,6 +353,10 @@ static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp, if (err) return err; + err = mlxsw_sp_flower_parse_ip(mlxsw_sp, rulei, f, n_proto_key & n_proto_mask); + if (err) + return err; + return mlxsw_sp_flower_parse_actions(mlxsw_sp, dev, rulei, f->exts); } -- cgit v1.2.3 From 80d0fe4710c80e2ade26d7e3030c5c985f34907e Mon Sep 17 00:00:00 2001 From: Or Gerlitz Date: Mon, 17 Jul 2017 14:07:29 +0200 Subject: mlxsw: acl: Add ip tos acl element Define new element for ip tos (ecn, dscp) and place it into scratch area. Signed-off-by: Or Gerlitz Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h index 789ebb31f4e5..f6963b0b4a55 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h @@ -58,6 +58,8 @@ enum mlxsw_afk_element { MLXSW_AFK_ELEMENT_PCP, MLXSW_AFK_ELEMENT_TCP_FLAGS, MLXSW_AFK_ELEMENT_IP_TTL_, + MLXSW_AFK_ELEMENT_IP_ECN, + MLXSW_AFK_ELEMENT_IP_DSCP, MLXSW_AFK_ELEMENT_MAX, }; @@ -106,6 +108,8 @@ static const struct mlxsw_afk_element_info mlxsw_afk_element_infos[] = { MLXSW_AFK_ELEMENT_INFO_U32(PCP, 0x10, 20, 3), MLXSW_AFK_ELEMENT_INFO_U32(TCP_FLAGS, 0x10, 23, 9), MLXSW_AFK_ELEMENT_INFO_U32(IP_TTL_, 0x14, 0, 8), + MLXSW_AFK_ELEMENT_INFO_U32(IP_ECN, 0x14, 9, 2), + MLXSW_AFK_ELEMENT_INFO_U32(IP_DSCP, 0x14, 11, 6), MLXSW_AFK_ELEMENT_INFO_U32(SRC_IP4, 0x18, 0, 32), MLXSW_AFK_ELEMENT_INFO_U32(DST_IP4, 0x1C, 0, 32), MLXSW_AFK_ELEMENT_INFO_BUF(SRC_IP6_HI, 0x18, 8), -- cgit v1.2.3 From abac7b011d527cfc98dba6a7422bdedcdedda039 Mon Sep 17 00:00:00 2001 From: Or Gerlitz Date: Mon, 17 Jul 2017 14:07:30 +0200 Subject: mlxsw: spectrum: Add tos to the ipv4 acl block Add ecn and dscp fields to the ipv4 acl block. Signed-off-by: Or Gerlitz Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.h | 2 ++ drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 2 ++ 2 files changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.h index 8a4767ca6909..fb8031828454 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.h @@ -70,7 +70,9 @@ static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_dip[] = { static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4[] = { MLXSW_AFK_ELEMENT_INST_U32(SRC_IP4, 0x00, 0, 32), + MLXSW_AFK_ELEMENT_INST_U32(IP_ECN, 0x04, 4, 2), MLXSW_AFK_ELEMENT_INST_U32(IP_TTL_, 0x04, 24, 8), + MLXSW_AFK_ELEMENT_INST_U32(IP_DSCP, 0x08, 0, 6), MLXSW_AFK_ELEMENT_INST_U32(TCP_FLAGS, 0x08, 8, 9), /* TCP_CONTROL+TCP_ECN */ }; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index 2c57be7a8399..bc5173f1b5c1 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -985,6 +985,8 @@ static const enum mlxsw_afk_element mlxsw_sp_acl_tcam_pattern_ipv4[] = { MLXSW_AFK_ELEMENT_PCP, MLXSW_AFK_ELEMENT_TCP_FLAGS, MLXSW_AFK_ELEMENT_IP_TTL_, + MLXSW_AFK_ELEMENT_IP_ECN, + MLXSW_AFK_ELEMENT_IP_DSCP, }; static const enum mlxsw_afk_element mlxsw_sp_acl_tcam_pattern_ipv6[] = { -- cgit v1.2.3 From 87996f91f739b7971097428372165a0b66683d0d Mon Sep 17 00:00:00 2001 From: Or Gerlitz Date: Mon, 17 Jul 2017 14:07:31 +0200 Subject: mlxsw: spectrum_flower: Add support for ip tos Support offloading rules that match on ip tos. Signed-off-by: Or Gerlitz Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c index 84fe33cf1e95..400ad4081660 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c @@ -235,6 +235,13 @@ static int mlxsw_sp_flower_parse_ip(struct mlxsw_sp *mlxsw_sp, f->mask); mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_IP_TTL_, key->ttl, mask->ttl); + + mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_IP_ECN, + key->tos & 0x3, mask->tos & 0x3); + + mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_IP_DSCP, + key->tos >> 6, mask->tos >> 6); + return 0; } -- cgit v1.2.3 From 0fcc484748c9dcad5238373a4b2e1b2f309392eb Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Mon, 17 Jul 2017 14:15:29 +0200 Subject: mlxsw: spectrum: Mark packets trapped in router In commit 1c6c6d221e2b ("mlxsw: spectrum: Mirror certain packets to CPU") we marked packets that were mirrored to the CPU, so that they won't be flooded again by the bridge driver. However, certain packets are trapped in the device's router block, after passing through the bridge block where they were potentially flooded. Mark all packets coming from L3 traps, so that they won't be potentially flooded again by the bridge driver. Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 60bf8f27cc00..83e77b959703 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -3334,14 +3334,14 @@ static const struct mlxsw_listener mlxsw_sp_listener[] = { MLXSW_SP_RXL_MARK(ARPUC, MIRROR_TO_CPU, ARP, false), MLXSW_SP_RXL_NO_MARK(FID_MISS, TRAP_TO_CPU, IP2ME, false), /* L3 traps */ - MLXSW_SP_RXL_NO_MARK(MTUERROR, TRAP_TO_CPU, ROUTER_EXP, false), - MLXSW_SP_RXL_NO_MARK(TTLERROR, TRAP_TO_CPU, ROUTER_EXP, false), - MLXSW_SP_RXL_NO_MARK(LBERROR, TRAP_TO_CPU, ROUTER_EXP, false), + MLXSW_SP_RXL_MARK(MTUERROR, TRAP_TO_CPU, ROUTER_EXP, false), + MLXSW_SP_RXL_MARK(TTLERROR, TRAP_TO_CPU, ROUTER_EXP, false), + MLXSW_SP_RXL_MARK(LBERROR, TRAP_TO_CPU, ROUTER_EXP, false), MLXSW_SP_RXL_MARK(OSPF, TRAP_TO_CPU, OSPF, false), - MLXSW_SP_RXL_NO_MARK(IP2ME, TRAP_TO_CPU, IP2ME, false), - MLXSW_SP_RXL_NO_MARK(RTR_INGRESS0, TRAP_TO_CPU, REMOTE_ROUTE, false), - MLXSW_SP_RXL_NO_MARK(HOST_MISS_IPV4, TRAP_TO_CPU, ARP_MISS, false), - MLXSW_SP_RXL_NO_MARK(BGP_IPV4, TRAP_TO_CPU, BGP_IPV4, false), + MLXSW_SP_RXL_MARK(IP2ME, TRAP_TO_CPU, IP2ME, false), + MLXSW_SP_RXL_MARK(RTR_INGRESS0, TRAP_TO_CPU, REMOTE_ROUTE, false), + MLXSW_SP_RXL_MARK(HOST_MISS_IPV4, TRAP_TO_CPU, ARP_MISS, false), + MLXSW_SP_RXL_MARK(BGP_IPV4, TRAP_TO_CPU, BGP_IPV4, false), /* PKT Sample trap */ MLXSW_RXL(mlxsw_sp_rx_listener_sample_func, PKT_SAMPLE, MIRROR_TO_CPU, false, SP_IP2ME, DISCARD), -- cgit v1.2.3 From 7607dd35fc34893214284cca740d015154d20452 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Mon, 17 Jul 2017 14:15:30 +0200 Subject: mlxsw: spectrum: Trap IPv4 packets with Router Alert option In case local sockets have the IP_ROUTER_ALERT socket option set, then they expect to get packets with the Router Alert option. Trap such packets, so that the kernel could inspect them and potentially send them to interested sockets. Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 1 + drivers/net/ethernet/mellanox/mlxsw/trap.h | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 83e77b959703..bc35b400e6f1 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -3342,6 +3342,7 @@ static const struct mlxsw_listener mlxsw_sp_listener[] = { MLXSW_SP_RXL_MARK(RTR_INGRESS0, TRAP_TO_CPU, REMOTE_ROUTE, false), MLXSW_SP_RXL_MARK(HOST_MISS_IPV4, TRAP_TO_CPU, ARP_MISS, false), MLXSW_SP_RXL_MARK(BGP_IPV4, TRAP_TO_CPU, BGP_IPV4, false), + MLXSW_SP_RXL_MARK(ROUTER_ALERT_IPV4, TRAP_TO_CPU, ROUTER_EXP, false), /* PKT Sample trap */ MLXSW_RXL(mlxsw_sp_rx_listener_sample_func, PKT_SAMPLE, MIRROR_TO_CPU, false, SP_IP2ME, DISCARD), diff --git a/drivers/net/ethernet/mellanox/mlxsw/trap.h b/drivers/net/ethernet/mellanox/mlxsw/trap.h index 12b5ed58f3eb..4946d4e2b3f9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/trap.h +++ b/drivers/net/ethernet/mellanox/mlxsw/trap.h @@ -66,6 +66,7 @@ enum { MLXSW_TRAP_ID_RTR_INGRESS0 = 0x70, MLXSW_TRAP_ID_BGP_IPV4 = 0x88, MLXSW_TRAP_ID_HOST_MISS_IPV4 = 0x90, + MLXSW_TRAP_ID_ROUTER_ALERT_IPV4 = 0xD6, MLXSW_TRAP_ID_ACL0 = 0x1C0, MLXSW_TRAP_ID_MAX = 0x1FF -- cgit v1.2.3 From 588823f97df3d5bf219d8f0bfea1c23ce367b84d Mon Sep 17 00:00:00 2001 From: Arkadi Sharshevsky Date: Mon, 17 Jul 2017 14:15:31 +0200 Subject: mlxsw: spectrum: Add support for IPv6 MLDv1/2 traps Add support for IPv6 MLDv1/2 packet trapping. Signed-off-by: Arkadi Sharshevsky Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 1 + drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 10 ++++++++++ drivers/net/ethernet/mellanox/mlxsw/trap.h | 4 ++++ 3 files changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 1bd34d9a7b9e..0ca196899e18 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -3688,6 +3688,7 @@ enum mlxsw_reg_htgt_trap_group { MLXSW_REG_HTGT_TRAP_GROUP_SP_IP2ME, MLXSW_REG_HTGT_TRAP_GROUP_SP_DHCP, MLXSW_REG_HTGT_TRAP_GROUP_SP_EVENT, + MLXSW_REG_HTGT_TRAP_GROUP_SP_IPV6_MLD, }; /* reg_htgt_trap_group diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index bc35b400e6f1..1aa6298ea6cd 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -3333,6 +3333,14 @@ static const struct mlxsw_listener mlxsw_sp_listener[] = { MLXSW_SP_RXL_MARK(ARPBC, MIRROR_TO_CPU, ARP, false), MLXSW_SP_RXL_MARK(ARPUC, MIRROR_TO_CPU, ARP, false), MLXSW_SP_RXL_NO_MARK(FID_MISS, TRAP_TO_CPU, IP2ME, false), + MLXSW_SP_RXL_MARK(IPV6_MLDV12_LISTENER_QUERY, MIRROR_TO_CPU, IPV6_MLD, + false), + MLXSW_SP_RXL_NO_MARK(IPV6_MLDV1_LISTENER_REPORT, TRAP_TO_CPU, IPV6_MLD, + false), + MLXSW_SP_RXL_NO_MARK(IPV6_MLDV1_LISTENER_DONE, TRAP_TO_CPU, IPV6_MLD, + false), + MLXSW_SP_RXL_NO_MARK(IPV6_MLDV2_LISTENER_REPORT, TRAP_TO_CPU, IPV6_MLD, + false), /* L3 traps */ MLXSW_SP_RXL_MARK(MTUERROR, TRAP_TO_CPU, ROUTER_EXP, false), MLXSW_SP_RXL_MARK(TTLERROR, TRAP_TO_CPU, ROUTER_EXP, false), @@ -3377,6 +3385,7 @@ static int mlxsw_sp_cpu_policers_set(struct mlxsw_core *mlxsw_core) burst_size = 7; break; case MLXSW_REG_HTGT_TRAP_GROUP_SP_IGMP: + case MLXSW_REG_HTGT_TRAP_GROUP_SP_IPV6_MLD: rate = 16 * 1024; burst_size = 10; break; @@ -3441,6 +3450,7 @@ static int mlxsw_sp_trap_groups_set(struct mlxsw_core *mlxsw_core) break; case MLXSW_REG_HTGT_TRAP_GROUP_SP_IGMP: case MLXSW_REG_HTGT_TRAP_GROUP_SP_IP2ME: + case MLXSW_REG_HTGT_TRAP_GROUP_SP_IPV6_MLD: priority = 3; tc = 3; break; diff --git a/drivers/net/ethernet/mellanox/mlxsw/trap.h b/drivers/net/ethernet/mellanox/mlxsw/trap.h index 4946d4e2b3f9..891b4ee6eeb2 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/trap.h +++ b/drivers/net/ethernet/mellanox/mlxsw/trap.h @@ -63,6 +63,10 @@ enum { MLXSW_TRAP_ID_LBERROR = 0x54, MLXSW_TRAP_ID_OSPF = 0x55, MLXSW_TRAP_ID_IP2ME = 0x5F, + MLXSW_TRAP_ID_IPV6_MLDV12_LISTENER_QUERY = 0x65, + MLXSW_TRAP_ID_IPV6_MLDV1_LISTENER_REPORT = 0x66, + MLXSW_TRAP_ID_IPV6_MLDV1_LISTENER_DONE = 0x67, + MLXSW_TRAP_ID_IPV6_MLDV2_LISTENER_REPORT = 0x68, MLXSW_TRAP_ID_RTR_INGRESS0 = 0x70, MLXSW_TRAP_ID_BGP_IPV4 = 0x88, MLXSW_TRAP_ID_HOST_MISS_IPV4 = 0x90, -- cgit v1.2.3 From 9df552ef3e214e32b7a0458d3bdc430643aa553b Mon Sep 17 00:00:00 2001 From: Arkadi Sharshevsky Date: Mon, 17 Jul 2017 14:15:32 +0200 Subject: mlxsw: spectrum: Improve IPv6 unregistered multicast flooding Up until now IPv6 unregistered multicast traffic would be flooded like broadcast, even when MLD snooping was enabled on the bridge. This was intentional as MLD packet traps were missing, preventing the bridge driver from programming MDB entries to the device. Previous patch added these traps, so we can now finally flood IPv6 unregistered multicast packets to specific ports via the multicast table instead of flooding them to all ports via the broadcast table. Signed-off-by: Arkadi Sharshevsky Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c index 6afbe9ec64e2..bbd238e50f05 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c @@ -109,7 +109,6 @@ static const int mlxsw_sp_sfgc_uc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = { static const int mlxsw_sp_sfgc_bc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = { [MLXSW_REG_SFGC_TYPE_BROADCAST] = 1, - [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6] = 1, [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP] = 1, [MLXSW_REG_SFGC_TYPE_IPV4_LINK_LOCAL] = 1, [MLXSW_REG_SFGC_TYPE_IPV6_ALL_HOST] = 1, @@ -117,6 +116,7 @@ static const int mlxsw_sp_sfgc_bc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = { static const int mlxsw_sp_sfgc_mc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = { [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4] = 1, + [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6] = 1, }; static const int *mlxsw_sp_packet_type_sfgc_types[] = { -- cgit v1.2.3 From 90382dca61137444cb8f639db0a76c4d084763d7 Mon Sep 17 00:00:00 2001 From: John Fastabend Date: Mon, 17 Jul 2017 09:26:24 -0700 Subject: ixgbe: NULL xdp_tx rings on resource cleanup tx_rings and rx_rings are cleaned up on close paths in ixgbe driver however, xdp_rings are not. Set the xdp_rings to NULL here so that we can use the pointer to indicate if the XDP rings are initialized. Signed-off-by: John Fastabend Acked-by: Daniel Borkmann Acked-by: Jesper Dangaard Brouer Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c index b45fdc98033d..f1bfae0c41d0 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c @@ -1018,8 +1018,12 @@ static void ixgbe_free_q_vector(struct ixgbe_adapter *adapter, int v_idx) struct ixgbe_q_vector *q_vector = adapter->q_vector[v_idx]; struct ixgbe_ring *ring; - ixgbe_for_each_ring(ring, q_vector->tx) - adapter->tx_ring[ring->queue_index] = NULL; + ixgbe_for_each_ring(ring, q_vector->tx) { + if (ring_is_xdp(ring)) + adapter->xdp_ring[ring->queue_index] = NULL; + else + adapter->tx_ring[ring->queue_index] = NULL; + } ixgbe_for_each_ring(ring, q_vector->rx) adapter->rx_ring[ring->queue_index] = NULL; -- cgit v1.2.3 From 6453073987ba392510ab6c8b657844a9312c67f7 Mon Sep 17 00:00:00 2001 From: John Fastabend Date: Mon, 17 Jul 2017 09:28:12 -0700 Subject: ixgbe: add initial support for xdp redirect There are optimizations we can add after the basic feature is enabled. But, for now keep the patch simple. Signed-off-by: John Fastabend Acked-by: Daniel Borkmann Acked-by: Jesper Dangaard Brouer Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 41 ++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index f1dbdf26d8e1..3db04736a048 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -2214,7 +2214,7 @@ static struct sk_buff *ixgbe_run_xdp(struct ixgbe_adapter *adapter, struct ixgbe_ring *rx_ring, struct xdp_buff *xdp) { - int result = IXGBE_XDP_PASS; + int err, result = IXGBE_XDP_PASS; struct bpf_prog *xdp_prog; u32 act; @@ -2231,6 +2231,13 @@ static struct sk_buff *ixgbe_run_xdp(struct ixgbe_adapter *adapter, case XDP_TX: result = ixgbe_xmit_xdp_ring(adapter, xdp); break; + case XDP_REDIRECT: + err = xdp_do_redirect(adapter->netdev, xdp); + if (!err) + result = IXGBE_XDP_TX; + else + result = IXGBE_XDP_CONSUMED; + break; default: bpf_warn_invalid_xdp_action(act); /* fallthrough */ @@ -9823,6 +9830,37 @@ static int ixgbe_xdp(struct net_device *dev, struct netdev_xdp *xdp) } } +static int ixgbe_xdp_xmit(struct net_device *dev, struct xdp_buff *xdp) +{ + struct ixgbe_adapter *adapter = netdev_priv(dev); + struct ixgbe_ring *ring; + int err; + + if (unlikely(test_bit(__IXGBE_DOWN, &adapter->state))) + return -EINVAL; + + /* During program transitions its possible adapter->xdp_prog is assigned + * but ring has not been configured yet. In this case simply abort xmit. + */ + ring = adapter->xdp_prog ? adapter->xdp_ring[smp_processor_id()] : NULL; + if (unlikely(!ring)) + return -EINVAL; + + err = ixgbe_xmit_xdp_ring(adapter, xdp); + if (err != IXGBE_XDP_TX) + return -ENOMEM; + + /* Force memory writes to complete before letting h/w know there + * are new descriptors to fetch. + */ + wmb(); + + ring = adapter->xdp_ring[smp_processor_id()]; + writel(ring->next_to_use, ring->tail); + + return 0; +} + static const struct net_device_ops ixgbe_netdev_ops = { .ndo_open = ixgbe_open, .ndo_stop = ixgbe_close, @@ -9869,6 +9907,7 @@ static const struct net_device_ops ixgbe_netdev_ops = { .ndo_udp_tunnel_del = ixgbe_del_udp_tunnel_port, .ndo_features_check = ixgbe_features_check, .ndo_xdp = ixgbe_xdp, + .ndo_xdp_xmit = ixgbe_xdp_xmit, }; /** -- cgit v1.2.3 From 5acaee0a8964c9bab7775ab8bedcd1f66a2a1011 Mon Sep 17 00:00:00 2001 From: John Fastabend Date: Mon, 17 Jul 2017 09:28:35 -0700 Subject: xdp: add trace event for xdp redirect This adds a trace event for xdp redirect which may help when debugging XDP programs that use redirect bpf commands. Signed-off-by: John Fastabend Acked-by: Daniel Borkmann Acked-by: Jesper Dangaard Brouer Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 2 +- include/linux/filter.h | 4 +++- include/trace/events/xdp.h | 31 ++++++++++++++++++++++++++- net/core/filter.c | 13 +++++++---- 4 files changed, 43 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 3db04736a048..38f7ff97d636 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -2232,7 +2232,7 @@ static struct sk_buff *ixgbe_run_xdp(struct ixgbe_adapter *adapter, result = ixgbe_xmit_xdp_ring(adapter, xdp); break; case XDP_REDIRECT: - err = xdp_do_redirect(adapter->netdev, xdp); + err = xdp_do_redirect(adapter->netdev, xdp, xdp_prog); if (!err) result = IXGBE_XDP_TX; else diff --git a/include/linux/filter.h b/include/linux/filter.h index 10df7daf5ec6..ce8211fa91c7 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h @@ -713,7 +713,9 @@ struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off, const struct bpf_insn *patch, u32 len); int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb); -int xdp_do_redirect(struct net_device *dev, struct xdp_buff *xdp); +int xdp_do_redirect(struct net_device *dev, + struct xdp_buff *xdp, + struct bpf_prog *prog); void bpf_warn_invalid_xdp_action(u32 act); void bpf_warn_invalid_xdp_redirect(u32 ifindex); diff --git a/include/trace/events/xdp.h b/include/trace/events/xdp.h index 1b61357d3f57..7b1eb7b4be41 100644 --- a/include/trace/events/xdp.h +++ b/include/trace/events/xdp.h @@ -12,7 +12,8 @@ FN(ABORTED) \ FN(DROP) \ FN(PASS) \ - FN(TX) + FN(TX) \ + FN(REDIRECT) #define __XDP_ACT_TP_FN(x) \ TRACE_DEFINE_ENUM(XDP_##x); @@ -48,6 +49,34 @@ TRACE_EVENT(xdp_exception, __print_symbolic(__entry->act, __XDP_ACT_SYM_TAB)) ); +TRACE_EVENT(xdp_redirect, + + TP_PROTO(const struct net_device *from, + const struct net_device *to, + const struct bpf_prog *xdp, u32 act), + + TP_ARGS(from, to, xdp, act), + + TP_STRUCT__entry( + __string(name_from, from->name) + __string(name_to, to->name) + __array(u8, prog_tag, 8) + __field(u32, act) + ), + + TP_fast_assign( + BUILD_BUG_ON(sizeof(__entry->prog_tag) != sizeof(xdp->tag)); + memcpy(__entry->prog_tag, xdp->tag, sizeof(xdp->tag)); + __assign_str(name_from, from->name); + __assign_str(name_to, to->name); + __entry->act = act; + ), + + TP_printk("prog=%s from=%s to=%s action=%s", + __print_hex_str(__entry->prog_tag, 8), + __get_str(name_from), __get_str(name_to), + __print_symbolic(__entry->act, __XDP_ACT_SYM_TAB)) +); #endif /* _TRACE_XDP_H */ #include diff --git a/net/core/filter.c b/net/core/filter.c index eeb713461c25..e30d38b27f21 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -55,6 +55,7 @@ #include #include #include +#include /** * sk_filter_trim_cap - run a packet through a socket filter @@ -2422,18 +2423,22 @@ static int __bpf_tx_xdp(struct net_device *dev, struct xdp_buff *xdp) return -EOPNOTSUPP; } -int xdp_do_redirect(struct net_device *dev, struct xdp_buff *xdp) +int xdp_do_redirect(struct net_device *dev, struct xdp_buff *xdp, + struct bpf_prog *xdp_prog) { struct redirect_info *ri = this_cpu_ptr(&redirect_info); + struct net_device *fwd; - dev = dev_get_by_index_rcu(dev_net(dev), ri->ifindex); + fwd = dev_get_by_index_rcu(dev_net(dev), ri->ifindex); ri->ifindex = 0; - if (unlikely(!dev)) { + if (unlikely(!fwd)) { bpf_warn_invalid_xdp_redirect(ri->ifindex); return -EINVAL; } - return __bpf_tx_xdp(dev, xdp); + trace_xdp_redirect(dev, fwd, xdp_prog, XDP_REDIRECT); + + return __bpf_tx_xdp(fwd, xdp); } EXPORT_SYMBOL_GPL(xdp_do_redirect); -- cgit v1.2.3 From 11393cc9b9be2a1f61559e6fb9c27bc8fa20b1ff Mon Sep 17 00:00:00 2001 From: John Fastabend Date: Mon, 17 Jul 2017 09:29:40 -0700 Subject: xdp: Add batching support to redirect map For performance reasons we want to avoid updating the tail pointer in the driver tx ring as much as possible. To accomplish this we add batching support to the redirect path in XDP. This adds another ndo op "xdp_flush" that is used to inform the driver that it should bump the tail pointer on the TX ring. Signed-off-by: John Fastabend Signed-off-by: Jesper Dangaard Brouer Acked-by: Daniel Borkmann Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 28 ++++++++- include/linux/bpf.h | 2 + include/linux/filter.h | 7 +++ include/linux/netdevice.h | 5 +- kernel/bpf/devmap.c | 84 ++++++++++++++++++++++++++- net/core/filter.c | 55 ++++++++++++++---- 6 files changed, 166 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 38f7ff97d636..0f867dcda65f 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -2415,6 +2415,8 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, */ wmb(); writel(ring->next_to_use, ring->tail); + + xdp_do_flush_map(); } u64_stats_update_begin(&rx_ring->syncp); @@ -5817,6 +5819,9 @@ void ixgbe_down(struct ixgbe_adapter *adapter) usleep_range(10000, 20000); + /* synchronize_sched() needed for pending XDP buffers to drain */ + if (adapter->xdp_ring[0]) + synchronize_sched(); netif_tx_stop_all_queues(netdev); /* call carrier off first to avoid false dev_watchdog timeouts */ @@ -9850,15 +9855,31 @@ static int ixgbe_xdp_xmit(struct net_device *dev, struct xdp_buff *xdp) if (err != IXGBE_XDP_TX) return -ENOMEM; + return 0; +} + +static void ixgbe_xdp_flush(struct net_device *dev) +{ + struct ixgbe_adapter *adapter = netdev_priv(dev); + struct ixgbe_ring *ring; + + /* Its possible the device went down between xdp xmit and flush so + * we need to ensure device is still up. + */ + if (unlikely(test_bit(__IXGBE_DOWN, &adapter->state))) + return; + + ring = adapter->xdp_prog ? adapter->xdp_ring[smp_processor_id()] : NULL; + if (unlikely(!ring)) + return; + /* Force memory writes to complete before letting h/w know there * are new descriptors to fetch. */ wmb(); - - ring = adapter->xdp_ring[smp_processor_id()]; writel(ring->next_to_use, ring->tail); - return 0; + return; } static const struct net_device_ops ixgbe_netdev_ops = { @@ -9908,6 +9929,7 @@ static const struct net_device_ops ixgbe_netdev_ops = { .ndo_features_check = ixgbe_features_check, .ndo_xdp = ixgbe_xdp, .ndo_xdp_xmit = ixgbe_xdp_xmit, + .ndo_xdp_flush = ixgbe_xdp_flush, }; /** diff --git a/include/linux/bpf.h b/include/linux/bpf.h index d0d3281ac678..6850a760dc94 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -381,5 +381,7 @@ u64 bpf_user_rnd_u32(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5); /* Map specifics */ struct net_device *__dev_map_lookup_elem(struct bpf_map *map, u32 key); +void __dev_map_insert_ctx(struct bpf_map *map, u32 index); +void __dev_map_flush(struct bpf_map *map); #endif /* _LINUX_BPF_H */ diff --git a/include/linux/filter.h b/include/linux/filter.h index ce8211fa91c7..3323ee91c172 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h @@ -712,10 +712,17 @@ bool bpf_helper_changes_pkt_data(void *func); struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off, const struct bpf_insn *patch, u32 len); +/* The pair of xdp_do_redirect and xdp_do_flush_map MUST be called in the + * same cpu context. Further for best results no more than a single map + * for the do_redirect/do_flush pair should be used. This limitation is + * because we only track one map and force a flush when the map changes. + * This does not appear to be a real limiation for existing software. + */ int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb); int xdp_do_redirect(struct net_device *dev, struct xdp_buff *xdp, struct bpf_prog *prog); +void xdp_do_flush_map(void); void bpf_warn_invalid_xdp_action(u32 act); void bpf_warn_invalid_xdp_redirect(u32 ifindex); diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 77f5376005e6..03b104908235 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1142,7 +1142,9 @@ struct xfrmdev_ops { * int (*ndo_xdp_xmit)(struct net_device *dev, struct xdp_buff *xdp); * This function is used to submit a XDP packet for transmit on a * netdevice. - * + * void (*ndo_xdp_flush)(struct net_device *dev); + * This function is used to inform the driver to flush a paticular + * xpd tx queue. Must be called on same CPU as xdp_xmit. */ struct net_device_ops { int (*ndo_init)(struct net_device *dev); @@ -1329,6 +1331,7 @@ struct net_device_ops { struct netdev_xdp *xdp); int (*ndo_xdp_xmit)(struct net_device *dev, struct xdp_buff *xdp); + void (*ndo_xdp_flush)(struct net_device *dev); }; /** diff --git a/kernel/bpf/devmap.c b/kernel/bpf/devmap.c index 36dc13deb2e1..b2ef04a1c86a 100644 --- a/kernel/bpf/devmap.c +++ b/kernel/bpf/devmap.c @@ -53,6 +53,7 @@ struct bpf_dtab_netdev { struct bpf_dtab { struct bpf_map map; struct bpf_dtab_netdev **netdev_map; + unsigned long int __percpu *flush_needed; }; static struct bpf_map *dev_map_alloc(union bpf_attr *attr) @@ -87,6 +88,7 @@ static struct bpf_map *dev_map_alloc(union bpf_attr *attr) /* make sure page count doesn't overflow */ cost = (u64) dtab->map.max_entries * sizeof(struct bpf_dtab_netdev *); + cost += BITS_TO_LONGS(attr->max_entries) * sizeof(unsigned long); if (cost >= U32_MAX - PAGE_SIZE) goto free_dtab; @@ -97,6 +99,14 @@ static struct bpf_map *dev_map_alloc(union bpf_attr *attr) if (err) goto free_dtab; + /* A per cpu bitfield with a bit per possible net device */ + dtab->flush_needed = __alloc_percpu( + BITS_TO_LONGS(attr->max_entries) * + sizeof(unsigned long), + __alignof__(unsigned long)); + if (!dtab->flush_needed) + goto free_dtab; + dtab->netdev_map = bpf_map_area_alloc(dtab->map.max_entries * sizeof(struct bpf_dtab_netdev *)); if (!dtab->netdev_map) @@ -105,6 +115,7 @@ static struct bpf_map *dev_map_alloc(union bpf_attr *attr) return &dtab->map; free_dtab: + free_percpu(dtab->flush_needed); kfree(dtab); return ERR_PTR(err); } @@ -112,7 +123,7 @@ free_dtab: static void dev_map_free(struct bpf_map *map) { struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map); - int i; + int i, cpu; /* At this point bpf_prog->aux->refcnt == 0 and this map->refcnt == 0, * so the programs (can be more than one that used this map) were @@ -123,6 +134,18 @@ static void dev_map_free(struct bpf_map *map) */ synchronize_rcu(); + /* To ensure all pending flush operations have completed wait for flush + * bitmap to indicate all flush_needed bits to be zero on _all_ cpus. + * Because the above synchronize_rcu() ensures the map is disconnected + * from the program we can assume no new bits will be set. + */ + for_each_online_cpu(cpu) { + unsigned long *bitmap = per_cpu_ptr(dtab->flush_needed, cpu); + + while (!bitmap_empty(bitmap, dtab->map.max_entries)) + cpu_relax(); + } + for (i = 0; i < dtab->map.max_entries; i++) { struct bpf_dtab_netdev *dev; @@ -137,6 +160,7 @@ static void dev_map_free(struct bpf_map *map) /* At this point bpf program is detached and all pending operations * _must_ be complete */ + free_percpu(dtab->flush_needed); bpf_map_area_free(dtab->netdev_map); kfree(dtab); } @@ -159,6 +183,14 @@ static int dev_map_get_next_key(struct bpf_map *map, void *key, void *next_key) return 0; } +void __dev_map_insert_ctx(struct bpf_map *map, u32 key) +{ + struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map); + unsigned long *bitmap = this_cpu_ptr(dtab->flush_needed); + + __set_bit(key, bitmap); +} + struct net_device *__dev_map_lookup_elem(struct bpf_map *map, u32 key) { struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map); @@ -171,6 +203,39 @@ struct net_device *__dev_map_lookup_elem(struct bpf_map *map, u32 key) return dev ? dev->dev : NULL; } +/* __dev_map_flush is called from xdp_do_flush_map() which _must_ be signaled + * from the driver before returning from its napi->poll() routine. The poll() + * routine is called either from busy_poll context or net_rx_action signaled + * from NET_RX_SOFTIRQ. Either way the poll routine must complete before the + * net device can be torn down. On devmap tear down we ensure the ctx bitmap + * is zeroed before completing to ensure all flush operations have completed. + */ +void __dev_map_flush(struct bpf_map *map) +{ + struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map); + unsigned long *bitmap = this_cpu_ptr(dtab->flush_needed); + u32 bit; + + for_each_set_bit(bit, bitmap, map->max_entries) { + struct bpf_dtab_netdev *dev = READ_ONCE(dtab->netdev_map[bit]); + struct net_device *netdev; + + /* This is possible if the dev entry is removed by user space + * between xdp redirect and flush op. + */ + if (unlikely(!dev)) + continue; + + netdev = dev->dev; + + __clear_bit(bit, bitmap); + if (unlikely(!netdev || !netdev->netdev_ops->ndo_xdp_flush)) + continue; + + netdev->netdev_ops->ndo_xdp_flush(netdev); + } +} + /* rcu_read_lock (from syscall and BPF contexts) ensures that if a delete and/or * update happens in parallel here a dev_put wont happen until after reading the * ifindex. @@ -188,11 +253,28 @@ static void *dev_map_lookup_elem(struct bpf_map *map, void *key) return dev ? &dev->dev->ifindex : NULL; } +static void dev_map_flush_old(struct bpf_dtab_netdev *old_dev) +{ + if (old_dev->dev->netdev_ops->ndo_xdp_flush) { + struct net_device *fl = old_dev->dev; + unsigned long *bitmap; + int cpu; + + for_each_online_cpu(cpu) { + bitmap = per_cpu_ptr(old_dev->dtab->flush_needed, cpu); + __clear_bit(old_dev->key, bitmap); + + fl->netdev_ops->ndo_xdp_flush(old_dev->dev); + } + } +} + static void __dev_map_entry_free(struct rcu_head *rcu) { struct bpf_dtab_netdev *old_dev; old_dev = container_of(rcu, struct bpf_dtab_netdev, rcu); + dev_map_flush_old(old_dev); dev_put(old_dev->dev); kfree(old_dev); } diff --git a/net/core/filter.c b/net/core/filter.c index e93a558324b5..e23aa6fa1119 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -1780,6 +1780,7 @@ struct redirect_info { u32 ifindex; u32 flags; struct bpf_map *map; + struct bpf_map *map_to_flush; }; static DEFINE_PER_CPU(struct redirect_info, redirect_info); @@ -2438,34 +2439,68 @@ static const struct bpf_func_proto bpf_xdp_adjust_head_proto = { .arg2_type = ARG_ANYTHING, }; -static int __bpf_tx_xdp(struct net_device *dev, struct xdp_buff *xdp) +static int __bpf_tx_xdp(struct net_device *dev, + struct bpf_map *map, + struct xdp_buff *xdp, + u32 index) { - if (dev->netdev_ops->ndo_xdp_xmit) { - dev->netdev_ops->ndo_xdp_xmit(dev, xdp); - return 0; + int err; + + if (!dev->netdev_ops->ndo_xdp_xmit) { + bpf_warn_invalid_xdp_redirect(dev->ifindex); + return -EOPNOTSUPP; } - bpf_warn_invalid_xdp_redirect(dev->ifindex); - return -EOPNOTSUPP; + + err = dev->netdev_ops->ndo_xdp_xmit(dev, xdp); + if (err) + return err; + + if (map) + __dev_map_insert_ctx(map, index); + else + dev->netdev_ops->ndo_xdp_flush(dev); + + return err; } +void xdp_do_flush_map(void) +{ + struct redirect_info *ri = this_cpu_ptr(&redirect_info); + struct bpf_map *map = ri->map_to_flush; + + ri->map = NULL; + ri->map_to_flush = NULL; + + if (map) + __dev_map_flush(map); +} +EXPORT_SYMBOL_GPL(xdp_do_flush_map); + int xdp_do_redirect_map(struct net_device *dev, struct xdp_buff *xdp, struct bpf_prog *xdp_prog) { struct redirect_info *ri = this_cpu_ptr(&redirect_info); struct bpf_map *map = ri->map; + u32 index = ri->ifindex; struct net_device *fwd; int err = -EINVAL; ri->ifindex = 0; ri->map = NULL; - fwd = __dev_map_lookup_elem(map, ri->ifindex); + fwd = __dev_map_lookup_elem(map, index); if (!fwd) goto out; - trace_xdp_redirect(dev, fwd, xdp_prog, XDP_REDIRECT); - err = __bpf_tx_xdp(fwd, xdp); + if (ri->map_to_flush && (ri->map_to_flush != map)) + xdp_do_flush_map(); + + err = __bpf_tx_xdp(fwd, map, xdp, index); + if (likely(!err)) + ri->map_to_flush = map; + out: + trace_xdp_redirect(dev, fwd, xdp_prog, XDP_REDIRECT); return err; } @@ -2488,7 +2523,7 @@ int xdp_do_redirect(struct net_device *dev, struct xdp_buff *xdp, trace_xdp_redirect(dev, fwd, xdp_prog, XDP_REDIRECT); - return __bpf_tx_xdp(fwd, xdp); + return __bpf_tx_xdp(fwd, NULL, xdp, 0); } EXPORT_SYMBOL_GPL(xdp_do_redirect); -- cgit v1.2.3 From ed22e2f6b72de9dc2a2fe43cd553cf4d36f70785 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 3 Jul 2017 06:28:56 -0700 Subject: s2io: Remove UFO support. Signed-off-by: David S. Miller --- drivers/net/ethernet/neterion/s2io.c | 45 ------------------------------------ 1 file changed, 45 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c index fd2ec36c6fa1..462eda926b1c 100644 --- a/drivers/net/ethernet/neterion/s2io.c +++ b/drivers/net/ethernet/neterion/s2io.c @@ -42,8 +42,6 @@ * aggregated as a single large packet * napi: This parameter used to enable/disable NAPI (polling Rx) * Possible values '1' for enable and '0' for disable. Default is '1' - * ufo: This parameter used to enable/disable UDP Fragmentation Offload(UFO) - * Possible values '1' for enable and '0' for disable. Default is '0' * vlan_tag_strip: This can be used to enable or disable vlan stripping. * Possible values '1' for enable , '0' for disable. * Default is '2' - which means disable in promisc mode @@ -453,7 +451,6 @@ S2IO_PARM_INT(lro_max_pkts, 0xFFFF); S2IO_PARM_INT(indicate_max_pkts, 0); S2IO_PARM_INT(napi, 1); -S2IO_PARM_INT(ufo, 0); S2IO_PARM_INT(vlan_tag_strip, NO_STRIP_IN_PROMISC); static unsigned int tx_fifo_len[MAX_TX_FIFOS] = @@ -4128,32 +4125,6 @@ static netdev_tx_t s2io_xmit(struct sk_buff *skb, struct net_device *dev) } frg_len = skb_headlen(skb); - if (offload_type == SKB_GSO_UDP) { - int ufo_size; - - ufo_size = s2io_udp_mss(skb); - ufo_size &= ~7; - txdp->Control_1 |= TXD_UFO_EN; - txdp->Control_1 |= TXD_UFO_MSS(ufo_size); - txdp->Control_1 |= TXD_BUFFER0_SIZE(8); -#ifdef __BIG_ENDIAN - /* both variants do cpu_to_be64(be32_to_cpu(...)) */ - fifo->ufo_in_band_v[put_off] = - (__force u64)skb_shinfo(skb)->ip6_frag_id; -#else - fifo->ufo_in_band_v[put_off] = - (__force u64)skb_shinfo(skb)->ip6_frag_id << 32; -#endif - txdp->Host_Control = (unsigned long)fifo->ufo_in_band_v; - txdp->Buffer_Pointer = pci_map_single(sp->pdev, - fifo->ufo_in_band_v, - sizeof(u64), - PCI_DMA_TODEVICE); - if (pci_dma_mapping_error(sp->pdev, txdp->Buffer_Pointer)) - goto pci_map_failed; - txdp++; - } - txdp->Buffer_Pointer = pci_map_single(sp->pdev, skb->data, frg_len, PCI_DMA_TODEVICE); if (pci_dma_mapping_error(sp->pdev, txdp->Buffer_Pointer)) @@ -4161,8 +4132,6 @@ static netdev_tx_t s2io_xmit(struct sk_buff *skb, struct net_device *dev) txdp->Host_Control = (unsigned long)skb; txdp->Control_1 |= TXD_BUFFER0_SIZE(frg_len); - if (offload_type == SKB_GSO_UDP) - txdp->Control_1 |= TXD_UFO_EN; frg_cnt = skb_shinfo(skb)->nr_frags; /* For fragmented SKB. */ @@ -4177,14 +4146,9 @@ static netdev_tx_t s2io_xmit(struct sk_buff *skb, struct net_device *dev) skb_frag_size(frag), DMA_TO_DEVICE); txdp->Control_1 = TXD_BUFFER0_SIZE(skb_frag_size(frag)); - if (offload_type == SKB_GSO_UDP) - txdp->Control_1 |= TXD_UFO_EN; } txdp->Control_1 |= TXD_GATHER_CODE_LAST; - if (offload_type == SKB_GSO_UDP) - frg_cnt++; /* as Txd0 was used for inband header */ - tx_fifo = mac_control->tx_FIFO_start[queue]; val64 = fifo->list_info[put_off].list_phy_addr; writeq(val64, &tx_fifo->TxDL_Pointer); @@ -7910,11 +7874,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) NETIF_F_RXCSUM | NETIF_F_LRO; dev->features |= dev->hw_features | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; - if (sp->device_type & XFRAME_II_DEVICE) { - dev->hw_features |= NETIF_F_UFO; - if (ufo) - dev->features |= NETIF_F_UFO; - } if (sp->high_dma_flag == true) dev->features |= NETIF_F_HIGHDMA; dev->watchdog_timeo = WATCH_DOG_TIMEOUT; @@ -8147,10 +8106,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) DBG_PRINT(ERR_DBG, "%s: Large receive offload enabled\n", dev->name); - if (ufo) - DBG_PRINT(ERR_DBG, - "%s: UDP Fragmentation Offload(UFO) enabled\n", - dev->name); /* Initialize device name */ snprintf(sp->name, sizeof(sp->name), "%s Neterion %s", dev->name, sp->product_name); -- cgit v1.2.3 From f9c45ae020bab86a820d8ef9097d021d5496b855 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 3 Jul 2017 06:31:05 -0700 Subject: macb: Remove bogus reference to NETIF_F_UFO. This driver doesn't actually support UFO explicitly yet it advertises this in netdev->features. Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 26d25749c3e4..6df2cad61647 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -68,7 +68,7 @@ #define GEM_MAX_TX_LEN ((unsigned int)((1 << GEM_TX_FRMLEN_SIZE) - 1) & ~((unsigned int)(MACB_TX_LEN_ALIGN - 1))) #define GEM_MTU_MIN_SIZE ETH_MIN_MTU -#define MACB_NETIF_LSO (NETIF_F_TSO | NETIF_F_UFO) +#define MACB_NETIF_LSO NETIF_F_TSO #define MACB_WOL_HAS_MAGIC_PACKET (0x1 << 0) #define MACB_WOL_ENABLED (0x1 << 1) -- cgit v1.2.3 From 182e0b6b58463b85f9a34dd038847e4ab3604a4f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 3 Jul 2017 06:32:14 -0700 Subject: ipvlan: Stop advertising NETIF_F_UFO support. It is going away. Signed-off-by: David S. Miller --- drivers/net/ipvlan/ipvlan_main.c | 2 +- drivers/net/ipvlan/ipvtap.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c index f37e3c1fd4e7..fdde20735416 100644 --- a/drivers/net/ipvlan/ipvlan_main.c +++ b/drivers/net/ipvlan/ipvlan_main.c @@ -169,7 +169,7 @@ static void ipvlan_port_destroy(struct net_device *dev) #define IPVLAN_FEATURES \ (NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \ - NETIF_F_GSO | NETIF_F_TSO | NETIF_F_UFO | NETIF_F_GSO_ROBUST | \ + NETIF_F_GSO | NETIF_F_TSO | NETIF_F_GSO_ROBUST | \ NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_GRO | NETIF_F_RXCSUM | \ NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_STAG_FILTER) diff --git a/drivers/net/ipvlan/ipvtap.c b/drivers/net/ipvlan/ipvtap.c index 22f133ea8d7b..5dea2063dbc8 100644 --- a/drivers/net/ipvlan/ipvtap.c +++ b/drivers/net/ipvlan/ipvtap.c @@ -24,7 +24,7 @@ #include #define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \ - NETIF_F_TSO6 | NETIF_F_UFO) + NETIF_F_TSO6) static dev_t ipvtap_major; static struct cdev ipvtap_cdev; -- cgit v1.2.3 From fb652fdfe83710da0ca13448a41b7ed027d0a984 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 3 Jul 2017 06:33:08 -0700 Subject: macvlan/macvtap: Remove NETIF_F_UFO advertisement. It is going away. Signed-off-by: David S. Miller --- drivers/net/macvlan.c | 2 +- drivers/net/macvtap.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 0f581ee74fe4..ca35c6ba7947 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -841,7 +841,7 @@ static struct lock_class_key macvlan_netdev_addr_lock_key; #define MACVLAN_FEATURES \ (NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \ - NETIF_F_GSO | NETIF_F_TSO | NETIF_F_UFO | NETIF_F_LRO | \ + NETIF_F_GSO | NETIF_F_TSO | NETIF_F_LRO | \ NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_GRO | NETIF_F_RXCSUM | \ NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_STAG_FILTER) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 91e7b19bbf86..c2d0ea2fb019 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -49,7 +49,7 @@ static struct class macvtap_class = { static struct cdev macvtap_cdev; #define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \ - NETIF_F_TSO6 | NETIF_F_UFO) + NETIF_F_TSO6) static void macvtap_count_tx_dropped(struct tap_dev *tap) { -- cgit v1.2.3 From d591a1f3aad92ade4642e4173f4c368006c27f0f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 3 Jul 2017 06:35:32 -0700 Subject: tun/tap: Remove references to NETIF_F_UFO. It is going away. Signed-off-by: David S. Miller --- drivers/net/tap.c | 7 ++----- drivers/net/tun.c | 7 +------ 2 files changed, 3 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tap.c b/drivers/net/tap.c index 3570c7576993..ca267fd28ab8 100644 --- a/drivers/net/tap.c +++ b/drivers/net/tap.c @@ -943,9 +943,6 @@ static int set_offload(struct tap_queue *q, unsigned long arg) if (arg & TUN_F_TSO6) feature_mask |= NETIF_F_TSO6; } - - if (arg & TUN_F_UFO) - feature_mask |= NETIF_F_UFO; } /* tun/tap driver inverts the usage for TSO offloads, where @@ -956,7 +953,7 @@ static int set_offload(struct tap_queue *q, unsigned long arg) * When user space turns off TSO, we turn off GSO/LRO so that * user-space will not receive TSO frames. */ - if (feature_mask & (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_UFO)) + if (feature_mask & (NETIF_F_TSO | NETIF_F_TSO6)) features |= RX_OFFLOADS; else features &= ~RX_OFFLOADS; @@ -1078,7 +1075,7 @@ static long tap_ioctl(struct file *file, unsigned int cmd, case TUNSETOFFLOAD: /* let the user check for future flags */ if (arg & ~(TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 | - TUN_F_TSO_ECN | TUN_F_UFO)) + TUN_F_TSO_ECN)) return -EINVAL; rtnl_lock(); diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 3d4c24572ecd..a93392d7a340 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -199,7 +199,7 @@ struct tun_struct { struct net_device *dev; netdev_features_t set_features; #define TUN_USER_FEATURES (NETIF_F_HW_CSUM|NETIF_F_TSO_ECN|NETIF_F_TSO| \ - NETIF_F_TSO6|NETIF_F_UFO) + NETIF_F_TSO6) int align; int vnet_hdr_sz; @@ -1921,11 +1921,6 @@ static int set_offload(struct tun_struct *tun, unsigned long arg) features |= NETIF_F_TSO6; arg &= ~(TUN_F_TSO4|TUN_F_TSO6); } - - if (arg & TUN_F_UFO) { - features |= NETIF_F_UFO; - arg &= ~TUN_F_UFO; - } } /* This gives the user a way to test for new features in future by -- cgit v1.2.3 From 2082499a95ad31b88466e50f4c61513e3873ba9e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 3 Jul 2017 06:36:07 -0700 Subject: dummy: Remove references to NETIF_F_UFO. It is going away. Signed-off-by: David S. Miller --- drivers/net/dummy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c index d0c165d2086e..d0a1f9ce3168 100644 --- a/drivers/net/dummy.c +++ b/drivers/net/dummy.c @@ -345,7 +345,7 @@ static void dummy_setup(struct net_device *dev) dev->flags &= ~IFF_MULTICAST; dev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_NO_QUEUE; dev->features |= NETIF_F_SG | NETIF_F_FRAGLIST; - dev->features |= NETIF_F_ALL_TSO | NETIF_F_UFO; + dev->features |= NETIF_F_ALL_TSO; dev->features |= NETIF_F_HW_CSUM | NETIF_F_HIGHDMA | NETIF_F_LLTX; dev->features |= NETIF_F_GSO_ENCAP_ALL; dev->hw_features |= dev->features; -- cgit v1.2.3 From e078de03788353b220f3d501fc3607cc92db28c1 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 3 Jul 2017 06:37:32 -0700 Subject: virtio_net: Remove references to NETIF_F_UFO. It is going away. Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 99a26a9efec1..99830167ea2f 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -2429,7 +2429,7 @@ static int virtnet_probe(struct virtio_device *vdev) dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG; if (virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) { - dev->hw_features |= NETIF_F_TSO | NETIF_F_UFO + dev->hw_features |= NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6; } /* Individual feature bits: what can host handle? */ @@ -2439,13 +2439,11 @@ static int virtnet_probe(struct virtio_device *vdev) dev->hw_features |= NETIF_F_TSO6; if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_ECN)) dev->hw_features |= NETIF_F_TSO_ECN; - if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_UFO)) - dev->hw_features |= NETIF_F_UFO; dev->features |= NETIF_F_GSO_ROBUST; if (gso) - dev->features |= dev->hw_features & (NETIF_F_ALL_TSO|NETIF_F_UFO); + dev->features |= dev->hw_features & NETIF_F_ALL_TSO; /* (!csum && gso) case will be fixed by register_netdev() */ } if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_CSUM)) -- cgit v1.2.3 From bc240eec4b074f5dc2753f295e980e66b72c90fb Mon Sep 17 00:00:00 2001 From: Logan Gunthorpe Date: Mon, 26 Jun 2017 13:50:41 -0600 Subject: ntb: use correct mw_count function in ntb_tool and ntb_transport After converting to the new API, both ntb_tool and ntb_transport are using ntb_mw_count to iterate through ntb_peer_get_addr when they should be using ntb_peer_mw_count. This probably isn't an issue with the Intel and AMD drivers but this will matter for any future driver with asymetric memory window counts. Signed-off-by: Logan Gunthorpe Acked-by: Allen Hubbe Signed-off-by: Jon Mason Fixes: 443b9a14ecbe ("NTB: Alter MW API to support multi-ports devices") --- drivers/ntb/ntb_transport.c | 2 +- drivers/ntb/test/ntb_tool.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c index 9a03c5871efe..b29558ddfe95 100644 --- a/drivers/ntb/ntb_transport.c +++ b/drivers/ntb/ntb_transport.c @@ -1059,7 +1059,7 @@ static int ntb_transport_probe(struct ntb_client *self, struct ntb_dev *ndev) int node; int rc, i; - mw_count = ntb_mw_count(ndev, PIDX); + mw_count = ntb_peer_mw_count(ndev); if (!ndev->ops->mw_set_trans) { dev_err(&ndev->dev, "Inbound MW based NTB API is required\n"); diff --git a/drivers/ntb/test/ntb_tool.c b/drivers/ntb/test/ntb_tool.c index f002bf48a08d..a69815c45ce6 100644 --- a/drivers/ntb/test/ntb_tool.c +++ b/drivers/ntb/test/ntb_tool.c @@ -959,7 +959,7 @@ static int tool_probe(struct ntb_client *self, struct ntb_dev *ntb) tc->ntb = ntb; init_waitqueue_head(&tc->link_wq); - tc->mw_count = min(ntb_mw_count(tc->ntb, PIDX), MAX_MWS); + tc->mw_count = min(ntb_peer_mw_count(tc->ntb), MAX_MWS); for (i = 0; i < tc->mw_count; i++) { rc = tool_init_mw(tc, i); if (rc) -- cgit v1.2.3 From 6d7489c74a6ed73b4751b58b56c247bedd780a78 Mon Sep 17 00:00:00 2001 From: Eugeniy Paltsev Date: Wed, 21 Jun 2017 22:16:26 +0300 Subject: clk: axs10x: introduce AXS10X pll driver AXS10X boards manages it's clocks using various PLLs. These PLL has same dividers and corresponding control registers mapped to different addresses. So we add one common driver for such PLLs. Each PLL on AXS10X board consist of three dividers: IDIV, FBDIV and ODIV. Output clock value is managed using these dividers. We add pre-defined tables with supported rate values and appropriate configurations of IDIV, FBDIV and ODIV for each value. As of today we add support for PLLs that generate clock for the following devices: * ARC core on AXC CPU tiles. * ARC PGU on ARC SDP Mainboard. and more to come later. By this patch we add support for two plls (arc core pll and pgu pll), so we had to use two different init types: CLK_OF_DECLARE for arc core pll and regular probing for pgu pll. Acked-by: Rob Herring Acked-by: Jose Abreu Signed-off-by: Eugeniy Paltsev Signed-off-by: Vlad Zakharov Signed-off-by: Jose Abreu [sboyd@codeaurora.org: Silence dubious !x & y sparse warning, make of_axs10x_pll_clk_setup() unregister clk on failure] Signed-off-by: Stephen Boyd --- .../devicetree/bindings/clock/snps,pll-clock.txt | 28 ++ MAINTAINERS | 6 + drivers/clk/axs10x/Makefile | 1 + drivers/clk/axs10x/pll_clock.c | 346 +++++++++++++++++++++ 4 files changed, 381 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/snps,pll-clock.txt create mode 100644 drivers/clk/axs10x/pll_clock.c (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/clock/snps,pll-clock.txt b/Documentation/devicetree/bindings/clock/snps,pll-clock.txt new file mode 100644 index 000000000000..11fe4876612c --- /dev/null +++ b/Documentation/devicetree/bindings/clock/snps,pll-clock.txt @@ -0,0 +1,28 @@ +Binding for the AXS10X Generic PLL clock + +This binding uses the common clock binding[1]. + +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt + +Required properties: +- compatible: should be "snps,axs10x--pll-clock" + "snps,axs10x-arc-pll-clock" + "snps,axs10x-pgu-pll-clock" +- reg: should always contain 2 pairs address - length: first for PLL config +registers and second for corresponding LOCK CGU register. +- clocks: shall be the input parent clock phandle for the PLL. +- #clock-cells: from common clock binding; Should always be set to 0. + +Example: + input-clk: input-clk { + clock-frequency = <33333333>; + compatible = "fixed-clock"; + #clock-cells = <0>; + }; + + core-clk: core-clk@80 { + compatible = "snps,axs10x-arc-pll-clock"; + reg = <0x80 0x10>, <0x100 0x10>; + #clock-cells = <0>; + clocks = <&input-clk>; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 205d3977ac46..c571fcf62740 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12745,6 +12745,12 @@ F: arch/arc/plat-axs10x F: arch/arc/boot/dts/ax* F: Documentation/devicetree/bindings/arc/axs10* +SYNOPSYS ARC SDP clock driver +M: Eugeniy Paltsev +S: Supported +F: drivers/clk/axs10x/* +F: Documentation/devicetree/bindings/clock/snps,pll-clock.txt + SYSTEM CONFIGURATION (SYSCON) M: Lee Jones M: Arnd Bergmann diff --git a/drivers/clk/axs10x/Makefile b/drivers/clk/axs10x/Makefile index 01996b871b06..d747deafbf1e 100644 --- a/drivers/clk/axs10x/Makefile +++ b/drivers/clk/axs10x/Makefile @@ -1 +1,2 @@ obj-y += i2s_pll_clock.o +obj-y += pll_clock.o diff --git a/drivers/clk/axs10x/pll_clock.c b/drivers/clk/axs10x/pll_clock.c new file mode 100644 index 000000000000..25d8c240ddfb --- /dev/null +++ b/drivers/clk/axs10x/pll_clock.c @@ -0,0 +1,346 @@ +/* + * Synopsys AXS10X SDP Generic PLL clock driver + * + * Copyright (C) 2017 Synopsys + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* PLL registers addresses */ +#define PLL_REG_IDIV 0x0 +#define PLL_REG_FBDIV 0x4 +#define PLL_REG_ODIV 0x8 + +/* + * Bit fields of the PLL IDIV/FBDIV/ODIV registers: + * ________________________________________________________________________ + * |31 15| 14 | 13 | 12 |11 6|5 0| + * |-------RESRVED------|-NOUPDATE-|-BYPASS-|-EDGE-|--HIGHTIME--|--LOWTIME--| + * |____________________|__________|________|______|____________|___________| + * + * Following macros determine the way of access to these registers + * They should be set up only using the macros. + * reg should be an u32 variable. + */ + +#define PLL_REG_GET_LOW(reg) \ + (((reg) & (0x3F << 0)) >> 0) +#define PLL_REG_GET_HIGH(reg) \ + (((reg) & (0x3F << 6)) >> 6) +#define PLL_REG_GET_EDGE(reg) \ + (((reg) & (BIT(12))) ? 1 : 0) +#define PLL_REG_GET_BYPASS(reg) \ + (((reg) & (BIT(13))) ? 1 : 0) +#define PLL_REG_GET_NOUPD(reg) \ + (((reg) & (BIT(14))) ? 1 : 0) +#define PLL_REG_GET_PAD(reg) \ + (((reg) & (0x1FFFF << 15)) >> 15) + +#define PLL_REG_SET_LOW(reg, value) \ + { reg |= (((value) & 0x3F) << 0); } +#define PLL_REG_SET_HIGH(reg, value) \ + { reg |= (((value) & 0x3F) << 6); } +#define PLL_REG_SET_EDGE(reg, value) \ + { reg |= (((value) & 0x01) << 12); } +#define PLL_REG_SET_BYPASS(reg, value) \ + { reg |= (((value) & 0x01) << 13); } +#define PLL_REG_SET_NOUPD(reg, value) \ + { reg |= (((value) & 0x01) << 14); } +#define PLL_REG_SET_PAD(reg, value) \ + { reg |= (((value) & 0x1FFFF) << 15); } + +#define PLL_LOCK BIT(0) +#define PLL_ERROR BIT(1) +#define PLL_MAX_LOCK_TIME 100 /* 100 us */ + +struct axs10x_pll_cfg { + u32 rate; + u32 idiv; + u32 fbdiv; + u32 odiv; +}; + +static const struct axs10x_pll_cfg arc_pll_cfg[] = { + { 33333333, 1, 1, 1 }, + { 50000000, 1, 30, 20 }, + { 75000000, 2, 45, 10 }, + { 90000000, 2, 54, 10 }, + { 100000000, 1, 30, 10 }, + { 125000000, 2, 45, 6 }, + {} +}; + +static const struct axs10x_pll_cfg pgu_pll_cfg[] = { + { 25200000, 1, 84, 90 }, + { 50000000, 1, 100, 54 }, + { 74250000, 1, 44, 16 }, + {} +}; + +struct axs10x_pll_clk { + struct clk_hw hw; + void __iomem *base; + void __iomem *lock; + const struct axs10x_pll_cfg *pll_cfg; + struct device *dev; +}; + +static inline void axs10x_pll_write(struct axs10x_pll_clk *clk, u32 reg, + u32 val) +{ + iowrite32(val, clk->base + reg); +} + +static inline u32 axs10x_pll_read(struct axs10x_pll_clk *clk, u32 reg) +{ + return ioread32(clk->base + reg); +} + +static inline struct axs10x_pll_clk *to_axs10x_pll_clk(struct clk_hw *hw) +{ + return container_of(hw, struct axs10x_pll_clk, hw); +} + +static inline u32 axs10x_div_get_value(u32 reg) +{ + if (PLL_REG_GET_BYPASS(reg)) + return 1; + + return PLL_REG_GET_HIGH(reg) + PLL_REG_GET_LOW(reg); +} + +static inline u32 axs10x_encode_div(unsigned int id, int upd) +{ + u32 div = 0; + + PLL_REG_SET_LOW(div, (id % 2 == 0) ? id >> 1 : (id >> 1) + 1); + PLL_REG_SET_HIGH(div, id >> 1); + PLL_REG_SET_EDGE(div, id % 2); + PLL_REG_SET_BYPASS(div, id == 1 ? 1 : 0); + PLL_REG_SET_NOUPD(div, upd == 0 ? 1 : 0); + + return div; +} + +static unsigned long axs10x_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + u64 rate; + u32 idiv, fbdiv, odiv; + struct axs10x_pll_clk *clk = to_axs10x_pll_clk(hw); + + idiv = axs10x_div_get_value(axs10x_pll_read(clk, PLL_REG_IDIV)); + fbdiv = axs10x_div_get_value(axs10x_pll_read(clk, PLL_REG_FBDIV)); + odiv = axs10x_div_get_value(axs10x_pll_read(clk, PLL_REG_ODIV)); + + rate = (u64)parent_rate * fbdiv; + do_div(rate, idiv * odiv); + + return rate; +} + +static long axs10x_pll_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + int i; + long best_rate; + struct axs10x_pll_clk *clk = to_axs10x_pll_clk(hw); + const struct axs10x_pll_cfg *pll_cfg = clk->pll_cfg; + + if (pll_cfg[0].rate == 0) + return -EINVAL; + + best_rate = pll_cfg[0].rate; + + for (i = 1; pll_cfg[i].rate != 0; i++) { + if (abs(rate - pll_cfg[i].rate) < abs(rate - best_rate)) + best_rate = pll_cfg[i].rate; + } + + return best_rate; +} + +static int axs10x_pll_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + int i; + struct axs10x_pll_clk *clk = to_axs10x_pll_clk(hw); + const struct axs10x_pll_cfg *pll_cfg = clk->pll_cfg; + + for (i = 0; pll_cfg[i].rate != 0; i++) { + if (pll_cfg[i].rate == rate) { + axs10x_pll_write(clk, PLL_REG_IDIV, + axs10x_encode_div(pll_cfg[i].idiv, 0)); + axs10x_pll_write(clk, PLL_REG_FBDIV, + axs10x_encode_div(pll_cfg[i].fbdiv, 0)); + axs10x_pll_write(clk, PLL_REG_ODIV, + axs10x_encode_div(pll_cfg[i].odiv, 1)); + + /* + * Wait until CGU relocks and check error status. + * If after timeout CGU is unlocked yet return error + */ + udelay(PLL_MAX_LOCK_TIME); + if (!(ioread32(clk->lock) & PLL_LOCK)) + return -ETIMEDOUT; + + if (ioread32(clk->lock) & PLL_ERROR) + return -EINVAL; + + return 0; + } + } + + dev_err(clk->dev, "invalid rate=%ld, parent_rate=%ld\n", rate, + parent_rate); + return -EINVAL; +} + +static const struct clk_ops axs10x_pll_ops = { + .recalc_rate = axs10x_pll_recalc_rate, + .round_rate = axs10x_pll_round_rate, + .set_rate = axs10x_pll_set_rate, +}; + +static int axs10x_pll_clk_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + const char *parent_name; + struct axs10x_pll_clk *pll_clk; + struct resource *mem; + struct clk_init_data init = { }; + int ret; + + pll_clk = devm_kzalloc(dev, sizeof(*pll_clk), GFP_KERNEL); + if (!pll_clk) + return -ENOMEM; + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + pll_clk->base = devm_ioremap_resource(dev, mem); + if (IS_ERR(pll_clk->base)) + return PTR_ERR(pll_clk->base); + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); + pll_clk->lock = devm_ioremap_resource(dev, mem); + if (IS_ERR(pll_clk->lock)) + return PTR_ERR(pll_clk->lock); + + init.name = dev->of_node->name; + init.ops = &axs10x_pll_ops; + parent_name = of_clk_get_parent_name(dev->of_node, 0); + init.parent_names = &parent_name; + init.num_parents = 1; + pll_clk->hw.init = &init; + pll_clk->dev = dev; + pll_clk->pll_cfg = of_device_get_match_data(dev); + + if (!pll_clk->pll_cfg) { + dev_err(dev, "No OF match data provided\n"); + return -EINVAL; + } + + ret = devm_clk_hw_register(dev, &pll_clk->hw); + if (ret) { + dev_err(dev, "failed to register %s clock\n", init.name); + return ret; + } + + return of_clk_add_hw_provider(dev->of_node, of_clk_hw_simple_get, + &pll_clk->hw); +} + +static int axs10x_pll_clk_remove(struct platform_device *pdev) +{ + of_clk_del_provider(pdev->dev.of_node); + return 0; +} + +static void __init of_axs10x_pll_clk_setup(struct device_node *node) +{ + const char *parent_name; + struct axs10x_pll_clk *pll_clk; + struct clk_init_data init = { }; + int ret; + + pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL); + if (!pll_clk) + return; + + pll_clk->base = of_iomap(node, 0); + if (!pll_clk->base) { + pr_err("failed to map pll div registers\n"); + goto err_free_pll_clk; + } + + pll_clk->lock = of_iomap(node, 1); + if (!pll_clk->lock) { + pr_err("failed to map pll lock register\n"); + goto err_unmap_base; + } + + init.name = node->name; + init.ops = &axs10x_pll_ops; + parent_name = of_clk_get_parent_name(node, 0); + init.parent_names = &parent_name; + init.num_parents = parent_name ? 1 : 0; + pll_clk->hw.init = &init; + pll_clk->pll_cfg = arc_pll_cfg; + + ret = clk_hw_register(NULL, &pll_clk->hw); + if (ret) { + pr_err("failed to register %s clock\n", node->name); + goto err_unmap_lock; + } + + ret = of_clk_add_hw_provider(node, of_clk_hw_simple_get, &pll_clk->hw); + if (ret) { + pr_err("failed to add hw provider for %s clock\n", node->name); + goto err_unregister_clk; + } + + return; + +err_unregister_clk: + clk_hw_unregister(&pll_clk->hw); +err_unmap_lock: + iounmap(pll_clk->lock); +err_unmap_base: + iounmap(pll_clk->base); +err_free_pll_clk: + kfree(pll_clk); +} +CLK_OF_DECLARE(axs10x_pll_clock, "snps,axs10x-arc-pll-clock", + of_axs10x_pll_clk_setup); + +static const struct of_device_id axs10x_pll_clk_id[] = { + { .compatible = "snps,axs10x-pgu-pll-clock", .data = &pgu_pll_cfg}, + { } +}; +MODULE_DEVICE_TABLE(of, axs10x_pll_clk_id); + +static struct platform_driver axs10x_pll_clk_driver = { + .driver = { + .name = "axs10x-pll-clock", + .of_match_table = axs10x_pll_clk_id, + }, + .probe = axs10x_pll_clk_probe, + .remove = axs10x_pll_clk_remove, +}; +builtin_platform_driver(axs10x_pll_clk_driver); + +MODULE_AUTHOR("Vlad Zakharov "); +MODULE_DESCRIPTION("Synopsys AXS10X SDP Generic PLL Clock Driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 3bded569cab4d839a47fcbd83e4e8926ae6ddad5 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 9 Jul 2017 15:28:07 +0200 Subject: clk: vc5: Prevent division by zero on unconfigured outputs In case the initial values of the FOD registers are not configured in the OTP or by the bootloader, it is possible that the FOD registers will contain zeroes. The code in vc5_fod_recalc_rate() immediately feeds the FOD divider value obtained from the FOD registers into the div64_u64() and if the FOD divider value is zero, triggers division by zero exception. Check if the FOD divider value is zero and return the frequency of the FOD output as 0 Hz if it is so. This prevents the division by zero exception. Signed-off-by: Marek Vasut Cc: Stephen Boyd Cc: Alexey Firago Cc: Michael Turquette Cc: Laurent Pinchart Cc: linux-renesas-soc@vger.kernel.org Tested-by: Laurent Pinchart # Salvator-XS with the display LVDS output. Signed-off-by: Stephen Boyd --- drivers/clk/clk-versaclock5.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c index ea7d552a2f2b..194d3f420847 100644 --- a/drivers/clk/clk-versaclock5.c +++ b/drivers/clk/clk-versaclock5.c @@ -426,6 +426,10 @@ static unsigned long vc5_fod_recalc_rate(struct clk_hw *hw, div_frc = (od_frc[0] << 22) | (od_frc[1] << 14) | (od_frc[2] << 6) | (od_frc[3] >> 2); + /* Avoid division by zero if the output is not configured. */ + if (div_int == 0 && div_frc == 0) + return 0; + /* The PLL divider has 12 integer bits and 30 fractional bits */ return div64_u64((u64)f_in << 24ULL, ((u64)div_int << 24ULL) + div_frc); } -- cgit v1.2.3 From a4decf5899c8073e9ec5631b720d6054f349a8ab Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 9 Jul 2017 15:28:08 +0200 Subject: clk: vc5: Fix trivial typo Fix trivial typo in vc5_clk_out_unprepare() , s/Enable/Disable/ . Signed-off-by: Marek Vasut Cc: Stephen Boyd Cc: Alexey Firago Cc: Michael Turquette Cc: Laurent Pinchart Cc: linux-renesas-soc@vger.kernel.org Tested-by: Laurent Pinchart # Salvator-XS with the display LVDS output. Signed-off-by: Stephen Boyd --- drivers/clk/clk-versaclock5.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c index 194d3f420847..b70c2e684de6 100644 --- a/drivers/clk/clk-versaclock5.c +++ b/drivers/clk/clk-versaclock5.c @@ -520,7 +520,7 @@ static void vc5_clk_out_unprepare(struct clk_hw *hw) struct vc5_hw_data *hwdata = container_of(hw, struct vc5_hw_data, hw); struct vc5_driver_data *vc5 = hwdata->vc5; - /* Enable the clock buffer */ + /* Disable the clock buffer */ regmap_update_bits(vc5->regmap, VC5_CLK_OUTPUT_CFG(hwdata->num, 1), VC5_CLK_OUTPUT_CFG1_EN_CLKBUF, 0); } -- cgit v1.2.3 From 325b7b90f9a87a4bdee7059d10bd98a11154ceae Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 9 Jul 2017 15:28:09 +0200 Subject: clk: vc5: Do not warn about disabled output buffer input muxes The output buffer input mux can be configured in either of three states -- disabled, input from FOD, input from previous output. If the output buffer input mux is set to disabled, the code in vc5_clk_out_get_parent() would consider this an invalid setting and warn about it, which is not necessarily the case. In case the output buffer input mux is disabled, default to input from FOD to have some parent and don't print the warning. Signed-off-by: Marek Vasut Cc: Stephen Boyd Cc: Alexey Firago Cc: Michael Turquette Cc: Laurent Pinchart Cc: linux-renesas-soc@vger.kernel.org Tested-by: Laurent Pinchart # Salvator-XS with the display LVDS output. Signed-off-by: Stephen Boyd --- drivers/clk/clk-versaclock5.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c index b70c2e684de6..185d7a5d36e0 100644 --- a/drivers/clk/clk-versaclock5.c +++ b/drivers/clk/clk-versaclock5.c @@ -541,6 +541,9 @@ static unsigned char vc5_clk_out_get_parent(struct clk_hw *hw) regmap_read(vc5->regmap, VC5_OUT_DIV_CONTROL(hwdata->num), &src); src &= mask; + if (src == 0) /* Input mux set to DISABLED */ + return 0; + if ((src & fodclkmask) == VC5_OUT_DIV_CONTROL_EN_FOD) return 0; -- cgit v1.2.3 From 718f4694ea15a1033f48ea2e44f6428df705a1a8 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 9 Jul 2017 15:28:10 +0200 Subject: clk: vc5: Configure the output buffer input mux on prepare The output buffer input mux can be configured in either of three states -- disabled, input from FOD, input from previous output. Once the .prepare() callback of the output buffer is called, the output buffer input mux must be set to either input from FOD or input from previous output, it cannot be set to Disabled anymore or the output won't work. Default to the input from FOD if the output buffer input mux was Disabled and the .prepare() was called on it. Note that we do not set the output buffer input mux back to Disabled in the .unprepare() callback as there is no obvious benefit of doing so. We disable the entire output buffer in the .unprepare() callback already. Signed-off-by: Marek Vasut Cc: Stephen Boyd Cc: Alexey Firago Cc: Michael Turquette Cc: Laurent Pinchart Cc: linux-renesas-soc@vger.kernel.org Tested-by: Laurent Pinchart # Salvator-XS with the display LVDS output. Signed-off-by: Stephen Boyd --- drivers/clk/clk-versaclock5.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c index 185d7a5d36e0..29df1100f96d 100644 --- a/drivers/clk/clk-versaclock5.c +++ b/drivers/clk/clk-versaclock5.c @@ -507,6 +507,25 @@ static int vc5_clk_out_prepare(struct clk_hw *hw) { struct vc5_hw_data *hwdata = container_of(hw, struct vc5_hw_data, hw); struct vc5_driver_data *vc5 = hwdata->vc5; + const u8 mask = VC5_OUT_DIV_CONTROL_SELB_NORM | + VC5_OUT_DIV_CONTROL_SEL_EXT | + VC5_OUT_DIV_CONTROL_EN_FOD; + unsigned int src; + int ret; + + /* + * If the input mux is disabled, enable it first and + * select source from matching FOD. + */ + regmap_read(vc5->regmap, VC5_OUT_DIV_CONTROL(hwdata->num), &src); + if ((src & mask) == 0) { + src = VC5_OUT_DIV_CONTROL_RESET | VC5_OUT_DIV_CONTROL_EN_FOD; + ret = regmap_update_bits(vc5->regmap, + VC5_OUT_DIV_CONTROL(hwdata->num), + mask | VC5_OUT_DIV_CONTROL_RESET, src); + if (ret) + return ret; + } /* Enable the clock buffer */ regmap_update_bits(vc5->regmap, VC5_CLK_OUTPUT_CFG(hwdata->num, 1), -- cgit v1.2.3 From 55997db52e997ea7fd8b036966c1f1943fc32a6f Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 9 Jul 2017 15:28:11 +0200 Subject: clk: vc5: Split clock input mux and predivider Split the VC5 clock input mux and the predivider to more accurately model the hardware and fix the previously incorrect assumption that both the OUT_SEL_I2CB and the PLL are fed from the predivider. It is in fact the clock input mux output which is directly feeding the clock into the OUT_SEL_I2CB output, while the clock input mux output first passes through the predivider before it is fed into the PLL. Signed-off-by: Marek Vasut Cc: Stephen Boyd Cc: Alexey Firago Cc: Michael Turquette Cc: Laurent Pinchart Cc: linux-renesas-soc@vger.kernel.org Tested-by: Laurent Pinchart on Salvator-XS with the display LVDS output. Signed-off-by: Stephen Boyd --- drivers/clk/clk-versaclock5.c | 46 ++++++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c index 29df1100f96d..cae07267a884 100644 --- a/drivers/clk/clk-versaclock5.c +++ b/drivers/clk/clk-versaclock5.c @@ -157,6 +157,7 @@ struct vc5_driver_data { struct clk *pin_clkin; unsigned char clk_mux_ins; struct clk_hw clk_mux; + struct clk_hw clk_pfd; struct vc5_hw_data clk_pll; struct vc5_hw_data clk_fod[VC5_MAX_FOD_NUM]; struct vc5_hw_data clk_out[VC5_MAX_CLK_OUT_NUM]; @@ -166,6 +167,10 @@ static const char * const vc5_mux_names[] = { "mux" }; +static const char * const vc5_pfd_names[] = { + "pfd" +}; + static const char * const vc5_pll_names[] = { "pll" }; @@ -254,11 +259,16 @@ static int vc5_mux_set_parent(struct clk_hw *hw, u8 index) return regmap_update_bits(vc5->regmap, VC5_PRIM_SRC_SHDN, mask, src); } -static unsigned long vc5_mux_recalc_rate(struct clk_hw *hw, +static const struct clk_ops vc5_mux_ops = { + .set_parent = vc5_mux_set_parent, + .get_parent = vc5_mux_get_parent, +}; + +static unsigned long vc5_pfd_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct vc5_driver_data *vc5 = - container_of(hw, struct vc5_driver_data, clk_mux); + container_of(hw, struct vc5_driver_data, clk_pfd); unsigned int prediv, div; regmap_read(vc5->regmap, VC5_VCO_CTRL_AND_PREDIV, &prediv); @@ -276,7 +286,7 @@ static unsigned long vc5_mux_recalc_rate(struct clk_hw *hw, return parent_rate / VC5_REF_DIVIDER_REF_DIV(div); } -static long vc5_mux_round_rate(struct clk_hw *hw, unsigned long rate, +static long vc5_pfd_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) { unsigned long idiv; @@ -296,11 +306,11 @@ static long vc5_mux_round_rate(struct clk_hw *hw, unsigned long rate, return *parent_rate / idiv; } -static int vc5_mux_set_rate(struct clk_hw *hw, unsigned long rate, +static int vc5_pfd_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct vc5_driver_data *vc5 = - container_of(hw, struct vc5_driver_data, clk_mux); + container_of(hw, struct vc5_driver_data, clk_pfd); unsigned long idiv; u8 div; @@ -328,12 +338,10 @@ static int vc5_mux_set_rate(struct clk_hw *hw, unsigned long rate, return 0; } -static const struct clk_ops vc5_mux_ops = { - .set_parent = vc5_mux_set_parent, - .get_parent = vc5_mux_get_parent, - .recalc_rate = vc5_mux_recalc_rate, - .round_rate = vc5_mux_round_rate, - .set_rate = vc5_mux_set_rate, +static const struct clk_ops vc5_pfd_ops = { + .recalc_rate = vc5_pfd_recalc_rate, + .round_rate = vc5_pfd_round_rate, + .set_rate = vc5_pfd_set_rate, }; /* @@ -698,12 +706,26 @@ static int vc5_probe(struct i2c_client *client, goto err_clk; } + /* Register PFD */ + memset(&init, 0, sizeof(init)); + init.name = vc5_pfd_names[0]; + init.ops = &vc5_pfd_ops; + init.flags = CLK_SET_RATE_PARENT; + init.parent_names = vc5_mux_names; + init.num_parents = 1; + vc5->clk_pfd.init = &init; + ret = devm_clk_hw_register(&client->dev, &vc5->clk_pfd); + if (ret) { + dev_err(&client->dev, "unable to register %s\n", init.name); + goto err_clk; + } + /* Register PLL */ memset(&init, 0, sizeof(init)); init.name = vc5_pll_names[0]; init.ops = &vc5_pll_ops; init.flags = CLK_SET_RATE_PARENT; - init.parent_names = vc5_mux_names; + init.parent_names = vc5_pfd_names; init.num_parents = 1; vc5->clk_pll.num = 0; vc5->clk_pll.vc5 = vc5; -- cgit v1.2.3 From 8c1ebe9762670159ca982167131af63c94ff1571 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 9 Jul 2017 15:28:12 +0200 Subject: clk: vc5: Add support for the input frequency doubler The VersaClock 6 has an input frequency doubler between the input clock mux and the predivider. Add new capability flag and support for this frequency doubler block into the driver. Signed-off-by: Marek Vasut Cc: Stephen Boyd Cc: Alexey Firago Cc: Michael Turquette Cc: Laurent Pinchart Cc: linux-renesas-soc@vger.kernel.org Tested-by: Laurent Pinchart on Salvator-XS with the display LVDS output. Signed-off-by: Stephen Boyd --- drivers/clk/clk-versaclock5.c | 78 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c index cae07267a884..2bdd456f89e4 100644 --- a/drivers/clk/clk-versaclock5.c +++ b/drivers/clk/clk-versaclock5.c @@ -57,6 +57,7 @@ #define VC5_PRIM_SRC_SHDN 0x10 #define VC5_PRIM_SRC_SHDN_EN_XTAL BIT(7) #define VC5_PRIM_SRC_SHDN_EN_CLKIN BIT(6) +#define VC5_PRIM_SRC_SHDN_EN_DOUBLE_XTAL_FREQ BIT(3) #define VC5_PRIM_SRC_SHDN_SP BIT(1) #define VC5_PRIM_SRC_SHDN_EN_GBL_SHDN BIT(0) @@ -122,6 +123,8 @@ /* flags to describe chip features */ /* chip has built-in oscilator */ #define VC5_HAS_INTERNAL_XTAL BIT(0) +/* chip has PFD requency doubler */ +#define VC5_HAS_PFD_FREQ_DBL BIT(1) /* Supported IDT VC5 models. */ enum vc5_model { @@ -157,6 +160,7 @@ struct vc5_driver_data { struct clk *pin_clkin; unsigned char clk_mux_ins; struct clk_hw clk_mux; + struct clk_hw clk_mul; struct clk_hw clk_pfd; struct vc5_hw_data clk_pll; struct vc5_hw_data clk_fod[VC5_MAX_FOD_NUM]; @@ -167,6 +171,10 @@ static const char * const vc5_mux_names[] = { "mux" }; +static const char * const vc5_dbl_names[] = { + "dbl" +}; + static const char * const vc5_pfd_names[] = { "pfd" }; @@ -264,6 +272,54 @@ static const struct clk_ops vc5_mux_ops = { .get_parent = vc5_mux_get_parent, }; +static unsigned long vc5_dbl_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct vc5_driver_data *vc5 = + container_of(hw, struct vc5_driver_data, clk_mul); + unsigned int premul; + + regmap_read(vc5->regmap, VC5_PRIM_SRC_SHDN, &premul); + if (premul & VC5_PRIM_SRC_SHDN_EN_DOUBLE_XTAL_FREQ) + parent_rate *= 2; + + return parent_rate; +} + +static long vc5_dbl_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + if ((*parent_rate == rate) || ((*parent_rate * 2) == rate)) + return rate; + else + return -EINVAL; +} + +static int vc5_dbl_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct vc5_driver_data *vc5 = + container_of(hw, struct vc5_driver_data, clk_mul); + u32 mask; + + if ((parent_rate * 2) == rate) + mask = VC5_PRIM_SRC_SHDN_EN_DOUBLE_XTAL_FREQ; + else + mask = 0; + + regmap_update_bits(vc5->regmap, VC5_PRIM_SRC_SHDN, + VC5_PRIM_SRC_SHDN_EN_DOUBLE_XTAL_FREQ, + mask); + + return 0; +} + +static const struct clk_ops vc5_dbl_ops = { + .recalc_rate = vc5_dbl_recalc_rate, + .round_rate = vc5_dbl_round_rate, + .set_rate = vc5_dbl_set_rate, +}; + static unsigned long vc5_pfd_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { @@ -706,12 +762,32 @@ static int vc5_probe(struct i2c_client *client, goto err_clk; } + if (vc5->chip_info->flags & VC5_HAS_PFD_FREQ_DBL) { + /* Register frequency doubler */ + memset(&init, 0, sizeof(init)); + init.name = vc5_dbl_names[0]; + init.ops = &vc5_dbl_ops; + init.flags = CLK_SET_RATE_PARENT; + init.parent_names = vc5_mux_names; + init.num_parents = 1; + vc5->clk_mul.init = &init; + ret = devm_clk_hw_register(&client->dev, &vc5->clk_mul); + if (ret) { + dev_err(&client->dev, "unable to register %s\n", + init.name); + goto err_clk; + } + } + /* Register PFD */ memset(&init, 0, sizeof(init)); init.name = vc5_pfd_names[0]; init.ops = &vc5_pfd_ops; init.flags = CLK_SET_RATE_PARENT; - init.parent_names = vc5_mux_names; + if (vc5->chip_info->flags & VC5_HAS_PFD_FREQ_DBL) + init.parent_names = vc5_dbl_names; + else + init.parent_names = vc5_mux_names; init.num_parents = 1; vc5->clk_pfd.init = &init; ret = devm_clk_hw_register(&client->dev, &vc5->clk_pfd); -- cgit v1.2.3 From dbf6b16f56830c995515e0d7350e9c639e6d186f Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 9 Jul 2017 15:28:14 +0200 Subject: clk: vc5: Add support for IDT VersaClock 5P49V6901 Update IDT VersaClock 5 driver to support IDT VersaClock 6 5P49V6901. This chip has two clock inputs (external XTAL or external CLKIN), four fractional dividers (FODs) and five clock outputs (four universal clock outputs and one reference clock output at OUT0_SELB_I2C). Signed-off-by: Marek Vasut Cc: Alexey Firago Cc: Stephen Boyd Cc: Michael Turquette Cc: Laurent Pinchart Cc: linux-renesas-soc@vger.kernel.org Tested-by: Laurent Pinchart on Salvator-XS with the display LVDS output. Signed-off-by: Stephen Boyd --- drivers/clk/Kconfig | 6 +++--- drivers/clk/clk-versaclock5.c | 11 +++++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 68ca2d9fcd73..a874b72612d0 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -210,14 +210,14 @@ config COMMON_CLK_OXNAS Support for the OXNAS SoC Family clocks. config COMMON_CLK_VC5 - tristate "Clock driver for IDT VersaClock5 devices" + tristate "Clock driver for IDT VersaClock 5,6 devices" depends on I2C depends on OF select REGMAP_I2C help ---help--- - This driver supports the IDT VersaClock5 programmable clock - generator. + This driver supports the IDT VersaClock 5 and VersaClock 6 + programmable clock generators. source "drivers/clk/bcm/Kconfig" source "drivers/clk/hisilicon/Kconfig" diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c index 2bdd456f89e4..e4c36dfdc851 100644 --- a/drivers/clk/clk-versaclock5.c +++ b/drivers/clk/clk-versaclock5.c @@ -131,6 +131,7 @@ enum vc5_model { IDT_VC5_5P49V5923, IDT_VC5_5P49V5933, IDT_VC5_5P49V5935, + IDT_VC6_5P49V6901, }; /* Structure to describe features of a particular VC5 model */ @@ -686,6 +687,7 @@ static int vc5_map_index_to_output(const enum vc5_model model, return (n == 0) ? 0 : 3; case IDT_VC5_5P49V5923: case IDT_VC5_5P49V5935: + case IDT_VC6_5P49V6901: default: return n; } @@ -923,10 +925,18 @@ static const struct vc5_chip_info idt_5p49v5935_info = { .flags = VC5_HAS_INTERNAL_XTAL, }; +static const struct vc5_chip_info idt_5p49v6901_info = { + .model = IDT_VC6_5P49V6901, + .clk_fod_cnt = 4, + .clk_out_cnt = 5, + .flags = VC5_HAS_PFD_FREQ_DBL, +}; + static const struct i2c_device_id vc5_id[] = { { "5p49v5923", .driver_data = IDT_VC5_5P49V5923 }, { "5p49v5933", .driver_data = IDT_VC5_5P49V5933 }, { "5p49v5935", .driver_data = IDT_VC5_5P49V5935 }, + { "5p49v6901", .driver_data = IDT_VC6_5P49V6901 }, { } }; MODULE_DEVICE_TABLE(i2c, vc5_id); @@ -935,6 +945,7 @@ static const struct of_device_id clk_vc5_of_match[] = { { .compatible = "idt,5p49v5923", .data = &idt_5p49v5923_info }, { .compatible = "idt,5p49v5933", .data = &idt_5p49v5933_info }, { .compatible = "idt,5p49v5935", .data = &idt_5p49v5935_info }, + { .compatible = "idt,5p49v6901", .data = &idt_5p49v6901_info }, { }, }; MODULE_DEVICE_TABLE(of, clk_vc5_of_match); -- cgit v1.2.3 From b191155541f2a4cfbe62697c8d65919549f948c0 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Sun, 9 Jul 2017 20:39:57 +0300 Subject: clk: vc5: Add support for IDT VersaClock 5P49V5925 Update IDT VersaClock 5 driver to support 5P49V5925. This chip has only external clock input, four fractional dividers (FODs) and five clock outputs (four universal clock outputs and one reference clock output at OUT0_SELB_I2C). Signed-off-by: Vladimir Barinov Reviewed-by: Marek Vasut Signed-off-by: Stephen Boyd --- drivers/clk/clk-versaclock5.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c index e4c36dfdc851..decffb3826ec 100644 --- a/drivers/clk/clk-versaclock5.c +++ b/drivers/clk/clk-versaclock5.c @@ -129,6 +129,7 @@ /* Supported IDT VC5 models. */ enum vc5_model { IDT_VC5_5P49V5923, + IDT_VC5_5P49V5925, IDT_VC5_5P49V5933, IDT_VC5_5P49V5935, IDT_VC6_5P49V6901, @@ -686,6 +687,7 @@ static int vc5_map_index_to_output(const enum vc5_model model, case IDT_VC5_5P49V5933: return (n == 0) ? 0 : 3; case IDT_VC5_5P49V5923: + case IDT_VC5_5P49V5925: case IDT_VC5_5P49V5935: case IDT_VC6_5P49V6901: default: @@ -911,6 +913,13 @@ static const struct vc5_chip_info idt_5p49v5923_info = { .flags = 0, }; +static const struct vc5_chip_info idt_5p49v5925_info = { + .model = IDT_VC5_5P49V5925, + .clk_fod_cnt = 4, + .clk_out_cnt = 5, + .flags = 0, +}; + static const struct vc5_chip_info idt_5p49v5933_info = { .model = IDT_VC5_5P49V5933, .clk_fod_cnt = 2, @@ -934,6 +943,7 @@ static const struct vc5_chip_info idt_5p49v6901_info = { static const struct i2c_device_id vc5_id[] = { { "5p49v5923", .driver_data = IDT_VC5_5P49V5923 }, + { "5p49v5925", .driver_data = IDT_VC5_5P49V5925 }, { "5p49v5933", .driver_data = IDT_VC5_5P49V5933 }, { "5p49v5935", .driver_data = IDT_VC5_5P49V5935 }, { "5p49v6901", .driver_data = IDT_VC6_5P49V6901 }, @@ -943,6 +953,7 @@ MODULE_DEVICE_TABLE(i2c, vc5_id); static const struct of_device_id clk_vc5_of_match[] = { { .compatible = "idt,5p49v5923", .data = &idt_5p49v5923_info }, + { .compatible = "idt,5p49v5925", .data = &idt_5p49v5925_info }, { .compatible = "idt,5p49v5933", .data = &idt_5p49v5933_info }, { .compatible = "idt,5p49v5935", .data = &idt_5p49v5935_info }, { .compatible = "idt,5p49v6901", .data = &idt_5p49v6901_info }, -- cgit v1.2.3 From ad364f447e367a4b997cc75093600663caeedb68 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 14 Jul 2017 20:12:12 -0700 Subject: drm/vgem: add compat_ioctl support DRM drivers should supply a compat version if they're going to provide an ioctl implementation at all. This can confuse 32-bit user space on a 64-bit system. Signed-off-by: Brian Norris Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20170715031212.108695-1-briannorris@chromium.org --- drivers/gpu/drm/vgem/vgem_drv.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/vgem/vgem_drv.c b/drivers/gpu/drm/vgem/vgem_drv.c index c938af8c40cf..12289673f457 100644 --- a/drivers/gpu/drm/vgem/vgem_drv.c +++ b/drivers/gpu/drm/vgem/vgem_drv.c @@ -278,6 +278,7 @@ static const struct file_operations vgem_driver_fops = { .poll = drm_poll, .read = drm_read, .unlocked_ioctl = drm_ioctl, + .compat_ioctl = drm_compat_ioctl, .release = drm_release, }; -- cgit v1.2.3 From e59e18989c68a8d7941005f81ad6abc4ca682de0 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 13 Jul 2017 15:13:41 +0200 Subject: iio: accel: bmc150: Always restore device to normal mode after suspend-resume After probe we would put the device in normal mode, after a runtime suspend-resume we would put it back in normal mode. But for a regular suspend-resume we would only put it back in normal mode if triggers or events have been requested. This is not consistent and breaks reading raw values after a suspend-resume. This commit changes the regular resume path to also unconditionally put the device back in normal mode, fixing reading of raw values not working after a regular suspend-resume cycle. Signed-off-by: Hans de Goede Reviewed-by: Srinivas Pandruvada Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/accel/bmc150-accel-core.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/accel/bmc150-accel-core.c b/drivers/iio/accel/bmc150-accel-core.c index 6b5d3be283c4..807299dd45eb 100644 --- a/drivers/iio/accel/bmc150-accel-core.c +++ b/drivers/iio/accel/bmc150-accel-core.c @@ -193,7 +193,6 @@ struct bmc150_accel_data { struct regmap *regmap; int irq; struct bmc150_accel_interrupt interrupts[BMC150_ACCEL_INTERRUPTS]; - atomic_t active_intr; struct bmc150_accel_trigger triggers[BMC150_ACCEL_TRIGGERS]; struct mutex mutex; u8 fifo_mode, watermark; @@ -493,11 +492,6 @@ static int bmc150_accel_set_interrupt(struct bmc150_accel_data *data, int i, goto out_fix_power_state; } - if (state) - atomic_inc(&data->active_intr); - else - atomic_dec(&data->active_intr); - return 0; out_fix_power_state: @@ -1710,8 +1704,7 @@ static int bmc150_accel_resume(struct device *dev) struct bmc150_accel_data *data = iio_priv(indio_dev); mutex_lock(&data->mutex); - if (atomic_read(&data->active_intr)) - bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_NORMAL, 0); + bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_NORMAL, 0); bmc150_accel_fifo_set_mode(data); mutex_unlock(&data->mutex); -- cgit v1.2.3 From c744cf5b9dea1da57a6fdb314c8b403cb22075c0 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Mon, 17 Jul 2017 23:41:52 +0530 Subject: net: cadence: macb: constify pci_device_id. pci_device_id are not supposed to change at runtime. All functions working with pci_device_id provided by work with const pci_device_id. So mark the non-const structs as const. File size before: text data bss dec hex filename 791 336 0 1127 467 net/ethernet/cadence/macb_pci.o File size After adding 'const': text data bss dec hex filename 855 272 0 1127 467 net/ethernet/cadence/macb_pci.o Signed-off-by: Arvind Yadav Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/cadence/macb_pci.c b/drivers/net/ethernet/cadence/macb_pci.c index 9906fda76087..248a8fc45069 100644 --- a/drivers/net/ethernet/cadence/macb_pci.c +++ b/drivers/net/ethernet/cadence/macb_pci.c @@ -128,7 +128,7 @@ static void macb_remove(struct pci_dev *pdev) clk_unregister(plat_data->hclk); } -static struct pci_device_id dev_id_table[] = { +static const struct pci_device_id dev_id_table[] = { { PCI_DEVICE(CDNS_VENDOR_ID, CDNS_DEVICE_ID), }, { 0, } }; -- cgit v1.2.3 From 7924a42133324d1cbec1c217eca598712707bd03 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Mon, 17 Jul 2017 23:42:34 +0530 Subject: net: ec_bhf: constify pci_device_id. pci_device_id are not supposed to change at runtime. All functions working with pci_device_id provided by work with const pci_device_id. So mark the non-const structs as const. File size before: text data bss dec hex filename 5113 384 0 5497 1579 drivers/net/ethernet/ec_bhf.o File size After adding 'const': text data bss dec hex filename 5177 320 0 5497 1579 drivers/net/ethernet/ec_bhf.o Signed-off-by: Arvind Yadav Signed-off-by: David S. Miller --- drivers/net/ethernet/ec_bhf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/ec_bhf.c b/drivers/net/ethernet/ec_bhf.c index 4ee042c034a1..1b79a6defd56 100644 --- a/drivers/net/ethernet/ec_bhf.c +++ b/drivers/net/ethernet/ec_bhf.c @@ -73,7 +73,7 @@ #define ETHERCAT_MASTER_ID 0x14 -static struct pci_device_id ids[] = { +static const struct pci_device_id ids[] = { { PCI_DEVICE(0x15ec, 0x5000), }, { 0, } }; -- cgit v1.2.3 From 50db2cd408a4a8883e738874208c84527e3c6a41 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 15 Jul 2017 22:07:44 +0200 Subject: iio: orientation: hid-sensor-rotation: Drop unnecessary static Drop static on a local variable, when the variable is initialized before any possible use. Thus, the static has no benefit. The semantic patch that fixes this problem is as follows: (http://coccinelle.lip6.fr/) // @bad exists@ position p; identifier x; type T; @@ static T x@p; ... x = <+...x...+> @@ identifier x; expression e; type T; position p != bad.p; @@ -static T x@p; ... when != x when strict ?x = e; // Signed-off-by: Julia Lawall Signed-off-by: Jonathan Cameron --- drivers/iio/orientation/hid-sensor-rotation.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/orientation/hid-sensor-rotation.c b/drivers/iio/orientation/hid-sensor-rotation.c index e9fa86c87db5..98fe0c5df380 100644 --- a/drivers/iio/orientation/hid-sensor-rotation.c +++ b/drivers/iio/orientation/hid-sensor-rotation.c @@ -238,7 +238,7 @@ static int dev_rot_parse_report(struct platform_device *pdev, static int hid_dev_rot_probe(struct platform_device *pdev) { int ret; - static char *name; + char *name; struct iio_dev *indio_dev; struct dev_rot_state *rot_state; struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; -- cgit v1.2.3 From 8b298fb789aaf093897d2f2b905d0fbee8663c2e Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sun, 16 Jul 2017 18:26:03 -0300 Subject: iio: adc: ad7766: Remove unneeded gpiod NULL check The gpiod API checks for NULL descriptors, so there is no need to duplicate the check in the driver. Signed-off-by: Fabio Estevam Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7766.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/adc/ad7766.c b/drivers/iio/adc/ad7766.c index 75cca42b6e70..ce45037295d8 100644 --- a/drivers/iio/adc/ad7766.c +++ b/drivers/iio/adc/ad7766.c @@ -103,8 +103,7 @@ static int ad7766_preenable(struct iio_dev *indio_dev) return ret; } - if (ad7766->pd_gpio) - gpiod_set_value(ad7766->pd_gpio, 0); + gpiod_set_value(ad7766->pd_gpio, 0); return 0; } @@ -113,8 +112,7 @@ static int ad7766_postdisable(struct iio_dev *indio_dev) { struct ad7766 *ad7766 = iio_priv(indio_dev); - if (ad7766->pd_gpio) - gpiod_set_value(ad7766->pd_gpio, 1); + gpiod_set_value(ad7766->pd_gpio, 1); /* * The PD pin is synchronous to the clock, so give it some time to -- cgit v1.2.3 From 95b80bf3db03c2bf572a357cf74b9a6aefef0a4a Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 17 Jul 2017 18:09:09 -0300 Subject: mdio_bus: Remove unneeded gpiod NULL check The gpiod API checks for NULL descriptors, so there is no need to duplicate the check in the driver. Signed-off-by: Fabio Estevam Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/mdio_bus.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 2df7b62c1a36..b6f9fa670168 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -399,8 +399,7 @@ error: } /* Put PHYs in RESET to save power */ - if (bus->reset_gpiod) - gpiod_set_value_cansleep(bus->reset_gpiod, 1); + gpiod_set_value_cansleep(bus->reset_gpiod, 1); device_del(&bus->dev); return err; @@ -425,8 +424,7 @@ void mdiobus_unregister(struct mii_bus *bus) } /* Put PHYs in RESET to save power */ - if (bus->reset_gpiod) - gpiod_set_value_cansleep(bus->reset_gpiod, 1); + gpiod_set_value_cansleep(bus->reset_gpiod, 1); device_del(&bus->dev); } -- cgit v1.2.3 From fa12167cedea353e71dfb776023b84381305b4d9 Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Mon, 17 Jul 2017 14:01:19 +0800 Subject: clk: mediatek: fixed static checker warning in clk_cpumux_get_parent call Fixed the signedness bug returning '(-22)' on the return type as u8 with removing the sanity checker in clk_cpumux_get_parent() since clk_cpumux_set_parent() always ensures validity in clk_cpumux_get_parent() got called. Fixes: 1e17de9049da ("clk: mediatek: add missing cpu mux causing Mediatek cpufreq can't work") Reported-by: Dan Carpenter Signed-off-by: Sean Wang Signed-off-by: Stephen Boyd --- drivers/clk/mediatek/clk-cpumux.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/mediatek/clk-cpumux.c b/drivers/clk/mediatek/clk-cpumux.c index edd8e6918050..347d7990b30f 100644 --- a/drivers/clk/mediatek/clk-cpumux.c +++ b/drivers/clk/mediatek/clk-cpumux.c @@ -27,7 +27,6 @@ static inline struct mtk_clk_cpumux *to_mtk_clk_cpumux(struct clk_hw *_hw) static u8 clk_cpumux_get_parent(struct clk_hw *hw) { struct mtk_clk_cpumux *mux = to_mtk_clk_cpumux(hw); - int num_parents = clk_hw_get_num_parents(hw); unsigned int val; regmap_read(mux->regmap, mux->reg, &val); @@ -35,9 +34,6 @@ static u8 clk_cpumux_get_parent(struct clk_hw *hw) val >>= mux->shift; val &= mux->mask; - if (val >= num_parents) - return -EINVAL; - return val; } -- cgit v1.2.3 From d515e027a9bcadbabfb95fa15fde94bd372d48bd Mon Sep 17 00:00:00 2001 From: Georgi Djakov Date: Mon, 17 Jul 2017 18:35:42 +0300 Subject: clk: qcom: clk-smd-rpm: Fix the reported rate of branches As there is no way to actually query the hardware for the current clock rate, now racalc_rate() just returns the last rate that was previously set. But if the rate was not set yet, we return the bogus rate of 1000Hz. The branch clocks have the same rate as their parent, so in this case we just need to remove recalc_rate ops and then the core framework will handle this automagically. The round_rate() is unused, so remove it as well. Reported-by: Archit Taneja Fixes: 00f64b58874e ("clk: qcom: Add support for SMD-RPM Clocks") Signed-off-by: Georgi Djakov Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-smd-rpm.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index d990fe44aef3..cc03d5508627 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -412,8 +412,6 @@ static const struct clk_ops clk_smd_rpm_ops = { static const struct clk_ops clk_smd_rpm_branch_ops = { .prepare = clk_smd_rpm_prepare, .unprepare = clk_smd_rpm_unprepare, - .round_rate = clk_smd_rpm_round_rate, - .recalc_rate = clk_smd_rpm_recalc_rate, }; /* msm8916 */ -- cgit v1.2.3 From c8108cf2c0c8fd1c1f0bef34b4a31d567488e171 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 4 Jul 2017 17:36:50 -0500 Subject: clk: moxart: remove unnecessary statics Remove unnecessary static on local variable _base_ in both functions moxart_of_pll_clk_init() and moxart_of_apb_clk_init(). Such variables are initialized before being used, on every execution path throughout the mentioned functions. The statics have no benefit and, removing them reduce the code size. This issue was detected using Coccinelle and the following semantic patch: @bad exists@ position p; identifier x; type T; @@ static T x@p; ... x = <+...x...+> @@ identifier x; expression e; type T; position p != bad.p; @@ -static T x@p; ... when != x when strict ?x = e; In the following log you can see the difference in the code size. Also, notice that the bss segment is reduced down to zero. This log is the output of the size command, before and after the code change: before: text data bss dec hex filename 1724 384 128 2236 8bc drivers/clk/clk-moxart.o after: text data bss dec hex filename 1697 240 0 1937 791 drivers/clk/clk-moxart.o Signed-off-by: Gustavo A. R. Silva Signed-off-by: Stephen Boyd --- drivers/clk/clk-moxart.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk-moxart.c b/drivers/clk/clk-moxart.c index b86dac851116..1f66ccbfc03c 100644 --- a/drivers/clk/clk-moxart.c +++ b/drivers/clk/clk-moxart.c @@ -18,7 +18,7 @@ static void __init moxart_of_pll_clk_init(struct device_node *node) { - static void __iomem *base; + void __iomem *base; struct clk_hw *hw; struct clk *ref_clk; unsigned int mul; @@ -57,7 +57,7 @@ CLK_OF_DECLARE(moxart_pll_clock, "moxa,moxart-pll-clock", static void __init moxart_of_apb_clk_init(struct device_node *node) { - static void __iomem *base; + void __iomem *base; struct clk_hw *hw; struct clk *pll_clk; unsigned int div, val; -- cgit v1.2.3 From 4aafe9c603029b7e3e91707875beef9950ba35c5 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 15 Jul 2017 22:07:36 +0200 Subject: clk: mmp: Drop unnecessary static Drop static on a local variable, when the variable is initialized before any possible use. Thus, the static has no benefit. The semantic patch that fixes this problem is as follows: (http://coccinelle.lip6.fr/) // @bad exists@ position p; identifier x; type T; @@ static T x@p; ... x = <+...x...+> @@ identifier x; expression e; type T; position p != bad.p; @@ -static T x@p; ... when != x when strict ?x = e; // Signed-off-by: Julia Lawall Signed-off-by: Stephen Boyd --- drivers/clk/mmp/clk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/mmp/clk.c b/drivers/clk/mmp/clk.c index 61893fe73251..089927e4cda2 100644 --- a/drivers/clk/mmp/clk.c +++ b/drivers/clk/mmp/clk.c @@ -9,7 +9,7 @@ void mmp_clk_init(struct device_node *np, struct mmp_clk_unit *unit, int nr_clks) { - static struct clk **clk_table; + struct clk **clk_table; clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL); if (!clk_table) -- cgit v1.2.3 From cea3a330ee20e90011b10fc03944664e767e0dd2 Mon Sep 17 00:00:00 2001 From: Philippe CORNU Date: Mon, 17 Jul 2017 09:40:17 +0200 Subject: drm/stm: ltdc: Fix leak of px clk enable in some error paths The pixel clock gets enabled early during init, since it's required in order to read registers. This pixel clock must be disabled if errors during this init phase. Signed-off-by: Eric Anholt Acked-by: Philippe Cornu Signed-off-by: Archit Taneja Link: https://patchwork.freedesktop.org/patch/msgid/1500277223-29553-2-git-send-email-philippe.cornu@st.com --- drivers/gpu/drm/stm/ltdc.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c index 533176015cbb..7f64d5aeb080 100644 --- a/drivers/gpu/drm/stm/ltdc.c +++ b/drivers/gpu/drm/stm/ltdc.c @@ -1045,13 +1045,15 @@ int ltdc_load(struct drm_device *ddev) if (of_address_to_resource(np, 0, &res)) { DRM_ERROR("Unable to get resource\n"); - return -ENODEV; + ret = -ENODEV; + goto err; } ldev->regs = devm_ioremap_resource(dev, &res); if (IS_ERR(ldev->regs)) { DRM_ERROR("Unable to get ltdc registers\n"); - return PTR_ERR(ldev->regs); + ret = PTR_ERR(ldev->regs); + goto err; } for (i = 0; i < MAX_IRQ; i++) { @@ -1064,7 +1066,7 @@ int ltdc_load(struct drm_device *ddev) dev_name(dev), ddev); if (ret) { DRM_ERROR("Failed to register LTDC interrupt\n"); - return ret; + goto err; } } @@ -1079,7 +1081,7 @@ int ltdc_load(struct drm_device *ddev) if (ret) { DRM_ERROR("hardware identifier (0x%08x) not supported!\n", ldev->caps.hw_version); - return ret; + goto err; } DRM_INFO("ltdc hw version 0x%08x - ready\n", ldev->caps.hw_version); -- cgit v1.2.3 From bdf31bcf3d84ef0d107bbfb9442297cdb07a98b0 Mon Sep 17 00:00:00 2001 From: Philippe CORNU Date: Mon, 17 Jul 2017 09:40:18 +0200 Subject: drm/stm: ltdc: Add panel-bridge support Add the panel-bridge support for both panels & bridges (used by DSI host & HDMI/LVDS bridges). Signed-off-by: Philippe CORNU Reviewed-by: Archit Taneja Signed-off-by: Archit Taneja Link: https://patchwork.freedesktop.org/patch/msgid/1500277223-29553-3-git-send-email-philippe.cornu@st.com --- drivers/gpu/drm/stm/Kconfig | 2 +- drivers/gpu/drm/stm/ltdc.c | 210 ++++++++------------------------------------ drivers/gpu/drm/stm/ltdc.h | 3 +- 3 files changed, 38 insertions(+), 177 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/stm/Kconfig b/drivers/gpu/drm/stm/Kconfig index 2c4817fb0890..4b88223f9aed 100644 --- a/drivers/gpu/drm/stm/Kconfig +++ b/drivers/gpu/drm/stm/Kconfig @@ -4,7 +4,7 @@ config DRM_STM select DRM_KMS_HELPER select DRM_GEM_CMA_HELPER select DRM_KMS_CMA_HELPER - select DRM_PANEL + select DRM_PANEL_BRIDGE select VIDEOMODE_HELPERS select FB_PROVIDE_GET_FB_UNMAPPED_AREA default y diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c index 7f64d5aeb080..e46b427eacc7 100644 --- a/drivers/gpu/drm/stm/ltdc.c +++ b/drivers/gpu/drm/stm/ltdc.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include