aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.h4
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c133
2 files changed, 136 insertions, 1 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h
index 7efb6ab749df..eb51fe9f369d 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
@@ -492,12 +492,14 @@ typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr);
492 * @msix_table_backup: backup msix table 492 * @msix_table_backup: backup msix table
493 * @scsi_io_cb_idx: shost generated commands 493 * @scsi_io_cb_idx: shost generated commands
494 * @tm_cb_idx: task management commands 494 * @tm_cb_idx: task management commands
495 * @scsih_cb_idx: scsih internal commands
495 * @transport_cb_idx: transport internal commands 496 * @transport_cb_idx: transport internal commands
496 * @ctl_cb_idx: clt internal commands 497 * @ctl_cb_idx: clt internal commands
497 * @base_cb_idx: base internal commands 498 * @base_cb_idx: base internal commands
498 * @config_cb_idx: base internal commands 499 * @config_cb_idx: base internal commands
499 * @base_cmds: 500 * @base_cmds:
500 * @transport_cmds: 501 * @transport_cmds:
502 * @scsih_cmds:
501 * @tm_cmds: 503 * @tm_cmds:
502 * @ctl_cmds: 504 * @ctl_cmds:
503 * @config_cmds: 505 * @config_cmds:
@@ -624,6 +626,7 @@ struct MPT2SAS_ADAPTER {
624 u8 scsi_io_cb_idx; 626 u8 scsi_io_cb_idx;
625 u8 tm_cb_idx; 627 u8 tm_cb_idx;
626 u8 transport_cb_idx; 628 u8 transport_cb_idx;
629 u8 scsih_cb_idx;
627 u8 ctl_cb_idx; 630 u8 ctl_cb_idx;
628 u8 base_cb_idx; 631 u8 base_cb_idx;
629 u8 config_cb_idx; 632 u8 config_cb_idx;
@@ -631,6 +634,7 @@ struct MPT2SAS_ADAPTER {
631 u8 tm_sas_control_cb_idx; 634 u8 tm_sas_control_cb_idx;
632 struct _internal_cmd base_cmds; 635 struct _internal_cmd base_cmds;
633 struct _internal_cmd transport_cmds; 636 struct _internal_cmd transport_cmds;
637 struct _internal_cmd scsih_cmds;
634 struct _internal_cmd tm_cmds; 638 struct _internal_cmd tm_cmds;
635 struct _internal_cmd ctl_cmds; 639 struct _internal_cmd ctl_cmds;
636 struct _internal_cmd config_cmds; 640 struct _internal_cmd config_cmds;
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