From 667063acb81931e2f8fd0cb91df9fcccad131d9a Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 29 Sep 2017 16:23:01 +0800 Subject: regmap: add iopoll-like polling macro for regmap_field This patch adds a macro regmap_field_read_poll_timeout that works similar to the readx_poll_timeout defined in linux/iopoll.h, except that this can also return the error value returned by a failed regmap_field_read. Signed-off-by: Chen-Yu Tsai Signed-off-by: Mark Brown --- include/linux/regmap.h | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'include') diff --git a/include/linux/regmap.h b/include/linux/regmap.h index 978abfbac617..93a4663d7acb 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h @@ -139,6 +139,45 @@ struct reg_sequence { pollret ?: ((cond) ? 0 : -ETIMEDOUT); \ }) +/** + * regmap_field_read_poll_timeout - Poll until a condition is met or timeout + * + * @field: Regmap field to read from + * @val: Unsigned integer variable to read the value into + * @cond: Break condition (usually involving @val) + * @sleep_us: Maximum time to sleep between reads in us (0 + * tight-loops). Should be less than ~20ms since usleep_range + * is used (see Documentation/timers/timers-howto.txt). + * @timeout_us: Timeout in us, 0 means never timeout + * + * Returns 0 on success and -ETIMEDOUT upon a timeout or the regmap_field_read + * error return value in case of a error read. In the two former cases, + * the last read value at @addr is stored in @val. Must not be called + * from atomic context if sleep_us or timeout_us are used. + * + * This is modelled after the readx_poll_timeout macros in linux/iopoll.h. + */ +#define regmap_field_read_poll_timeout(field, val, cond, sleep_us, timeout_us) \ +({ \ + ktime_t timeout = ktime_add_us(ktime_get(), timeout_us); \ + int pollret; \ + might_sleep_if(sleep_us); \ + for (;;) { \ + pollret = regmap_field_read((field), &(val)); \ + if (pollret) \ + break; \ + if (cond) \ + break; \ + if (timeout_us && ktime_compare(ktime_get(), timeout) > 0) { \ + pollret = regmap_field_read((field), &(val)); \ + break; \ + } \ + if (sleep_us) \ + usleep_range((sleep_us >> 2) + 1, sleep_us); \ + } \ + pollret ?: ((cond) ? 0 : -ETIMEDOUT); \ +}) + #ifdef CONFIG_REGMAP enum regmap_endian { -- cgit v1.2.3 From f0d2e86c1b9ecd9cbe967b94e2f0d197f30cb3e7 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 27 Sep 2017 10:35:31 +0200 Subject: drm/atomic: Remove unneeded null check for private objects It can be seen in drm_atomic_get_private_obj_state() that ptr will never be NULL, so skip the check for that case. Signed-off-by: Maarten Lankhorst Link: https://patchwork.freedesktop.org/patch/msgid/20170927083532.5756-1-maarten.lankhorst@linux.intel.com Reviewed-by: Daniel Vetter --- include/drm/drm_atomic.h | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 5834580d75bc..6fae95f28e10 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -768,8 +768,7 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); ((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) + (__i)++) /** * for_each_old_private_obj_in_state - iterate over all private objects in an atomic update @@ -787,8 +786,7 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); (__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) + (__i)++) /** * for_each_new_private_obj_in_state - iterate over all private objects in an atomic update @@ -806,8 +804,7 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); (__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) + (__i)++) /** * drm_atomic_crtc_needs_modeset - compute combined modeset need -- cgit v1.2.3 From 331494eb51002d0ee99414e3918e06d5e9a3962d Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 27 Sep 2017 10:35:32 +0200 Subject: drm/atomic: Make atomic iterators less surprising Commit 669c9215afea ("drm/atomic: Make async plane update checks work as intended, v2.") assumed incorrectly that if only 1 plane is matched in the loop, the variables will be set to that plane. In reality we reset them to NULL every time a new plane was iterated. This behavior is surprising, so fix this by making the for loops only assign the variables on a match. When we have not added all the planes/crtc/connector to the state, and there's a few NULL ones after the last one we iterated, te assumption is broken that the pointers will hold the values from the last loop iteration, which holds true for all other for_each macros we're using. Except of course the iterator pointer itself, but that one really is entirely internal. Cc: Dmitry Osipenko Fixes: 669c9215afea ("drm/atomic: Make async plane update checks work as intended, v2.") Signed-off-by: Maarten Lankhorst Link: https://patchwork.freedesktop.org/patch/msgid/20170927083532.5756-2-maarten.lankhorst@linux.intel.com Reviewed-by: Daniel Vetter Tested-by: Dmitry Osipenko --- include/drm/drm_atomic.h | 85 ++++++++++++++++++++++++------------------------ 1 file changed, 42 insertions(+), 43 deletions(-) (limited to 'include') diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 6fae95f28e10..5afd6e364fb6 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -585,12 +585,12 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); */ #define for_each_oldnew_connector_in_state(__state, connector, old_connector_state, new_connector_state, __i) \ for ((__i) = 0; \ - (__i) < (__state)->num_connector && \ - ((connector) = (__state)->connectors[__i].ptr, \ - (old_connector_state) = (__state)->connectors[__i].old_state, \ - (new_connector_state) = (__state)->connectors[__i].new_state, 1); \ - (__i)++) \ - for_each_if (connector) + (__i) < (__state)->num_connector; \ + (__i)++) \ + for_each_if ((__state)->connectors[__i].ptr && \ + ((connector) = (__state)->connectors[__i].ptr, \ + (old_connector_state) = (__state)->connectors[__i].old_state, \ + (new_connector_state) = (__state)->connectors[__i].new_state, 1)) /** * for_each_old_connector_in_state - iterate over all connectors in an atomic update @@ -606,11 +606,11 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); */ #define for_each_old_connector_in_state(__state, connector, old_connector_state, __i) \ for ((__i) = 0; \ - (__i) < (__state)->num_connector && \ - ((connector) = (__state)->connectors[__i].ptr, \ - (old_connector_state) = (__state)->connectors[__i].old_state, 1); \ - (__i)++) \ - for_each_if (connector) + (__i) < (__state)->num_connector; \ + (__i)++) \ + for_each_if ((__state)->connectors[__i].ptr && \ + ((connector) = (__state)->connectors[__i].ptr, \ + (old_connector_state) = (__state)->connectors[__i].old_state, 1)) /** * for_each_new_connector_in_state - iterate over all connectors in an atomic update @@ -626,11 +626,11 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); */ #define for_each_new_connector_in_state(__state, connector, new_connector_state, __i) \ for ((__i) = 0; \ - (__i) < (__state)->num_connector && \ - ((connector) = (__state)->connectors[__i].ptr, \ - (new_connector_state) = (__state)->connectors[__i].new_state, 1); \ - (__i)++) \ - for_each_if (connector) + (__i) < (__state)->num_connector; \ + (__i)++) \ + for_each_if ((__state)->connectors[__i].ptr && \ + ((connector) = (__state)->connectors[__i].ptr, \ + (new_connector_state) = (__state)->connectors[__i].new_state, 1)) /** * for_each_oldnew_crtc_in_state - iterate over all CRTCs in an atomic update @@ -646,12 +646,12 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); */ #define for_each_oldnew_crtc_in_state(__state, crtc, old_crtc_state, new_crtc_state, __i) \ for ((__i) = 0; \ - (__i) < (__state)->dev->mode_config.num_crtc && \ - ((crtc) = (__state)->crtcs[__i].ptr, \ - (old_crtc_state) = (__state)->crtcs[__i].old_state, \ - (new_crtc_state) = (__state)->crtcs[__i].new_state, 1); \ + (__i) < (__state)->dev->mode_config.num_crtc; \ (__i)++) \ - for_each_if (crtc) + for_each_if ((__state)->crtcs[__i].ptr && \ + ((crtc) = (__state)->crtcs[__i].ptr, \ + (old_crtc_state) = (__state)->crtcs[__i].old_state, \ + (new_crtc_state) = (__state)->crtcs[__i].new_state, 1)) /** * for_each_old_crtc_in_state - iterate over all CRTCs in an atomic update @@ -666,11 +666,11 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); */ #define for_each_old_crtc_in_state(__state, crtc, old_crtc_state, __i) \ for ((__i) = 0; \ - (__i) < (__state)->dev->mode_config.num_crtc && \ - ((crtc) = (__state)->crtcs[__i].ptr, \ - (old_crtc_state) = (__state)->crtcs[__i].old_state, 1); \ + (__i) < (__state)->dev->mode_config.num_crtc; \ (__i)++) \ - for_each_if (crtc) + for_each_if ((__state)->crtcs[__i].ptr && \ + ((crtc) = (__state)->crtcs[__i].ptr, \ + (old_crtc_state) = (__state)->crtcs[__i].old_state, 1)) /** * for_each_new_crtc_in_state - iterate over all CRTCs in an atomic update @@ -685,11 +685,11 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); */ #define for_each_new_crtc_in_state(__state, crtc, new_crtc_state, __i) \ for ((__i) = 0; \ - (__i) < (__state)->dev->mode_config.num_crtc && \ - ((crtc) = (__state)->crtcs[__i].ptr, \ - (new_crtc_state) = (__state)->crtcs[__i].new_state, 1); \ + (__i) < (__state)->dev->mode_config.num_crtc; \ (__i)++) \ - for_each_if (crtc) + for_each_if ((__state)->crtcs[__i].ptr && \ + ((crtc) = (__state)->crtcs[__i].ptr, \ + (new_crtc_state) = (__state)->crtcs[__i].new_state, 1)) /** * for_each_oldnew_plane_in_state - iterate over all planes in an atomic update @@ -705,12 +705,12 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); */ #define for_each_oldnew_plane_in_state(__state, plane, old_plane_state, new_plane_state, __i) \ for ((__i) = 0; \ - (__i) < (__state)->dev->mode_config.num_total_plane && \ - ((plane) = (__state)->planes[__i].ptr, \ - (old_plane_state) = (__state)->planes[__i].old_state, \ - (new_plane_state) = (__state)->planes[__i].new_state, 1); \ + (__i) < (__state)->dev->mode_config.num_total_plane; \ (__i)++) \ - for_each_if (plane) + for_each_if ((__state)->planes[__i].ptr && \ + ((plane) = (__state)->planes[__i].ptr, \ + (old_plane_state) = (__state)->planes[__i].old_state,\ + (new_plane_state) = (__state)->planes[__i].new_state, 1)) /** * for_each_old_plane_in_state - iterate over all planes in an atomic update @@ -725,12 +725,11 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); */ #define for_each_old_plane_in_state(__state, plane, old_plane_state, __i) \ for ((__i) = 0; \ - (__i) < (__state)->dev->mode_config.num_total_plane && \ - ((plane) = (__state)->planes[__i].ptr, \ - (old_plane_state) = (__state)->planes[__i].old_state, 1); \ + (__i) < (__state)->dev->mode_config.num_total_plane; \ (__i)++) \ - for_each_if (plane) - + for_each_if ((__state)->planes[__i].ptr && \ + ((plane) = (__state)->planes[__i].ptr, \ + (old_plane_state) = (__state)->planes[__i].old_state, 1)) /** * for_each_new_plane_in_state - iterate over all planes in an atomic update * @__state: &struct drm_atomic_state pointer @@ -744,11 +743,11 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); */ #define for_each_new_plane_in_state(__state, plane, new_plane_state, __i) \ for ((__i) = 0; \ - (__i) < (__state)->dev->mode_config.num_total_plane && \ - ((plane) = (__state)->planes[__i].ptr, \ - (new_plane_state) = (__state)->planes[__i].new_state, 1); \ + (__i) < (__state)->dev->mode_config.num_total_plane; \ (__i)++) \ - for_each_if (plane) + for_each_if ((__state)->planes[__i].ptr && \ + ((plane) = (__state)->planes[__i].ptr, \ + (new_plane_state) = (__state)->planes[__i].new_state, 1)) /** * for_each_oldnew_private_obj_in_state - iterate over all private objects in an atomic update -- cgit v1.2.3 From f8e0731db4a02c8c5624e1dce6dc983210a51f64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Fri, 15 Sep 2017 11:53:07 +0200 Subject: dma-fence: fix dma_fence_get_rcu_safe v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When dma_fence_get_rcu() fails to acquire a reference it doesn't necessary mean that there is no fence at all. It usually mean that the fence was replaced by a new one and in this situation we certainly want to have the new one as result and *NOT* NULL. v2: Keep extra check after dma_fence_get_rcu(). Signed-off-by: Christian König Cc: Chris Wilson Cc: Daniel Vetter Cc: Sumit Semwal Cc: linux-media@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: linaro-mm-sig@lists.linaro.org Reviewed-by: Maarten Lankhorst Signed-off-by: Alex Deucher Link: https://patchwork.freedesktop.org/patch/msgid/1505469187-3565-1-git-send-email-deathsimple@vodafone.de --- include/linux/dma-fence.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/dma-fence.h b/include/linux/dma-fence.h index 171895072435..ca974224d92e 100644 --- a/include/linux/dma-fence.h +++ b/include/linux/dma-fence.h @@ -248,9 +248,12 @@ dma_fence_get_rcu_safe(struct dma_fence * __rcu *fencep) struct dma_fence *fence; fence = rcu_dereference(*fencep); - if (!fence || !dma_fence_get_rcu(fence)) + if (!fence) return NULL; + if (!dma_fence_get_rcu(fence)) + continue; + /* The atomic_inc_not_zero() inside dma_fence_get_rcu() * provides a full memory barrier upon success (such as now). * This is paired with the write barrier from assigning -- cgit v1.2.3 From c70087e8f16f1dfe703d223aadd95ede1cde8e30 Mon Sep 17 00:00:00 2001 From: "benjamin.gaignard@linaro.org" Date: Mon, 2 Oct 2017 11:34:45 +0200 Subject: drm/drm_of: add drm_of_panel_bridge_remove function This function is the pendant of drm_of_find_panel_or_bridge() to remove a previously allocated panel_bridge. Given a specific port and endpoint it remove the panel bridge. Since drm_panel_bridge_remove() will check that bridge parameter is not NULL and is a real drm_panel_bridge and no a simple bridge it is safe to call it directly. Signed-off-by: Benjamin Gaignard Reviewed-by: Philippe Cornu Tested-by: Philippe Cornu Link: https://patchwork.freedesktop.org/patch/msgid/1506936888-23844-3-git-send-email-benjamin.gaignard@linaro.org --- include/drm/drm_of.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'include') diff --git a/include/drm/drm_of.h b/include/drm/drm_of.h index 104dd517fdbe..390966e4a308 100644 --- a/include/drm/drm_of.h +++ b/include/drm/drm_of.h @@ -29,6 +29,8 @@ int drm_of_find_panel_or_bridge(const struct device_node *np, int port, int endpoint, struct drm_panel **panel, struct drm_bridge **bridge); +int drm_of_panel_bridge_remove(const struct device_node *np, + int port, int endpoint); #else static inline uint32_t drm_of_find_possible_crtcs(struct drm_device *dev, struct device_node *port) @@ -65,6 +67,12 @@ static inline int drm_of_find_panel_or_bridge(const struct device_node *np, { return -EINVAL; } + +static inline int drm_of_panel_bridge_remove(const struct device_node *np, + int port, int endpoint) +{ + return -EINVAL; +} #endif static inline int drm_of_encoder_active_endpoint_id(struct device_node *node, -- cgit v1.2.3 From e25f1f7c94e16d4493398300efa03e5b6c77fcbf Mon Sep 17 00:00:00 2001 From: Maciej Purski Date: Thu, 24 Aug 2017 10:58:07 +0200 Subject: drm/bridge/sii8620: add remote control support MHL specification defines Remote Control Protocol(RCP) to send input events between MHL devices. The driver now recognizes RCP messages and reacts to them by reporting key events to input subsystem, allowing a user to control a device using TV remote control. Signed-off-by: Maciej Purski Acked-by: Sean Young Acked-by: Mauro Carvalho Chehab Signed-off-by: Andrzej Hajda Link: https://patchwork.freedesktop.org/patch/msgid/1503565087-19730-1-git-send-email-m.purski@samsung.com --- include/drm/bridge/mhl.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include') diff --git a/include/drm/bridge/mhl.h b/include/drm/bridge/mhl.h index fbdfc8d7f3c7..96a5e0f6ff12 100644 --- a/include/drm/bridge/mhl.h +++ b/include/drm/bridge/mhl.h @@ -262,6 +262,10 @@ enum { #define MHL_RAPK_UNSUPPORTED 0x02 /* Rcvd RAP action code not supported */ #define MHL_RAPK_BUSY 0x03 /* Responder too busy to respond */ +/* Bit masks for RCP messages */ +#define MHL_RCP_KEY_RELEASED_MASK 0x80 +#define MHL_RCP_KEY_ID_MASK 0x7F + /* * Error status codes for RCPE messages */ -- cgit v1.2.3