// SPDX-License-Identifier: GPL-2.0-or-later /* * Adaptec AAC series RAID controller driver * (c) Copyright 2001 Red Hat Inc. * * based on the old aacraid driver that is.. * Adaptec aacraid device driver for Linux. * * Copyright (c) 2000-2010 Adaptec, Inc. * 2010-2015 PMC-Sierra, Inc. ([email protected]) * 2016-2017 Microsemi Corp. ([email protected]) * * Module Name: * commsup.c * * Abstract: Contain all routines that are required for FSA host/adapter * communication. */ #include <linux/kernel.h> #include <linux/init.h> #include <linux/crash_dump.h> #include <linux/types.h> #include <linux/sched.h> #include <linux/pci.h> #include <linux/spinlock.h> #include <linux/slab.h> #include <linux/completion.h> #include <linux/blkdev.h> #include <linux/delay.h> #include <linux/kthread.h> #include <linux/interrupt.h> #include <linux/bcd.h> #include <scsi/scsi.h> #include <scsi/scsi_host.h> #include <scsi/scsi_device.h> #include <scsi/scsi_cmnd.h> #include "aacraid.h" /** * fib_map_alloc - allocate the fib objects * @dev: Adapter to allocate for * * Allocate and map the shared PCI space for the FIB blocks used to * talk to the Adaptec firmware. */ static int fib_map_alloc(struct aac_dev *dev) { … } /** * aac_fib_map_free - free the fib objects * @dev: Adapter to free * * Free the PCI mappings and the memory allocated for FIB blocks * on this adapter. */ void aac_fib_map_free(struct aac_dev *dev) { … } void aac_fib_vector_assign(struct aac_dev *dev) { … } /** * aac_fib_setup - setup the fibs * @dev: Adapter to set up * * Allocate the PCI space for the fibs, map it and then initialise the * fib area, the unmapped fib data and also the free list */ int aac_fib_setup(struct aac_dev * dev) { … } /** * aac_fib_alloc_tag-allocate a fib using tags * @dev: Adapter to allocate the fib for * @scmd: SCSI command * * Allocate a fib from the adapter fib pool using tags * from the blk layer. */ struct fib *aac_fib_alloc_tag(struct aac_dev *dev, struct scsi_cmnd *scmd) { … } /** * aac_fib_alloc - allocate a fib * @dev: Adapter to allocate the fib for * * Allocate a fib from the adapter fib pool. If the pool is empty we * return NULL. */ struct fib *aac_fib_alloc(struct aac_dev *dev) { … } /** * aac_fib_free - free a fib * @fibptr: fib to free up * * Frees up a fib and places it on the appropriate queue */ void aac_fib_free(struct fib *fibptr) { … } /** * aac_fib_init - initialise a fib * @fibptr: The fib to initialize * * Set up the generic fib fields ready for use */ void aac_fib_init(struct fib *fibptr) { … } /** * fib_dealloc - deallocate a fib * @fibptr: fib to deallocate * * Will deallocate and return to the free pool the FIB pointed to by the * caller. */ static void fib_dealloc(struct fib * fibptr) { … } /* * Commuication primitives define and support the queuing method we use to * support host to adapter commuication. All queue accesses happen through * these routines and are the only routines which have a knowledge of the * how these queues are implemented. */ /** * aac_get_entry - get a queue entry * @dev: Adapter * @qid: Queue Number * @entry: Entry return * @index: Index return * @nonotify: notification control * * With a priority the routine returns a queue entry if the queue has free entries. If the queue * is full(no free entries) than no entry is returned and the function returns 0 otherwise 1 is * returned. */ static int aac_get_entry (struct aac_dev * dev, u32 qid, struct aac_entry **entry, u32 * index, unsigned long *nonotify) { … } /** * aac_queue_get - get the next free QE * @dev: Adapter * @index: Returned index * @qid: Queue number * @hw_fib: Fib to associate with the queue entry * @wait: Wait if queue full * @fibptr: Driver fib object to go with fib * @nonotify: Don't notify the adapter * * Gets the next free QE off the requested priorty adapter command * queue and associates the Fib with the QE. The QE represented by * index is ready to insert on the queue when this routine returns * success. */ int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw_fib, int wait, struct fib * fibptr, unsigned long *nonotify) { … } /* * Define the highest level of host to adapter communication routines. * These routines will support host to adapter FS commuication. These * routines have no knowledge of the commuication method used. This level * sends and receives FIBs. This level has no knowledge of how these FIBs * get passed back and forth. */ /** * aac_fib_send - send a fib to the adapter * @command: Command to send * @fibptr: The fib * @size: Size of fib data area * @priority: Priority of Fib * @wait: Async/sync select * @reply: True if a reply is wanted * @callback: Called with reply * @callback_data: Passed to callback * * Sends the requested FIB to the adapter and optionally will wait for a * response FIB. If the caller does not wish to wait for a response than * an event to wait on must be supplied. This event will be set when a * response FIB is received from the adapter. */ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, int priority, int wait, int reply, fib_callback callback, void *callback_data) { … } int aac_hba_send(u8 command, struct fib *fibptr, fib_callback callback, void *callback_data) { … } /** * aac_consumer_get - get the top of the queue * @dev: Adapter * @q: Queue * @entry: Return entry * * Will return a pointer to the entry on the top of the queue requested that * we are a consumer of, and return the address of the queue entry. It does * not change the state of the queue. */ int aac_consumer_get(struct aac_dev * dev, struct aac_queue * q, struct aac_entry **entry) { … } /** * aac_consumer_free - free consumer entry * @dev: Adapter * @q: Queue * @qid: Queue ident * * Frees up the current top of the queue we are a consumer of. If the * queue was full notify the producer that the queue is no longer full. */ void aac_consumer_free(struct aac_dev * dev, struct aac_queue *q, u32 qid) { … } /** * aac_fib_adapter_complete - complete adapter issued fib * @fibptr: fib to complete * @size: size of fib * * Will do all necessary work to complete a FIB that was sent from * the adapter. */ int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size) { … } /** * aac_fib_complete - fib completion handler * @fibptr: FIB to complete * * Will do all necessary work to complete a FIB. */ int aac_fib_complete(struct fib *fibptr) { … } /** * aac_printf - handle printf from firmware * @dev: Adapter * @val: Message info * * Print a message passed to us by the controller firmware on the * Adaptec board */ void aac_printf(struct aac_dev *dev, u32 val) { … } static inline int aac_aif_data(struct aac_aifcmd *aifcmd, uint32_t index) { … } static void aac_handle_aif_bu(struct aac_dev *dev, struct aac_aifcmd *aifcmd) { … } #define AIF_SNIFF_TIMEOUT … /** * aac_handle_aif - Handle a message from the firmware * @dev: Which adapter this fib is from * @fibptr: Pointer to fibptr from adapter * * This routine handles a driver notify fib from the adapter and * dispatches it to the appropriate routine for handling. */ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) { … } static void aac_schedule_bus_scan(struct aac_dev *aac) { … } static int _aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type) { … } int aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type) { … } int aac_check_health(struct aac_dev * aac) { … } static inline int is_safw_raid_volume(struct aac_dev *aac, int bus, int target) { … } static struct scsi_device *aac_lookup_safw_scsi_device(struct aac_dev *dev, int bus, int target) { … } static int aac_add_safw_device(struct aac_dev *dev, int bus, int target) { … } static void aac_put_safw_scsi_device(struct scsi_device *sdev) { … } static void aac_remove_safw_device(struct aac_dev *dev, int bus, int target) { … } static inline int aac_is_safw_scan_count_equal(struct aac_dev *dev, int bus, int target) { … } static int aac_is_safw_target_valid(struct aac_dev *dev, int bus, int target) { … } static int aac_is_safw_device_exposed(struct aac_dev *dev, int bus, int target) { … } static int aac_update_safw_host_devices(struct aac_dev *dev) { … } static int aac_scan_safw_host(struct aac_dev *dev) { … } int aac_scan_host(struct aac_dev *dev) { … } void aac_src_reinit_aif_worker(struct work_struct *work) { … } /** * aac_handle_sa_aif - Handle a message from the firmware * @dev: Which adapter this fib is from * @fibptr: Pointer to fibptr from adapter * * This routine handles a driver notify fib from the adapter and * dispatches it to the appropriate routine for handling. */ static void aac_handle_sa_aif(struct aac_dev *dev, struct fib *fibptr) { … } static int get_fib_count(struct aac_dev *dev) { … } static int fillup_pools(struct aac_dev *dev, struct hw_fib **hw_fib_pool, struct fib **fib_pool, unsigned int num) { … } static void wakeup_fibctx_threads(struct aac_dev *dev, struct hw_fib **hw_fib_pool, struct fib **fib_pool, struct fib *fib, struct hw_fib *hw_fib, unsigned int num) { … } static void aac_process_events(struct aac_dev *dev) { … } static int aac_send_wellness_command(struct aac_dev *dev, char *wellness_str, u32 datasize) { … } static int aac_send_safw_hostttime(struct aac_dev *dev, struct timespec64 *now) { … } static int aac_send_hosttime(struct aac_dev *dev, struct timespec64 *now) { … } /** * aac_command_thread - command processing thread * @data: Adapter to monitor * * Waits on the commandready event in it's queue. When the event gets set * it will pull FIBs off it's queue. It will continue to pull FIBs off * until the queue is empty. When the queue is empty it will wait for * more FIBs. */ int aac_command_thread(void *data) { … } int aac_acquire_irq(struct aac_dev *dev) { … } void aac_free_irq(struct aac_dev *dev) { … }