aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/mpt2sas/mpt2sas_scsih.c
diff options
context:
space:
mode:
authorKashyap, Desai <kashyap.desai@lsi.com>2009-10-05 06:26:56 -0400
committerJames Bottomley <James.Bottomley@suse.de>2009-10-29 13:03:16 -0400
commit744090d38b47ed8ead8f68b6f0c65866c0b9b17a (patch)
tree2154fc14b1da12517f280c6e9ca5b4d3f1662c10 /drivers/scsi/mpt2sas/mpt2sas_scsih.c
parent8ffc457ed6fe33728657a0cfb7509b90d554c21f (diff)
[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: Kashyap Desai <kashyap.desai@lsi.com> Signed-off-by: Eric Moore <Eric.moore@lsi.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/mpt2sas/mpt2sas_scsih.c')
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c133
1 files changed, 132 insertions, 1 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index c81e84291d2e..5916bddf3551 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -76,6 +76,7 @@ static u8 tm_cb_idx = -1;
76static u8 ctl_cb_idx = -1; 76static u8 ctl_cb_idx = -1;
77static u8 base_cb_idx = -1; 77static u8 base_cb_idx = -1;
78static u8 transport_cb_idx = -1; 78static u8 transport_cb_idx = -1;
79static u8 scsih_cb_idx = -1;
79static u8 config_cb_idx = -1; 80static u8 config_cb_idx = -1;
80static int mpt_ids; 81static int mpt_ids;
81 82
@@ -3794,6 +3795,40 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle)
3794} 3795}
3795 3796
3796/** 3797/**
3798 * _scsih_done - scsih callback handler.
3799 * @ioc: per adapter object
3800 * @smid: system request message index
3801 * @msix_index: MSIX table index supplied by the OS
3802 * @reply: reply message frame(lower 32bit addr)
3803 *
3804 * Callback handler when sending internal generated message frames.
3805 * The callback index passed is `ioc->scsih_cb_idx`
3806 *
3807 * Return 1 meaning mf should be freed from _base_interrupt
3808 * 0 means the mf is freed from this function.
3809 */
3810static u8
3811_scsih_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
3812{
3813 MPI2DefaultReply_t *mpi_reply;
3814
3815 mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
3816 if (ioc->scsih_cmds.status == MPT2_CMD_NOT_USED)
3817 return 1;
3818 if (ioc->scsih_cmds.smid != smid)
3819 return 1;
3820 ioc->scsih_cmds.status |= MPT2_CMD_COMPLETE;
3821 if (mpi_reply) {
3822 memcpy(ioc->scsih_cmds.reply, mpi_reply,
3823 mpi_reply->MsgLength*4);
3824 ioc->scsih_cmds.status |= MPT2_CMD_REPLY_VALID;
3825 }
3826 ioc->scsih_cmds.status &= ~MPT2_CMD_PENDING;
3827 complete(&ioc->scsih_cmds.done);
3828 return 1;
3829}
3830
3831/**
3797 * _scsih_expander_remove - removing expander object 3832 * _scsih_expander_remove - removing expander object
3798 * @ioc: per adapter object 3833 * @ioc: per adapter object
3799 * @sas_address: expander sas_address 3834 * @sas_address: expander sas_address
@@ -5854,9 +5889,99 @@ _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc,
5854} 5889}
5855 5890
5856/** 5891/**
5892 * _scsih_ir_shutdown - IR shutdown notification
5893 * @ioc: per adapter object
5894 *
5895 * Sending RAID Action to alert the Integrated RAID subsystem of the IOC that
5896 * the host system is shutting down.
5897 *
5898 * Return nothing.
5899 */
5900static void
5901_scsih_ir_shutdown(struct MPT2SAS_ADAPTER *ioc)
5902{
5903 Mpi2RaidActionRequest_t *mpi_request;
5904 Mpi2RaidActionReply_t *mpi_reply;
5905 u16 smid;
5906
5907 /* is IR firmware build loaded ? */
5908 if (!ioc->ir_firmware)
5909 return;
5910
5911 /* are there any volumes ? */
5912 if (list_empty(&ioc->raid_device_list))
5913 return;
5914
5915 mutex_lock(&ioc->scsih_cmds.mutex);
5916
5917 if (ioc->scsih_cmds.status != MPT2_CMD_NOT_USED) {
5918 printk(MPT2SAS_ERR_FMT "%s: scsih_cmd in use\n",
5919 ioc->name, __func__);
5920 goto out;
5921 }
5922 ioc->scsih_cmds.status = MPT2_CMD_PENDING;
5923
5924 smid = mpt2sas_base_get_smid(ioc, ioc->scsih_cb_idx);
5925 if (!smid) {
5926 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
5927 ioc->name, __func__);
5928 ioc->scsih_cmds.status = MPT2_CMD_NOT_USED;
5929 goto out;
5930 }
5931
5932 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
5933 ioc->scsih_cmds.smid = smid;
5934 memset(mpi_request, 0, sizeof(Mpi2RaidActionRequest_t));
5935
5936 mpi_request->Function = MPI2_FUNCTION_RAID_ACTION;
5937 mpi_request->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED;
5938
5939 printk(MPT2SAS_INFO_FMT "IR shutdown (sending)\n", ioc->name);
5940 init_completion(&ioc->scsih_cmds.done);
5941 mpt2sas_base_put_smid_default(ioc, smid);
5942 wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ);
5943
5944 if (!(ioc->scsih_cmds.status & MPT2_CMD_COMPLETE)) {
5945 printk(MPT2SAS_ERR_FMT "%s: timeout\n",
5946 ioc->name, __func__);
5947 goto out;
5948 }
5949
5950 if (ioc->scsih_cmds.status & MPT2_CMD_REPLY_VALID) {
5951 mpi_reply = ioc->scsih_cmds.reply;
5952
5953 printk(MPT2SAS_INFO_FMT "IR shutdown (complete): "
5954 "ioc_status(0x%04x), loginfo(0x%08x)\n",
5955 ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
5956 le32_to_cpu(mpi_reply->IOCLogInfo));
5957 }
5958
5959 out:
5960 ioc->scsih_cmds.status = MPT2_CMD_NOT_USED;
5961 mutex_unlock(&ioc->scsih_cmds.mutex);
5962}
5963
5964/**
5965 * _scsih_shutdown - routine call during system shutdown
5966 * @pdev: PCI device struct
5967 *
5968 * Return nothing.
5969 */
5970static void
5971_scsih_shutdown(struct pci_dev *pdev)
5972{
5973 struct Scsi_Host *shost = pci_get_drvdata(pdev);
5974 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
5975
5976 _scsih_ir_shutdown(ioc);
5977 mpt2sas_base_detach(ioc);
5978}
5979
5980/**
5857 * _scsih_remove - detach and remove add host 5981 * _scsih_remove - detach and remove add host
5858 * @pdev: PCI device struct 5982 * @pdev: PCI device struct
5859 * 5983 *
5984 * Routine called when unloading the driver.
5860 * Return nothing. 5985 * Return nothing.
5861 */ 5986 */
5862static void __devexit 5987static void __devexit
@@ -5913,7 +6038,7 @@ _scsih_remove(struct pci_dev *pdev)
5913 } 6038 }
5914 6039
5915 sas_remove_host(shost); 6040 sas_remove_host(shost);
5916 mpt2sas_base_detach(ioc); 6041 _scsih_shutdown(pdev);
5917 list_del(&ioc->list); 6042 list_del(&ioc->list);
5918 scsi_remove_host(shost); 6043 scsi_remove_host(shost);
5919 scsi_host_put(shost); 6044 scsi_host_put(shost);
@@ -6097,6 +6222,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
6097 ioc->ctl_cb_idx = ctl_cb_idx; 6222 ioc->ctl_cb_idx = ctl_cb_idx;
6098 ioc->base_cb_idx = base_cb_idx; 6223 ioc->base_cb_idx = base_cb_idx;
6099 ioc->transport_cb_idx = transport_cb_idx; 6224 ioc->transport_cb_idx = transport_cb_idx;
6225 ioc->scsih_cb_idx = scsih_cb_idx;
6100 ioc->config_cb_idx = config_cb_idx; 6226 ioc->config_cb_idx = config_cb_idx;
6101 ioc->tm_tr_cb_idx = tm_tr_cb_idx; 6227 ioc->tm_tr_cb_idx = tm_tr_cb_idx;
6102 ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx; 6228 ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx;
@@ -6234,6 +6360,7 @@ static struct pci_driver scsih_driver = {
6234 .id_table = scsih_pci_table, 6360 .id_table = scsih_pci_table,
6235 .probe = _scsih_probe, 6361 .probe = _scsih_probe,
6236 .remove = __devexit_p(_scsih_remove), 6362 .remove = __devexit_p(_scsih_remove),
6363 .shutdown = _scsih_shutdown,
6237#ifdef CONFIG_PM 6364#ifdef CONFIG_PM
6238 .suspend = _scsih_suspend, 6365 .suspend = _scsih_suspend,
6239 .resume = _scsih_resume, 6366 .resume = _scsih_resume,
@@ -6275,6 +6402,9 @@ _scsih_init(void)
6275 transport_cb_idx = mpt2sas_base_register_callback_handler( 6402 transport_cb_idx = mpt2sas_base_register_callback_handler(
6276 mpt2sas_transport_done); 6403 mpt2sas_transport_done);
6277 6404
6405 /* scsih internal commands callback handler */
6406 scsih_cb_idx = mpt2sas_base_register_callback_handler(_scsih_done);
6407
6278 /* configuration page API internal commands callback handler */ 6408 /* configuration page API internal commands callback handler */
6279 config_cb_idx = mpt2sas_base_register_callback_handler( 6409 config_cb_idx = mpt2sas_base_register_callback_handler(
6280 mpt2sas_config_done); 6410 mpt2sas_config_done);
@@ -6314,6 +6444,7 @@ _scsih_exit(void)
6314 mpt2sas_base_release_callback_handler(tm_cb_idx); 6444 mpt2sas_base_release_callback_handler(tm_cb_idx);
6315 mpt2sas_base_release_callback_handler(base_cb_idx); 6445 mpt2sas_base_release_callback_handler(base_cb_idx);
6316 mpt2sas_base_release_callback_handler(transport_cb_idx); 6446 mpt2sas_base_release_callback_handler(transport_cb_idx);
6447 mpt2sas_base_release_callback_handler(scsih_cb_idx);
6317 mpt2sas_base_release_callback_handler(config_cb_idx); 6448 mpt2sas_base_release_callback_handler(config_cb_idx);
6318 mpt2sas_base_release_callback_handler(ctl_cb_idx); 6449 mpt2sas_base_release_callback_handler(ctl_cb_idx);
6319 6450