LCOV - code coverage report
Current view: top level - arch/x86/kernel - io_delay.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 4 26 15.4 %
Date: 2021-04-22 12:43:58 Functions: 1 3 33.3 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * I/O delay strategies for inb_p/outb_p
       4             :  *
       5             :  * Allow for a DMI based override of port 0x80, needed for certain HP laptops
       6             :  * and possibly other systems. Also allow for the gradual elimination of
       7             :  * outb_p/inb_p API uses.
       8             :  */
       9             : #include <linux/kernel.h>
      10             : #include <linux/export.h>
      11             : #include <linux/delay.h>
      12             : #include <linux/init.h>
      13             : #include <linux/dmi.h>
      14             : #include <linux/io.h>
      15             : 
      16             : #define IO_DELAY_TYPE_0X80      0
      17             : #define IO_DELAY_TYPE_0XED      1
      18             : #define IO_DELAY_TYPE_UDELAY    2
      19             : #define IO_DELAY_TYPE_NONE      3
      20             : 
      21             : #if defined(CONFIG_IO_DELAY_0X80)
      22             : #define DEFAULT_IO_DELAY_TYPE   IO_DELAY_TYPE_0X80
      23             : #elif defined(CONFIG_IO_DELAY_0XED)
      24             : #define DEFAULT_IO_DELAY_TYPE   IO_DELAY_TYPE_0XED
      25             : #elif defined(CONFIG_IO_DELAY_UDELAY)
      26             : #define DEFAULT_IO_DELAY_TYPE   IO_DELAY_TYPE_UDELAY
      27             : #elif defined(CONFIG_IO_DELAY_NONE)
      28             : #define DEFAULT_IO_DELAY_TYPE   IO_DELAY_TYPE_NONE
      29             : #endif
      30             : 
      31             : int io_delay_type __read_mostly = DEFAULT_IO_DELAY_TYPE;
      32             : 
      33             : static int __initdata io_delay_override;
      34             : 
      35             : /*
      36             :  * Paravirt wants native_io_delay to be a constant.
      37             :  */
      38           0 : void native_io_delay(void)
      39             : {
      40           0 :         switch (io_delay_type) {
      41           0 :         default:
      42             :         case IO_DELAY_TYPE_0X80:
      43           0 :                 asm volatile ("outb %al, $0x80");
      44           0 :                 break;
      45           0 :         case IO_DELAY_TYPE_0XED:
      46           0 :                 asm volatile ("outb %al, $0xed");
      47           0 :                 break;
      48             :         case IO_DELAY_TYPE_UDELAY:
      49             :                 /*
      50             :                  * 2 usecs is an upper-bound for the outb delay but
      51             :                  * note that udelay doesn't have the bus-level
      52             :                  * side-effects that outb does, nor does udelay() have
      53             :                  * precise timings during very early bootup (the delays
      54             :                  * are shorter until calibrated):
      55             :                  */
      56           0 :                 udelay(2);
      57             :                 break;
      58             :         case IO_DELAY_TYPE_NONE:
      59             :                 break;
      60             :         }
      61           0 : }
      62             : EXPORT_SYMBOL(native_io_delay);
      63             : 
      64             : static int __init dmi_io_delay_0xed_port(const struct dmi_system_id *id)
      65             : {
      66             :         if (io_delay_type == IO_DELAY_TYPE_0X80) {
      67             :                 pr_notice("%s: using 0xed I/O delay port\n", id->ident);
      68             :                 io_delay_type = IO_DELAY_TYPE_0XED;
      69             :         }
      70             : 
      71             :         return 0;
      72             : }
      73             : 
      74             : /*
      75             :  * Quirk table for systems that misbehave (lock up, etc.) if port
      76             :  * 0x80 is used:
      77             :  */
      78             : static const struct dmi_system_id io_delay_0xed_port_dmi_table[] __initconst = {
      79             :         {
      80             :                 .callback       = dmi_io_delay_0xed_port,
      81             :                 .ident          = "Compaq Presario V6000",
      82             :                 .matches        = {
      83             :                         DMI_MATCH(DMI_BOARD_VENDOR,     "Quanta"),
      84             :                         DMI_MATCH(DMI_BOARD_NAME,       "30B7")
      85             :                 }
      86             :         },
      87             :         {
      88             :                 .callback       = dmi_io_delay_0xed_port,
      89             :                 .ident          = "HP Pavilion dv9000z",
      90             :                 .matches        = {
      91             :                         DMI_MATCH(DMI_BOARD_VENDOR,     "Quanta"),
      92             :                         DMI_MATCH(DMI_BOARD_NAME,       "30B9")
      93             :                 }
      94             :         },
      95             :         {
      96             :                 .callback       = dmi_io_delay_0xed_port,
      97             :                 .ident          = "HP Pavilion dv6000",
      98             :                 .matches        = {
      99             :                         DMI_MATCH(DMI_BOARD_VENDOR,     "Quanta"),
     100             :                         DMI_MATCH(DMI_BOARD_NAME,       "30B8")
     101             :                 }
     102             :         },
     103             :         {
     104             :                 .callback       = dmi_io_delay_0xed_port,
     105             :                 .ident          = "HP Pavilion tx1000",
     106             :                 .matches        = {
     107             :                         DMI_MATCH(DMI_BOARD_VENDOR,     "Quanta"),
     108             :                         DMI_MATCH(DMI_BOARD_NAME,       "30BF")
     109             :                 }
     110             :         },
     111             :         {
     112             :                 .callback       = dmi_io_delay_0xed_port,
     113             :                 .ident          = "Presario F700",
     114             :                 .matches        = {
     115             :                         DMI_MATCH(DMI_BOARD_VENDOR,     "Quanta"),
     116             :                         DMI_MATCH(DMI_BOARD_NAME,       "30D3")
     117             :                 }
     118             :         },
     119             :         { }
     120             : };
     121             : 
     122           1 : void __init io_delay_init(void)
     123             : {
     124           1 :         if (!io_delay_override)
     125           1 :                 dmi_check_system(io_delay_0xed_port_dmi_table);
     126           1 : }
     127             : 
     128           0 : static int __init io_delay_param(char *s)
     129             : {
     130           0 :         if (!s)
     131             :                 return -EINVAL;
     132             : 
     133           0 :         if (!strcmp(s, "0x80"))
     134           0 :                 io_delay_type = IO_DELAY_TYPE_0X80;
     135           0 :         else if (!strcmp(s, "0xed"))
     136           0 :                 io_delay_type = IO_DELAY_TYPE_0XED;
     137           0 :         else if (!strcmp(s, "udelay"))
     138           0 :                 io_delay_type = IO_DELAY_TYPE_UDELAY;
     139           0 :         else if (!strcmp(s, "none"))
     140           0 :                 io_delay_type = IO_DELAY_TYPE_NONE;
     141             :         else
     142             :                 return -EINVAL;
     143             : 
     144           0 :         io_delay_override = 1;
     145           0 :         return 0;
     146             : }
     147             : 
     148             : early_param("io_delay", io_delay_param);

Generated by: LCOV version 1.14