linux/drivers/acpi/acpi_dbg.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * ACPI AML interfacing support
   4 *
   5 * Copyright (C) 2015, Intel Corporation
   6 * Authors: Lv Zheng <lv.zheng@intel.com>
   7 */
   8
   9/* #define DEBUG */
  10#define pr_fmt(fmt) "ACPI: AML: " fmt
  11
  12#include <linux/kernel.h>
  13#include <linux/module.h>
  14#include <linux/wait.h>
  15#include <linux/poll.h>
  16#include <linux/sched.h>
  17#include <linux/kthread.h>
  18#include <linux/proc_fs.h>
  19#include <linux/debugfs.h>
  20#include <linux/circ_buf.h>
  21#include <linux/acpi.h>
  22#include "internal.h"
  23
  24#define ACPI_AML_BUF_ALIGN      (sizeof (acpi_size))
  25#define ACPI_AML_BUF_SIZE       PAGE_SIZE
  26
  27#define circ_count(circ) \
  28        (CIRC_CNT((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
  29#define circ_count_to_end(circ) \
  30        (CIRC_CNT_TO_END((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
  31#define circ_space(circ) \
  32        (CIRC_SPACE((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
  33#define circ_space_to_end(circ) \
  34        (CIRC_SPACE_TO_END((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
  35
  36#define ACPI_AML_OPENED         0x0001
  37#define ACPI_AML_CLOSED         0x0002
  38#define ACPI_AML_IN_USER        0x0004 /* user space is writing cmd */
  39#define ACPI_AML_IN_KERN        0x0008 /* kernel space is reading cmd */
  40#define ACPI_AML_OUT_USER       0x0010 /* user space is reading log */
  41#define ACPI_AML_OUT_KERN       0x0020 /* kernel space is writing log */
  42#define ACPI_AML_USER           (ACPI_AML_IN_USER | ACPI_AML_OUT_USER)
  43#define ACPI_AML_KERN           (ACPI_AML_IN_KERN | ACPI_AML_OUT_KERN)
  44#define ACPI_AML_BUSY           (ACPI_AML_USER | ACPI_AML_KERN)
  45#define ACPI_AML_OPEN           (ACPI_AML_OPENED | ACPI_AML_CLOSED)
  46
  47struct acpi_aml_io {
  48        wait_queue_head_t wait;
  49        unsigned long flags;
  50        unsigned long users;
  51        struct mutex lock;
  52        struct task_struct *thread;
  53        char out_buf[ACPI_AML_BUF_SIZE] __aligned(ACPI_AML_BUF_ALIGN);
  54        struct circ_buf out_crc;
  55        char in_buf[ACPI_AML_BUF_SIZE] __aligned(ACPI_AML_BUF_ALIGN);
  56        struct circ_buf in_crc;
  57        acpi_osd_exec_callback function;
  58        void *context;
  59        unsigned long usages;
  60};
  61
  62static struct acpi_aml_io acpi_aml_io;
  63static bool acpi_aml_initialized;
  64static struct file *acpi_aml_active_reader;
  65static struct dentry *acpi_aml_dentry;
  66
  67static inline bool __acpi_aml_running(void)
  68{
  69        return acpi_aml_io.thread ? true : false;
  70}
  71
  72static inline bool __acpi_aml_access_ok(unsigned long flag)
  73{
  74        /*
  75         * The debugger interface is in opened state (OPENED && !CLOSED),
  76         * then it is allowed to access the debugger buffers from either
  77         * user space or the kernel space.
  78         * In addition, for the kernel space, only the debugger thread
  79         * (thread ID matched) is allowed to access.
  80         */
  81        if (!(acpi_aml_io.flags & ACPI_AML_OPENED) ||
  82            (acpi_aml_io.flags & ACPI_AML_CLOSED) ||
  83            !__acpi_aml_running())
  84                return false;
  85        if ((flag & ACPI_AML_KERN) &&
  86            current != acpi_aml_io.thread)
  87                return false;
  88        return true;
  89}
  90
  91static inline bool __acpi_aml_readable(struct circ_buf *circ, unsigned long flag)
  92{
  93        /*
  94         * Another read is not in progress and there is data in buffer
  95         * available for read.
  96         */
  97        if (!(acpi_aml_io.flags & flag) && circ_count(circ))
  98                return true;
  99        return false;
 100}
 101
 102static inline bool __acpi_aml_writable(struct circ_buf *circ, unsigned long flag)
 103{
 104        /*
 105         * Another write is not in progress and there is buffer space
 106         * available for write.
 107         */
 108        if (!(acpi_aml_io.flags & flag) && circ_space(circ))
 109                return true;
 110        return false;
 111}
 112
 113static inline bool __acpi_aml_busy(void)
 114{
 115        if (acpi_aml_io.flags & ACPI_AML_BUSY)
 116                return true;
 117        return false;
 118}
 119
 120static inline bool __acpi_aml_opened(void)
 121{
 122        if (acpi_aml_io.flags & ACPI_AML_OPEN)
 123                return true;
 124        return false;
 125}
 126
 127static inline bool __acpi_aml_used(void)
 128{
 129        return acpi_aml_io.usages ? true : false;
 130}
 131
 132static inline bool acpi_aml_running(void)
 133{
 134        bool ret;
 135
 136        mutex_lock(&acpi_aml_io.lock);
 137        ret = __acpi_aml_running();
 138        mutex_unlock(&acpi_aml_io.lock);
 139        return ret;
 140}
 141
 142static bool acpi_aml_busy(void)
 143{
 144        bool ret;
 145
 146        mutex_lock(&acpi_aml_io.lock);
 147        ret = __acpi_aml_busy();
 148        mutex_unlock(&acpi_aml_io.lock);
 149        return ret;
 150}
 151
 152static bool acpi_aml_used(void)
 153{
 154        bool ret;
 155
 156        /*
 157         * The usage count is prepared to avoid race conditions between the
 158         * starts and the stops of the debugger thread.
 159         */
 160        mutex_lock(&acpi_aml_io.lock);
 161        ret = __acpi_aml_used();
 162        mutex_unlock(&acpi_aml_io.lock);
 163        return ret;
 164}
 165
 166static bool acpi_aml_kern_readable(void)
 167{
 168        bool ret;
 169
 170        mutex_lock(&acpi_aml_io.lock);
 171        ret = !__acpi_aml_access_ok(ACPI_AML_IN_KERN) ||
 172              __acpi_aml_readable(&acpi_aml_io.in_crc, ACPI_AML_IN_KERN);
 173        mutex_unlock(&acpi_aml_io.lock);
 174        return ret;
 175}
 176
 177static bool acpi_aml_kern_writable(void)
 178{
 179        bool ret;
 180
 181        mutex_lock(&acpi_aml_io.lock);
 182        ret = !__acpi_aml_access_ok(ACPI_AML_OUT_KERN) ||
 183              __acpi_aml_writable(&acpi_aml_io.out_crc, ACPI_AML_OUT_KERN);
 184        mutex_unlock(&acpi_aml_io.lock);
 185        return ret;
 186}
 187
 188static bool acpi_aml_user_readable(void)
 189{
 190        bool ret;
 191
 192        mutex_lock(&acpi_aml_io.lock);
 193        ret = !__acpi_aml_access_ok(ACPI_AML_OUT_USER) ||
 194              __acpi_aml_readable(&acpi_aml_io.out_crc, ACPI_AML_OUT_USER);
 195        mutex_unlock(&acpi_aml_io.lock);
 196        return ret;
 197}
 198
 199static bool acpi_aml_user_writable(void)
 200{
 201        bool ret;
 202
 203        mutex_lock(&acpi_aml_io.lock);
 204        ret = !__acpi_aml_access_ok(ACPI_AML_IN_USER) ||
 205              __acpi_aml_writable(&acpi_aml_io.in_crc, ACPI_AML_IN_USER);
 206        mutex_unlock(&acpi_aml_io.lock);
 207        return ret;
 208}
 209
 210static int acpi_aml_lock_write(struct circ_buf *circ, unsigned long flag)
 211{
 212        int ret = 0;
 213
 214        mutex_lock(&acpi_aml_io.lock);
 215        if (!__acpi_aml_access_ok(flag)) {
 216                ret = -EFAULT;
 217                goto out;
 218        }
 219        if (!__acpi_aml_writable(circ, flag)) {
 220                ret = -EAGAIN;
 221                goto out;
 222        }
 223        acpi_aml_io.flags |= flag;
 224out:
 225        mutex_unlock(&acpi_aml_io.lock);
 226        return ret;
 227}
 228
 229static int acpi_aml_lock_read(struct circ_buf *circ, unsigned long flag)
 230{
 231        int ret = 0;
 232
 233        mutex_lock(&acpi_aml_io.lock);
 234        if (!__acpi_aml_access_ok(flag)) {
 235                ret = -EFAULT;
 236                goto out;
 237        }
 238        if (!__acpi_aml_readable(circ, flag)) {
 239                ret = -EAGAIN;
 240                goto out;
 241        }
 242        acpi_aml_io.flags |= flag;
 243out:
 244        mutex_unlock(&acpi_aml_io.lock);
 245        return ret;
 246}
 247
 248static void acpi_aml_unlock_fifo(unsigned long flag, bool wakeup)
 249{
 250        mutex_lock(&acpi_aml_io.lock);
 251        acpi_aml_io.flags &= ~flag;
 252        if (wakeup)
 253                wake_up_interruptible(&acpi_aml_io.wait);
 254        mutex_unlock(&acpi_aml_io.lock);
 255}
 256
 257static int acpi_aml_write_kern(const char *buf, int len)
 258{
 259        int ret;
 260        struct circ_buf *crc = &acpi_aml_io.out_crc;
 261        int n;
 262        char *p;
 263
 264        ret = acpi_aml_lock_write(crc, ACPI_AML_OUT_KERN);
 265        if (ret < 0)
 266                return ret;
 267        /* sync tail before inserting logs */
 268        smp_mb();
 269        p = &crc->buf[crc->head];
 270        n = min(len, circ_space_to_end(crc));
 271        memcpy(p, buf, n);
 272        /* sync head after inserting logs */
 273        smp_wmb();
 274        crc->head = (crc->head + n) & (ACPI_AML_BUF_SIZE - 1);
 275        acpi_aml_unlock_fifo(ACPI_AML_OUT_KERN, true);
 276        return n;
 277}
 278
 279static int acpi_aml_readb_kern(void)
 280{
 281        int ret;
 282        struct circ_buf *crc = &acpi_aml_io.in_crc;
 283        char *p;
 284
 285        ret = acpi_aml_lock_read(crc, ACPI_AML_IN_KERN);
 286        if (ret < 0)
 287                return ret;
 288        /* sync head before removing cmds */
 289        smp_rmb();
 290        p = &crc->buf[crc->tail];
 291        ret = (int)*p;
 292        /* sync tail before inserting cmds */
 293        smp_mb();
 294        crc->tail = (crc->tail + 1) & (ACPI_AML_BUF_SIZE - 1);
 295        acpi_aml_unlock_fifo(ACPI_AML_IN_KERN, true);
 296        return ret;
 297}
 298
 299/*
 300 * acpi_aml_write_log() - Capture debugger output
 301 * @msg: the debugger output
 302 *
 303 * This function should be used to implement acpi_os_printf() to filter out
 304 * the debugger output and store the output into the debugger interface
 305 * buffer. Return the size of stored logs or errno.
 306 */
 307static ssize_t acpi_aml_write_log(const char *msg)
 308{
 309        int ret = 0;
 310        int count = 0, size = 0;
 311
 312        if (!acpi_aml_initialized)
 313                return -ENODEV;
 314        if (msg)
 315                count = strlen(msg);
 316        while (count > 0) {
 317again:
 318                ret = acpi_aml_write_kern(msg + size, count);
 319                if (ret == -EAGAIN) {
 320                        ret = wait_event_interruptible(acpi_aml_io.wait,
 321                                acpi_aml_kern_writable());
 322                        /*
 323                         * We need to retry when the condition
 324                         * becomes true.
 325                         */
 326                        if (ret == 0)
 327                                goto again;
 328                        break;
 329                }
 330                if (ret < 0)
 331                        break;
 332                size += ret;
 333                count -= ret;
 334        }
 335        return size > 0 ? size : ret;
 336}
 337
 338/*
 339 * acpi_aml_read_cmd() - Capture debugger input
 340 * @msg: the debugger input
 341 * @size: the size of the debugger input
 342 *
 343 * This function should be used to implement acpi_os_get_line() to capture
 344 * the debugger input commands and store the input commands into the
 345 * debugger interface buffer. Return the size of stored commands or errno.
 346 */
 347static ssize_t acpi_aml_read_cmd(char *msg, size_t count)
 348{
 349        int ret = 0;
 350        int size = 0;
 351
 352        /*
 353         * This is ensured by the running fact of the debugger thread
 354         * unless a bug is introduced.
 355         */
 356        BUG_ON(!acpi_aml_initialized);
 357        while (count > 0) {
 358again:
 359                /*
 360                 * Check each input byte to find the end of the command.
 361                 */
 362                ret = acpi_aml_readb_kern();
 363                if (ret == -EAGAIN) {
 364                        ret = wait_event_interruptible(acpi_aml_io.wait,
 365                                acpi_aml_kern_readable());
 366                        /*
 367                         * We need to retry when the condition becomes
 368                         * true.
 369                         */
 370                        if (ret == 0)
 371                                goto again;
 372                }
 373                if (ret < 0)
 374                        break;
 375                *(msg + size) = (char)ret;
 376                size++;
 377                count--;
 378                if (ret == '\n') {
 379                        /*
 380                         * acpi_os_get_line() requires a zero terminated command
 381                         * string.
 382                         */
 383                        *(msg + size - 1) = '\0';
 384                        break;
 385                }
 386        }
 387        return size > 0 ? size : ret;
 388}
 389
 390static int acpi_aml_thread(void *unused)
 391{
 392        acpi_osd_exec_callback function = NULL;
 393        void *context;
 394
 395        mutex_lock(&acpi_aml_io.lock);
 396        if (acpi_aml_io.function) {
 397                acpi_aml_io.usages++;
 398                function = acpi_aml_io.function;
 399                context = acpi_aml_io.context;
 400        }
 401        mutex_unlock(&acpi_aml_io.lock);
 402
 403        if (function)
 404                function(context);
 405
 406        mutex_lock(&acpi_aml_io.lock);
 407        acpi_aml_io.usages--;
 408        if (!__acpi_aml_used()) {
 409                acpi_aml_io.thread = NULL;
 410                wake_up(&acpi_aml_io.wait);
 411        }
 412        mutex_unlock(&acpi_aml_io.lock);
 413
 414        return 0;
 415}
 416
 417/*
 418 * acpi_aml_create_thread() - Create AML debugger thread
 419 * @function: the debugger thread callback
 420 * @context: the context to be passed to the debugger thread
 421 *
 422 * This function should be used to implement acpi_os_execute() which is
 423 * used by the ACPICA debugger to create the debugger thread.
 424 */
 425static int acpi_aml_create_thread(acpi_osd_exec_callback function, void *context)
 426{
 427        struct task_struct *t;
 428
 429        mutex_lock(&acpi_aml_io.lock);
 430        acpi_aml_io.function = function;
 431        acpi_aml_io.context = context;
 432        mutex_unlock(&acpi_aml_io.lock);
 433
 434        t = kthread_create(acpi_aml_thread, NULL, "aml");
 435        if (IS_ERR(t)) {
 436                pr_err("Failed to create AML debugger thread.\n");
 437                return PTR_ERR(t);
 438        }
 439
 440        mutex_lock(&acpi_aml_io.lock);
 441        acpi_aml_io.thread = t;
 442        acpi_set_debugger_thread_id((acpi_thread_id)(unsigned long)t);
 443        wake_up_process(t);
 444        mutex_unlock(&acpi_aml_io.lock);
 445        return 0;
 446}
 447
 448static int acpi_aml_wait_command_ready(bool single_step,
 449                                       char *buffer, size_t length)
 450{
 451        acpi_status status;
 452
 453        if (single_step)
 454                acpi_os_printf("\n%1c ", ACPI_DEBUGGER_EXECUTE_PROMPT);
 455        else
 456                acpi_os_printf("\n%1c ", ACPI_DEBUGGER_COMMAND_PROMPT);
 457
 458        status = acpi_os_get_line(buffer, length, NULL);
 459        if (ACPI_FAILURE(status))
 460                return -EINVAL;
 461        return 0;
 462}
 463
 464static int acpi_aml_notify_command_complete(void)
 465{
 466        return 0;
 467}
 468
 469static int acpi_aml_open(struct inode *inode, struct file *file)
 470{
 471        int ret = 0;
 472        acpi_status status;
 473
 474        mutex_lock(&acpi_aml_io.lock);
 475        /*
 476         * The debugger interface is being closed, no new user is allowed
 477         * during this period.
 478         */
 479        if (acpi_aml_io.flags & ACPI_AML_CLOSED) {
 480                ret = -EBUSY;
 481                goto err_lock;
 482        }
 483        if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
 484                /*
 485                 * Only one reader is allowed to initiate the debugger
 486                 * thread.
 487                 */
 488                if (acpi_aml_active_reader) {
 489                        ret = -EBUSY;
 490                        goto err_lock;
 491                } else {
 492                        pr_debug("Opening debugger reader.\n");
 493                        acpi_aml_active_reader = file;
 494                }
 495        } else {
 496                /*
 497                 * No writer is allowed unless the debugger thread is
 498                 * ready.
 499                 */
 500                if (!(acpi_aml_io.flags & ACPI_AML_OPENED)) {
 501                        ret = -ENODEV;
 502                        goto err_lock;
 503                }
 504        }
 505        if (acpi_aml_active_reader == file) {
 506                pr_debug("Opening debugger interface.\n");
 507                mutex_unlock(&acpi_aml_io.lock);
 508
 509                pr_debug("Initializing debugger thread.\n");
 510                status = acpi_initialize_debugger();
 511                if (ACPI_FAILURE(status)) {
 512                        pr_err("Failed to initialize debugger.\n");
 513                        ret = -EINVAL;
 514                        goto err_exit;
 515                }
 516                pr_debug("Debugger thread initialized.\n");
 517
 518                mutex_lock(&acpi_aml_io.lock);
 519                acpi_aml_io.flags |= ACPI_AML_OPENED;
 520                acpi_aml_io.out_crc.head = acpi_aml_io.out_crc.tail = 0;
 521                acpi_aml_io.in_crc.head = acpi_aml_io.in_crc.tail = 0;
 522                pr_debug("Debugger interface opened.\n");
 523        }
 524        acpi_aml_io.users++;
 525err_lock:
 526        if (ret < 0) {
 527                if (acpi_aml_active_reader == file)
 528                        acpi_aml_active_reader = NULL;
 529        }
 530        mutex_unlock(&acpi_aml_io.lock);
 531err_exit:
 532        return ret;
 533}
 534
 535static int acpi_aml_release(struct inode *inode, struct file *file)
 536{
 537        mutex_lock(&acpi_aml_io.lock);
 538        acpi_aml_io.users--;
 539        if (file == acpi_aml_active_reader) {
 540                pr_debug("Closing debugger reader.\n");
 541                acpi_aml_active_reader = NULL;
 542
 543                pr_debug("Closing debugger interface.\n");
 544                acpi_aml_io.flags |= ACPI_AML_CLOSED;
 545
 546                /*
 547                 * Wake up all user space/kernel space blocked
 548                 * readers/writers.
 549                 */
 550                wake_up_interruptible(&acpi_aml_io.wait);
 551                mutex_unlock(&acpi_aml_io.lock);
 552                /*
 553                 * Wait all user space/kernel space readers/writers to
 554                 * stop so that ACPICA command loop of the debugger thread
 555                 * should fail all its command line reads after this point.
 556                 */
 557                wait_event(acpi_aml_io.wait, !acpi_aml_busy());
 558
 559                /*
 560                 * Then we try to terminate the debugger thread if it is
 561                 * not terminated.
 562                 */
 563                pr_debug("Terminating debugger thread.\n");
 564                acpi_terminate_debugger();
 565                wait_event(acpi_aml_io.wait, !acpi_aml_used());
 566                pr_debug("Debugger thread terminated.\n");
 567
 568                mutex_lock(&acpi_aml_io.lock);
 569                acpi_aml_io.flags &= ~ACPI_AML_OPENED;
 570        }
 571        if (acpi_aml_io.users == 0) {
 572                pr_debug("Debugger interface closed.\n");
 573                acpi_aml_io.flags &= ~ACPI_AML_CLOSED;
 574        }
 575        mutex_unlock(&acpi_aml_io.lock);
 576        return 0;
 577}
 578
 579static int acpi_aml_read_user(char __user *buf, int len)
 580{
 581        int ret;
 582        struct circ_buf *crc = &acpi_aml_io.out_crc;
 583        int n;
 584        char *p;
 585
 586        ret = acpi_aml_lock_read(crc, ACPI_AML_OUT_USER);
 587        if (ret < 0)
 588                return ret;
 589        /* sync head before removing logs */
 590        smp_rmb();
 591        p = &crc->buf[crc->tail];
 592        n = min(len, circ_count_to_end(crc));
 593        if (copy_to_user(buf, p, n)) {
 594                ret = -EFAULT;
 595                goto out;
 596        }
 597        /* sync tail after removing logs */
 598        smp_mb();
 599        crc->tail = (crc->tail + n) & (ACPI_AML_BUF_SIZE - 1);
 600        ret = n;
 601out:
 602        acpi_aml_unlock_fifo(ACPI_AML_OUT_USER, ret >= 0);
 603        return ret;
 604}
 605
 606static ssize_t acpi_aml_read(struct file *file, char __user *buf,
 607                             size_t count, loff_t *ppos)
 608{
 609        int ret = 0;
 610        int size = 0;
 611
 612        if (!count)
 613                return 0;
 614        if (!access_ok(buf, count))
 615                return -EFAULT;
 616
 617        while (count > 0) {
 618again:
 619                ret = acpi_aml_read_user(buf + size, count);
 620                if (ret == -EAGAIN) {
 621                        if (file->f_flags & O_NONBLOCK)
 622                                break;
 623                        else {
 624                                ret = wait_event_interruptible(acpi_aml_io.wait,
 625                                        acpi_aml_user_readable());
 626                                /*
 627                                 * We need to retry when the condition
 628                                 * becomes true.
 629                                 */
 630                                if (ret == 0)
 631                                        goto again;
 632                        }
 633                }
 634                if (ret < 0) {
 635                        if (!acpi_aml_running())
 636                                ret = 0;
 637                        break;
 638                }
 639                if (ret) {
 640                        size += ret;
 641                        count -= ret;
 642                        *ppos += ret;
 643                        break;
 644                }
 645        }
 646        return size > 0 ? size : ret;
 647}
 648
 649static int acpi_aml_write_user(const char __user *buf, int len)
 650{
 651        int ret;
 652        struct circ_buf *crc = &acpi_aml_io.in_crc;
 653        int n;
 654        char *p;
 655
 656        ret = acpi_aml_lock_write(crc, ACPI_AML_IN_USER);
 657        if (ret < 0)
 658                return ret;
 659        /* sync tail before inserting cmds */
 660        smp_mb();
 661        p = &crc->buf[crc->head];
 662        n = min(len, circ_space_to_end(crc));
 663        if (copy_from_user(p, buf, n)) {
 664                ret = -EFAULT;
 665                goto out;
 666        }
 667        /* sync head after inserting cmds */
 668        smp_wmb();
 669        crc->head = (crc->head + n) & (ACPI_AML_BUF_SIZE - 1);
 670        ret = n;
 671out:
 672        acpi_aml_unlock_fifo(ACPI_AML_IN_USER, ret >= 0);
 673        return n;
 674}
 675
 676static ssize_t acpi_aml_write(struct file *file, const char __user *buf,
 677                              size_t count, loff_t *ppos)
 678{
 679        int ret = 0;
 680        int size = 0;
 681
 682        if (!count)
 683                return 0;
 684        if (!access_ok(buf, count))
 685                return -EFAULT;
 686
 687        while (count > 0) {
 688again:
 689                ret = acpi_aml_write_user(buf + size, count);
 690                if (ret == -EAGAIN) {
 691                        if (file->f_flags & O_NONBLOCK)
 692                                break;
 693                        else {
 694                                ret = wait_event_interruptible(acpi_aml_io.wait,
 695                                        acpi_aml_user_writable());
 696                                /*
 697                                 * We need to retry when the condition
 698                                 * becomes true.
 699                                 */
 700                                if (ret == 0)
 701                                        goto again;
 702                        }
 703                }
 704                if (ret < 0) {
 705                        if (!acpi_aml_running())
 706                                ret = 0;
 707                        break;
 708                }
 709                if (ret) {
 710                        size += ret;
 711                        count -= ret;
 712                        *ppos += ret;
 713                }
 714        }
 715        return size > 0 ? size : ret;
 716}
 717
 718static __poll_t acpi_aml_poll(struct file *file, poll_table *wait)
 719{
 720        __poll_t masks = 0;
 721
 722        poll_wait(file, &acpi_aml_io.wait, wait);
 723        if (acpi_aml_user_readable())
 724                masks |= EPOLLIN | EPOLLRDNORM;
 725        if (acpi_aml_user_writable())
 726                masks |= EPOLLOUT | EPOLLWRNORM;
 727
 728        return masks;
 729}
 730
 731static const struct file_operations acpi_aml_operations = {
 732        .read           = acpi_aml_read,
 733        .write          = acpi_aml_write,
 734        .poll           = acpi_aml_poll,
 735        .open           = acpi_aml_open,
 736        .release        = acpi_aml_release,
 737        .llseek         = generic_file_llseek,
 738};
 739
 740static const struct acpi_debugger_ops acpi_aml_debugger = {
 741        .create_thread           = acpi_aml_create_thread,
 742        .read_cmd                = acpi_aml_read_cmd,
 743        .write_log               = acpi_aml_write_log,
 744        .wait_command_ready      = acpi_aml_wait_command_ready,
 745        .notify_command_complete = acpi_aml_notify_command_complete,
 746};
 747
 748int __init acpi_aml_init(void)
 749{
 750        int ret;
 751
 752        /* Initialize AML IO interface */
 753        mutex_init(&acpi_aml_io.lock);
 754        init_waitqueue_head(&acpi_aml_io.wait);
 755        acpi_aml_io.out_crc.buf = acpi_aml_io.out_buf;
 756        acpi_aml_io.in_crc.buf = acpi_aml_io.in_buf;
 757
 758        acpi_aml_dentry = debugfs_create_file("acpidbg",
 759                                              S_IFREG | S_IRUGO | S_IWUSR,
 760                                              acpi_debugfs_dir, NULL,
 761                                              &acpi_aml_operations);
 762
 763        ret = acpi_register_debugger(THIS_MODULE, &acpi_aml_debugger);
 764        if (ret) {
 765                debugfs_remove(acpi_aml_dentry);
 766                acpi_aml_dentry = NULL;
 767                return ret;
 768        }
 769
 770        acpi_aml_initialized = true;
 771        return 0;
 772}
 773
 774void __exit acpi_aml_exit(void)
 775{
 776        if (acpi_aml_initialized) {
 777                acpi_unregister_debugger(&acpi_aml_debugger);
 778                debugfs_remove(acpi_aml_dentry);
 779                acpi_aml_dentry = NULL;
 780                acpi_aml_initialized = false;
 781        }
 782}
 783
 784module_init(acpi_aml_init);
 785module_exit(acpi_aml_exit);
 786
 787MODULE_AUTHOR("Lv Zheng");
 788MODULE_DESCRIPTION("ACPI debugger userspace IO driver");
 789MODULE_LICENSE("GPL");
 790