summaryrefslogtreecommitdiffstats
path: root/drivers/staging
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-12-16 09:39:16 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2016-12-16 09:39:16 -0800
commitbd9999cd6a5eb899504ce14c1f70c5479143bbbc (patch)
treeea8cba08f86c431d49cb3f58254dac8ca60e96d8 /drivers/staging
parent9dfe495c7b4896fb88aa745660254a9704ae5930 (diff)
parent65390ea01ce678379da32b01f39fcfac4903f256 (diff)
Merge tag 'media/v4.10-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab: - new Mediatek drivers: mtk-mdp and mtk-vcodec - some additions at the media documentation - the CEC core and drivers were promoted from staging to mainstream - some cleanups at the DVB core - the LIRC serial driver got promoted from staging to mainstream - added a driver for Renesas R-Car FDP1 driver - add DVBv5 statistics support to mn88473 driver - several fixes related to printk continuation lines - add support for HSV encoding formats - lots of other cleanups, fixups and driver improvements. * tag 'media/v4.10-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (496 commits) [media] v4l: tvp5150: Add missing break in set control handler [media] v4l: tvp5150: Don't inline the tvp5150_selmux() function [media] v4l: tvp5150: Compile tvp5150_link_setup out if !CONFIG_MEDIA_CONTROLLER [media] em28xx: don't store usb_device at struct em28xx [media] em28xx: use usb_interface for dev_foo() calls [media] em28xx: don't change the device's name [media] mn88472: fix chip id check on probe [media] mn88473: fix chip id check on probe [media] lirc: fix error paths in lirc_cdev_add() [media] s5p-mfc: Add support for MFC v8 available in Exynos 5433 SoCs [media] s5p-mfc: Rework clock handling [media] s5p-mfc: Don't keep clock prepared all the time [media] s5p-mfc: Kill all IS_ERR_OR_NULL in clocks management code [media] s5p-mfc: Remove dead conditional code [media] s5p-mfc: Ensure that clock is disabled before turning power off [media] s5p-mfc: Remove special clock rate management [media] s5p-mfc: Use printk_ratelimited for reporting ioctl errors [media] s5p-mfc: Set DMA_ATTR_ALLOC_SINGLE_PAGES [media] vivid: Set color_enc on HSV formats [media] v4l2-tpg: Init hv_enc field with a valid value ...
Diffstat (limited to 'drivers/staging')
-rw-r--r--drivers/staging/media/Kconfig4
-rw-r--r--drivers/staging/media/Makefile2
-rw-r--r--drivers/staging/media/bcm2048/radio-bcm2048.c66
-rw-r--r--drivers/staging/media/bcm2048/radio-bcm2048.h5
-rw-r--r--drivers/staging/media/cec/Kconfig12
-rw-r--r--drivers/staging/media/cec/Makefile5
-rw-r--r--drivers/staging/media/cec/TODO32
-rw-r--r--drivers/staging/media/cec/cec-adap.c1660
-rw-r--r--drivers/staging/media/cec/cec-api.c579
-rw-r--r--drivers/staging/media/cec/cec-core.c411
-rw-r--r--drivers/staging/media/cec/cec-priv.h56
-rw-r--r--drivers/staging/media/davinci_vpfe/Makefile4
-rw-r--r--drivers/staging/media/davinci_vpfe/dm365_resizer.c31
-rw-r--r--drivers/staging/media/davinci_vpfe/dm365_resizer.h2
-rw-r--r--drivers/staging/media/davinci_vpfe/vpfe_video.c4
-rw-r--r--drivers/staging/media/lirc/Kconfig13
-rw-r--r--drivers/staging/media/lirc/Makefile1
-rw-r--r--drivers/staging/media/lirc/lirc_imon.c11
-rw-r--r--drivers/staging/media/lirc/lirc_sasem.c5
-rw-r--r--drivers/staging/media/lirc/lirc_serial.c1130
-rw-r--r--drivers/staging/media/pulse8-cec/Kconfig10
-rw-r--r--drivers/staging/media/pulse8-cec/Makefile1
-rw-r--r--drivers/staging/media/pulse8-cec/TODO52
-rw-r--r--drivers/staging/media/pulse8-cec/pulse8-cec.c753
-rw-r--r--drivers/staging/media/s5p-cec/Kconfig2
-rw-r--r--drivers/staging/media/s5p-cec/TODO12
-rw-r--r--drivers/staging/media/s5p-cec/s5p_cec.c10
-rw-r--r--drivers/staging/media/st-cec/Kconfig2
-rw-r--r--drivers/staging/media/st-cec/TODO7
-rw-r--r--drivers/staging/media/st-cec/stih-cec.c7
30 files changed, 83 insertions, 4806 deletions
diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig
index 6620d96ee44d..ffb8fa72c3da 100644
--- a/drivers/staging/media/Kconfig
+++ b/drivers/staging/media/Kconfig
@@ -21,16 +21,12 @@ if STAGING_MEDIA && MEDIA_SUPPORT
# Please keep them in alphabetic order
source "drivers/staging/media/bcm2048/Kconfig"
-source "drivers/staging/media/cec/Kconfig"
-
source "drivers/staging/media/cxd2099/Kconfig"
source "drivers/staging/media/davinci_vpfe/Kconfig"
source "drivers/staging/media/omap4iss/Kconfig"
-source "drivers/staging/media/pulse8-cec/Kconfig"
-
source "drivers/staging/media/s5p-cec/Kconfig"
# Keep LIRC at the end, as it has sub-menus
diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile
index 906257e94dda..a28e82cf6447 100644
--- a/drivers/staging/media/Makefile
+++ b/drivers/staging/media/Makefile
@@ -1,9 +1,7 @@
obj-$(CONFIG_I2C_BCM2048) += bcm2048/
-obj-$(CONFIG_MEDIA_CEC) += cec/
obj-$(CONFIG_VIDEO_SAMSUNG_S5P_CEC) += s5p-cec/
obj-$(CONFIG_DVB_CXD2099) += cxd2099/
obj-$(CONFIG_LIRC_STAGING) += lirc/
obj-$(CONFIG_VIDEO_DM365_VPFE) += davinci_vpfe/
obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/
-obj-$(CONFIG_USB_PULSE8_CEC) += pulse8-cec/
obj-$(CONFIG_VIDEO_STI_HDMI_CEC) += st-cec/
diff --git a/drivers/staging/media/bcm2048/radio-bcm2048.c b/drivers/staging/media/bcm2048/radio-bcm2048.c
index c5116c058cea..37bd439ee08b 100644
--- a/drivers/staging/media/bcm2048/radio-bcm2048.c
+++ b/drivers/staging/media/bcm2048/radio-bcm2048.c
@@ -17,10 +17,6 @@
* 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, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
*/
/*
@@ -999,7 +995,7 @@ static int bcm2048_set_fm_search_tune_mode(struct bcm2048_device *bdev,
timeout = BCM2048_AUTO_SEARCH_TIMEOUT;
if (!wait_for_completion_timeout(&bdev->compl,
- msecs_to_jiffies(timeout)))
+ msecs_to_jiffies(timeout)))
dev_err(&bdev->client->dev, "IRQ timeout.\n");
if (value)
@@ -2059,67 +2055,67 @@ property_signed_read(fm_rssi, int, "%d")
DEFINE_SYSFS_PROPERTY(region, unsigned, int, "%u", 0)
static struct device_attribute attrs[] = {
- __ATTR(power_state, S_IRUGO | S_IWUSR, bcm2048_power_state_read,
+ __ATTR(power_state, 0644, bcm2048_power_state_read,
bcm2048_power_state_write),
- __ATTR(mute, S_IRUGO | S_IWUSR, bcm2048_mute_read,
+ __ATTR(mute, 0644, bcm2048_mute_read,
bcm2048_mute_write),
- __ATTR(audio_route, S_IRUGO | S_IWUSR, bcm2048_audio_route_read,
+ __ATTR(audio_route, 0644, bcm2048_audio_route_read,
bcm2048_audio_route_write),
- __ATTR(dac_output, S_IRUGO | S_IWUSR, bcm2048_dac_output_read,
+ __ATTR(dac_output, 0644, bcm2048_dac_output_read,
bcm2048_dac_output_write),
- __ATTR(fm_hi_lo_injection, S_IRUGO | S_IWUSR,
+ __ATTR(fm_hi_lo_injection, 0644,
bcm2048_fm_hi_lo_injection_read,
bcm2048_fm_hi_lo_injection_write),
- __ATTR(fm_frequency, S_IRUGO | S_IWUSR, bcm2048_fm_frequency_read,
+ __ATTR(fm_frequency, 0644, bcm2048_fm_frequency_read,
bcm2048_fm_frequency_write),
- __ATTR(fm_af_frequency, S_IRUGO | S_IWUSR,
+ __ATTR(fm_af_frequency, 0644,
bcm2048_fm_af_frequency_read,
bcm2048_fm_af_frequency_write),
- __ATTR(fm_deemphasis, S_IRUGO | S_IWUSR, bcm2048_fm_deemphasis_read,
+ __ATTR(fm_deemphasis, 0644, bcm2048_fm_deemphasis_read,
bcm2048_fm_deemphasis_write),
- __ATTR(fm_rds_mask, S_IRUGO | S_IWUSR, bcm2048_fm_rds_mask_read,
+ __ATTR(fm_rds_mask, 0644, bcm2048_fm_rds_mask_read,
bcm2048_fm_rds_mask_write),
- __ATTR(fm_best_tune_mode, S_IRUGO | S_IWUSR,
+ __ATTR(fm_best_tune_mode, 0644,
bcm2048_fm_best_tune_mode_read,
bcm2048_fm_best_tune_mode_write),
- __ATTR(fm_search_rssi_threshold, S_IRUGO | S_IWUSR,
+ __ATTR(fm_search_rssi_threshold, 0644,
bcm2048_fm_search_rssi_threshold_read,
bcm2048_fm_search_rssi_threshold_write),
- __ATTR(fm_search_mode_direction, S_IRUGO | S_IWUSR,
+ __ATTR(fm_search_mode_direction, 0644,
bcm2048_fm_search_mode_direction_read,
bcm2048_fm_search_mode_direction_write),
- __ATTR(fm_search_tune_mode, S_IRUGO | S_IWUSR,
+ __ATTR(fm_search_tune_mode, 0644,
bcm2048_fm_search_tune_mode_read,
bcm2048_fm_search_tune_mode_write),
- __ATTR(rds, S_IRUGO | S_IWUSR, bcm2048_rds_read,
+ __ATTR(rds, 0644, bcm2048_rds_read,
bcm2048_rds_write),
- __ATTR(rds_b_block_mask, S_IRUGO | S_IWUSR,
+ __ATTR(rds_b_block_mask, 0644,
bcm2048_rds_b_block_mask_read,
bcm2048_rds_b_block_mask_write),
- __ATTR(rds_b_block_match, S_IRUGO | S_IWUSR,
+ __ATTR(rds_b_block_match, 0644,
bcm2048_rds_b_block_match_read,
bcm2048_rds_b_block_match_write),
- __ATTR(rds_pi_mask, S_IRUGO | S_IWUSR, bcm2048_rds_pi_mask_read,
+ __ATTR(rds_pi_mask, 0644, bcm2048_rds_pi_mask_read,
bcm2048_rds_pi_mask_write),
- __ATTR(rds_pi_match, S_IRUGO | S_IWUSR, bcm2048_rds_pi_match_read,
+ __ATTR(rds_pi_match, 0644, bcm2048_rds_pi_match_read,
bcm2048_rds_pi_match_write),
- __ATTR(rds_wline, S_IRUGO | S_IWUSR, bcm2048_rds_wline_read,
+ __ATTR(rds_wline, 0644, bcm2048_rds_wline_read,
bcm2048_rds_wline_write),
- __ATTR(rds_pi, S_IRUGO, bcm2048_rds_pi_read, NULL),
- __ATTR(rds_rt, S_IRUGO, bcm2048_rds_rt_read, NULL),
- __ATTR(rds_ps, S_IRUGO, bcm2048_rds_ps_read, NULL),
- __ATTR(fm_rds_flags, S_IRUGO, bcm2048_fm_rds_flags_read, NULL),
- __ATTR(region_bottom_frequency, S_IRUGO,
+ __ATTR(rds_pi, 0444, bcm2048_rds_pi_read, NULL),
+ __ATTR(rds_rt, 0444, bcm2048_rds_rt_read, NULL),
+ __ATTR(rds_ps, 0444, bcm2048_rds_ps_read, NULL),
+ __ATTR(fm_rds_flags, 0444, bcm2048_fm_rds_flags_read, NULL),
+ __ATTR(region_bottom_frequency, 0444,
bcm2048_region_bottom_frequency_read, NULL),
- __ATTR(region_top_frequency, S_IRUGO,
+ __ATTR(region_top_frequency, 0444,
bcm2048_region_top_frequency_read, NULL),
- __ATTR(fm_carrier_error, S_IRUGO,
+ __ATTR(fm_carrier_error, 0444,
bcm2048_fm_carrier_error_read, NULL),
- __ATTR(fm_rssi, S_IRUGO,
+ __ATTR(fm_rssi, 0444,
bcm2048_fm_rssi_read, NULL),
- __ATTR(region, S_IRUGO | S_IWUSR, bcm2048_region_read,
+ __ATTR(region, 0644, bcm2048_region_read,
bcm2048_region_write),
- __ATTR(rds_data, S_IRUGO, bcm2048_rds_data_read, NULL),
+ __ATTR(rds_data, 0444, bcm2048_rds_data_read, NULL),
};
static int bcm2048_sysfs_unregister_properties(struct bcm2048_device *bdev,
@@ -2204,7 +2200,7 @@ static ssize_t bcm2048_fops_read(struct file *file, char __user *buf,
}
/* interruptible_sleep_on(&bdev->read_queue); */
if (wait_event_interruptible(bdev->read_queue,
- bdev->rds_data_available) < 0) {
+ bdev->rds_data_available) < 0) {
retval = -EINTR;
goto done;
}
diff --git a/drivers/staging/media/bcm2048/radio-bcm2048.h b/drivers/staging/media/bcm2048/radio-bcm2048.h
index 4c90a32db795..4d950c1e2e8b 100644
--- a/drivers/staging/media/bcm2048/radio-bcm2048.h
+++ b/drivers/staging/media/bcm2048/radio-bcm2048.h
@@ -14,11 +14,6 @@
* 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, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
*/
#ifndef BCM2048_H
diff --git a/drivers/staging/media/cec/Kconfig b/drivers/staging/media/cec/Kconfig
deleted file mode 100644
index 6e12d41b1f86..000000000000
--- a/drivers/staging/media/cec/Kconfig
+++ /dev/null
@@ -1,12 +0,0 @@
-config MEDIA_CEC
- bool "CEC API (EXPERIMENTAL)"
- depends on MEDIA_SUPPORT
- select MEDIA_CEC_EDID
- ---help---
- Enable the CEC API.
-
-config MEDIA_CEC_DEBUG
- bool "CEC debugfs interface (EXPERIMENTAL)"
- depends on MEDIA_CEC && DEBUG_FS
- ---help---
- Turns on the DebugFS interface for CEC devices.
diff --git a/drivers/staging/media/cec/Makefile b/drivers/staging/media/cec/Makefile
deleted file mode 100644
index bd7f3c593468..000000000000
--- a/drivers/staging/media/cec/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-cec-objs := cec-core.o cec-adap.o cec-api.o
-
-ifeq ($(CONFIG_MEDIA_CEC),y)
- obj-$(CONFIG_MEDIA_SUPPORT) += cec.o
-endif
diff --git a/drivers/staging/media/cec/TODO b/drivers/staging/media/cec/TODO
deleted file mode 100644
index 13224694a8ae..000000000000
--- a/drivers/staging/media/cec/TODO
+++ /dev/null
@@ -1,32 +0,0 @@
-The reason why cec.c is still in staging is that I would like
-to have a bit more confidence in the uABI. The kABI is fine,
-no problem there, but I would like to let the public API mature
-a bit.
-
-Once I'm confident that I didn't miss anything then the cec.c source
-can move to drivers/media and the linux/cec.h and linux/cec-funcs.h
-headers can move to uapi/linux and added to uapi/linux/Kbuild to make
-them public.
-
-Hopefully this will happen later in 2016.
-
-Other TODOs:
-
-- There are two possible replies to CEC_MSG_INITIATE_ARC. How to handle that?
-- Add a flag to inhibit passing CEC RC messages to the rc subsystem.
- Applications should be able to choose this when calling S_LOG_ADDRS.
-- If the reply field of cec_msg is set then when the reply arrives it
- is only sent to the filehandle that transmitted the original message
- and not to any followers. Should this behavior change or perhaps
- controlled through a cec_msg flag?
-- Should CEC_LOG_ADDR_TYPE_SPECIFIC be replaced by TYPE_2ND_TV and TYPE_PROCESSOR?
- And also TYPE_SWITCH and TYPE_CDC_ONLY in addition to the TYPE_UNREGISTERED?
- This should give the framework more information about the device type
- since SPECIFIC and UNREGISTERED give no useful information.
-- Once this is out of staging this should no longer be a separate
- config option, instead it should be selected by drivers that want it.
-- Revisit the IS_REACHABLE(RC_CORE): perhaps the RC_CORE support should
- be enabled through a separate config option in drivers/media/Kconfig
- or rc/Kconfig?
-
-Hans Verkuil <hans.verkuil@cisco.com>
diff --git a/drivers/staging/media/cec/cec-adap.c b/drivers/staging/media/cec/cec-adap.c
deleted file mode 100644
index 611e07b78bfe..000000000000
--- a/drivers/staging/media/cec/cec-adap.c
+++ /dev/null
@@ -1,1660 +0,0 @@
-/*
- * cec-adap.c - HDMI Consumer Electronics Control framework - CEC adapter
- *
- * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- *
- * This program is free software; you may 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.
- *
- * 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 AUTHORS OR COPYRIGHT HOLDERS
- * 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 <linux/errno.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/kmod.h>
-#include <linux/ktime.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/types.h>
-
-#include "cec-priv.h"
-
-static int cec_report_features(struct cec_adapter *adap, unsigned int la_idx);
-static int cec_report_phys_addr(struct cec_adapter *adap, unsigned int la_idx);
-
-/*
- * 400 ms is the time it takes for one 16 byte message to be
- * transferred and 5 is the maximum number of retries. Add
- * another 100 ms as a margin. So if the transmit doesn't
- * finish before that time something is really wrong and we
- * have to time out.
- *
- * This is a sign that something it really wrong and a warning
- * will be issued.
- */
-#define CEC_XFER_TIMEOUT_MS (5 * 400 + 100)
-
-#define call_op(adap, op, arg...) \
- (adap->ops->op ? adap->ops->op(adap, ## arg) : 0)
-
-#define call_void_op(adap, op, arg...) \
- do { \
- if (adap->ops->op) \
- adap->ops->op(adap, ## arg); \
- } while (0)
-
-static int cec_log_addr2idx(const struct cec_adapter *adap, u8 log_addr)
-{
- int i;
-
- for (i = 0; i < adap->log_addrs.num_log_addrs; i++)
- if (adap->log_addrs.log_addr[i] == log_addr)
- return i;
- return -1;
-}
-
-static unsigned int cec_log_addr2dev(const struct cec_adapter *adap, u8 log_addr)
-{
- int i = cec_log_addr2idx(adap, log_addr);
-
- return adap->log_addrs.primary_device_type[i < 0 ? 0 : i];
-}
-
-/*
- * Queue a new event for this filehandle. If ts == 0, then set it
- * to the current time.
- *
- * The two events that are currently defined do not need to keep track
- * of intermediate events, so no actual queue of events is needed,
- * instead just store the latest state and the total number of lost
- * messages.
- *
- * Should new events be added in the future that require intermediate
- * results to be queued as well, then a proper queue data structure is
- * required. But until then, just keep it simple.
- */
-void cec_queue_event_fh(struct cec_fh *fh,
- const struct cec_event *new_ev, u64 ts)
-{
- struct cec_event *ev = &fh->events[new_ev->event - 1];
-
- if (ts == 0)
- ts = ktime_get_ns();
-
- mutex_lock(&fh->lock);
- if (new_ev->event == CEC_EVENT_LOST_MSGS &&
- fh->pending_events & (1 << new_ev->event)) {
- /*
- * If there is already a lost_msgs event, then just
- * update the lost_msgs count. This effectively
- * merges the old and new events into one.
- */
- ev->lost_msgs.lost_msgs += new_ev->lost_msgs.lost_msgs;
- goto unlock;
- }
-
- /*
- * Intermediate states are not interesting, so just
- * overwrite any older event.
- */
- *ev = *new_ev;
- ev->ts = ts;
- fh->pending_events |= 1 << new_ev->event;
-
-unlock:
- mutex_unlock(&fh->lock);
- wake_up_interruptible(&fh->wait);
-}
-
-/* Queue a new event for all open filehandles. */
-static void cec_queue_event(struct cec_adapter *adap,
- const struct cec_event *ev)
-{
- u64 ts = ktime_get_ns();
- struct cec_fh *fh;
-
- mutex_lock(&adap->devnode.lock);
- list_for_each_entry(fh, &adap->devnode.fhs, list)
- cec_queue_event_fh(fh, ev, ts);
- mutex_unlock(&adap->devnode.lock);
-}
-
-/*
- * Queue a new message for this filehandle. If there is no more room
- * in the queue, then send the LOST_MSGS event instead.
- */
-static void cec_queue_msg_fh(struct cec_fh *fh, const struct cec_msg *msg)
-{
- static const struct cec_event ev_lost_msg = {
- .ts = 0,
- .event = CEC_EVENT_LOST_MSGS,
- .flags = 0,
- {
- .lost_msgs.lost_msgs = 1,
- },
- };
- struct cec_msg_entry *entry;
-
- mutex_lock(&fh->lock);
- entry = kmalloc(sizeof(*entry), GFP_KERNEL);
- if (!entry)
- goto lost_msgs;
-
- entry->msg = *msg;
- /* Add new msg at the end of the queue */
- list_add_tail(&entry->list, &fh->msgs);
-
- /*
- * if the queue now has more than CEC_MAX_MSG_RX_QUEUE_SZ
- * messages, drop the oldest one and send a lost message event.
- */
- if (fh->queued_msgs == CEC_MAX_MSG_RX_QUEUE_SZ) {
- list_del(&entry->list);
- goto lost_msgs;
- }
- fh->queued_msgs++;
- mutex_unlock(&fh->lock);
- wake_up_interruptible(&fh->wait);
- return;
-
-lost_msgs:
- mutex_unlock(&fh->lock);
- cec_queue_event_fh(fh, &ev_lost_msg, 0);
-}
-
-/*
- * Queue the message for those filehandles that are in monitor mode.
- * If valid_la is true (this message is for us or was sent by us),
- * then pass it on to any monitoring filehandle. If this message
- * isn't for us or from us, then only give it to filehandles that
- * are in MONITOR_ALL mode.
- *
- * This can only happen if the CEC_CAP_MONITOR_ALL capability is
- * set and the CEC adapter was placed in 'monitor all' mode.
- */
-static void cec_queue_msg_monitor(struct cec_adapter *adap,
- const struct cec_msg *msg,
- bool valid_la)
-{
- struct cec_fh *fh;
- u32 monitor_mode = valid_la ? CEC_MODE_MONITOR :
- CEC_MODE_MONITOR_ALL;
-
- mutex_lock(&adap->devnode.lock);
- list_for_each_entry(fh, &adap->devnode.fhs, list) {
- if (fh->mode_follower >= monitor_mode)
- cec_queue_msg_fh(fh, msg);
- }
- mutex_unlock(&adap->devnode.lock);
-}
-
-/*
- * Queue the message for follower filehandles.
- */
-static void cec_queue_msg_followers(struct cec_adapter *adap,
- const struct cec_msg *msg)
-{
- struct cec_fh *fh;
-
- mutex_lock(&adap->devnode.lock);
- list_for_each_entry(fh, &adap->devnode.fhs, list) {
- if (fh->mode_follower == CEC_MODE_FOLLOWER)
- cec_queue_msg_fh(fh, msg);
- }
- mutex_unlock(&adap->devnode.lock);
-}
-
-/* Notify userspace of an adapter state change. */
-static void cec_post_state_event(struct cec_adapter *adap)
-{
- struct cec_event ev = {
- .event = CEC_EVENT_STATE_CHANGE,
- };
-
- ev.state_change.phys_addr = adap->phys_addr;
- ev.state_change.log_addr_mask = adap->log_addrs.log_addr_mask;
- cec_queue_event(adap, &ev);
-}
-
-/*
- * A CEC transmit (and a possible wait for reply) completed.
- * If this was in blocking mode, then complete it, otherwise
- * queue the message for userspace to dequeue later.
- *
- * This function is called with adap->lock held.
- */
-static void cec_data_completed(struct cec_data *data)
-{
- /*
- * Delete this transmit from the filehandle's xfer_list since
- * we're done with it.
- *
- * Note that if the filehandle is closed before this transmit
- * finished, then the release() function will set data->fh to NULL.
- * Without that we would be referring to a closed filehandle.
- */
- if (data->fh)
- list_del(&data->xfer_list);
-
- if (data->blocking) {
- /*
- * Someone is blocking so mark the message as completed
- * and call complete.
- */
- data->completed = true;
- complete(&data->c);
- } else {
- /*
- * No blocking, so just queue the message if needed and
- * free the memory.
- */
- if (data->fh)
- cec_queue_msg_fh(data->fh, &data->msg);
- kfree(data);
- }
-}
-
-/*
- * A pending CEC transmit needs to be cancelled, either because the CEC
- * adapter is disabled or the transmit takes an impossibly long time to
- * finish.
- *
- * This function is called with adap->lock held.
- */
-static void cec_data_cancel(struct cec_data *data)
-{
- /*
- * It's either the current transmit, or it is a pending
- * transmit. Take the appropriate action to clear it.
- */
- if (data->adap->transmitting == data) {
- data->adap->transmitting = NULL;
- } else {
- list_del_init(&data->list);
- if (!(data->msg.tx_status & CEC_TX_STATUS_OK))
- data->adap->transmit_queue_sz--;
- }
-
- /* Mark it as an error */
- data->msg.tx_ts = ktime_get_ns();
- data->msg.tx_status = CEC_TX_STATUS_ERROR |
- CEC_TX_STATUS_MAX_RETRIES;
- data->attempts = 0;
- data->msg.tx_error_cnt = 1;
- /* Queue transmitted message for monitoring purposes */
- cec_queue_msg_monitor(data->adap, &data->msg, 1);
-
- cec_data_completed(data);
-}
-
-/*
- * Main CEC state machine
- *
- * Wait until the thread should be stopped, or we are not transmitting and
- * a new transmit message is queued up, in which case we start transmitting
- * that message. When the adapter finished transmitting the message it will
- * call cec_transmit_done().
- *
- * If the adapter is disabled, then remove all queued messages instead.
- *
- * If the current transmit times out, then cancel that transmit.
- */
-int cec_thread_func(void *_adap)
-{
- struct cec_adapter *adap = _adap;
-
- for (;;) {
- unsigned int signal_free_time;
- struct cec_data *data;
- bool timeout = false;
- u8 attempts;
-
- if (adap->transmitting) {
- int err;
-
- /*
- * We are transmitting a message, so add a timeout
- * to prevent the state machine to get stuck waiting
- * for this message to finalize and add a check to
- * see if the adapter is disabled in which case the
- * transmit should be canceled.
- */
- err = wait_event_interruptible_timeout(adap->kthread_waitq,
- kthread_should_stop() ||
- (!adap->is_configured && !adap->is_configuring) ||
- (!adap->transmitting &&
- !list_empty(&adap->transmit_queue)),
- msecs_to_jiffies(CEC_XFER_TIMEOUT_MS));
- timeout = err == 0;
- } else {
- /* Otherwise we just wait for something to happen. */
- wait_event_interruptible(adap->kthread_waitq,
- kthread_should_stop() ||
- (!adap->transmitting &&
- !list_empty(&adap->transmit_queue)));
- }
-
- mutex_lock(&adap->lock);
-
- if ((!adap->is_configured && !adap->is_configuring) ||
- kthread_should_stop()) {
- /*
- * If the adapter is disabled, or we're asked to stop,
- * then cancel any pending transmits.
- */
- while (!list_empty(&adap->transmit_queue)) {
- data = list_first_entry(&adap->transmit_queue,
- struct cec_data, list);
- cec_data_cancel(data);
- }
- if (adap->transmitting)
- cec_data_cancel(adap->transmitting);
-
- /*
- * Cancel the pending timeout work. We have to unlock
- * the mutex when flushing the work since
- * cec_wait_timeout() will take it. This is OK since
- * no new entries can be added to wait_queue as long
- * as adap->transmitting is NULL, which it is due to
- * the cec_data_cancel() above.
- */
- while (!list_empty(&adap->wait_queue)) {
- data = list_first_entry(&adap->wait_queue,
- struct cec_data, list);
-
- if (!cancel_delayed_work(&data->work)) {
- mutex_unlock(&adap->lock);
- flush_scheduled_work();
- mutex_lock(&adap->lock);
- }
- cec_data_cancel(data);
- }
- goto unlock;
- }
-
- if (adap->transmitting && timeout) {
- /*
- * If we timeout, then log that. This really shouldn't
- * happen and is an indication of a faulty CEC adapter
- * driver, or the CEC bus is in some weird state.
- */
- dprintk(0, "message %*ph timed out!\n",
- adap->transmitting->msg.len,
- adap->transmitting->msg.msg);
- /* Just give up on this. */
- cec_data_cancel(adap->transmitting);
- goto unlock;
- }
-
- /*
- * If we are still transmitting, or there is nothing new to
- * transmit, then just continue waiting.
- */
- if (adap->transmitting || list_empty(&adap->transmit_queue))
- goto unlock;
-
- /* Get a new message to transmit */
- data = list_first_entry(&adap->transmit_queue,
- struct cec_data, list);
- list_del_init(&data->list);
- adap->transmit_queue_sz--;
- /* Make this the current transmitting message */
- adap->transmitting = data;
-
- /*
- * Suggested number of attempts as per the CEC 2.0 spec:
- * 4 attempts is the default, except for 'secondary poll
- * messages', i.e. poll messages not sent during the adapter
- * configuration phase when it allocates logical addresses.
- */
- if (data->msg.len == 1 && adap->is_configured)
- attempts = 2;
- else
- attempts = 4;
-
- /* Set the suggested signal free time */
- if (data->attempts) {
- /* should be >= 3 data bit periods for a retry */
- signal_free_time = CEC_SIGNAL_FREE_TIME_RETRY;
- } else if (data->new_initiator) {
- /* should be >= 5 data bit periods for new initiator */
- signal_free_time = CEC_SIGNAL_FREE_TIME_NEW_INITIATOR;
- } else {
- /*
- * should be >= 7 data bit periods for sending another
- * frame immediately after another.
- */
- signal_free_time = CEC_SIGNAL_FREE_TIME_NEXT_XFER;
- }
- if (data->attempts == 0)
- data->attempts = attempts;
-
- /* Tell the adapter to transmit, cancel on error */
- if (adap->ops->adap_transmit(adap, data->attempts,
- signal_free_time, &data->msg))
- cec_data_cancel(data);
-
-unlock:
- mutex_unlock(&adap->lock);
-
- if (kthread_should_stop())
- break;
- }
- return 0;
-}
-
-/*
- * Called by the CEC adapter if a transmit finished.
- */
-void cec_transmit_done(struct cec_adapter *adap, u8 status, u8 arb_lost_cnt,
- u8 nack_cnt, u8 low_drive_cnt, u8 error_cnt)
-{
- struct cec_data *data;
- struct cec_msg *msg;
- u64 ts = ktime_get_ns();
-
- dprintk(2, "cec_transmit_done %02x\n", status);
- mutex_lock(&adap->lock);
- data = adap->transmitting;
- if (!data) {
- /*
- * This can happen if a transmit was issued and the cable is
- * unplugged while the transmit is ongoing. Ignore this
- * transmit in that case.
- */
- dprintk(1, "cec_transmit_done without an ongoing transmit!\n");
- goto unlock;
- }
-
- msg = &data->msg;
-
- /* Drivers must fill in the status! */
- WARN_ON(status == 0);
- msg->tx_ts = ts;
- msg->tx_status |= status;
- msg->tx_arb_lost_cnt += arb_lost_cnt;
- msg->tx_nack_cnt += nack_cnt;
- msg->tx_low_drive_cnt += low_drive_cnt;
- msg->tx_error_cnt += error_cnt;
-
- /* Mark that we're done with this transmit */
- adap->transmitting = NULL;
-
- /*
- * If there are still retry attempts left and there was an error and
- * the hardware didn't signal that it retried itself (by setting
- * CEC_TX_STATUS_MAX_RETRIES), then we will retry ourselves.
- */
- if (data->attempts > 1 &&
- !(status & (CEC_TX_STATUS_MAX_RETRIES | CEC_TX_STATUS_OK))) {
- /* Retry this message */
- data->attempts--;
- /* Add the message in front of the transmit queue */
- list_add(&data->list, &adap->transmit_queue);
- adap->transmit_queue_sz++;
- goto wake_thread;
- }
-
- data->attempts = 0;
-
- /* Always set CEC_TX_STATUS_MAX_RETRIES on error */
- if (!(status & CEC_TX_STATUS_OK))
- msg->tx_status |= CEC_TX_STATUS_MAX_RETRIES;
-
- /* Queue transmitted message for monitoring purposes */
- cec_queue