root/drivers/media/cec/cec-api.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cec_devnode_data
  2. cec_poll
  3. cec_is_busy
  4. cec_adap_g_caps
  5. cec_adap_g_phys_addr
  6. cec_validate_phys_addr
  7. cec_adap_s_phys_addr
  8. cec_adap_g_log_addrs
  9. cec_adap_s_log_addrs
  10. cec_transmit
  11. cec_receive_msg
  12. cec_receive
  13. cec_dqevent
  14. cec_g_mode
  15. cec_s_mode
  16. cec_ioctl
  17. cec_open
  18. cec_release

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * cec-api.c - HDMI Consumer Electronics Control framework - API
   4  *
   5  * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
   6  */
   7 
   8 #include <linux/errno.h>
   9 #include <linux/init.h>
  10 #include <linux/module.h>
  11 #include <linux/kernel.h>
  12 #include <linux/kmod.h>
  13 #include <linux/ktime.h>
  14 #include <linux/slab.h>
  15 #include <linux/mm.h>
  16 #include <linux/string.h>
  17 #include <linux/types.h>
  18 #include <linux/uaccess.h>
  19 #include <linux/version.h>
  20 
  21 #include <media/cec-pin.h>
  22 #include "cec-priv.h"
  23 #include "cec-pin-priv.h"
  24 
  25 static inline struct cec_devnode *cec_devnode_data(struct file *filp)
  26 {
  27         struct cec_fh *fh = filp->private_data;
  28 
  29         return &fh->adap->devnode;
  30 }
  31 
  32 /* CEC file operations */
  33 
  34 static __poll_t cec_poll(struct file *filp,
  35                              struct poll_table_struct *poll)
  36 {
  37         struct cec_fh *fh = filp->private_data;
  38         struct cec_adapter *adap = fh->adap;
  39         __poll_t res = 0;
  40 
  41         poll_wait(filp, &fh->wait, poll);
  42         if (!cec_is_registered(adap))
  43                 return EPOLLERR | EPOLLHUP;
  44         mutex_lock(&adap->lock);
  45         if (adap->is_configured &&
  46             adap->transmit_queue_sz < CEC_MAX_MSG_TX_QUEUE_SZ)
  47                 res |= EPOLLOUT | EPOLLWRNORM;
  48         if (fh->queued_msgs)
  49                 res |= EPOLLIN | EPOLLRDNORM;
  50         if (fh->total_queued_events)
  51                 res |= EPOLLPRI;
  52         mutex_unlock(&adap->lock);
  53         return res;
  54 }
  55 
  56 static bool cec_is_busy(const struct cec_adapter *adap,
  57                         const struct cec_fh *fh)
  58 {
  59         bool valid_initiator = adap->cec_initiator && adap->cec_initiator == fh;
  60         bool valid_follower = adap->cec_follower && adap->cec_follower == fh;
  61 
  62         /*
  63          * Exclusive initiators and followers can always access the CEC adapter
  64          */
  65         if (valid_initiator || valid_follower)
  66                 return false;
  67         /*
  68          * All others can only access the CEC adapter if there is no
  69          * exclusive initiator and they are in INITIATOR mode.
  70          */
  71         return adap->cec_initiator ||
  72                fh->mode_initiator == CEC_MODE_NO_INITIATOR;
  73 }
  74 
  75 static long cec_adap_g_caps(struct cec_adapter *adap,
  76                             struct cec_caps __user *parg)
  77 {
  78         struct cec_caps caps = {};
  79 
  80         strscpy(caps.driver, adap->devnode.dev.parent->driver->name,
  81                 sizeof(caps.driver));
  82         strscpy(caps.name, adap->name, sizeof(caps.name));
  83         caps.available_log_addrs = adap->available_log_addrs;
  84         caps.capabilities = adap->capabilities;
  85         caps.version = LINUX_VERSION_CODE;
  86         if (copy_to_user(parg, &caps, sizeof(caps)))
  87                 return -EFAULT;
  88         return 0;
  89 }
  90 
  91 static long cec_adap_g_phys_addr(struct cec_adapter *adap,
  92                                  __u16 __user *parg)
  93 {
  94         u16 phys_addr;
  95 
  96         mutex_lock(&adap->lock);
  97         phys_addr = adap->phys_addr;
  98         mutex_unlock(&adap->lock);
  99         if (copy_to_user(parg, &phys_addr, sizeof(phys_addr)))
 100                 return -EFAULT;
 101         return 0;
 102 }
 103 
 104 static int cec_validate_phys_addr(u16 phys_addr)
 105 {
 106         int i;
 107 
 108         if (phys_addr == CEC_PHYS_ADDR_INVALID)
 109                 return 0;
 110         for (i = 0; i < 16; i += 4)
 111                 if (phys_addr & (0xf << i))
 112                         break;
 113         if (i == 16)
 114                 return 0;
 115         for (i += 4; i < 16; i += 4)
 116                 if ((phys_addr & (0xf << i)) == 0)
 117                         return -EINVAL;
 118         return 0;
 119 }
 120 
 121 static long cec_adap_s_phys_addr(struct cec_adapter *adap, struct cec_fh *fh,
 122                                  bool block, __u16 __user *parg)
 123 {
 124         u16 phys_addr;
 125         long err;
 126 
 127         if (!(adap->capabilities & CEC_CAP_PHYS_ADDR))
 128                 return -ENOTTY;
 129         if (copy_from_user(&phys_addr, parg, sizeof(phys_addr)))
 130                 return -EFAULT;
 131 
 132         err = cec_validate_phys_addr(phys_addr);
 133         if (err)
 134                 return err;
 135         mutex_lock(&adap->lock);
 136         if (cec_is_busy(adap, fh))
 137                 err = -EBUSY;
 138         else
 139                 __cec_s_phys_addr(adap, phys_addr, block);
 140         mutex_unlock(&adap->lock);
 141         return err;
 142 }
 143 
 144 static long cec_adap_g_log_addrs(struct cec_adapter *adap,
 145                                  struct cec_log_addrs __user *parg)
 146 {
 147         struct cec_log_addrs log_addrs;
 148 
 149         mutex_lock(&adap->lock);
 150         log_addrs = adap->log_addrs;
 151         if (!adap->is_configured)
 152                 memset(log_addrs.log_addr, CEC_LOG_ADDR_INVALID,
 153                        sizeof(log_addrs.log_addr));
 154         mutex_unlock(&adap->lock);
 155 
 156         if (copy_to_user(parg, &log_addrs, sizeof(log_addrs)))
 157                 return -EFAULT;
 158         return 0;
 159 }
 160 
 161 static long cec_adap_s_log_addrs(struct cec_adapter *adap, struct cec_fh *fh,
 162                                  bool block, struct cec_log_addrs __user *parg)
 163 {
 164         struct cec_log_addrs log_addrs;
 165         long err = -EBUSY;
 166 
 167         if (!(adap->capabilities & CEC_CAP_LOG_ADDRS))
 168                 return -ENOTTY;
 169         if (copy_from_user(&log_addrs, parg, sizeof(log_addrs)))
 170                 return -EFAULT;
 171         log_addrs.flags &= CEC_LOG_ADDRS_FL_ALLOW_UNREG_FALLBACK |
 172                            CEC_LOG_ADDRS_FL_ALLOW_RC_PASSTHRU |
 173                            CEC_LOG_ADDRS_FL_CDC_ONLY;
 174         mutex_lock(&adap->lock);
 175         if (!adap->is_configuring &&
 176             (!log_addrs.num_log_addrs || !adap->is_configured) &&
 177             !cec_is_busy(adap, fh)) {
 178                 err = __cec_s_log_addrs(adap, &log_addrs, block);
 179                 if (!err)
 180                         log_addrs = adap->log_addrs;
 181         }
 182         mutex_unlock(&adap->lock);
 183         if (err)
 184                 return err;
 185         if (copy_to_user(parg, &log_addrs, sizeof(log_addrs)))
 186                 return -EFAULT;
 187         return 0;
 188 }
 189 
 190 static long cec_transmit(struct cec_adapter *adap, struct cec_fh *fh,
 191                          bool block, struct cec_msg __user *parg)
 192 {
 193         struct cec_msg msg = {};
 194         long err = 0;
 195 
 196         if (!(adap->capabilities & CEC_CAP_TRANSMIT))
 197                 return -ENOTTY;
 198         if (copy_from_user(&msg, parg, sizeof(msg)))
 199                 return -EFAULT;
 200 
 201         mutex_lock(&adap->lock);
 202         if (adap->log_addrs.num_log_addrs == 0)
 203                 err = -EPERM;
 204         else if (adap->is_configuring)
 205                 err = -ENONET;
 206         else if (cec_is_busy(adap, fh))
 207                 err = -EBUSY;
 208         else
 209                 err = cec_transmit_msg_fh(adap, &msg, fh, block);
 210         mutex_unlock(&adap->lock);
 211         if (err)
 212                 return err;
 213         if (copy_to_user(parg, &msg, sizeof(msg)))
 214                 return -EFAULT;
 215         return 0;
 216 }
 217 
 218 /* Called by CEC_RECEIVE: wait for a message to arrive */
 219 static int cec_receive_msg(struct cec_fh *fh, struct cec_msg *msg, bool block)
 220 {
 221         u32 timeout = msg->timeout;
 222         int res;
 223 
 224         do {
 225                 mutex_lock(&fh->lock);
 226                 /* Are there received messages queued up? */
 227                 if (fh->queued_msgs) {
 228                         /* Yes, return the first one */
 229                         struct cec_msg_entry *entry =
 230                                 list_first_entry(&fh->msgs,
 231                                                  struct cec_msg_entry, list);
 232 
 233                         list_del(&entry->list);
 234                         *msg = entry->msg;
 235                         kfree(entry);
 236                         fh->queued_msgs--;
 237                         mutex_unlock(&fh->lock);
 238                         /* restore original timeout value */
 239                         msg->timeout = timeout;
 240                         return 0;
 241                 }
 242 
 243                 /* No, return EAGAIN in non-blocking mode or wait */
 244                 mutex_unlock(&fh->lock);
 245 
 246                 /* Return when in non-blocking mode */
 247                 if (!block)
 248                         return -EAGAIN;
 249 
 250                 if (msg->timeout) {
 251                         /* The user specified a timeout */
 252                         res = wait_event_interruptible_timeout(fh->wait,
 253                                                                fh->queued_msgs,
 254                                 msecs_to_jiffies(msg->timeout));
 255                         if (res == 0)
 256                                 res = -ETIMEDOUT;
 257                         else if (res > 0)
 258                                 res = 0;
 259                 } else {
 260                         /* Wait indefinitely */
 261                         res = wait_event_interruptible(fh->wait,
 262                                                        fh->queued_msgs);
 263                 }
 264                 /* Exit on error, otherwise loop to get the new message */
 265         } while (!res);
 266         return res;
 267 }
 268 
 269 static long cec_receive(struct cec_adapter *adap, struct cec_fh *fh,
 270                         bool block, struct cec_msg __user *parg)
 271 {
 272         struct cec_msg msg = {};
 273         long err;
 274 
 275         if (copy_from_user(&msg, parg, sizeof(msg)))
 276                 return -EFAULT;
 277 
 278         err = cec_receive_msg(fh, &msg, block);
 279         if (err)
 280                 return err;
 281         msg.flags = 0;
 282         if (copy_to_user(parg, &msg, sizeof(msg)))
 283                 return -EFAULT;
 284         return 0;
 285 }
 286 
 287 static long cec_dqevent(struct cec_adapter *adap, struct cec_fh *fh,
 288                         bool block, struct cec_event __user *parg)
 289 {
 290         struct cec_event_entry *ev = NULL;
 291         u64 ts = ~0ULL;
 292         unsigned int i;
 293         unsigned int ev_idx;
 294         long err = 0;
 295 
 296         mutex_lock(&fh->lock);
 297         while (!fh->total_queued_events && block) {
 298                 mutex_unlock(&fh->lock);
 299                 err = wait_event_interruptible(fh->wait,
 300                                                fh->total_queued_events);
 301                 if (err)
 302                         return err;
 303                 mutex_lock(&fh->lock);
 304         }
 305 
 306         /* Find the oldest event */
 307         for (i = 0; i < CEC_NUM_EVENTS; i++) {
 308                 struct cec_event_entry *entry =
 309                         list_first_entry_or_null(&fh->events[i],
 310                                                  struct cec_event_entry, list);
 311 
 312                 if (entry && entry->ev.ts <= ts) {
 313                         ev = entry;
 314                         ev_idx = i;
 315                         ts = ev->ev.ts;
 316                 }
 317         }
 318 
 319         if (!ev) {
 320                 err = -EAGAIN;
 321                 goto unlock;
 322         }
 323         list_del(&ev->list);
 324 
 325         if (copy_to_user(parg, &ev->ev, sizeof(ev->ev)))
 326                 err = -EFAULT;
 327         if (ev_idx >= CEC_NUM_CORE_EVENTS)
 328                 kfree(ev);
 329         fh->queued_events[ev_idx]--;
 330         fh->total_queued_events--;
 331 
 332 unlock:
 333         mutex_unlock(&fh->lock);
 334         return err;
 335 }
 336 
 337 static long cec_g_mode(struct cec_adapter *adap, struct cec_fh *fh,
 338                        u32 __user *parg)
 339 {
 340         u32 mode = fh->mode_initiator | fh->mode_follower;
 341 
 342         if (copy_to_user(parg, &mode, sizeof(mode)))
 343                 return -EFAULT;
 344         return 0;
 345 }
 346 
 347 static long cec_s_mode(struct cec_adapter *adap, struct cec_fh *fh,
 348                        u32 __user *parg)
 349 {
 350         u32 mode;
 351         u8 mode_initiator;
 352         u8 mode_follower;
 353         bool send_pin_event = false;
 354         long err = 0;
 355 
 356         if (copy_from_user(&mode, parg, sizeof(mode)))
 357                 return -EFAULT;
 358         if (mode & ~(CEC_MODE_INITIATOR_MSK | CEC_MODE_FOLLOWER_MSK)) {
 359                 dprintk(1, "%s: invalid mode bits set\n", __func__);
 360                 return -EINVAL;
 361         }
 362 
 363         mode_initiator = mode & CEC_MODE_INITIATOR_MSK;
 364         mode_follower = mode & CEC_MODE_FOLLOWER_MSK;
 365 
 366         if (mode_initiator > CEC_MODE_EXCL_INITIATOR ||
 367             mode_follower > CEC_MODE_MONITOR_ALL) {
 368                 dprintk(1, "%s: unknown mode\n", __func__);
 369                 return -EINVAL;
 370         }
 371 
 372         if (mode_follower == CEC_MODE_MONITOR_ALL &&
 373             !(adap->capabilities & CEC_CAP_MONITOR_ALL)) {
 374                 dprintk(1, "%s: MONITOR_ALL not supported\n", __func__);
 375                 return -EINVAL;
 376         }
 377 
 378         if (mode_follower == CEC_MODE_MONITOR_PIN &&
 379             !(adap->capabilities & CEC_CAP_MONITOR_PIN)) {
 380                 dprintk(1, "%s: MONITOR_PIN not supported\n", __func__);
 381                 return -EINVAL;
 382         }
 383 
 384         /* Follower modes should always be able to send CEC messages */
 385         if ((mode_initiator == CEC_MODE_NO_INITIATOR ||
 386              !(adap->capabilities & CEC_CAP_TRANSMIT)) &&
 387             mode_follower >= CEC_MODE_FOLLOWER &&
 388             mode_follower <= CEC_MODE_EXCL_FOLLOWER_PASSTHRU) {
 389                 dprintk(1, "%s: cannot transmit\n", __func__);
 390                 return -EINVAL;
 391         }
 392 
 393         /* Monitor modes require CEC_MODE_NO_INITIATOR */
 394         if (mode_initiator && mode_follower >= CEC_MODE_MONITOR_PIN) {
 395                 dprintk(1, "%s: monitor modes require NO_INITIATOR\n",
 396                         __func__);
 397                 return -EINVAL;
 398         }
 399 
 400         /* Monitor modes require CAP_NET_ADMIN */
 401         if (mode_follower >= CEC_MODE_MONITOR_PIN && !capable(CAP_NET_ADMIN))
 402                 return -EPERM;
 403 
 404         mutex_lock(&adap->lock);
 405         /*
 406          * You can't become exclusive follower if someone else already
 407          * has that job.
 408          */
 409         if ((mode_follower == CEC_MODE_EXCL_FOLLOWER ||
 410              mode_follower == CEC_MODE_EXCL_FOLLOWER_PASSTHRU) &&
 411             adap->cec_follower && adap->cec_follower != fh)
 412                 err = -EBUSY;
 413         /*
 414          * You can't become exclusive initiator if someone else already
 415          * has that job.
 416          */
 417         if (mode_initiator == CEC_MODE_EXCL_INITIATOR &&
 418             adap->cec_initiator && adap->cec_initiator != fh)
 419                 err = -EBUSY;
 420 
 421         if (!err) {
 422                 bool old_mon_all = fh->mode_follower == CEC_MODE_MONITOR_ALL;
 423                 bool new_mon_all = mode_follower == CEC_MODE_MONITOR_ALL;
 424 
 425                 if (old_mon_all != new_mon_all) {
 426                         if (new_mon_all)
 427                                 err = cec_monitor_all_cnt_inc(adap);
 428                         else
 429                                 cec_monitor_all_cnt_dec(adap);
 430                 }
 431         }
 432 
 433         if (!err) {
 434                 bool old_mon_pin = fh->mode_follower == CEC_MODE_MONITOR_PIN;
 435                 bool new_mon_pin = mode_follower == CEC_MODE_MONITOR_PIN;
 436 
 437                 if (old_mon_pin != new_mon_pin) {
 438                         send_pin_event = new_mon_pin;
 439                         if (new_mon_pin)
 440                                 err = cec_monitor_pin_cnt_inc(adap);
 441                         else
 442                                 cec_monitor_pin_cnt_dec(adap);
 443                 }
 444         }
 445 
 446         if (err) {
 447                 mutex_unlock(&adap->lock);
 448                 return err;
 449         }
 450 
 451         if (fh->mode_follower == CEC_MODE_FOLLOWER)
 452                 adap->follower_cnt--;
 453         if (mode_follower == CEC_MODE_FOLLOWER)
 454                 adap->follower_cnt++;
 455         if (send_pin_event) {
 456                 struct cec_event ev = {
 457                         .flags = CEC_EVENT_FL_INITIAL_STATE,
 458                 };
 459 
 460                 ev.event = adap->cec_pin_is_high ? CEC_EVENT_PIN_CEC_HIGH :
 461                                                    CEC_EVENT_PIN_CEC_LOW;
 462                 cec_queue_event_fh(fh, &ev, 0);
 463         }
 464         if (mode_follower == CEC_MODE_EXCL_FOLLOWER ||
 465             mode_follower == CEC_MODE_EXCL_FOLLOWER_PASSTHRU) {
 466                 adap->passthrough =
 467                         mode_follower == CEC_MODE_EXCL_FOLLOWER_PASSTHRU;
 468                 adap->cec_follower = fh;
 469         } else if (adap->cec_follower == fh) {
 470                 adap->passthrough = false;
 471                 adap->cec_follower = NULL;
 472         }
 473         if (mode_initiator == CEC_MODE_EXCL_INITIATOR)
 474                 adap->cec_initiator = fh;
 475         else if (adap->cec_initiator == fh)
 476                 adap->cec_initiator = NULL;
 477         fh->mode_initiator = mode_initiator;
 478         fh->mode_follower = mode_follower;
 479         mutex_unlock(&adap->lock);
 480         return 0;
 481 }
 482 
 483 static long cec_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 484 {
 485         struct cec_fh *fh = filp->private_data;
 486         struct cec_adapter *adap = fh->adap;
 487         bool block = !(filp->f_flags & O_NONBLOCK);
 488         void __user *parg = (void __user *)arg;
 489 
 490         if (!cec_is_registered(adap))
 491                 return -ENODEV;
 492 
 493         switch (cmd) {
 494         case CEC_ADAP_G_CAPS:
 495                 return cec_adap_g_caps(adap, parg);
 496 
 497         case CEC_ADAP_G_PHYS_ADDR:
 498                 return cec_adap_g_phys_addr(adap, parg);
 499 
 500         case CEC_ADAP_S_PHYS_ADDR:
 501                 return cec_adap_s_phys_addr(adap, fh, block, parg);
 502 
 503         case CEC_ADAP_G_LOG_ADDRS:
 504                 return cec_adap_g_log_addrs(adap, parg);
 505 
 506         case CEC_ADAP_S_LOG_ADDRS:
 507                 return cec_adap_s_log_addrs(adap, fh, block, parg);
 508 
 509         case CEC_TRANSMIT:
 510                 return cec_transmit(adap, fh, block, parg);
 511 
 512         case CEC_RECEIVE:
 513                 return cec_receive(adap, fh, block, parg);
 514 
 515         case CEC_DQEVENT:
 516                 return cec_dqevent(adap, fh, block, parg);
 517 
 518         case CEC_G_MODE:
 519                 return cec_g_mode(adap, fh, parg);
 520 
 521         case CEC_S_MODE:
 522                 return cec_s_mode(adap, fh, parg);
 523 
 524         default:
 525                 return -ENOTTY;
 526         }
 527 }
 528 
 529 static int cec_open(struct inode *inode, struct file *filp)
 530 {
 531         struct cec_devnode *devnode =
 532                 container_of(inode->i_cdev, struct cec_devnode, cdev);
 533         struct cec_adapter *adap = to_cec_adapter(devnode);
 534         struct cec_fh *fh = kzalloc(sizeof(*fh), GFP_KERNEL);
 535         /*
 536          * Initial events that are automatically sent when the cec device is
 537          * opened.
 538          */
 539         struct cec_event ev = {
 540                 .event = CEC_EVENT_STATE_CHANGE,
 541                 .flags = CEC_EVENT_FL_INITIAL_STATE,
 542         };
 543         unsigned int i;
 544         int err;
 545 
 546         if (!fh)
 547                 return -ENOMEM;
 548 
 549         INIT_LIST_HEAD(&fh->msgs);
 550         INIT_LIST_HEAD(&fh->xfer_list);
 551         for (i = 0; i < CEC_NUM_EVENTS; i++)
 552                 INIT_LIST_HEAD(&fh->events[i]);
 553         mutex_init(&fh->lock);
 554         init_waitqueue_head(&fh->wait);
 555 
 556         fh->mode_initiator = CEC_MODE_INITIATOR;
 557         fh->adap = adap;
 558 
 559         err = cec_get_device(devnode);
 560         if (err) {
 561                 kfree(fh);
 562                 return err;
 563         }
 564 
 565         mutex_lock(&devnode->lock);
 566         if (list_empty(&devnode->fhs) &&
 567             !adap->needs_hpd &&
 568             adap->phys_addr == CEC_PHYS_ADDR_INVALID) {
 569                 err = adap->ops->adap_enable(adap, true);
 570                 if (err) {
 571                         mutex_unlock(&devnode->lock);
 572                         kfree(fh);
 573                         return err;
 574                 }
 575         }
 576         filp->private_data = fh;
 577 
 578         /* Queue up initial state events */
 579         ev.state_change.phys_addr = adap->phys_addr;
 580         ev.state_change.log_addr_mask = adap->log_addrs.log_addr_mask;
 581         cec_queue_event_fh(fh, &ev, 0);
 582 #ifdef CONFIG_CEC_PIN
 583         if (adap->pin && adap->pin->ops->read_hpd) {
 584                 err = adap->pin->ops->read_hpd(adap);
 585                 if (err >= 0) {
 586                         ev.event = err ? CEC_EVENT_PIN_HPD_HIGH :
 587                                          CEC_EVENT_PIN_HPD_LOW;
 588                         cec_queue_event_fh(fh, &ev, 0);
 589                 }
 590         }
 591         if (adap->pin && adap->pin->ops->read_5v) {
 592                 err = adap->pin->ops->read_5v(adap);
 593                 if (err >= 0) {
 594                         ev.event = err ? CEC_EVENT_PIN_5V_HIGH :
 595                                          CEC_EVENT_PIN_5V_LOW;
 596                         cec_queue_event_fh(fh, &ev, 0);
 597                 }
 598         }
 599 #endif
 600 
 601         list_add(&fh->list, &devnode->fhs);
 602         mutex_unlock(&devnode->lock);
 603 
 604         return 0;
 605 }
 606 
 607 /* Override for the release function */
 608 static int cec_release(struct inode *inode, struct file *filp)
 609 {
 610         struct cec_devnode *devnode = cec_devnode_data(filp);
 611         struct cec_adapter *adap = to_cec_adapter(devnode);
 612         struct cec_fh *fh = filp->private_data;
 613         unsigned int i;
 614 
 615         mutex_lock(&adap->lock);
 616         if (adap->cec_initiator == fh)
 617                 adap->cec_initiator = NULL;
 618         if (adap->cec_follower == fh) {
 619                 adap->cec_follower = NULL;
 620                 adap->passthrough = false;
 621         }
 622         if (fh->mode_follower == CEC_MODE_FOLLOWER)
 623                 adap->follower_cnt--;
 624         if (fh->mode_follower == CEC_MODE_MONITOR_PIN)
 625                 cec_monitor_pin_cnt_dec(adap);
 626         if (fh->mode_follower == CEC_MODE_MONITOR_ALL)
 627                 cec_monitor_all_cnt_dec(adap);
 628         mutex_unlock(&adap->lock);
 629 
 630         mutex_lock(&devnode->lock);
 631         list_del(&fh->list);
 632         if (cec_is_registered(adap) && list_empty(&devnode->fhs) &&
 633             !adap->needs_hpd && adap->phys_addr == CEC_PHYS_ADDR_INVALID) {
 634                 WARN_ON(adap->ops->adap_enable(adap, false));
 635         }
 636         mutex_unlock(&devnode->lock);
 637 
 638         /* Unhook pending transmits from this filehandle. */
 639         mutex_lock(&adap->lock);
 640         while (!list_empty(&fh->xfer_list)) {
 641                 struct cec_data *data =
 642                         list_first_entry(&fh->xfer_list, struct cec_data, xfer_list);
 643 
 644                 data->blocking = false;
 645                 data->fh = NULL;
 646                 list_del(&data->xfer_list);
 647         }
 648         mutex_unlock(&adap->lock);
 649         while (!list_empty(&fh->msgs)) {
 650                 struct cec_msg_entry *entry =
 651                         list_first_entry(&fh->msgs, struct cec_msg_entry, list);
 652 
 653                 list_del(&entry->list);
 654                 kfree(entry);
 655         }
 656         for (i = CEC_NUM_CORE_EVENTS; i < CEC_NUM_EVENTS; i++) {
 657                 while (!list_empty(&fh->events[i])) {
 658                         struct cec_event_entry *entry =
 659                                 list_first_entry(&fh->events[i],
 660                                                  struct cec_event_entry, list);
 661 
 662                         list_del(&entry->list);
 663                         kfree(entry);
 664                 }
 665         }
 666         kfree(fh);
 667 
 668         cec_put_device(devnode);
 669         filp->private_data = NULL;
 670         return 0;
 671 }
 672 
 673 const struct file_operations cec_devnode_fops = {
 674         .owner = THIS_MODULE,
 675         .open = cec_open,
 676         .unlocked_ioctl = cec_ioctl,
 677         .compat_ioctl = cec_ioctl,
 678         .release = cec_release,
 679         .poll = cec_poll,
 680         .llseek = no_llseek,
 681 };

/* [<][>][^][v][top][bottom][index][help] */