Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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