Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 
0003 /*
0004  * IBM ASM Service Processor Device Driver
0005  *
0006  * Copyright (C) IBM Corporation, 2004
0007  *
0008  * Author: Max Asböck <amax@us.ibm.com>
0009  *
0010  * This driver is based on code originally written by Pete Reynolds
0011  * and others.
0012  */
0013 
0014 /*
0015  * The ASM device driver does the following things:
0016  *
0017  * 1) When loaded it sends a message to the service processor,
0018  * indicating that an OS is * running. This causes the service processor
0019  * to send periodic heartbeats to the OS.
0020  *
0021  * 2) Answers the periodic heartbeats sent by the service processor.
0022  * Failure to do so would result in system reboot.
0023  *
0024  * 3) Acts as a pass through for dot commands sent from user applications.
0025  * The interface for this is the ibmasmfs file system.
0026  *
0027  * 4) Allows user applications to register for event notification. Events
0028  * are sent to the driver through interrupts. They can be read from user
0029  * space through the ibmasmfs file system.
0030  *
0031  * 5) Allows user space applications to send heartbeats to the service
0032  * processor (aka reverse heartbeats). Again this happens through ibmasmfs.
0033  *
0034  * 6) Handles remote mouse and keyboard event interrupts and makes them
0035  * available to user applications through ibmasmfs.
0036  *
0037  */
0038 
0039 #include <linux/pci.h>
0040 #include <linux/init.h>
0041 #include <linux/slab.h>
0042 #include "ibmasm.h"
0043 #include "lowlevel.h"
0044 #include "remote.h"
0045 
0046 int ibmasm_debug = 0;
0047 module_param(ibmasm_debug, int , S_IRUGO | S_IWUSR);
0048 MODULE_PARM_DESC(ibmasm_debug, " Set debug mode on or off");
0049 
0050 
0051 static int ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
0052 {
0053     int result;
0054     struct service_processor *sp;
0055 
0056     if ((result = pci_enable_device(pdev))) {
0057         dev_err(&pdev->dev, "Failed to enable PCI device\n");
0058         return result;
0059     }
0060     if ((result = pci_request_regions(pdev, DRIVER_NAME))) {
0061         dev_err(&pdev->dev, "Failed to allocate PCI resources\n");
0062         goto error_resources;
0063     }
0064     /* vnc client won't work without bus-mastering */
0065     pci_set_master(pdev);
0066 
0067     sp = kzalloc(sizeof(struct service_processor), GFP_KERNEL);
0068     if (sp == NULL) {
0069         dev_err(&pdev->dev, "Failed to allocate memory\n");
0070         result = -ENOMEM;
0071         goto error_kmalloc;
0072     }
0073 
0074     spin_lock_init(&sp->lock);
0075     INIT_LIST_HEAD(&sp->command_queue);
0076 
0077     pci_set_drvdata(pdev, (void *)sp);
0078     sp->dev = &pdev->dev;
0079     sp->number = pdev->bus->number;
0080     snprintf(sp->dirname, IBMASM_NAME_SIZE, "%d", sp->number);
0081     snprintf(sp->devname, IBMASM_NAME_SIZE, "%s%d", DRIVER_NAME, sp->number);
0082 
0083     result = ibmasm_event_buffer_init(sp);
0084     if (result) {
0085         dev_err(sp->dev, "Failed to allocate event buffer\n");
0086         goto error_eventbuffer;
0087     }
0088 
0089     result = ibmasm_heartbeat_init(sp);
0090     if (result) {
0091         dev_err(sp->dev, "Failed to allocate heartbeat command\n");
0092         goto error_heartbeat;
0093     }
0094 
0095     sp->irq = pdev->irq;
0096     sp->base_address = pci_ioremap_bar(pdev, 0);
0097     if (!sp->base_address) {
0098         dev_err(sp->dev, "Failed to ioremap pci memory\n");
0099         result =  -ENODEV;
0100         goto error_ioremap;
0101     }
0102 
0103     result = request_irq(sp->irq, ibmasm_interrupt_handler, IRQF_SHARED, sp->devname, (void*)sp);
0104     if (result) {
0105         dev_err(sp->dev, "Failed to register interrupt handler\n");
0106         goto error_request_irq;
0107     }
0108 
0109     enable_sp_interrupts(sp->base_address);
0110 
0111     result = ibmasm_init_remote_input_dev(sp);
0112     if (result) {
0113         dev_err(sp->dev, "Failed to initialize remote queue\n");
0114         goto error_init_remote;
0115     }
0116 
0117     result = ibmasm_send_driver_vpd(sp);
0118     if (result) {
0119         dev_err(sp->dev, "Failed to send driver VPD to service processor\n");
0120         goto error_send_message;
0121     }
0122     result = ibmasm_send_os_state(sp, SYSTEM_STATE_OS_UP);
0123     if (result) {
0124         dev_err(sp->dev, "Failed to send OS state to service processor\n");
0125         goto error_send_message;
0126     }
0127     ibmasmfs_add_sp(sp);
0128 
0129     ibmasm_register_uart(sp);
0130 
0131     return 0;
0132 
0133 error_send_message:
0134     ibmasm_free_remote_input_dev(sp);
0135 error_init_remote:
0136     disable_sp_interrupts(sp->base_address);
0137     free_irq(sp->irq, (void *)sp);
0138 error_request_irq:
0139     iounmap(sp->base_address);
0140 error_ioremap:
0141     ibmasm_heartbeat_exit(sp);
0142 error_heartbeat:
0143     ibmasm_event_buffer_exit(sp);
0144 error_eventbuffer:
0145     kfree(sp);
0146 error_kmalloc:
0147         pci_release_regions(pdev);
0148 error_resources:
0149         pci_disable_device(pdev);
0150 
0151     return result;
0152 }
0153 
0154 static void ibmasm_remove_one(struct pci_dev *pdev)
0155 {
0156     struct service_processor *sp = pci_get_drvdata(pdev);
0157 
0158     dbg("Unregistering UART\n");
0159     ibmasm_unregister_uart(sp);
0160     dbg("Sending OS down message\n");
0161     if (ibmasm_send_os_state(sp, SYSTEM_STATE_OS_DOWN))
0162         err("failed to get response to 'Send OS State' command\n");
0163     dbg("Disabling heartbeats\n");
0164     ibmasm_heartbeat_exit(sp);
0165     dbg("Disabling interrupts\n");
0166     disable_sp_interrupts(sp->base_address);
0167     dbg("Freeing SP irq\n");
0168     free_irq(sp->irq, (void *)sp);
0169     dbg("Cleaning up\n");
0170     ibmasm_free_remote_input_dev(sp);
0171     iounmap(sp->base_address);
0172     ibmasm_event_buffer_exit(sp);
0173     kfree(sp);
0174     pci_release_regions(pdev);
0175     pci_disable_device(pdev);
0176 }
0177 
0178 static struct pci_device_id ibmasm_pci_table[] =
0179 {
0180     { PCI_DEVICE(VENDORID_IBM, DEVICEID_RSA) },
0181     {},
0182 };
0183 
0184 static struct pci_driver ibmasm_driver = {
0185     .name       = DRIVER_NAME,
0186     .id_table   = ibmasm_pci_table,
0187     .probe      = ibmasm_init_one,
0188     .remove     = ibmasm_remove_one,
0189 };
0190 
0191 static void __exit ibmasm_exit (void)
0192 {
0193     ibmasm_unregister_panic_notifier();
0194     ibmasmfs_unregister();
0195     pci_unregister_driver(&ibmasm_driver);
0196     info(DRIVER_DESC " version " DRIVER_VERSION " unloaded");
0197 }
0198 
0199 static int __init ibmasm_init(void)
0200 {
0201     int result = pci_register_driver(&ibmasm_driver);
0202     if (result)
0203         return result;
0204 
0205     result = ibmasmfs_register();
0206     if (result) {
0207         pci_unregister_driver(&ibmasm_driver);
0208         err("Failed to register ibmasmfs file system");
0209         return result;
0210     }
0211 
0212     ibmasm_register_panic_notifier();
0213     info(DRIVER_DESC " version " DRIVER_VERSION " loaded");
0214     return 0;
0215 }
0216 
0217 module_init(ibmasm_init);
0218 module_exit(ibmasm_exit);
0219 
0220 MODULE_AUTHOR(DRIVER_AUTHOR);
0221 MODULE_DESCRIPTION(DRIVER_DESC);
0222 MODULE_LICENSE("GPL");
0223 MODULE_DEVICE_TABLE(pci, ibmasm_pci_table);
0224