// SPDX-License-Identifier: GPL-2.0-or-later /* * * Linux MegaRAID device driver * * Copyright (c) 2003-2004 LSI Logic Corporation. * * FILE : megaraid_mm.c * Version : v2.20.2.7 (Jul 16 2006) * * Common management module */ #include <linux/sched.h> #include <linux/slab.h> #include <linux/mutex.h> #include "megaraid_mm.h" // Entry points for char node driver static DEFINE_MUTEX(mraid_mm_mutex); static int mraid_mm_open(struct inode *, struct file *); static long mraid_mm_unlocked_ioctl(struct file *, uint, unsigned long); // routines to convert to and from the old the format static int mimd_to_kioc(mimd_t __user *, mraid_mmadp_t *, uioc_t *); static int kioc_to_mimd(uioc_t *, mimd_t __user *); // Helper functions static int handle_drvrcmd(void __user *, uint8_t, int *); static int lld_ioctl(mraid_mmadp_t *, uioc_t *); static void ioctl_done(uioc_t *); static void lld_timedout(struct timer_list *); static void hinfo_to_cinfo(mraid_hba_info_t *, mcontroller_t *); static mraid_mmadp_t *mraid_mm_get_adapter(mimd_t __user *, int *); static uioc_t *mraid_mm_alloc_kioc(mraid_mmadp_t *); static void mraid_mm_dealloc_kioc(mraid_mmadp_t *, uioc_t *); static int mraid_mm_attach_buf(mraid_mmadp_t *, uioc_t *, int); static int mraid_mm_setup_dma_pools(mraid_mmadp_t *); static void mraid_mm_free_adp_resources(mraid_mmadp_t *); static void mraid_mm_teardown_dma_pools(mraid_mmadp_t *); MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …; MODULE_VERSION(…); static int dbglevel = …; module_param_named(dlevel, dbglevel, int, 0); MODULE_PARM_DESC(…) …; EXPORT_SYMBOL(…); EXPORT_SYMBOL(…); EXPORT_SYMBOL(…); static uint32_t drvr_ver = …; static int adapters_count_g; static struct list_head adapters_list_g; static wait_queue_head_t wait_q; static const struct file_operations lsi_fops = …; static struct miscdevice megaraid_mm_dev = …; /** * mraid_mm_open - open routine for char node interface * @inode : unused * @filep : unused * * Allow ioctl operations by apps only if they have superuser privilege. */ static int mraid_mm_open(struct inode *inode, struct file *filep) { … } /** * mraid_mm_ioctl - module entry-point for ioctls * @filep : file operations pointer (ignored) * @cmd : ioctl command * @arg : user ioctl packet */ static int mraid_mm_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) { … } static long mraid_mm_unlocked_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) { … } /** * mraid_mm_get_adapter - Returns corresponding adapters for the mimd packet * @umimd : User space mimd_t ioctl packet * @rval : returned success/error status * * The function return value is a pointer to the located @adapter. */ static mraid_mmadp_t * mraid_mm_get_adapter(mimd_t __user *umimd, int *rval) { … } /** * handle_drvrcmd - Checks if the opcode is a driver cmd and if it is, handles it. * @arg : packet sent by the user app * @old_ioctl : mimd if 1; uioc otherwise * @rval : pointer for command's returned value (not function status) */ static int handle_drvrcmd(void __user *arg, uint8_t old_ioctl, int *rval) { … } /** * mimd_to_kioc - Converter from old to new ioctl format * @umimd : user space old MIMD IOCTL * @adp : adapter softstate * @kioc : kernel space new format IOCTL * * Routine to convert MIMD interface IOCTL to new interface IOCTL packet. The * new packet is in kernel space so that driver can perform operations on it * freely. */ static int mimd_to_kioc(mimd_t __user *umimd, mraid_mmadp_t *adp, uioc_t *kioc) { … } /** * mraid_mm_attach_buf - Attach a free dma buffer for required size * @adp : Adapter softstate * @kioc : kioc that the buffer needs to be attached to * @xferlen : required length for buffer * * First we search for a pool with smallest buffer that is >= @xferlen. If * that pool has no free buffer, we will try for the next bigger size. If none * is available, we will try to allocate the smallest buffer that is >= * @xferlen and attach it the pool. */ static int mraid_mm_attach_buf(mraid_mmadp_t *adp, uioc_t *kioc, int xferlen) { … } /** * mraid_mm_alloc_kioc - Returns a uioc_t from free list * @adp : Adapter softstate for this module * * The kioc_semaphore is initialized with number of kioc nodes in the * free kioc pool. If the kioc pool is empty, this function blocks till * a kioc becomes free. */ static uioc_t * mraid_mm_alloc_kioc(mraid_mmadp_t *adp) { … } /** * mraid_mm_dealloc_kioc - Return kioc to free pool * @adp : Adapter softstate * @kioc : uioc_t node to be returned to free pool */ static void mraid_mm_dealloc_kioc(mraid_mmadp_t *adp, uioc_t *kioc) { … } /** * lld_ioctl - Routine to issue ioctl to low level drvr * @adp : The adapter handle * @kioc : The ioctl packet with kernel addresses */ static int lld_ioctl(mraid_mmadp_t *adp, uioc_t *kioc) { … } /** * ioctl_done - callback from the low level driver * @kioc : completed ioctl packet */ static void ioctl_done(uioc_t *kioc) { … } /** * lld_timedout - callback from the expired timer * @t : timer that timed out */ static void lld_timedout(struct timer_list *t) { … } /** * kioc_to_mimd - Converter from new back to old format * @kioc : Kernel space IOCTL packet (successfully issued) * @mimd : User space MIMD packet */ static int kioc_to_mimd(uioc_t *kioc, mimd_t __user *mimd) { … } /** * hinfo_to_cinfo - Convert new format hba info into old format * @hinfo : New format, more comprehensive adapter info * @cinfo : Old format adapter info to support mimd_t apps */ static void hinfo_to_cinfo(mraid_hba_info_t *hinfo, mcontroller_t *cinfo) { … } /** * mraid_mm_register_adp - Registration routine for low level drivers * @lld_adp : Adapter object */ int mraid_mm_register_adp(mraid_mmadp_t *lld_adp) { … } /** * mraid_mm_adapter_app_handle - return the application handle for this adapter * @unique_id : adapter unique identifier * * For the given driver data, locate the adapter in our global list and * return the corresponding handle, which is also used by applications to * uniquely identify an adapter. * * Return adapter handle if found in the list. * Return 0 if adapter could not be located, should never happen though. */ uint32_t mraid_mm_adapter_app_handle(uint32_t unique_id) { … } /** * mraid_mm_setup_dma_pools - Set up dma buffer pools per adapter * @adp : Adapter softstate * * We maintain a pool of dma buffers per each adapter. Each pool has one * buffer. E.g, we may have 5 dma pools - one each for 4k, 8k ... 64k buffers. * We have just one 4k buffer in 4k pool, one 8k buffer in 8k pool etc. We * dont' want to waste too much memory by allocating more buffers per each * pool. */ static int mraid_mm_setup_dma_pools(mraid_mmadp_t *adp) { … } /** * mraid_mm_unregister_adp - Unregister routine for low level drivers * @unique_id : UID of the adpater * * Assumes no outstanding ioctls to llds. */ int mraid_mm_unregister_adp(uint32_t unique_id) { … } /** * mraid_mm_free_adp_resources - Free adapter softstate * @adp : Adapter softstate */ static void mraid_mm_free_adp_resources(mraid_mmadp_t *adp) { … } /** * mraid_mm_teardown_dma_pools - Free all per adapter dma buffers * @adp : Adapter softstate */ static void mraid_mm_teardown_dma_pools(mraid_mmadp_t *adp) { … } /** * mraid_mm_init - Module entry point */ static int __init mraid_mm_init(void) { … } /** * mraid_mm_exit - Module exit point */ static void __exit mraid_mm_exit(void) { … } module_init(…) …; module_exit(mraid_mm_exit); /* vi: set ts=8 sw=8 tw=78: */