diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_base.h | 4 | ||||
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_scsih.c | 133 |
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; | |||
76 | static u8 ctl_cb_idx = -1; | 76 | static u8 ctl_cb_idx = -1; |
77 | static u8 base_cb_idx = -1; | 77 | static u8 base_cb_idx = -1; |
78 | static u8 transport_cb_idx = -1; | 78 | static u8 transport_cb_idx = -1; |
79 | static u8 scsih_cb_idx = -1; | ||
79 | static u8 config_cb_idx = -1; | 80 | static u8 config_cb_idx = -1; |
80 | static int mpt_ids; | 81 | static 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 | */ | ||
3810 | static 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 | */ | ||
5900 | static 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 | */ | ||
5970 | static 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 | */ |
5862 | static void __devexit | 5987 | static 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 | ||