root/drivers/misc/ibmasm/module.c

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

DEFINITIONS

This source file includes following definitions.
  1. ibmasm_init_one
  2. ibmasm_remove_one
  3. ibmasm_exit
  4. ibmasm_init

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 
   3 /*
   4  * IBM ASM Service Processor Device Driver
   5  *
   6  * Copyright (C) IBM Corporation, 2004
   7  *
   8  * Author: Max Asböck <amax@us.ibm.com>
   9  *
  10  * This driver is based on code originally written by Pete Reynolds
  11  * and others.
  12  */
  13 
  14 /*
  15  * The ASM device driver does the following things:
  16  *
  17  * 1) When loaded it sends a message to the service processor,
  18  * indicating that an OS is * running. This causes the service processor
  19  * to send periodic heartbeats to the OS.
  20  *
  21  * 2) Answers the periodic heartbeats sent by the service processor.
  22  * Failure to do so would result in system reboot.
  23  *
  24  * 3) Acts as a pass through for dot commands sent from user applications.
  25  * The interface for this is the ibmasmfs file system.
  26  *
  27  * 4) Allows user applications to register for event notification. Events
  28  * are sent to the driver through interrupts. They can be read from user
  29  * space through the ibmasmfs file system.
  30  *
  31  * 5) Allows user space applications to send heartbeats to the service
  32  * processor (aka reverse heartbeats). Again this happens through ibmasmfs.
  33  *
  34  * 6) Handles remote mouse and keyboard event interrupts and makes them
  35  * available to user applications through ibmasmfs.
  36  *
  37  */
  38 
  39 #include <linux/pci.h>
  40 #include <linux/init.h>
  41 #include <linux/slab.h>
  42 #include "ibmasm.h"
  43 #include "lowlevel.h"
  44 #include "remote.h"
  45 
  46 int ibmasm_debug = 0;
  47 module_param(ibmasm_debug, int , S_IRUGO | S_IWUSR);
  48 MODULE_PARM_DESC(ibmasm_debug, " Set debug mode on or off");
  49 
  50 
  51 static int ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
  52 {
  53         int result;
  54         struct service_processor *sp;
  55 
  56         if ((result = pci_enable_device(pdev))) {
  57                 dev_err(&pdev->dev, "Failed to enable PCI device\n");
  58                 return result;
  59         }
  60         if ((result = pci_request_regions(pdev, DRIVER_NAME))) {
  61                 dev_err(&pdev->dev, "Failed to allocate PCI resources\n");
  62                 goto error_resources;
  63         }
  64         /* vnc client won't work without bus-mastering */
  65         pci_set_master(pdev);
  66 
  67         sp = kzalloc(sizeof(struct service_processor), GFP_KERNEL);
  68         if (sp == NULL) {
  69                 dev_err(&pdev->dev, "Failed to allocate memory\n");
  70                 result = -ENOMEM;
  71                 goto error_kmalloc;
  72         }
  73 
  74         spin_lock_init(&sp->lock);
  75         INIT_LIST_HEAD(&sp->command_queue);
  76 
  77         pci_set_drvdata(pdev, (void *)sp);
  78         sp->dev = &pdev->dev;
  79         sp->number = pdev->bus->number;
  80         snprintf(sp->dirname, IBMASM_NAME_SIZE, "%d", sp->number);
  81         snprintf(sp->devname, IBMASM_NAME_SIZE, "%s%d", DRIVER_NAME, sp->number);
  82 
  83         result = ibmasm_event_buffer_init(sp);
  84         if (result) {
  85                 dev_err(sp->dev, "Failed to allocate event buffer\n");
  86                 goto error_eventbuffer;
  87         }
  88 
  89         result = ibmasm_heartbeat_init(sp);
  90         if (result) {
  91                 dev_err(sp->dev, "Failed to allocate heartbeat command\n");
  92                 goto error_heartbeat;
  93         }
  94 
  95         sp->irq = pdev->irq;
  96         sp->base_address = pci_ioremap_bar(pdev, 0);
  97         if (!sp->base_address) {
  98                 dev_err(sp->dev, "Failed to ioremap pci memory\n");
  99                 result =  -ENODEV;
 100                 goto error_ioremap;
 101         }
 102 
 103         result = request_irq(sp->irq, ibmasm_interrupt_handler, IRQF_SHARED, sp->devname, (void*)sp);
 104         if (result) {
 105                 dev_err(sp->dev, "Failed to register interrupt handler\n");
 106                 goto error_request_irq;
 107         }
 108 
 109         enable_sp_interrupts(sp->base_address);
 110 
 111         result = ibmasm_init_remote_input_dev(sp);
 112         if (result) {
 113                 dev_err(sp->dev, "Failed to initialize remote queue\n");
 114                 goto error_send_message;
 115         }
 116 
 117         result = ibmasm_send_driver_vpd(sp);
 118         if (result) {
 119                 dev_err(sp->dev, "Failed to send driver VPD to service processor\n");
 120                 goto error_send_message;
 121         }
 122         result = ibmasm_send_os_state(sp, SYSTEM_STATE_OS_UP);
 123         if (result) {
 124                 dev_err(sp->dev, "Failed to send OS state to service processor\n");
 125                 goto error_send_message;
 126         }
 127         ibmasmfs_add_sp(sp);
 128 
 129         ibmasm_register_uart(sp);
 130 
 131         return 0;
 132 
 133 error_send_message:
 134         disable_sp_interrupts(sp->base_address);
 135         ibmasm_free_remote_input_dev(sp);
 136         free_irq(sp->irq, (void *)sp);
 137 error_request_irq:
 138         iounmap(sp->base_address);
 139 error_ioremap:
 140         ibmasm_heartbeat_exit(sp);
 141 error_heartbeat:
 142         ibmasm_event_buffer_exit(sp);
 143 error_eventbuffer:
 144         kfree(sp);
 145 error_kmalloc:
 146         pci_release_regions(pdev);
 147 error_resources:
 148         pci_disable_device(pdev);
 149 
 150         return result;
 151 }
 152 
 153 static void ibmasm_remove_one(struct pci_dev *pdev)
 154 {
 155         struct service_processor *sp = pci_get_drvdata(pdev);
 156 
 157         dbg("Unregistering UART\n");
 158         ibmasm_unregister_uart(sp);
 159         dbg("Sending OS down message\n");
 160         if (ibmasm_send_os_state(sp, SYSTEM_STATE_OS_DOWN))
 161                 err("failed to get response to 'Send OS State' command\n");
 162         dbg("Disabling heartbeats\n");
 163         ibmasm_heartbeat_exit(sp);
 164         dbg("Disabling interrupts\n");
 165         disable_sp_interrupts(sp->base_address);
 166         dbg("Freeing SP irq\n");
 167         free_irq(sp->irq, (void *)sp);
 168         dbg("Cleaning up\n");
 169         ibmasm_free_remote_input_dev(sp);
 170         iounmap(sp->base_address);
 171         ibmasm_event_buffer_exit(sp);
 172         kfree(sp);
 173         pci_release_regions(pdev);
 174         pci_disable_device(pdev);
 175 }
 176 
 177 static struct pci_device_id ibmasm_pci_table[] =
 178 {
 179         { PCI_DEVICE(VENDORID_IBM, DEVICEID_RSA) },
 180         {},
 181 };
 182 
 183 static struct pci_driver ibmasm_driver = {
 184         .name           = DRIVER_NAME,
 185         .id_table       = ibmasm_pci_table,
 186         .probe          = ibmasm_init_one,
 187         .remove         = ibmasm_remove_one,
 188 };
 189 
 190 static void __exit ibmasm_exit (void)
 191 {
 192         ibmasm_unregister_panic_notifier();
 193         ibmasmfs_unregister();
 194         pci_unregister_driver(&ibmasm_driver);
 195         info(DRIVER_DESC " version " DRIVER_VERSION " unloaded");
 196 }
 197 
 198 static int __init ibmasm_init(void)
 199 {
 200         int result = pci_register_driver(&ibmasm_driver);
 201         if (result)
 202                 return result;
 203 
 204         result = ibmasmfs_register();
 205         if (result) {
 206                 pci_unregister_driver(&ibmasm_driver);
 207                 err("Failed to register ibmasmfs file system");
 208                 return result;
 209         }
 210 
 211         ibmasm_register_panic_notifier();
 212         info(DRIVER_DESC " version " DRIVER_VERSION " loaded");
 213         return 0;
 214 }
 215 
 216 module_init(ibmasm_init);
 217 module_exit(ibmasm_exit);
 218 
 219 MODULE_AUTHOR(DRIVER_AUTHOR);
 220 MODULE_DESCRIPTION(DRIVER_DESC);
 221 MODULE_LICENSE("GPL");
 222 MODULE_DEVICE_TABLE(pci, ibmasm_pci_table);
 223 

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