Skip to content

Commit

Permalink
[SCSI] mpt2sas : Add support for RAID Action System Shutdown Initiate…
Browse files Browse the repository at this point in the history
…d 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: Kashyap Desai <kashyap.desai@lsi.com>
Signed-off-by: Eric Moore <Eric.moore@lsi.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
  • Loading branch information
Kashyap, Desai authored and James Bottomley committed Oct 29, 2009
1 parent 8ffc457 commit 744090d
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 1 deletion.
4 changes: 4 additions & 0 deletions drivers/scsi/mpt2sas/mpt2sas_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -624,13 +626,15 @@ 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;
u8 tm_tr_cb_idx;
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;
Expand Down
133 changes: 132 additions & 1 deletion drivers/scsi/mpt2sas/mpt2sas_scsih.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);

Expand Down

0 comments on commit 744090d

Please sign in to comment.