linux/drivers/scsi/mpi3mr/mpi3mr_os.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Driver for Broadcom MPI3 Storage Controllers
 *
 * Copyright (C) 2017-2023 Broadcom Inc.
 *  (mailto: [email protected])
 *
 */

#include "mpi3mr.h"
#include <linux/idr.h>

/* global driver scop variables */
LIST_HEAD();
DEFINE_SPINLOCK();
static DEFINE_IDA(mrioc_ida);
static int warn_non_secure_ctlr;
atomic64_t event_counter;

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();
MODULE_VERSION();

/* Module parameters*/
int prot_mask =;
module_param(prot_mask, int, 0);
MODULE_PARM_DESC();

static int prot_guard_mask =;
module_param(prot_guard_mask, int, 0);
MODULE_PARM_DESC();
static int logging_level;
module_param(logging_level, int, 0);
MODULE_PARM_DESC();
static int max_sgl_entries =;
module_param(max_sgl_entries, int, 0444);
MODULE_PARM_DESC();

/* Forward declarations*/
static void mpi3mr_send_event_ack(struct mpi3mr_ioc *mrioc, u8 event,
	struct mpi3mr_drv_cmd *cmdparam, u32 event_ctx);

#define MPI3MR_DRIVER_EVENT_TG_QD_REDUCTION

#define MPI3_EVENT_WAIT_FOR_DEVICES_TO_REFRESH

/**
 * mpi3mr_host_tag_for_scmd - Get host tag for a scmd
 * @mrioc: Adapter instance reference
 * @scmd: SCSI command reference
 *
 * Calculate the host tag based on block tag for a given scmd.
 *
 * Return: Valid host tag or MPI3MR_HOSTTAG_INVALID.
 */
static u16 mpi3mr_host_tag_for_scmd(struct mpi3mr_ioc *mrioc,
	struct scsi_cmnd *scmd)
{}

/**
 * mpi3mr_scmd_from_host_tag - Get SCSI command from host tag
 * @mrioc: Adapter instance reference
 * @host_tag: Host tag
 * @qidx: Operational queue index
 *
 * Identify the block tag from the host tag and queue index and
 * retrieve associated scsi command using scsi_host_find_tag().
 *
 * Return: SCSI command reference or NULL.
 */
static struct scsi_cmnd *mpi3mr_scmd_from_host_tag(
	struct mpi3mr_ioc *mrioc, u16 host_tag, u16 qidx)
{}

/**
 * mpi3mr_clear_scmd_priv - Cleanup SCSI command private date
 * @mrioc: Adapter instance reference
 * @scmd: SCSI command reference
 *
 * Invalidate the SCSI command private data to mark the command
 * is not in LLD scope anymore.
 *
 * Return: Nothing.
 */
static void mpi3mr_clear_scmd_priv(struct mpi3mr_ioc *mrioc,
	struct scsi_cmnd *scmd)
{}

static void mpi3mr_dev_rmhs_send_tm(struct mpi3mr_ioc *mrioc, u16 handle,
	struct mpi3mr_drv_cmd *cmdparam, u8 iou_rc);
static void mpi3mr_fwevt_worker(struct work_struct *work);

/**
 * mpi3mr_fwevt_free - firmware event memory dealloctor
 * @r: k reference pointer of the firmware event
 *
 * Free firmware event memory when no reference.
 */
static void mpi3mr_fwevt_free(struct kref *r)
{}

/**
 * mpi3mr_fwevt_get - k reference incrementor
 * @fwevt: Firmware event reference
 *
 * Increment firmware event reference count.
 */
static void mpi3mr_fwevt_get(struct mpi3mr_fwevt *fwevt)
{}

/**
 * mpi3mr_fwevt_put - k reference decrementor
 * @fwevt: Firmware event reference
 *
 * decrement firmware event reference count.
 */
static void mpi3mr_fwevt_put(struct mpi3mr_fwevt *fwevt)
{}

/**
 * mpi3mr_alloc_fwevt - Allocate firmware event
 * @len: length of firmware event data to allocate
 *
 * Allocate firmware event with required length and initialize
 * the reference counter.
 *
 * Return: firmware event reference.
 */
static struct mpi3mr_fwevt *mpi3mr_alloc_fwevt(int len)
{}

/**
 * mpi3mr_fwevt_add_to_list - Add firmware event to the list
 * @mrioc: Adapter instance reference
 * @fwevt: Firmware event reference
 *
 * Add the given firmware event to the firmware event list.
 *
 * Return: Nothing.
 */
static void mpi3mr_fwevt_add_to_list(struct mpi3mr_ioc *mrioc,
	struct mpi3mr_fwevt *fwevt)
{}

/**
 * mpi3mr_hdb_trigger_data_event - Add hdb trigger data event to
 * the list
 * @mrioc: Adapter instance reference
 * @event_data: Event data
 *
 * Add the given hdb trigger data event to the firmware event
 * list.
 *
 * Return: Nothing.
 */
void mpi3mr_hdb_trigger_data_event(struct mpi3mr_ioc *mrioc,
	struct trigger_event_data *event_data)
{}

/**
 * mpi3mr_fwevt_del_from_list - Delete firmware event from list
 * @mrioc: Adapter instance reference
 * @fwevt: Firmware event reference
 *
 * Delete the given firmware event from the firmware event list.
 *
 * Return: Nothing.
 */
static void mpi3mr_fwevt_del_from_list(struct mpi3mr_ioc *mrioc,
	struct mpi3mr_fwevt *fwevt)
{}

/**
 * mpi3mr_dequeue_fwevt - Dequeue firmware event from the list
 * @mrioc: Adapter instance reference
 *
 * Dequeue a firmware event from the firmware event list.
 *
 * Return: firmware event.
 */
static struct mpi3mr_fwevt *mpi3mr_dequeue_fwevt(
	struct mpi3mr_ioc *mrioc)
{}

/**
 * mpi3mr_cancel_work - cancel firmware event
 * @fwevt: fwevt object which needs to be canceled
 *
 * Return: Nothing.
 */
static void mpi3mr_cancel_work(struct mpi3mr_fwevt *fwevt)
{}

/**
 * mpi3mr_cleanup_fwevt_list - Cleanup firmware event list
 * @mrioc: Adapter instance reference
 *
 * Flush all pending firmware events from the firmware event
 * list.
 *
 * Return: Nothing.
 */
void mpi3mr_cleanup_fwevt_list(struct mpi3mr_ioc *mrioc)
{}

/**
 * mpi3mr_queue_qd_reduction_event - Queue TG QD reduction event
 * @mrioc: Adapter instance reference
 * @tg: Throttle group information pointer
 *
 * Accessor to queue on synthetically generated driver event to
 * the event worker thread, the driver event will be used to
 * reduce the QD of all VDs in the TG from the worker thread.
 *
 * Return: None.
 */
static void mpi3mr_queue_qd_reduction_event(struct mpi3mr_ioc *mrioc,
	struct mpi3mr_throttle_group_info *tg)
{}

/**
 * mpi3mr_invalidate_devhandles -Invalidate device handles
 * @mrioc: Adapter instance reference
 *
 * Invalidate the device handles in the target device structures
 * . Called post reset prior to reinitializing the controller.
 *
 * Return: Nothing.
 */
void mpi3mr_invalidate_devhandles(struct mpi3mr_ioc *mrioc)
{}

/**
 * mpi3mr_print_scmd - print individual SCSI command
 * @rq: Block request
 * @data: Adapter instance reference
 *
 * Print the SCSI command details if it is in LLD scope.
 *
 * Return: true always.
 */
static bool mpi3mr_print_scmd(struct request *rq, void *data)
{}

/**
 * mpi3mr_flush_scmd - Flush individual SCSI command
 * @rq: Block request
 * @data: Adapter instance reference
 *
 * Return the SCSI command to the upper layers if it is in LLD
 * scope.
 *
 * Return: true always.
 */

static bool mpi3mr_flush_scmd(struct request *rq, void *data)
{}

/**
 * mpi3mr_count_dev_pending - Count commands pending for a lun
 * @rq: Block request
 * @data: SCSI device reference
 *
 * This is an iterator function called for each SCSI command in
 * a host and if the command is pending in the LLD for the
 * specific device(lun) then device specific pending I/O counter
 * is updated in the device structure.
 *
 * Return: true always.
 */

static bool mpi3mr_count_dev_pending(struct request *rq, void *data)
{}

/**
 * mpi3mr_count_tgt_pending - Count commands pending for target
 * @rq: Block request
 * @data: SCSI target reference
 *
 * This is an iterator function called for each SCSI command in
 * a host and if the command is pending in the LLD for the
 * specific target then target specific pending I/O counter is
 * updated in the target structure.
 *
 * Return: true always.
 */

static bool mpi3mr_count_tgt_pending(struct request *rq, void *data)
{}

/**
 * mpi3mr_flush_host_io -  Flush host I/Os
 * @mrioc: Adapter instance reference
 *
 * Flush all of the pending I/Os by calling
 * blk_mq_tagset_busy_iter() for each possible tag. This is
 * executed post controller reset
 *
 * Return: Nothing.
 */
void mpi3mr_flush_host_io(struct mpi3mr_ioc *mrioc)
{}

/**
 * mpi3mr_flush_cmds_for_unrecovered_controller - Flush all pending cmds
 * @mrioc: Adapter instance reference
 *
 * This function waits for currently running IO poll threads to
 * exit and then flushes all host I/Os and any internal pending
 * cmds. This is executed after controller is marked as
 * unrecoverable.
 *
 * Return: Nothing.
 */
void mpi3mr_flush_cmds_for_unrecovered_controller(struct mpi3mr_ioc *mrioc)
{}

/**
 * mpi3mr_alloc_tgtdev - target device allocator
 *
 * Allocate target device instance and initialize the reference
 * count
 *
 * Return: target device instance.
 */
static struct mpi3mr_tgt_dev *mpi3mr_alloc_tgtdev(void)
{}

/**
 * mpi3mr_tgtdev_add_to_list -Add tgtdevice to the list
 * @mrioc: Adapter instance reference
 * @tgtdev: Target device
 *
 * Add the target device to the target device list
 *
 * Return: Nothing.
 */
static void mpi3mr_tgtdev_add_to_list(struct mpi3mr_ioc *mrioc,
	struct mpi3mr_tgt_dev *tgtdev)
{}

/**
 * mpi3mr_tgtdev_del_from_list -Delete tgtdevice from the list
 * @mrioc: Adapter instance reference
 * @tgtdev: Target device
 * @must_delete: Must delete the target device from the list irrespective
 * of the device state.
 *
 * Remove the target device from the target device list
 *
 * Return: Nothing.
 */
static void mpi3mr_tgtdev_del_from_list(struct mpi3mr_ioc *mrioc,
	struct mpi3mr_tgt_dev *tgtdev, bool must_delete)
{}

/**
 * __mpi3mr_get_tgtdev_by_handle -Get tgtdev from device handle
 * @mrioc: Adapter instance reference
 * @handle: Device handle
 *
 * Accessor to retrieve target device from the device handle.
 * Non Lock version
 *
 * Return: Target device reference.
 */
static struct mpi3mr_tgt_dev  *__mpi3mr_get_tgtdev_by_handle(
	struct mpi3mr_ioc *mrioc, u16 handle)
{}

/**
 * mpi3mr_get_tgtdev_by_handle -Get tgtdev from device handle
 * @mrioc: Adapter instance reference
 * @handle: Device handle
 *
 * Accessor to retrieve target device from the device handle.
 * Lock version
 *
 * Return: Target device reference.
 */
struct mpi3mr_tgt_dev *mpi3mr_get_tgtdev_by_handle(
	struct mpi3mr_ioc *mrioc, u16 handle)
{}

/**
 * __mpi3mr_get_tgtdev_by_perst_id -Get tgtdev from persist ID
 * @mrioc: Adapter instance reference
 * @persist_id: Persistent ID
 *
 * Accessor to retrieve target device from the Persistent ID.
 * Non Lock version
 *
 * Return: Target device reference.
 */
static struct mpi3mr_tgt_dev  *__mpi3mr_get_tgtdev_by_perst_id(
	struct mpi3mr_ioc *mrioc, u16 persist_id)
{}

/**
 * mpi3mr_get_tgtdev_by_perst_id -Get tgtdev from persistent ID
 * @mrioc: Adapter instance reference
 * @persist_id: Persistent ID
 *
 * Accessor to retrieve target device from the Persistent ID.
 * Lock version
 *
 * Return: Target device reference.
 */
static struct mpi3mr_tgt_dev *mpi3mr_get_tgtdev_by_perst_id(
	struct mpi3mr_ioc *mrioc, u16 persist_id)
{}

/**
 * __mpi3mr_get_tgtdev_from_tgtpriv -Get tgtdev from tgt private
 * @mrioc: Adapter instance reference
 * @tgt_priv: Target private data
 *
 * Accessor to return target device from the target private
 * data. Non Lock version
 *
 * Return: Target device reference.
 */
static struct mpi3mr_tgt_dev  *__mpi3mr_get_tgtdev_from_tgtpriv(
	struct mpi3mr_ioc *mrioc, struct mpi3mr_stgt_priv_data *tgt_priv)
{}

/**
 * mpi3mr_set_io_divert_for_all_vd_in_tg -set divert for TG VDs
 * @mrioc: Adapter instance reference
 * @tg: Throttle group information pointer
 * @divert_value: 1 or 0
 *
 * Accessor to set io_divert flag for each device associated
 * with the given throttle group with the given value.
 *
 * Return: None.
 */
static void mpi3mr_set_io_divert_for_all_vd_in_tg(struct mpi3mr_ioc *mrioc,
	struct mpi3mr_throttle_group_info *tg, u8 divert_value)
{}

/**
 * mpi3mr_print_device_event_notice - print notice related to post processing of
 *					device event after controller reset.
 *
 * @mrioc: Adapter instance reference
 * @device_add: true for device add event and false for device removal event
 *
 * Return: None.
 */
void mpi3mr_print_device_event_notice(struct mpi3mr_ioc *mrioc,
	bool device_add)
{}

/**
 * mpi3mr_remove_tgtdev_from_host - Remove dev from upper layers
 * @mrioc: Adapter instance reference
 * @tgtdev: Target device structure
 *
 * Checks whether the device is exposed to upper layers and if it
 * is then remove the device from upper layers by calling
 * scsi_remove_target().
 *
 * Return: 0 on success, non zero on failure.
 */
void mpi3mr_remove_tgtdev_from_host(struct mpi3mr_ioc *mrioc,
	struct mpi3mr_tgt_dev *tgtdev)
{}

/**
 * mpi3mr_report_tgtdev_to_host - Expose device to upper layers
 * @mrioc: Adapter instance reference
 * @perst_id: Persistent ID of the device
 *
 * Checks whether the device can be exposed to upper layers and
 * if it is not then expose the device to upper layers by
 * calling scsi_scan_target().
 *
 * Return: 0 on success, non zero on failure.
 */
static int mpi3mr_report_tgtdev_to_host(struct mpi3mr_ioc *mrioc,
	u16 perst_id)
{}

/**
 * mpi3mr_change_queue_depth- Change QD callback handler
 * @sdev: SCSI device reference
 * @q_depth: Queue depth
 *
 * Validate and limit QD and call scsi_change_queue_depth.
 *
 * Return: return value of scsi_change_queue_depth
 */
static int mpi3mr_change_queue_depth(struct scsi_device *sdev,
	int q_depth)
{}

static void mpi3mr_configure_nvme_dev(struct mpi3mr_tgt_dev *tgt_dev,
		struct queue_limits *lim)
{}

static void mpi3mr_configure_tgt_dev(struct mpi3mr_tgt_dev *tgt_dev,
		struct queue_limits *lim)
{}

/**
 * mpi3mr_update_sdev - Update SCSI device information
 * @sdev: SCSI device reference
 * @data: target device reference
 *
 * This is an iterator function called for each SCSI device in a
 * target to update the target specific information into each
 * SCSI device.
 *
 * Return: Nothing.
 */
static void
mpi3mr_update_sdev(struct scsi_device *sdev, void *data)
{}

/**
 * mpi3mr_refresh_tgtdevs - Refresh target device exposure
 * @mrioc: Adapter instance reference
 *
 * This is executed post controller reset to identify any
 * missing devices during reset and remove from the upper layers
 * or expose any newly detected device to the upper layers.
 *
 * Return: Nothing.
 */
static void mpi3mr_refresh_tgtdevs(struct mpi3mr_ioc *mrioc)
{}

/**
 * mpi3mr_update_tgtdev - DevStatusChange evt bottomhalf
 * @mrioc: Adapter instance reference
 * @tgtdev: Target device internal structure
 * @dev_pg0: New device page0
 * @is_added: Flag to indicate the device is just added
 *
 * Update the information from the device page0 into the driver
 * cached target device structure.
 *
 * Return: Nothing.
 */
static void mpi3mr_update_tgtdev(struct mpi3mr_ioc *mrioc,
	struct mpi3mr_tgt_dev *tgtdev, struct mpi3_device_page0 *dev_pg0,
	bool is_added)
{}

/**
 * mpi3mr_devstatuschg_evt_bh - DevStatusChange evt bottomhalf
 * @mrioc: Adapter instance reference
 * @fwevt: Firmware event information.
 *
 * Process Device status Change event and based on device's new
 * information, either expose the device to the upper layers, or
 * remove the device from upper layers.
 *
 * Return: Nothing.
 */
static void mpi3mr_devstatuschg_evt_bh(struct mpi3mr_ioc *mrioc,
	struct mpi3mr_fwevt *fwevt)
{}

/**
 * mpi3mr_devinfochg_evt_bh - DeviceInfoChange evt bottomhalf
 * @mrioc: Adapter instance reference
 * @dev_pg0: New device page0
 *
 * Process Device Info Change event and based on device's new
 * information, either expose the device to the upper layers, or
 * remove the device from upper layers or update the details of
 * the device.
 *
 * Return: Nothing.
 */
static void mpi3mr_devinfochg_evt_bh(struct mpi3mr_ioc *mrioc,
	struct mpi3_device_page0 *dev_pg0)
{}

/**
 * mpi3mr_free_enclosure_list - release enclosures
 * @mrioc: Adapter instance reference
 *
 * Free memory allocated during encloure add.
 *
 * Return nothing.
 */
void mpi3mr_free_enclosure_list(struct mpi3mr_ioc *mrioc)
{}

/**
 * mpi3mr_enclosure_find_by_handle - enclosure search by handle
 * @mrioc: Adapter instance reference
 * @handle: Firmware device handle of the enclosure
 *
 * This searches for enclosure device based on handle, then returns the
 * enclosure object.
 *
 * Return: Enclosure object reference or NULL
 */
struct mpi3mr_enclosure_node *mpi3mr_enclosure_find_by_handle(
	struct mpi3mr_ioc *mrioc, u16 handle)
{}

/**
 * mpi3mr_process_trigger_data_event_bh - Process trigger event
 * data
 * @mrioc: Adapter instance reference
 * @event_data: Event data
 *
 * This function releases diage buffers or issues diag fault
 * based on trigger conditions
 *
 * Return: Nothing
 */
static void mpi3mr_process_trigger_data_event_bh(struct mpi3mr_ioc *mrioc,
	struct trigger_event_data *event_data)
{}

/**
 * mpi3mr_encldev_add_chg_evt_debug - debug for enclosure event
 * @mrioc: Adapter instance reference
 * @encl_pg0: Enclosure page 0.
 * @is_added: Added event or not
 *
 * Return nothing.
 */
static void mpi3mr_encldev_add_chg_evt_debug(struct mpi3mr_ioc *mrioc,
	struct mpi3_enclosure_page0 *encl_pg0, u8 is_added)
{}

/**
 * mpi3mr_encldev_add_chg_evt_bh - Enclosure evt bottomhalf
 * @mrioc: Adapter instance reference
 * @fwevt: Firmware event reference
 *
 * Prints information about the Enclosure device status or
 * Enclosure add events if logging is enabled and add or remove
 * the enclosure from the controller's internal list of
 * enclosures.
 *
 * Return: Nothing.
 */
static void mpi3mr_encldev_add_chg_evt_bh(struct mpi3mr_ioc *mrioc,
	struct mpi3mr_fwevt *fwevt)
{}

/**
 * mpi3mr_sastopochg_evt_debug - SASTopoChange details
 * @mrioc: Adapter instance reference
 * @event_data: SAS topology change list event data
 *
 * Prints information about the SAS topology change event.
 *
 * Return: Nothing.
 */
static void
mpi3mr_sastopochg_evt_debug(struct mpi3mr_ioc *mrioc,
	struct mpi3_event_data_sas_topology_change_list *event_data)
{}

/**
 * mpi3mr_sastopochg_evt_bh - SASTopologyChange evt bottomhalf
 * @mrioc: Adapter instance reference
 * @fwevt: Firmware event reference
 *
 * Prints information about the SAS topology change event and
 * for "not responding" event code, removes the device from the
 * upper layers.
 *
 * Return: Nothing.
 */
static void mpi3mr_sastopochg_evt_bh(struct mpi3mr_ioc *mrioc,
	struct mpi3mr_fwevt *fwevt)
{}

/**
 * mpi3mr_pcietopochg_evt_debug - PCIeTopoChange details
 * @mrioc: Adapter instance reference
 * @event_data: PCIe topology change list event data
 *
 * Prints information about the PCIe topology change event.
 *
 * Return: Nothing.
 */
static void
mpi3mr_pcietopochg_evt_debug(struct mpi3mr_ioc *mrioc,
	struct mpi3_event_data_pcie_topology_change_list *event_data)
{}

/**
 * mpi3mr_pcietopochg_evt_bh - PCIeTopologyChange evt bottomhalf
 * @mrioc: Adapter instance reference
 * @fwevt: Firmware event reference
 *
 * Prints information about the PCIe topology change event and
 * for "not responding" event code, removes the device from the
 * upper layers.
 *
 * Return: Nothing.
 */
static void mpi3mr_pcietopochg_evt_bh(struct mpi3mr_ioc *mrioc,
	struct mpi3mr_fwevt *fwevt)
{}

/**
 * mpi3mr_logdata_evt_bh -  Log data event bottomhalf
 * @mrioc: Adapter instance reference
 * @fwevt: Firmware event reference
 *
 * Extracts the event data and calls application interfacing
 * function to process the event further.
 *
 * Return: Nothing.
 */
static void mpi3mr_logdata_evt_bh(struct mpi3mr_ioc *mrioc,
	struct mpi3mr_fwevt *fwevt)
{}

/**
 * mpi3mr_update_sdev_qd - Update SCSI device queue depath
 * @sdev: SCSI device reference
 * @data: Queue depth reference
 *
 * This is an iterator function called for each SCSI device in a
 * target to update the QD of each SCSI device.
 *
 * Return: Nothing.
 */
static void mpi3mr_update_sdev_qd(struct scsi_device *sdev, void *data)
{}

/**
 * mpi3mr_set_qd_for_all_vd_in_tg -set QD for TG VDs
 * @mrioc: Adapter instance reference
 * @tg: Throttle group information pointer
 *
 * Accessor to reduce QD for each device associated with the
 * given throttle group.
 *
 * Return: None.
 */
static void mpi3mr_set_qd_for_all_vd_in_tg(struct mpi3mr_ioc *mrioc,
	struct mpi3mr_throttle_group_info *tg)
{}

/**
 * mpi3mr_fwevt_bh - Firmware event bottomhalf handler
 * @mrioc: Adapter instance reference
 * @fwevt: Firmware event reference
 *
 * Identifies the firmware event and calls corresponding bottomg
 * half handler and sends event acknowledgment if required.
 *
 * Return: Nothing.
 */
static void mpi3mr_fwevt_bh(struct mpi3mr_ioc *mrioc,
	struct mpi3mr_fwevt *fwevt)
{}

/**
 * mpi3mr_fwevt_worker - Firmware event worker
 * @work: Work struct containing firmware event
 *
 * Extracts the firmware event and calls mpi3mr_fwevt_bh.
 *
 * Return: Nothing.
 */
static void mpi3mr_fwevt_worker(struct work_struct *work)
{}

/**
 * mpi3mr_create_tgtdev - Create and add a target device
 * @mrioc: Adapter instance reference
 * @dev_pg0: Device Page 0 data
 *
 * If the device specified by the device page 0 data is not
 * present in the driver's internal list, allocate the memory
 * for the device, populate the data and add to the list, else
 * update the device data.  The key is persistent ID.
 *
 * Return: 0 on success, -ENOMEM on memory allocation failure
 */
static int mpi3mr_create_tgtdev(struct mpi3mr_ioc *mrioc,
	struct mpi3_device_page0 *dev_pg0)
{}

/**
 * mpi3mr_flush_delayed_cmd_lists - Flush pending commands
 * @mrioc: Adapter instance reference
 *
 * Flush pending commands in the delayed lists due to a
 * controller reset or driver removal as a cleanup.
 *
 * Return: Nothing
 */
void mpi3mr_flush_delayed_cmd_lists(struct mpi3mr_ioc *mrioc)
{}

/**
 * mpi3mr_dev_rmhs_complete_iou - Device removal IOUC completion
 * @mrioc: Adapter instance reference
 * @drv_cmd: Internal command tracker
 *
 * Issues a target reset TM to the firmware from the device
 * removal TM pend list or retry the removal handshake sequence
 * based on the IOU control request IOC status.
 *
 * Return: Nothing
 */
static void mpi3mr_dev_rmhs_complete_iou(struct mpi3mr_ioc *mrioc,
	struct mpi3mr_drv_cmd *drv_cmd)
{}

/**
 * mpi3mr_dev_rmhs_complete_tm - Device removal TM completion
 * @mrioc: Adapter instance reference
 * @drv_cmd: Internal command tracker
 *
 * Issues a target reset TM to the firmware from the device
 * removal TM pend list or issue IO unit control request as
 * part of device removal or hidden acknowledgment handshake.
 *
 * Return: Nothing
 */
static void mpi3mr_dev_rmhs_complete_tm(struct mpi3mr_ioc *mrioc,
	struct mpi3mr_drv_cmd *drv_cmd)
{}

/**
 * mpi3mr_dev_rmhs_send_tm - Issue TM for device removal
 * @mrioc: Adapter instance reference
 * @handle: Device handle
 * @cmdparam: Internal command tracker
 * @iou_rc: IO unit reason code
 *
 * Issues a target reset TM to the firmware or add it to a pend
 * list as part of device removal or hidden acknowledgment
 * handshake.
 *
 * Return: Nothing
 */
static void mpi3mr_dev_rmhs_send_tm(struct mpi3mr_ioc *mrioc, u16 handle,
	struct mpi3mr_drv_cmd *cmdparam, u8 iou_rc)
{}

/**
 * mpi3mr_complete_evt_ack - event ack request completion
 * @mrioc: Adapter instance reference
 * @drv_cmd: Internal command tracker
 *
 * This is the completion handler for non blocking event
 * acknowledgment sent to the firmware and this will issue any
 * pending event acknowledgment request.
 *
 * Return: Nothing
 */
static void mpi3mr_complete_evt_ack(struct mpi3mr_ioc *mrioc,
	struct mpi3mr_drv_cmd *drv_cmd)
{}

/**
 * mpi3mr_send_event_ack - Issue event acknwoledgment request
 * @mrioc: Adapter instance reference
 * @event: MPI3 event id
 * @cmdparam: Internal command tracker
 * @event_ctx: event context
 *
 * Issues event acknowledgment request to the firmware if there
 * is a free command to send the event ack else it to a pend
 * list so that it will be processed on a completion of a prior
 * event acknowledgment .
 *
 * Return: Nothing
 */
static void mpi3mr_send_event_ack(struct mpi3mr_ioc *mrioc, u8 event,
	struct mpi3mr_drv_cmd *cmdparam, u32 event_ctx)
{}

/**
 * mpi3mr_pcietopochg_evt_th - PCIETopologyChange evt tophalf
 * @mrioc: Adapter instance reference
 * @event_reply: event data
 *
 * Checks for the reason code and based on that either block I/O
 * to device, or unblock I/O to the device, or start the device
 * removal handshake with reason as remove with the firmware for
 * PCIe devices.
 *
 * Return: Nothing
 */
static void mpi3mr_pcietopochg_evt_th(struct mpi3mr_ioc *mrioc,
	struct mpi3_event_notification_reply *event_reply)
{}

/**
 * mpi3mr_sastopochg_evt_th - SASTopologyChange evt tophalf
 * @mrioc: Adapter instance reference
 * @event_reply: event data
 *
 * Checks for the reason code and based on that either block I/O
 * to device, or unblock I/O to the device, or start the device
 * removal handshake with reason as remove with the firmware for
 * SAS/SATA devices.
 *
 * Return: Nothing
 */
static void mpi3mr_sastopochg_evt_th(struct mpi3mr_ioc *mrioc,
	struct mpi3_event_notification_reply *event_reply)
{}

/**
 * mpi3mr_devstatuschg_evt_th - DeviceStatusChange evt tophalf
 * @mrioc: Adapter instance reference
 * @event_reply: event data
 *
 * Checks for the reason code and based on that either block I/O
 * to device, or unblock I/O to the device, or start the device
 * removal handshake with reason as remove/hide acknowledgment
 * with the firmware.
 *
 * Return: Nothing
 */
static void mpi3mr_devstatuschg_evt_th(struct mpi3mr_ioc *mrioc,
	struct mpi3_event_notification_reply *event_reply)
{}

/**
 * mpi3mr_preparereset_evt_th - Prepare for reset event tophalf
 * @mrioc: Adapter instance reference
 * @event_reply: event data
 *
 * Blocks and unblocks host level I/O based on the reason code
 *
 * Return: Nothing
 */
static void mpi3mr_preparereset_evt_th(struct mpi3mr_ioc *mrioc,
	struct mpi3_event_notification_reply *event_reply)
{}

/**
 * mpi3mr_energypackchg_evt_th - Energy pack change evt tophalf
 * @mrioc: Adapter instance reference
 * @event_reply: event data
 *
 * Identifies the new shutdown timeout value and update.
 *
 * Return: Nothing
 */
static void mpi3mr_energypackchg_evt_th(struct mpi3mr_ioc *mrioc,
	struct mpi3_event_notification_reply *event_reply)
{}

/**
 * mpi3mr_cablemgmt_evt_th - Cable management event tophalf
 * @mrioc: Adapter instance reference
 * @event_reply: event data
 *
 * Displays Cable manegemt event details.
 *
 * Return: Nothing
 */
static void mpi3mr_cablemgmt_evt_th(struct mpi3mr_ioc *mrioc,
	struct mpi3_event_notification_reply *event_reply)
{}

/**
 * mpi3mr_add_event_wait_for_device_refresh - Add Wait for Device Refresh Event
 * @mrioc: Adapter instance reference
 *
 * Add driver specific event to make sure that the driver won't process the
 * events until all the devices are refreshed during soft reset.
 *
 * Return: Nothing
 */
void mpi3mr_add_event_wait_for_device_refresh(struct mpi3mr_ioc *mrioc)
{}

/**
 * mpi3mr_os_handle_events - Firmware event handler
 * @mrioc: Adapter instance reference
 * @event_reply: event data
 *
 * Identify whteher the event has to handled and acknowledged
 * and either process the event in the tophalf and/or schedule a
 * bottom half through mpi3mr_fwevt_worker.
 *
 * Return: Nothing
 */
void mpi3mr_os_handle_events(struct mpi3mr_ioc *mrioc,
	struct mpi3_event_notification_reply *event_reply)
{}

/**
 * mpi3mr_setup_eedp - Setup EEDP information in MPI3 SCSI IO
 * @mrioc: Adapter instance reference
 * @scmd: SCSI command reference
 * @scsiio_req: MPI3 SCSI IO request
 *
 * Identifies the protection information flags from the SCSI
 * command and set appropriate flags in the MPI3 SCSI IO
 * request.
 *
 * Return: Nothing
 */
static void mpi3mr_setup_eedp(struct mpi3mr_ioc *mrioc,
	struct scsi_cmnd *scmd, struct mpi3_scsi_io_request *scsiio_req)
{}

/**
 * mpi3mr_build_sense_buffer - Map sense information
 * @desc: Sense type
 * @buf: Sense buffer to populate
 * @key: Sense key
 * @asc: Additional sense code
 * @ascq: Additional sense code qualifier
 *
 * Maps the given sense information into either descriptor or
 * fixed format sense data.
 *
 * Return: Nothing
 */
static inline void mpi3mr_build_sense_buffer(int desc, u8 *buf, u8 key,
	u8 asc, u8 ascq)
{}

/**
 * mpi3mr_map_eedp_error - Map EEDP errors from IOC status
 * @scmd: SCSI command reference
 * @ioc_status: status of MPI3 request
 *
 * Maps the EEDP error status of the SCSI IO request to sense
 * data.
 *
 * Return: Nothing
 */
static void mpi3mr_map_eedp_error(struct scsi_cmnd *scmd,
	u16 ioc_status)
{}

/**
 * mpi3mr_process_op_reply_desc - reply descriptor handler
 * @mrioc: Adapter instance reference
 * @reply_desc: Operational reply descriptor
 * @reply_dma: place holder for reply DMA address
 * @qidx: Operational queue index
 *
 * Process the operational reply descriptor and identifies the
 * descriptor type. Based on the descriptor map the MPI3 request
 * status to a SCSI command status and calls scsi_done call
 * back.
 *
 * Return: Nothing
 */
void mpi3mr_process_op_reply_desc(struct mpi3mr_ioc *mrioc,
	struct mpi3_default_reply_descriptor *reply_desc, u64 *reply_dma, u16 qidx)
{}

/**
 * mpi3mr_get_chain_idx - get free chain buffer index
 * @mrioc: Adapter instance reference
 *
 * Try to get a free chain buffer index from the free pool.
 *
 * Return: -1 on failure or the free chain buffer index
 */
static int mpi3mr_get_chain_idx(struct mpi3mr_ioc *mrioc)
{}

/**
 * mpi3mr_prepare_sg_scmd - build scatter gather list
 * @mrioc: Adapter instance reference
 * @scmd: SCSI command reference
 * @scsiio_req: MPI3 SCSI IO request
 *
 * This function maps SCSI command's data and protection SGEs to
 * MPI request SGEs. If required additional 4K chain buffer is
 * used to send the SGEs.
 *
 * Return: 0 on success, -ENOMEM on dma_map_sg failure
 */
static int mpi3mr_prepare_sg_scmd(struct mpi3mr_ioc *mrioc,
	struct scsi_cmnd *scmd, struct mpi3_scsi_io_request *scsiio_req)
{}

/**
 * mpi3mr_build_sg_scmd - build scatter gather list for SCSI IO
 * @mrioc: Adapter instance reference
 * @scmd: SCSI command reference
 * @scsiio_req: MPI3 SCSI IO request
 *
 * This function calls mpi3mr_prepare_sg_scmd for constructing
 * both data SGEs and protection information SGEs in the MPI
 * format from the SCSI Command as appropriate .
 *
 * Return: return value of mpi3mr_prepare_sg_scmd.
 */
static int mpi3mr_build_sg_scmd(struct mpi3mr_ioc *mrioc,
	struct scsi_cmnd *scmd, struct mpi3_scsi_io_request *scsiio_req)
{}

/**
 * mpi3mr_tm_response_name -  get TM response as a string
 * @resp_code: TM response code
 *
 * Convert known task management response code as a readable
 * string.
 *
 * Return: response code string.
 */
static const char *mpi3mr_tm_response_name(u8 resp_code)
{}

inline void mpi3mr_poll_pend_io_completions(struct mpi3mr_ioc *mrioc)
{}

/**
 * mpi3mr_issue_tm - Issue Task Management request
 * @mrioc: Adapter instance reference
 * @tm_type: Task Management type
 * @handle: Device handle
 * @lun: lun ID
 * @htag: Host tag of the TM request
 * @timeout: TM timeout value
 * @drv_cmd: Internal command tracker
 * @resp_code: Response code place holder
 * @scmd: SCSI command
 *
 * Issues a Task Management Request to the controller for a
 * specified target, lun and command and wait for its completion
 * and check TM response. Recover the TM if it timed out by
 * issuing controller reset.
 *
 * Return: 0 on success, non-zero on errors
 */
int mpi3mr_issue_tm(struct mpi3mr_ioc *mrioc, u8 tm_type,
	u16 handle, uint lun, u16 htag, ulong timeout,
	struct mpi3mr_drv_cmd *drv_cmd,
	u8 *resp_code, struct scsi_cmnd *scmd)
{}

/**
 * mpi3mr_bios_param - BIOS param callback
 * @sdev: SCSI device reference
 * @bdev: Block device reference
 * @capacity: Capacity in logical sectors
 * @params: Parameter array
 *
 * Just the parameters with heads/secots/cylinders.
 *
 * Return: 0 always
 */
static int mpi3mr_bios_param(struct scsi_device *sdev,
	struct block_device *bdev, sector_t capacity, int params[])
{}

/**
 * mpi3mr_map_queues - Map queues callback handler
 * @shost: SCSI host reference
 *
 * Maps default and poll queues.
 *
 * Return: return zero.
 */
static void mpi3mr_map_queues(struct Scsi_Host *shost)
{}

/**
 * mpi3mr_get_fw_pending_ios - Calculate pending I/O count
 * @mrioc: Adapter instance reference
 *
 * Calculate the pending I/Os for the controller and return.
 *
 * Return: Number of pending I/Os
 */
static inline int mpi3mr_get_fw_pending_ios(struct mpi3mr_ioc *mrioc)
{}

/**
 * mpi3mr_print_pending_host_io - print pending I/Os
 * @mrioc: Adapter instance reference
 *
 * Print number of pending I/Os and each I/O details prior to
 * reset for debug purpose.
 *
 * Return: Nothing
 */
static void mpi3mr_print_pending_host_io(struct mpi3mr_ioc *mrioc)
{}

/**
 * mpi3mr_wait_for_host_io - block for I/Os to complete
 * @mrioc: Adapter instance reference
 * @timeout: time out in seconds
 * Waits for pending I/Os for the given adapter to complete or
 * to hit the timeout.
 *
 * Return: Nothing
 */
void mpi3mr_wait_for_host_io(struct mpi3mr_ioc *mrioc, u32 timeout)
{}

/**
 * mpi3mr_setup_divert_ws - Setup Divert IO flag for write same
 * @mrioc: Adapter instance reference
 * @scmd: SCSI command reference
 * @scsiio_req: MPI3 SCSI IO request
 * @scsiio_flags: Pointer to MPI3 SCSI IO Flags
 * @wslen: write same max length
 *
 * Gets values of unmap, ndob and number of blocks from write
 * same scsi io and based on these values it sets divert IO flag
 * and reason for diverting IO to firmware.
 *
 * Return: Nothing
 */
static inline void mpi3mr_setup_divert_ws(struct mpi3mr_ioc *mrioc,
	struct scsi_cmnd *scmd, struct mpi3_scsi_io_request *scsiio_req,
	u32 *scsiio_flags, u16 wslen)
{}

/**
 * mpi3mr_eh_host_reset - Host reset error handling callback
 * @scmd: SCSI command reference
 *
 * Issue controller reset
 *
 * Return: SUCCESS of successful reset else FAILED
 */
static int mpi3mr_eh_host_reset(struct scsi_cmnd *scmd)
{}

/**
 * mpi3mr_eh_bus_reset - Bus reset error handling callback
 * @scmd: SCSI command reference
 *
 * Checks whether pending I/Os are present for the RAID volume;
 * if not there's no need to reset the adapter.
 *
 * Return: SUCCESS of successful reset else FAILED
 */
static int mpi3mr_eh_bus_reset(struct scsi_cmnd *scmd)
{}

/**
 * mpi3mr_eh_target_reset - Target reset error handling callback
 * @scmd: SCSI command reference
 *
 * Issue Target reset Task Management and verify the scmd is
 * terminated successfully and return status accordingly.
 *
 * Return: SUCCESS of successful termination of the scmd else
 *         FAILED
 */
static int mpi3mr_eh_target_reset(struct scsi_cmnd *scmd)
{}

/**
 * mpi3mr_eh_dev_reset- Device reset error handling callback
 * @scmd: SCSI command reference
 *
 * Issue lun reset Task Management and verify the scmd is
 * terminated successfully and return status accordingly.
 *
 * Return: SUCCESS of successful termination of the scmd else
 *         FAILED
 */
static int mpi3mr_eh_dev_reset(struct scsi_cmnd *scmd)
{}

/**
 * mpi3mr_scan_start - Scan start callback handler
 * @shost: SCSI host reference
 *
 * Issue port enable request asynchronously.
 *
 * Return: Nothing
 */
static void mpi3mr_scan_start(struct Scsi_Host *shost)
{}

/**
 * mpi3mr_scan_finished - Scan finished callback handler
 * @shost: SCSI host reference
 * @time: Jiffies from the scan start
 *
 * Checks whether the port enable is completed or timedout or
 * failed and set the scan status accordingly after taking any
 * recovery if required.
 *
 * Return: 1 on scan finished or timed out, 0 for in progress
 */
static int mpi3mr_scan_finished(struct Scsi_Host *shost,
	unsigned long time)
{}

/**
 * mpi3mr_slave_destroy - Slave destroy callback handler
 * @sdev: SCSI device reference
 *
 * Cleanup and free per device(lun) private data.
 *
 * Return: Nothing.
 */
static void mpi3mr_slave_destroy(struct scsi_device *sdev)
{}

/**
 * mpi3mr_target_destroy - Target destroy callback handler
 * @starget: SCSI target reference
 *
 * Cleanup and free per target private data.
 *
 * Return: Nothing.
 */
static void mpi3mr_target_destroy(struct scsi_target *starget)
{}

/**
 * mpi3mr_device_configure - Slave configure callback handler
 * @sdev: SCSI device reference
 * @lim: queue limits
 *
 * Configure queue depth, max hardware sectors and virt boundary
 * as required
 *
 * Return: 0 always.
 */
static int mpi3mr_device_configure(struct scsi_device *sdev,
		struct queue_limits *lim)
{}

/**
 * mpi3mr_slave_alloc -Slave alloc callback handler
 * @sdev: SCSI device reference
 *
 * Allocate per device(lun) private data and initialize it.
 *
 * Return: 0 on success -ENOMEM on memory allocation failure.
 */
static int mpi3mr_slave_alloc(struct scsi_device *sdev)
{}

/**
 * mpi3mr_target_alloc - Target alloc callback handler
 * @starget: SCSI target reference
 *
 * Allocate per target private data and initialize it.
 *
 * Return: 0 on success -ENOMEM on memory allocation failure.
 */
static int mpi3mr_target_alloc(struct scsi_target *starget)
{}

/**
 * mpi3mr_check_return_unmap - Whether an unmap is allowed
 * @mrioc: Adapter instance reference
 * @scmd: SCSI Command reference
 *
 * The controller hardware cannot handle certain unmap commands
 * for NVMe drives, this routine checks those and return true
 * and completes the SCSI command with proper status and sense
 * data.
 *
 * Return: TRUE for not  allowed unmap, FALSE otherwise.
 */
static bool mpi3mr_check_return_unmap(struct mpi3mr_ioc *mrioc,
	struct scsi_cmnd *scmd)
{}

/**
 * mpi3mr_allow_scmd_to_fw - Command is allowed during shutdown
 * @scmd: SCSI Command reference
 *
 * Checks whether a cdb is allowed during shutdown or not.
 *
 * Return: TRUE for allowed commands, FALSE otherwise.
 */

inline bool mpi3mr_allow_scmd_to_fw(struct scsi_cmnd *scmd)
{}

/**
 * mpi3mr_qcmd - I/O request despatcher
 * @shost: SCSI Host reference
 * @scmd: SCSI Command reference
 *
 * Issues the SCSI Command as an MPI3 request.
 *
 * Return: 0 on successful queueing of the request or if the
 *         request is completed with failure.
 *         SCSI_MLQUEUE_DEVICE_BUSY when the device is busy.
 *         SCSI_MLQUEUE_HOST_BUSY when the host queue is full.
 */
static int mpi3mr_qcmd(struct Scsi_Host *shost,
	struct scsi_cmnd *scmd)
{}

static const struct scsi_host_template mpi3mr_driver_template =;

/**
 * mpi3mr_init_drv_cmd - Initialize internal command tracker
 * @cmdptr: Internal command tracker
 * @host_tag: Host tag used for the specific command
 *
 * Initialize the internal command tracker structure with
 * specified host tag.
 *
 * Return: Nothing.
 */
static inline void mpi3mr_init_drv_cmd(struct mpi3mr_drv_cmd *cmdptr,
	u16 host_tag)
{}

/**
 * osintfc_mrioc_security_status -Check controller secure status
 * @pdev: PCI device instance
 *
 * Read the Device Serial Number capability from PCI config
 * space and decide whether the controller is secure or not.
 *
 * Return: 0 on success, non-zero on failure.
 */
static int
osintfc_mrioc_security_status(struct pci_dev *pdev)
{}

/**
 * mpi3mr_probe - PCI probe callback
 * @pdev: PCI device instance
 * @id: PCI device ID details
 *
 * controller initialization routine. Checks the security status
 * of the controller and if it is invalid or tampered return the
 * probe without initializing the controller. Otherwise,
 * allocate per adapter instance through shost_priv and
 * initialize controller specific data structures, initializae
 * the controller hardware, add shost to the SCSI subsystem.
 *
 * Return: 0 on success, non-zero on failure.
 */

static int
mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{}

/**
 * mpi3mr_remove - PCI remove callback
 * @pdev: PCI device instance
 *
 * Cleanup the IOC by issuing MUR and shutdown notification.
 * Free up all memory and resources associated with the
 * controllerand target devices, unregister the shost.
 *
 * Return: Nothing.
 */
static void mpi3mr_remove(struct pci_dev *pdev)
{}

/**
 * mpi3mr_shutdown - PCI shutdown callback
 * @pdev: PCI device instance
 *
 * Free up all memory and resources associated with the
 * controller
 *
 * Return: Nothing.
 */
static void mpi3mr_shutdown(struct pci_dev *pdev)
{}

/**
 * mpi3mr_suspend - PCI power management suspend callback
 * @dev: Device struct
 *
 * Change the power state to the given value and cleanup the IOC
 * by issuing MUR and shutdown notification
 *
 * Return: 0 always.
 */
static int __maybe_unused
mpi3mr_suspend(struct device *dev)
{}

/**
 * mpi3mr_resume - PCI power management resume callback
 * @dev: Device struct
 *
 * Restore the power state to D0 and reinitialize the controller
 * and resume I/O operations to the target devices
 *
 * Return: 0 on success, non-zero on failure
 */
static int __maybe_unused
mpi3mr_resume(struct device *dev)
{}

/**
 * mpi3mr_pcierr_error_detected - PCI error detected callback
 * @pdev: PCI device instance
 * @state: channel state
 *
 * This function is called by the PCI error recovery driver and
 * based on the state passed the driver decides what actions to
 * be recommended back to PCI driver.
 *
 * For all of the states if there is no valid mrioc or scsi host
 * references in the PCI device then this function will return
 * the result as disconnect.
 *
 * For normal state, this function will return the result as can
 * recover.
 *
 * For frozen state, this function will block for any pending
 * controller initialization or re-initialization to complete,
 * stop any new interactions with the controller and return
 * status as reset required.
 *
 * For permanent failure state, this function will mark the
 * controller as unrecoverable and return status as disconnect.
 *
 * Returns: PCI_ERS_RESULT_NEED_RESET or CAN_RECOVER or
 * DISCONNECT based on the controller state.
 */
static pci_ers_result_t
mpi3mr_pcierr_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
{}

/**
 * mpi3mr_pcierr_slot_reset - Post slot reset callback
 * @pdev: PCI device instance
 *
 * This function is called by the PCI error recovery driver
 * after a slot or link reset issued by it for the recovery, the
 * driver is expected to bring back the controller and
 * initialize it.
 *
 * This function restores PCI state and reinitializes controller
 * resources and the controller, this blocks for any pending
 * reset to complete.
 *
 * Returns: PCI_ERS_RESULT_DISCONNECT on failure or
 * PCI_ERS_RESULT_RECOVERED
 */
static pci_ers_result_t mpi3mr_pcierr_slot_reset(struct pci_dev *pdev)
{}

/**
 * mpi3mr_pcierr_resume - PCI error recovery resume
 * callback
 * @pdev: PCI device instance
 *
 * This function enables all I/O and IOCTLs post reset issued as
 * part of the PCI error recovery
 *
 * Return: Nothing.
 */
static void mpi3mr_pcierr_resume(struct pci_dev *pdev)
{}

/**
 * mpi3mr_pcierr_mmio_enabled - PCI error recovery callback
 * @pdev: PCI device instance
 *
 * This is called only if mpi3mr_pcierr_error_detected returns
 * PCI_ERS_RESULT_CAN_RECOVER.
 *
 * Return: PCI_ERS_RESULT_DISCONNECT when the controller is
 * unrecoverable or when the shost/mrioc reference cannot be
 * found, else return PCI_ERS_RESULT_RECOVERED
 */
static pci_ers_result_t mpi3mr_pcierr_mmio_enabled(struct pci_dev *pdev)
{}

static const struct pci_device_id mpi3mr_pci_id_table[] =;
MODULE_DEVICE_TABLE(pci, mpi3mr_pci_id_table);

static struct pci_error_handlers mpi3mr_err_handler =;

static SIMPLE_DEV_PM_OPS(mpi3mr_pm_ops, mpi3mr_suspend, mpi3mr_resume);

static struct pci_driver mpi3mr_pci_driver =;

static ssize_t event_counter_show(struct device_driver *dd, char *buf)
{}
static DRIVER_ATTR_RO(event_counter);

static int __init mpi3mr_init(void)
{}

static void __exit mpi3mr_exit(void)
{}

module_init();
module_exit(mpi3mr_exit);