scsi: mpi3mr: Add support for device add/remove event handling
Firmware can report various MPI Events. Enable support for processing the following events related to device addition/removal to the driver: - MPI3_EVENT_DEVICE_ADDED - MPI3_EVENT_DEVICE_INFO_CHANGED - MPI3_EVENT_DEVICE_STATUS_CHANGE - MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE - MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST - MPI3_EVENT_SAS_DISCOVERY - MPI3_EVENT_SAS_DEVICE_DISCOVERY_ERROR Link: https://lore.kernel.org/r/20210520152545.2710479-7-kashyap.desai@broadcom.com Cc: sathya.prakash@broadcom.com Reported-by: kernel test robot <lkp@intel.com> Reviewed-by: Tomas Henzl <thenzl@redhat.com> Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com> Reviewed-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Kashyap Desai <kashyap.desai@broadcom.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Родитель
672ae26c82
Коммит
13ef29ea4a
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,33 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright 2016-2021 Broadcom Inc. All rights reserved.
|
||||
*
|
||||
*/
|
||||
#ifndef MPI30_SAS_H
|
||||
#define MPI30_SAS_H 1
|
||||
#define MPI3_SAS_DEVICE_INFO_SSP_TARGET (0x00000100)
|
||||
#define MPI3_SAS_DEVICE_INFO_STP_SATA_TARGET (0x00000080)
|
||||
#define MPI3_SAS_DEVICE_INFO_SMP_TARGET (0x00000040)
|
||||
#define MPI3_SAS_DEVICE_INFO_SSP_INITIATOR (0x00000020)
|
||||
#define MPI3_SAS_DEVICE_INFO_STP_INITIATOR (0x00000010)
|
||||
#define MPI3_SAS_DEVICE_INFO_SMP_INITIATOR (0x00000008)
|
||||
#define MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_MASK (0x00000007)
|
||||
#define MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_NO_DEVICE (0x00000000)
|
||||
#define MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_END_DEVICE (0x00000001)
|
||||
#define MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_EXPANDER (0x00000002)
|
||||
struct mpi3_smp_passthrough_request {
|
||||
__le16 host_tag;
|
||||
u8 ioc_use_only02;
|
||||
u8 function;
|
||||
__le16 ioc_use_only04;
|
||||
u8 ioc_use_only06;
|
||||
u8 msg_flags;
|
||||
__le16 change_count;
|
||||
u8 reserved0a;
|
||||
u8 io_unit_port;
|
||||
__le32 reserved0c[3];
|
||||
__le64 sas_address;
|
||||
struct mpi3_sge_common request_sge;
|
||||
struct mpi3_sge_common response_sge;
|
||||
};
|
||||
#endif
|
|
@ -40,9 +40,11 @@
|
|||
#include <scsi/scsi_tcq.h>
|
||||
|
||||
#include "mpi/mpi30_transport.h"
|
||||
#include "mpi/mpi30_cnfg.h"
|
||||
#include "mpi/mpi30_image.h"
|
||||
#include "mpi/mpi30_init.h"
|
||||
#include "mpi/mpi30_ioc.h"
|
||||
#include "mpi/mpi30_sas.h"
|
||||
#include "mpi3mr_debug.h"
|
||||
|
||||
/* Global list and lock for storing multiple adapters managed by the driver */
|
||||
|
@ -137,6 +139,10 @@ extern struct list_head mrioc_list;
|
|||
#define MPI3MR_RSP_IO_QUEUED_ON_IOC \
|
||||
MPI3_SCSITASKMGMT_RSPCODE_IO_QUEUED_ON_IOC
|
||||
|
||||
#define MPI3MR_DEFAULT_MDTS (128 * 1024)
|
||||
/* Command retry count definitions */
|
||||
#define MPI3MR_DEV_RMHS_RETRY_COUNT 3
|
||||
|
||||
/* SGE Flag definition */
|
||||
#define MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST \
|
||||
(MPI3_SGE_FLAGS_ELEMENT_TYPE_SIMPLE | MPI3_SGE_FLAGS_DLAS_SYSTEM | \
|
||||
|
@ -316,6 +322,126 @@ struct mpi3mr_intr_info {
|
|||
char name[MPI3MR_NAME_LENGTH];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct tgt_dev_sas_sata - SAS/SATA device specific
|
||||
* information cached from firmware given data
|
||||
*
|
||||
* @sas_address: World wide unique SAS address
|
||||
* @dev_info: Device information bits
|
||||
*/
|
||||
struct tgt_dev_sas_sata {
|
||||
u64 sas_address;
|
||||
u16 dev_info;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct tgt_dev_pcie - PCIe device specific information cached
|
||||
* from firmware given data
|
||||
*
|
||||
* @mdts: Maximum data transfer size
|
||||
* @capb: Device capabilities
|
||||
* @pgsz: Device page size
|
||||
* @abort_to: Timeout for abort TM
|
||||
* @reset_to: Timeout for Target/LUN reset TM
|
||||
*/
|
||||
struct tgt_dev_pcie {
|
||||
u32 mdts;
|
||||
u16 capb;
|
||||
u8 pgsz;
|
||||
u8 abort_to;
|
||||
u8 reset_to;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct tgt_dev_volume - virtual device specific information
|
||||
* cached from firmware given data
|
||||
*
|
||||
* @state: State of the VD
|
||||
*/
|
||||
struct tgt_dev_volume {
|
||||
u8 state;
|
||||
};
|
||||
|
||||
/**
|
||||
* union _form_spec_inf - union of device specific information
|
||||
*/
|
||||
union _form_spec_inf {
|
||||
struct tgt_dev_sas_sata sas_sata_inf;
|
||||
struct tgt_dev_pcie pcie_inf;
|
||||
struct tgt_dev_volume vol_inf;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* struct mpi3mr_tgt_dev - target device data structure
|
||||
*
|
||||
* @list: List pointer
|
||||
* @starget: Scsi_target pointer
|
||||
* @dev_handle: FW device handle
|
||||
* @parent_handle: FW parent device handle
|
||||
* @slot: Slot number
|
||||
* @encl_handle: FW enclosure handle
|
||||
* @perst_id: FW assigned Persistent ID
|
||||
* @dev_type: SAS/SATA/PCIE device type
|
||||
* @is_hidden: Should be exposed to upper layers or not
|
||||
* @host_exposed: Already exposed to host or not
|
||||
* @q_depth: Device specific Queue Depth
|
||||
* @wwid: World wide ID
|
||||
* @dev_spec: Device type specific information
|
||||
* @ref_count: Reference count
|
||||
*/
|
||||
struct mpi3mr_tgt_dev {
|
||||
struct list_head list;
|
||||
struct scsi_target *starget;
|
||||
u16 dev_handle;
|
||||
u16 parent_handle;
|
||||
u16 slot;
|
||||
u16 encl_handle;
|
||||
u16 perst_id;
|
||||
u8 dev_type;
|
||||
u8 is_hidden;
|
||||
u8 host_exposed;
|
||||
u16 q_depth;
|
||||
u64 wwid;
|
||||
union _form_spec_inf dev_spec;
|
||||
struct kref ref_count;
|
||||
};
|
||||
|
||||
/**
|
||||
* mpi3mr_tgtdev_get - k reference incrementor
|
||||
* @s: Target device reference
|
||||
*
|
||||
* Increment target device reference count.
|
||||
*/
|
||||
static inline void mpi3mr_tgtdev_get(struct mpi3mr_tgt_dev *s)
|
||||
{
|
||||
kref_get(&s->ref_count);
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_free_tgtdev - target device memory dealloctor
|
||||
* @r: k reference pointer of the target device
|
||||
*
|
||||
* Free target device memory when no reference.
|
||||
*/
|
||||
static inline void mpi3mr_free_tgtdev(struct kref *r)
|
||||
{
|
||||
kfree(container_of(r, struct mpi3mr_tgt_dev, ref_count));
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_tgtdev_put - k reference decrementor
|
||||
* @s: Target device reference
|
||||
*
|
||||
* Decrement target device reference count.
|
||||
*/
|
||||
static inline void mpi3mr_tgtdev_put(struct mpi3mr_tgt_dev *s)
|
||||
{
|
||||
kref_put(&s->ref_count, mpi3mr_free_tgtdev);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* struct mpi3mr_stgt_priv_data - SCSI target private structure
|
||||
*
|
||||
|
@ -361,6 +487,7 @@ struct mpi3mr_sdev_priv_data {
|
|||
* @done: Completeor for wakeup
|
||||
* @reply: Firmware reply for internal commands
|
||||
* @sensebuf: Sensebuf for SCSI IO commands
|
||||
* @iou_rc: IO Unit control reason code
|
||||
* @state: Command State
|
||||
* @dev_handle: Firmware handle for device specific commands
|
||||
* @ioc_status: IOC status from the firmware
|
||||
|
@ -375,6 +502,7 @@ struct mpi3mr_drv_cmd {
|
|||
struct completion done;
|
||||
void *reply;
|
||||
u8 *sensebuf;
|
||||
u8 iou_rc;
|
||||
u16 state;
|
||||
u16 dev_handle;
|
||||
u16 ioc_status;
|
||||
|
@ -481,6 +609,11 @@ struct scmd_priv {
|
|||
* @sense_buf_q_dma: Sense buffer queue DMA address
|
||||
* @sbq_lock: Sense buffer queue lock
|
||||
* @sbq_host_index: Sense buffer queuehost index
|
||||
* @event_masks: Event mask bitmap
|
||||
* @fwevt_worker_name: Firmware event worker thread name
|
||||
* @fwevt_worker_thread: Firmware event worker thread
|
||||
* @fwevt_lock: Firmware event lock
|
||||
* @fwevt_list: Firmware event list
|
||||
* @watchdog_work_q_name: Fault watchdog worker thread name
|
||||
* @watchdog_work_q: Fault watchdog worker thread
|
||||
* @watchdog_work: Fault watchdog work
|
||||
|
@ -496,6 +629,12 @@ struct scmd_priv {
|
|||
* @chain_bitmap_sz: Chain buffer allocator bitmap size
|
||||
* @chain_bitmap: Chain buffer allocator bitmap
|
||||
* @chain_buf_lock: Chain buffer list lock
|
||||
* @dev_rmhs_cmds: Command tracker for device removal commands
|
||||
* @devrem_bitmap_sz: Device removal bitmap size
|
||||
* @devrem_bitmap: Device removal bitmap
|
||||
* @dev_handle_bitmap_sz: Device handle bitmap size
|
||||
* @removepend_bitmap: Remove pending bitmap
|
||||
* @delayed_rmhs_list: Delayed device removal list
|
||||
* @reset_in_progress: Reset in progress flag
|
||||
* @unrecoverable: Controller unrecoverable flag
|
||||
* @diagsave_timeout: Diagnostic information save timeout
|
||||
|
@ -579,6 +718,12 @@ struct mpi3mr_ioc {
|
|||
dma_addr_t sense_buf_q_dma;
|
||||
spinlock_t sbq_lock;
|
||||
u32 sbq_host_index;
|
||||
u32 event_masks[MPI3_EVENT_NOTIFY_EVENTMASK_WORDS];
|
||||
|
||||
char fwevt_worker_name[MPI3MR_NAME_LENGTH];
|
||||
struct workqueue_struct *fwevt_worker_thread;
|
||||
spinlock_t fwevt_lock;
|
||||
struct list_head fwevt_list;
|
||||
|
||||
char watchdog_work_q_name[20];
|
||||
struct workqueue_struct *watchdog_work_q;
|
||||
|
@ -591,6 +736,8 @@ struct mpi3mr_ioc {
|
|||
u8 stop_drv_processing;
|
||||
|
||||
u16 max_host_ios;
|
||||
spinlock_t tgtdev_lock;
|
||||
struct list_head tgtdev_list;
|
||||
|
||||
u32 chain_buf_count;
|
||||
struct dma_pool *chain_buf_pool;
|
||||
|
@ -599,6 +746,13 @@ struct mpi3mr_ioc {
|
|||
void *chain_bitmap;
|
||||
spinlock_t chain_buf_lock;
|
||||
|
||||
struct mpi3mr_drv_cmd dev_rmhs_cmds[MPI3MR_NUM_DEVRMCMD];
|
||||
u16 devrem_bitmap_sz;
|
||||
void *devrem_bitmap;
|
||||
u16 dev_handle_bitmap_sz;
|
||||
void *removepend_bitmap;
|
||||
struct list_head delayed_rmhs_list;
|
||||
|
||||
u8 reset_in_progress;
|
||||
u8 unrecoverable;
|
||||
|
||||
|
@ -611,6 +765,45 @@ struct mpi3mr_ioc {
|
|||
u16 op_reply_q_offset;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mpi3mr_fwevt - Firmware event structure.
|
||||
*
|
||||
* @list: list head
|
||||
* @work: Work structure
|
||||
* @mrioc: Adapter instance reference
|
||||
* @event_id: MPI3 firmware event ID
|
||||
* @send_ack: Event acknowledgment required or not
|
||||
* @process_evt: Bottomhalf processing required or not
|
||||
* @evt_ctx: Event context to send in Ack
|
||||
* @ref_count: kref count
|
||||
* @event_data: Actual MPI3 event data
|
||||
*/
|
||||
struct mpi3mr_fwevt {
|
||||
struct list_head list;
|
||||
struct work_struct work;
|
||||
struct mpi3mr_ioc *mrioc;
|
||||
u16 event_id;
|
||||
bool send_ack;
|
||||
bool process_evt;
|
||||
u32 evt_ctx;
|
||||
struct kref ref_count;
|
||||
char event_data[0] __aligned(4);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct delayed_dev_rmhs_node - Delayed device removal node
|
||||
*
|
||||
* @list: list head
|
||||
* @handle: Device handle
|
||||
* @iou_rc: IO Unit Control Reason Code
|
||||
*/
|
||||
struct delayed_dev_rmhs_node {
|
||||
struct list_head list;
|
||||
u16 handle;
|
||||
u8 iou_rc;
|
||||
};
|
||||
|
||||
int mpi3mr_setup_resources(struct mpi3mr_ioc *mrioc);
|
||||
void mpi3mr_cleanup_resources(struct mpi3mr_ioc *mrioc);
|
||||
int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc);
|
||||
|
@ -630,6 +823,8 @@ void *mpi3mr_get_reply_virt_addr(struct mpi3mr_ioc *mrioc,
|
|||
void mpi3mr_repost_sense_buf(struct mpi3mr_ioc *mrioc,
|
||||
u64 sense_buf_dma);
|
||||
|
||||
void mpi3mr_os_handle_events(struct mpi3mr_ioc *mrioc,
|
||||
struct mpi3_event_notification_reply *event_reply);
|
||||
void mpi3mr_process_op_reply_desc(struct mpi3mr_ioc *mrioc,
|
||||
struct mpi3_default_reply_descriptor *reply_desc,
|
||||
u64 *reply_dma, u16 qidx);
|
||||
|
@ -642,5 +837,14 @@ void mpi3mr_ioc_disable_intr(struct mpi3mr_ioc *mrioc);
|
|||
void mpi3mr_ioc_enable_intr(struct mpi3mr_ioc *mrioc);
|
||||
|
||||
enum mpi3mr_iocstate mpi3mr_get_iocstate(struct mpi3mr_ioc *mrioc);
|
||||
int mpi3mr_send_event_ack(struct mpi3mr_ioc *mrioc, u8 event,
|
||||
u32 event_ctx);
|
||||
|
||||
void mpi3mr_wait_for_host_io(struct mpi3mr_ioc *mrioc, u32 timeout);
|
||||
void mpi3mr_cleanup_fwevt_list(struct mpi3mr_ioc *mrioc);
|
||||
void mpi3mr_flush_host_io(struct mpi3mr_ioc *mrioc);
|
||||
void mpi3mr_invalidate_devhandles(struct mpi3mr_ioc *mrioc);
|
||||
void mpi3mr_rfresh_tgtdevs(struct mpi3mr_ioc *mrioc);
|
||||
void mpi3mr_flush_delayed_rmhs_list(struct mpi3mr_ioc *mrioc);
|
||||
|
||||
#endif /*MPI3MR_H_INCLUDED*/
|
||||
|
|
|
@ -160,12 +160,15 @@ static void mpi3mr_handle_events(struct mpi3mr_ioc *mrioc,
|
|||
(struct mpi3_event_notification_reply *)def_reply;
|
||||
|
||||
mrioc->change_count = le16_to_cpu(event_reply->ioc_change_count);
|
||||
mpi3mr_os_handle_events(mrioc, event_reply);
|
||||
}
|
||||
|
||||
static struct mpi3mr_drv_cmd *
|
||||
mpi3mr_get_drv_cmd(struct mpi3mr_ioc *mrioc, u16 host_tag,
|
||||
struct mpi3_default_reply *def_reply)
|
||||
{
|
||||
u16 idx;
|
||||
|
||||
switch (host_tag) {
|
||||
case MPI3MR_HOSTTAG_INITCMDS:
|
||||
return &mrioc->init_cmds;
|
||||
|
@ -177,6 +180,11 @@ mpi3mr_get_drv_cmd(struct mpi3mr_ioc *mrioc, u16 host_tag,
|
|||
default:
|
||||
break;
|
||||
}
|
||||
if (host_tag >= MPI3MR_HOSTTAG_DEVRMCMD_MIN &&
|
||||
host_tag <= MPI3MR_HOSTTAG_DEVRMCMD_MAX) {
|
||||
idx = host_tag - MPI3MR_HOSTTAG_DEVRMCMD_MIN;
|
||||
return &mrioc->dev_rmhs_cmds[idx];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1910,6 +1918,13 @@ static int mpi3mr_alloc_reply_sense_bufs(struct mpi3mr_ioc *mrioc)
|
|||
if (!mrioc->init_cmds.reply)
|
||||
goto out_failed;
|
||||
|
||||
for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) {
|
||||
mrioc->dev_rmhs_cmds[i].reply = kzalloc(mrioc->facts.reply_sz,
|
||||
GFP_KERNEL);
|
||||
if (!mrioc->dev_rmhs_cmds[i].reply)
|
||||
goto out_failed;
|
||||
}
|
||||
|
||||
mrioc->num_reply_bufs = mrioc->facts.max_reqs + MPI3MR_NUM_EVT_REPLIES;
|
||||
mrioc->reply_free_qsz = mrioc->num_reply_bufs + 1;
|
||||
mrioc->num_sense_bufs = mrioc->facts.max_reqs / MPI3MR_SENSEBUF_FACTOR;
|
||||
|
@ -2119,6 +2134,163 @@ out:
|
|||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_unmask_events - Unmask events in event mask bitmap
|
||||
* @mrioc: Adapter instance reference
|
||||
* @event: MPI event ID
|
||||
*
|
||||
* Un mask the specific event by resetting the event_mask
|
||||
* bitmap.
|
||||
*
|
||||
* Return: 0 on success, non-zero on failures.
|
||||
*/
|
||||
static void mpi3mr_unmask_events(struct mpi3mr_ioc *mrioc, u16 event)
|
||||
{
|
||||
u32 desired_event;
|
||||
u8 word;
|
||||
|
||||
if (event >= 128)
|
||||
return;
|
||||
|
||||
desired_event = (1 << (event % 32));
|
||||
word = event / 32;
|
||||
|
||||
mrioc->event_masks[word] &= ~desired_event;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_issue_event_notification - Send event notification
|
||||
* @mrioc: Adapter instance reference
|
||||
*
|
||||
* Issue event notification MPI request through admin queue and
|
||||
* wait for the completion of it or time out.
|
||||
*
|
||||
* Return: 0 on success, non-zero on failures.
|
||||
*/
|
||||
static int mpi3mr_issue_event_notification(struct mpi3mr_ioc *mrioc)
|
||||
{
|
||||
struct mpi3_event_notification_request evtnotify_req;
|
||||
int retval = 0;
|
||||
u8 i;
|
||||
|
||||
memset(&evtnotify_req, 0, sizeof(evtnotify_req));
|
||||
mutex_lock(&mrioc->init_cmds.mutex);
|
||||
if (mrioc->init_cmds.state & MPI3MR_CMD_PENDING) {
|
||||
retval = -1;
|
||||
ioc_err(mrioc, "Issue EvtNotify: Init command is in use\n");
|
||||
mutex_unlock(&mrioc->init_cmds.mutex);
|
||||
goto out;
|
||||
}
|
||||
mrioc->init_cmds.state = MPI3MR_CMD_PENDING;
|
||||
mrioc->init_cmds.is_waiting = 1;
|
||||
mrioc->init_cmds.callback = NULL;
|
||||
evtnotify_req.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_INITCMDS);
|
||||
evtnotify_req.function = MPI3_FUNCTION_EVENT_NOTIFICATION;
|
||||
for (i = 0; i < MPI3_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
|
||||
evtnotify_req.event_masks[i] =
|
||||
cpu_to_le32(mrioc->event_masks[i]);
|
||||
init_completion(&mrioc->init_cmds.done);
|
||||
retval = mpi3mr_admin_request_post(mrioc, &evtnotify_req,
|
||||
sizeof(evtnotify_req), 1);
|
||||
if (retval) {
|
||||
ioc_err(mrioc, "Issue EvtNotify: Admin Post failed\n");
|
||||
goto out_unlock;
|
||||
}
|
||||
wait_for_completion_timeout(&mrioc->init_cmds.done,
|
||||
(MPI3MR_INTADMCMD_TIMEOUT * HZ));
|
||||
if (!(mrioc->init_cmds.state & MPI3MR_CMD_COMPLETE)) {
|
||||
ioc_err(mrioc, "Issue EvtNotify: command timed out\n");
|
||||
mpi3mr_set_diagsave(mrioc);
|
||||
mpi3mr_issue_reset(mrioc,
|
||||
MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT,
|
||||
MPI3MR_RESET_FROM_EVTNOTIFY_TIMEOUT);
|
||||
mrioc->unrecoverable = 1;
|
||||
retval = -1;
|
||||
goto out_unlock;
|
||||
}
|
||||
if ((mrioc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK)
|
||||
!= MPI3_IOCSTATUS_SUCCESS) {
|
||||
ioc_err(mrioc,
|
||||
"Issue EvtNotify: Failed ioc_status(0x%04x) Loginfo(0x%08x)\n",
|
||||
(mrioc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK),
|
||||
mrioc->init_cmds.ioc_loginfo);
|
||||
retval = -1;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
mrioc->init_cmds.state = MPI3MR_CMD_NOTUSED;
|
||||
mutex_unlock(&mrioc->init_cmds.mutex);
|
||||
out:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_send_event_ack - Send event acknowledgment
|
||||
* @mrioc: Adapter instance reference
|
||||
* @event: MPI3 event ID
|
||||
* @event_ctx: Event context
|
||||
*
|
||||
* Send event acknowledgment through admin queue and wait for
|
||||
* it to complete.
|
||||
*
|
||||
* Return: 0 on success, non-zero on failures.
|
||||
*/
|
||||
int mpi3mr_send_event_ack(struct mpi3mr_ioc *mrioc, u8 event,
|
||||
u32 event_ctx)
|
||||
{
|
||||
struct mpi3_event_ack_request evtack_req;
|
||||
int retval = 0;
|
||||
|
||||
memset(&evtack_req, 0, sizeof(evtack_req));
|
||||
mutex_lock(&mrioc->init_cmds.mutex);
|
||||
if (mrioc->init_cmds.state & MPI3MR_CMD_PENDING) {
|
||||
retval = -1;
|
||||
ioc_err(mrioc, "Send EvtAck: Init command is in use\n");
|
||||
mutex_unlock(&mrioc->init_cmds.mutex);
|
||||
goto out;
|
||||
}
|
||||
mrioc->init_cmds.state = MPI3MR_CMD_PENDING;
|
||||
mrioc->init_cmds.is_waiting = 1;
|
||||
mrioc->init_cmds.callback = NULL;
|
||||
evtack_req.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_INITCMDS);
|
||||
evtack_req.function = MPI3_FUNCTION_EVENT_ACK;
|
||||
evtack_req.event = event;
|
||||
evtack_req.event_context = cpu_to_le32(event_ctx);
|
||||
|
||||
init_completion(&mrioc->init_cmds.done);
|
||||
retval = mpi3mr_admin_request_post(mrioc, &evtack_req,
|
||||
sizeof(evtack_req), 1);
|
||||
if (retval) {
|
||||
ioc_err(mrioc, "Send EvtAck: Admin Post failed\n");
|
||||
goto out_unlock;
|
||||
}
|
||||
wait_for_completion_timeout(&mrioc->init_cmds.done,
|
||||
(MPI3MR_INTADMCMD_TIMEOUT * HZ));
|
||||
if (!(mrioc->init_cmds.state & MPI3MR_CMD_COMPLETE)) {
|
||||
ioc_err(mrioc, "Issue EvtNotify: command timed out\n");
|
||||
mpi3mr_soft_reset_handler(mrioc,
|
||||
MPI3MR_RESET_FROM_EVTACK_TIMEOUT, 1);
|
||||
retval = -1;
|
||||
goto out_unlock;
|
||||
}
|
||||
if ((mrioc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK)
|
||||
!= MPI3_IOCSTATUS_SUCCESS) {
|
||||
ioc_err(mrioc,
|
||||
"Send EvtAck: Failed ioc_status(0x%04x) Loginfo(0x%08x)\n",
|
||||
(mrioc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK),
|
||||
mrioc->init_cmds.ioc_loginfo);
|
||||
retval = -1;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
mrioc->init_cmds.state = MPI3MR_CMD_NOTUSED;
|
||||
mutex_unlock(&mrioc->init_cmds.mutex);
|
||||
out:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_alloc_chain_bufs - Allocate chain buffers
|
||||
* @mrioc: Adapter instance reference
|
||||
|
@ -2396,7 +2568,7 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc)
|
|||
enum mpi3mr_iocstate ioc_state;
|
||||
u64 base_info;
|
||||
u32 timeout;
|
||||
u32 ioc_status, ioc_config;
|
||||
u32 ioc_status, ioc_config, i;
|
||||
struct mpi3_ioc_facts_data facts_data;
|
||||
|
||||
mrioc->change_count = 0;
|
||||
|
@ -2546,6 +2718,24 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc)
|
|||
goto out_failed;
|
||||
}
|
||||
|
||||
for (i = 0; i < MPI3_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
|
||||
mrioc->event_masks[i] = -1;
|
||||
|
||||
mpi3mr_unmask_events(mrioc, MPI3_EVENT_DEVICE_ADDED);
|
||||
mpi3mr_unmask_events(mrioc, MPI3_EVENT_DEVICE_INFO_CHANGED);
|
||||
mpi3mr_unmask_events(mrioc, MPI3_EVENT_DEVICE_STATUS_CHANGE);
|
||||
mpi3mr_unmask_events(mrioc, MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE);
|
||||
mpi3mr_unmask_events(mrioc, MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST);
|
||||
mpi3mr_unmask_events(mrioc, MPI3_EVENT_SAS_DISCOVERY);
|
||||
mpi3mr_unmask_events(mrioc, MPI3_EVENT_SAS_DEVICE_DISCOVERY_ERROR);
|
||||
|
||||
retval = mpi3mr_issue_event_notification(mrioc);
|
||||
if (retval) {
|
||||
ioc_err(mrioc, "Failed to issue event notification %d\n",
|
||||
retval);
|
||||
goto out_failed;
|
||||
}
|
||||
|
||||
return retval;
|
||||
|
||||
out_failed:
|
||||
|
@ -2627,6 +2817,11 @@ static void mpi3mr_free_mem(struct mpi3mr_ioc *mrioc)
|
|||
kfree(mrioc->chain_bitmap);
|
||||
mrioc->chain_bitmap = NULL;
|
||||
|
||||
for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) {
|
||||
kfree(mrioc->dev_rmhs_cmds[i].reply);
|
||||
mrioc->dev_rmhs_cmds[i].reply = NULL;
|
||||
}
|
||||
|
||||
if (mrioc->chain_buf_pool) {
|
||||
for (i = 0; i < mrioc->chain_buf_count; i++) {
|
||||
if (mrioc->chain_sgl_list[i].addr) {
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Загрузка…
Ссылка в новой задаче