Commit 744090d3 authored by Kashyap, Desai's avatar Kashyap, Desai Committed by James Bottomley

[SCSI] mpt2sas : Add support for RAID Action System Shutdown Initiated at OS shutdown

(1) Added new function _scsih_ir_shutdown.  This function will issue the
MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED request via
MPI2_FUNCTION_RAID_ACTION. The function will wait 10 seconds for reply
message frame, then print out the ioc status and loginfo.  This function is
only called when there are raid volumes present.

(2) Add shutdown callback in the struct pci_driver object scsih_driver. This
will be called only when the system is shutting down. From this function, we
will call _scsih_ir_shutdown mentioned above.

(3) Add support in _scsih_remove to call _scsih_ir_shutdown. The function
_scsih_remove will be called when the driver is unloaded (and system is
still running).

scsih internal command contex is added to send internal message frames
from mpt2sas_scsih.c.
Signed-off-by: default avatarKashyap Desai <kashyap.desai@lsi.com>
Signed-off-by: default avatarEric Moore <Eric.moore@lsi.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 8ffc457e
......@@ -492,12 +492,14 @@ typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr);
* @msix_table_backup: backup msix table
* @scsi_io_cb_idx: shost generated commands
* @tm_cb_idx: task management commands
* @scsih_cb_idx: scsih internal commands
* @transport_cb_idx: transport internal commands
* @ctl_cb_idx: clt internal commands
* @base_cb_idx: base internal commands
* @config_cb_idx: base internal commands
* @base_cmds:
* @transport_cmds:
* @scsih_cmds:
* @tm_cmds:
* @ctl_cmds:
* @config_cmds:
......@@ -624,6 +626,7 @@ struct MPT2SAS_ADAPTER {
u8 scsi_io_cb_idx;
u8 tm_cb_idx;
u8 transport_cb_idx;
u8 scsih_cb_idx;
u8 ctl_cb_idx;
u8 base_cb_idx;
u8 config_cb_idx;
......@@ -631,6 +634,7 @@ struct MPT2SAS_ADAPTER {
u8 tm_sas_control_cb_idx;
struct _internal_cmd base_cmds;
struct _internal_cmd transport_cmds;
struct _internal_cmd scsih_cmds;
struct _internal_cmd tm_cmds;
struct _internal_cmd ctl_cmds;
struct _internal_cmd config_cmds;
......
......@@ -76,6 +76,7 @@ static u8 tm_cb_idx = -1;
static u8 ctl_cb_idx = -1;
static u8 base_cb_idx = -1;
static u8 transport_cb_idx = -1;
static u8 scsih_cb_idx = -1;
static u8 config_cb_idx = -1;
static int mpt_ids;
......@@ -3793,6 +3794,40 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle)
return rc;
}
/**
* _scsih_done - scsih callback handler.
* @ioc: per adapter object
* @smid: system request message index
* @msix_index: MSIX table index supplied by the OS
* @reply: reply message frame(lower 32bit addr)
*
* Callback handler when sending internal generated message frames.
* The callback index passed is `ioc->scsih_cb_idx`
*
* Return 1 meaning mf should be freed from _base_interrupt
* 0 means the mf is freed from this function.
*/
static u8
_scsih_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
{
MPI2DefaultReply_t *mpi_reply;
mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
if (ioc->scsih_cmds.status == MPT2_CMD_NOT_USED)
return 1;
if (ioc->scsih_cmds.smid != smid)
return 1;
ioc->scsih_cmds.status |= MPT2_CMD_COMPLETE;
if (mpi_reply) {
memcpy(ioc->scsih_cmds.reply, mpi_reply,
mpi_reply->MsgLength*4);
ioc->scsih_cmds.status |= MPT2_CMD_REPLY_VALID;
}
ioc->scsih_cmds.status &= ~MPT2_CMD_PENDING;
complete(&ioc->scsih_cmds.done);
return 1;
}
/**
* _scsih_expander_remove - removing expander object
* @ioc: per adapter object
......@@ -5853,10 +5888,100 @@ _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc,
kfree(sas_expander);
}
/**
* _scsih_ir_shutdown - IR shutdown notification
* @ioc: per adapter object
*
* Sending RAID Action to alert the Integrated RAID subsystem of the IOC that
* the host system is shutting down.
*
* Return nothing.
*/
static void
_scsih_ir_shutdown(struct MPT2SAS_ADAPTER *ioc)
{
Mpi2RaidActionRequest_t *mpi_request;
Mpi2RaidActionReply_t *mpi_reply;
u16 smid;
/* is IR firmware build loaded ? */
if (!ioc->ir_firmware)
return;
/* are there any volumes ? */
if (list_empty(&ioc->raid_device_list))
return;
mutex_lock(&ioc->scsih_cmds.mutex);
if (ioc->scsih_cmds.status != MPT2_CMD_NOT_USED) {
printk(MPT2SAS_ERR_FMT "%s: scsih_cmd in use\n",
ioc->name, __func__);
goto out;
}
ioc->scsih_cmds.status = MPT2_CMD_PENDING;
smid = mpt2sas_base_get_smid(ioc, ioc->scsih_cb_idx);
if (!smid) {
printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
ioc->name, __func__);
ioc->scsih_cmds.status = MPT2_CMD_NOT_USED;
goto out;
}
mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
ioc->scsih_cmds.smid = smid;
memset(mpi_request, 0, sizeof(Mpi2RaidActionRequest_t));
mpi_request->Function = MPI2_FUNCTION_RAID_ACTION;
mpi_request->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED;
printk(MPT2SAS_INFO_FMT "IR shutdown (sending)\n", ioc->name);
init_completion(&ioc->scsih_cmds.done);
mpt2sas_base_put_smid_default(ioc, smid);
wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ);
if (!(ioc->scsih_cmds.status & MPT2_CMD_COMPLETE)) {
printk(MPT2SAS_ERR_FMT "%s: timeout\n",
ioc->name, __func__);
goto out;
}
if (ioc->scsih_cmds.status & MPT2_CMD_REPLY_VALID) {
mpi_reply = ioc->scsih_cmds.reply;
printk(MPT2SAS_INFO_FMT "IR shutdown (complete): "
"ioc_status(0x%04x), loginfo(0x%08x)\n",
ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
le32_to_cpu(mpi_reply->IOCLogInfo));
}
out:
ioc->scsih_cmds.status = MPT2_CMD_NOT_USED;
mutex_unlock(&ioc->scsih_cmds.mutex);
}
/**
* _scsih_shutdown - routine call during system shutdown
* @pdev: PCI device struct
*
* Return nothing.
*/
static void
_scsih_shutdown(struct pci_dev *pdev)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
_scsih_ir_shutdown(ioc);
mpt2sas_base_detach(ioc);
}
/**
* _scsih_remove - detach and remove add host
* @pdev: PCI device struct
*
* Routine called when unloading the driver.
* Return nothing.
*/
static void __devexit
......@@ -5913,7 +6038,7 @@ _scsih_remove(struct pci_dev *pdev)
}
sas_remove_host(shost);
mpt2sas_base_detach(ioc);
_scsih_shutdown(pdev);
list_del(&ioc->list);
scsi_remove_host(shost);
scsi_host_put(shost);
......@@ -6097,6 +6222,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->ctl_cb_idx = ctl_cb_idx;
ioc->base_cb_idx = base_cb_idx;
ioc->transport_cb_idx = transport_cb_idx;
ioc->scsih_cb_idx = scsih_cb_idx;
ioc->config_cb_idx = config_cb_idx;
ioc->tm_tr_cb_idx = tm_tr_cb_idx;
ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx;
......@@ -6234,6 +6360,7 @@ static struct pci_driver scsih_driver = {
.id_table = scsih_pci_table,
.probe = _scsih_probe,
.remove = __devexit_p(_scsih_remove),
.shutdown = _scsih_shutdown,
#ifdef CONFIG_PM
.suspend = _scsih_suspend,
.resume = _scsih_resume,
......@@ -6275,6 +6402,9 @@ _scsih_init(void)
transport_cb_idx = mpt2sas_base_register_callback_handler(
mpt2sas_transport_done);
/* scsih internal commands callback handler */
scsih_cb_idx = mpt2sas_base_register_callback_handler(_scsih_done);
/* configuration page API internal commands callback handler */
config_cb_idx = mpt2sas_base_register_callback_handler(
mpt2sas_config_done);
......@@ -6314,6 +6444,7 @@ _scsih_exit(void)
mpt2sas_base_release_callback_handler(tm_cb_idx);
mpt2sas_base_release_callback_handler(base_cb_idx);
mpt2sas_base_release_callback_handler(transport_cb_idx);
mpt2sas_base_release_callback_handler(scsih_cb_idx);
mpt2sas_base_release_callback_handler(config_cb_idx);
mpt2sas_base_release_callback_handler(ctl_cb_idx);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment