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