diff options
author | Kashyap, Desai <kashyap.desai@lsi.com> | 2009-09-14 01:34:23 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2009-10-02 10:48:38 -0400 |
commit | 77e63ed44305e89c0564f8292f9cd5764d4fddfb (patch) | |
tree | 66aab9af95be1daadf6e648b008f9c1d77cf1ac0 | |
parent | 595bb0bd62edb28a965993d90e0fa1285560ce53 (diff) |
[SCSI] mpt2sas: Target Reset will be issued from Interrupt context.
(1) Added three new functions to handle sending target resest and OP_REMOVE
from interrupt time, they are _scsih_tm_tr_send, _scsih_tm_tr_complete, and
_scsih_sas_control_complete. This code will create a link list of pending
target resets if there is no more available request in the hipriority
request queue. The list is stored in ioc->delayed_tr_list.
(2) All callback handler return type is changed from void to u8.
Now _base_interrupt will check for return type of callback handlers to
take decision of message frame is already freed or not.
In genral,
Return 1 meaning mf should be freed from _base_interrupt
0 means the mf is freed from function.
Signed-off-by: Kashyap Desai <kashyap.desai@lsi.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_base.c | 35 | ||||
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_base.h | 41 | ||||
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_config.c | 10 | ||||
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_ctl.c | 16 | ||||
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_scsih.c | 314 | ||||
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_transport.c | 10 |
6 files changed, 372 insertions, 54 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 4c583ff458db..a9c71769b4ec 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c | |||
@@ -575,9 +575,10 @@ _base_display_reply_info(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | |||
575 | * @msix_index: MSIX table index supplied by the OS | 575 | * @msix_index: MSIX table index supplied by the OS |
576 | * @reply: reply message frame(lower 32bit addr) | 576 | * @reply: reply message frame(lower 32bit addr) |
577 | * | 577 | * |
578 | * Return nothing. | 578 | * Return 1 meaning mf should be freed from _base_interrupt |
579 | * 0 means the mf is freed from this function. | ||
579 | */ | 580 | */ |
580 | void | 581 | u8 |
581 | mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | 582 | mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, |
582 | u32 reply) | 583 | u32 reply) |
583 | { | 584 | { |
@@ -585,10 +586,10 @@ mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | |||
585 | 586 | ||
586 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | 587 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); |
587 | if (mpi_reply && mpi_reply->Function == MPI2_FUNCTION_EVENT_ACK) | 588 | if (mpi_reply && mpi_reply->Function == MPI2_FUNCTION_EVENT_ACK) |
588 | return; | 589 | return 1; |
589 | 590 | ||
590 | if (ioc->base_cmds.status == MPT2_CMD_NOT_USED) | 591 | if (ioc->base_cmds.status == MPT2_CMD_NOT_USED) |
591 | return; | 592 | return 1; |
592 | 593 | ||
593 | ioc->base_cmds.status |= MPT2_CMD_COMPLETE; | 594 | ioc->base_cmds.status |= MPT2_CMD_COMPLETE; |
594 | if (mpi_reply) { | 595 | if (mpi_reply) { |
@@ -597,6 +598,7 @@ mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | |||
597 | } | 598 | } |
598 | ioc->base_cmds.status &= ~MPT2_CMD_PENDING; | 599 | ioc->base_cmds.status &= ~MPT2_CMD_PENDING; |
599 | complete(&ioc->base_cmds.done); | 600 | complete(&ioc->base_cmds.done); |
601 | return 1; | ||
600 | } | 602 | } |
601 | 603 | ||
602 | /** | 604 | /** |
@@ -605,9 +607,10 @@ mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | |||
605 | * @msix_index: MSIX table index supplied by the OS | 607 | * @msix_index: MSIX table index supplied by the OS |
606 | * @reply: reply message frame(lower 32bit addr) | 608 | * @reply: reply message frame(lower 32bit addr) |
607 | * | 609 | * |
608 | * Return nothing. | 610 | * Return 1 meaning mf should be freed from _base_interrupt |
611 | * 0 means the mf is freed from this function. | ||
609 | */ | 612 | */ |
610 | static void | 613 | static u8 |
611 | _base_async_event(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, u32 reply) | 614 | _base_async_event(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, u32 reply) |
612 | { | 615 | { |
613 | Mpi2EventNotificationReply_t *mpi_reply; | 616 | Mpi2EventNotificationReply_t *mpi_reply; |
@@ -616,9 +619,9 @@ _base_async_event(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, u32 reply) | |||
616 | 619 | ||
617 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | 620 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); |
618 | if (!mpi_reply) | 621 | if (!mpi_reply) |
619 | return; | 622 | return 1; |
620 | if (mpi_reply->Function != MPI2_FUNCTION_EVENT_NOTIFICATION) | 623 | if (mpi_reply->Function != MPI2_FUNCTION_EVENT_NOTIFICATION) |
621 | return; | 624 | return 1; |
622 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | 625 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING |
623 | _base_display_event_data(ioc, mpi_reply); | 626 | _base_display_event_data(ioc, mpi_reply); |
624 | #endif | 627 | #endif |
@@ -647,6 +650,8 @@ _base_async_event(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, u32 reply) | |||
647 | 650 | ||
648 | /* ctl callback handler */ | 651 | /* ctl callback handler */ |
649 | mpt2sas_ctl_event_callback(ioc, msix_index, reply); | 652 | mpt2sas_ctl_event_callback(ioc, msix_index, reply); |
653 | |||
654 | return 1; | ||
650 | } | 655 | } |
651 | 656 | ||
652 | /** | 657 | /** |
@@ -745,6 +750,7 @@ _base_interrupt(int irq, void *bus_id) | |||
745 | u8 msix_index; | 750 | u8 msix_index; |
746 | struct MPT2SAS_ADAPTER *ioc = bus_id; | 751 | struct MPT2SAS_ADAPTER *ioc = bus_id; |
747 | Mpi2ReplyDescriptorsUnion_t *rpf; | 752 | Mpi2ReplyDescriptorsUnion_t *rpf; |
753 | u8 rc; | ||
748 | 754 | ||
749 | if (ioc->mask_interrupts) | 755 | if (ioc->mask_interrupts) |
750 | return IRQ_NONE; | 756 | return IRQ_NONE; |
@@ -777,12 +783,13 @@ _base_interrupt(int irq, void *bus_id) | |||
777 | if (smid) | 783 | if (smid) |
778 | cb_idx = _base_get_cb_idx(ioc, smid); | 784 | cb_idx = _base_get_cb_idx(ioc, smid); |
779 | if (smid && cb_idx != 0xFF) { | 785 | if (smid && cb_idx != 0xFF) { |
780 | mpt_callbacks[cb_idx](ioc, smid, msix_index, | 786 | rc = mpt_callbacks[cb_idx](ioc, smid, msix_index, |
781 | reply); | 787 | reply); |
782 | if (reply) | 788 | if (reply) |
783 | _base_display_reply_info(ioc, smid, msix_index, | 789 | _base_display_reply_info(ioc, smid, msix_index, |
784 | reply); | 790 | reply); |
785 | mpt2sas_base_free_smid(ioc, smid); | 791 | if (rc) |
792 | mpt2sas_base_free_smid(ioc, smid); | ||
786 | } | 793 | } |
787 | if (!smid) | 794 | if (!smid) |
788 | _base_async_event(ioc, msix_index, reply); | 795 | _base_async_event(ioc, msix_index, reply); |
@@ -3323,10 +3330,18 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
3323 | unsigned long flags; | 3330 | unsigned long flags; |
3324 | u32 reply_address; | 3331 | u32 reply_address; |
3325 | u16 smid; | 3332 | u16 smid; |
3333 | struct _tr_list *delayed_tr, *delayed_tr_next; | ||
3326 | 3334 | ||
3327 | dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, | 3335 | dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, |
3328 | __func__)); | 3336 | __func__)); |
3329 | 3337 | ||
3338 | /* clean the delayed target reset list */ | ||
3339 | list_for_each_entry_safe(delayed_tr, delayed_tr_next, | ||
3340 | &ioc->delayed_tr_list, list) { | ||
3341 | list_del(&delayed_tr->list); | ||
3342 | kfree(delayed_tr); | ||
3343 | } | ||
3344 | |||
3330 | /* initialize the scsi lookup free list */ | 3345 | /* initialize the scsi lookup free list */ |
3331 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | 3346 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); |
3332 | INIT_LIST_HEAD(&ioc->free_list); | 3347 | INIT_LIST_HEAD(&ioc->free_list); |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index 91132626f4c5..7f94be90ad12 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h | |||
@@ -307,6 +307,7 @@ struct _sas_device { | |||
307 | u16 slot; | 307 | u16 slot; |
308 | u8 hidden_raid_component; | 308 | u8 hidden_raid_component; |
309 | u8 responding; | 309 | u8 responding; |
310 | u16 state; | ||
310 | }; | 311 | }; |
311 | 312 | ||
312 | /** | 313 | /** |
@@ -443,6 +444,17 @@ struct request_tracker { | |||
443 | struct list_head tracker_list; | 444 | struct list_head tracker_list; |
444 | }; | 445 | }; |
445 | 446 | ||
447 | /** | ||
448 | * struct _tr_list - target reset list | ||
449 | * @handle: device handle | ||
450 | * @state: state machine | ||
451 | */ | ||
452 | struct _tr_list { | ||
453 | struct list_head list; | ||
454 | u16 handle; | ||
455 | u16 state; | ||
456 | }; | ||
457 | |||
446 | typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr); | 458 | typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr); |
447 | 459 | ||
448 | /** | 460 | /** |
@@ -617,6 +629,8 @@ struct MPT2SAS_ADAPTER { | |||
617 | u8 ctl_cb_idx; | 629 | u8 ctl_cb_idx; |
618 | u8 base_cb_idx; | 630 | u8 base_cb_idx; |
619 | u8 config_cb_idx; | 631 | u8 config_cb_idx; |
632 | u8 tm_tr_cb_idx; | ||
633 | u8 tm_sas_control_cb_idx; | ||
620 | struct _internal_cmd base_cmds; | 634 | struct _internal_cmd base_cmds; |
621 | struct _internal_cmd transport_cmds; | 635 | struct _internal_cmd transport_cmds; |
622 | struct _internal_cmd tm_cmds; | 636 | struct _internal_cmd tm_cmds; |
@@ -727,6 +741,8 @@ struct MPT2SAS_ADAPTER { | |||
727 | struct dma_pool *reply_post_free_dma_pool; | 741 | struct dma_pool *reply_post_free_dma_pool; |
728 | u32 reply_post_host_index; | 742 | u32 reply_post_host_index; |
729 | 743 | ||
744 | struct list_head delayed_tr_list; | ||
745 | |||
730 | /* diag buffer support */ | 746 | /* diag buffer support */ |
731 | u8 *diag_buffer[MPI2_DIAG_BUF_TYPE_COUNT]; | 747 | u8 *diag_buffer[MPI2_DIAG_BUF_TYPE_COUNT]; |
732 | u32 diag_buffer_sz[MPI2_DIAG_BUF_TYPE_COUNT]; | 748 | u32 diag_buffer_sz[MPI2_DIAG_BUF_TYPE_COUNT]; |
@@ -738,8 +754,8 @@ struct MPT2SAS_ADAPTER { | |||
738 | u32 diagnostic_flags[MPI2_DIAG_BUF_TYPE_COUNT]; | 754 | u32 diagnostic_flags[MPI2_DIAG_BUF_TYPE_COUNT]; |
739 | }; | 755 | }; |
740 | 756 | ||
741 | typedef void (*MPT_CALLBACK)(struct MPT2SAS_ADAPTER *ioc, u16 smid, | 757 | typedef u8 (*MPT_CALLBACK)(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, |
742 | u8 msix_index, u32 reply); | 758 | u32 reply); |
743 | 759 | ||
744 | 760 | ||
745 | /* base shared API */ | 761 | /* base shared API */ |
@@ -757,7 +773,8 @@ int mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, | |||
757 | void *mpt2sas_base_get_msg_frame(struct MPT2SAS_ADAPTER *ioc, u16 smid); | 773 | void *mpt2sas_base_get_msg_frame(struct MPT2SAS_ADAPTER *ioc, u16 smid); |
758 | void *mpt2sas_base_get_sense_buffer(struct MPT2SAS_ADAPTER *ioc, u16 smid); | 774 | void *mpt2sas_base_get_sense_buffer(struct MPT2SAS_ADAPTER *ioc, u16 smid); |
759 | void mpt2sas_base_build_zero_len_sge(struct MPT2SAS_ADAPTER *ioc, void *paddr); | 775 | void mpt2sas_base_build_zero_len_sge(struct MPT2SAS_ADAPTER *ioc, void *paddr); |
760 | dma_addr_t mpt2sas_base_get_sense_buffer_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid); | 776 | dma_addr_t mpt2sas_base_get_sense_buffer_dma(struct MPT2SAS_ADAPTER *ioc, |
777 | u16 smid); | ||
761 | 778 | ||
762 | /* hi-priority queue */ | 779 | /* hi-priority queue */ |
763 | u16 mpt2sas_base_get_smid_hpr(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx); | 780 | u16 mpt2sas_base_get_smid_hpr(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx); |
@@ -776,7 +793,7 @@ void mpt2sas_base_initialize_callback_handler(void); | |||
776 | u8 mpt2sas_base_register_callback_handler(MPT_CALLBACK cb_func); | 793 | u8 mpt2sas_base_register_callback_handler(MPT_CALLBACK cb_func); |
777 | void mpt2sas_base_release_callback_handler(u8 cb_idx); | 794 | void mpt2sas_base_release_callback_handler(u8 cb_idx); |
778 | 795 | ||
779 | void mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | 796 | u8 mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, |
780 | u32 reply); | 797 | u32 reply); |
781 | void *mpt2sas_base_get_reply_virt_addr(struct MPT2SAS_ADAPTER *ioc, u32 phys_addr); | 798 | void *mpt2sas_base_get_reply_virt_addr(struct MPT2SAS_ADAPTER *ioc, u32 phys_addr); |
782 | 799 | ||
@@ -791,6 +808,8 @@ int mpt2sas_base_scsi_enclosure_processor(struct MPT2SAS_ADAPTER *ioc, | |||
791 | void mpt2sas_base_validate_event_type(struct MPT2SAS_ADAPTER *ioc, u32 *event_type); | 808 | void mpt2sas_base_validate_event_type(struct MPT2SAS_ADAPTER *ioc, u32 *event_type); |
792 | 809 | ||
793 | /* scsih shared API */ | 810 | /* scsih shared API */ |
811 | u8 mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, | ||
812 | u32 reply); | ||
794 | void mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint lun, | 813 | void mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint lun, |
795 | u8 type, u16 smid_task, ulong timeout); | 814 | u8 type, u16 smid_task, ulong timeout); |
796 | void mpt2sas_scsih_set_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle); | 815 | void mpt2sas_scsih_set_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle); |
@@ -802,12 +821,10 @@ struct _sas_node *mpt2sas_scsih_expander_find_by_sas_address(struct MPT2SAS_ADAP | |||
802 | struct _sas_device *mpt2sas_scsih_sas_device_find_by_sas_address( | 821 | struct _sas_device *mpt2sas_scsih_sas_device_find_by_sas_address( |
803 | struct MPT2SAS_ADAPTER *ioc, u64 sas_address); | 822 | struct MPT2SAS_ADAPTER *ioc, u64 sas_address); |
804 | 823 | ||
805 | void mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, | ||
806 | u32 reply); | ||
807 | void mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase); | 824 | void mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase); |
808 | 825 | ||
809 | /* config shared API */ | 826 | /* config shared API */ |
810 | void mpt2sas_config_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | 827 | u8 mpt2sas_config_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, |
811 | u32 reply); | 828 | u32 reply); |
812 | int mpt2sas_config_get_number_hba_phys(struct MPT2SAS_ADAPTER *ioc, u8 *num_phys); | 829 | int mpt2sas_config_get_number_hba_phys(struct MPT2SAS_ADAPTER *ioc, u8 *num_phys); |
813 | int mpt2sas_config_get_manufacturing_pg0(struct MPT2SAS_ADAPTER *ioc, | 830 | int mpt2sas_config_get_manufacturing_pg0(struct MPT2SAS_ADAPTER *ioc, |
@@ -861,17 +878,17 @@ extern struct device_attribute *mpt2sas_host_attrs[]; | |||
861 | extern struct device_attribute *mpt2sas_dev_attrs[]; | 878 | extern struct device_attribute *mpt2sas_dev_attrs[]; |
862 | void mpt2sas_ctl_init(void); | 879 | void mpt2sas_ctl_init(void); |
863 | void mpt2sas_ctl_exit(void); | 880 | void mpt2sas_ctl_exit(void); |
864 | void mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | 881 | u8 mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, |
865 | u32 reply); | 882 | u32 reply); |
866 | void mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase); | 883 | void mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase); |
867 | void mpt2sas_ctl_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, | 884 | u8 mpt2sas_ctl_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, |
868 | u32 reply); | 885 | u32 reply); |
869 | void mpt2sas_ctl_add_to_event_log(struct MPT2SAS_ADAPTER *ioc, | 886 | void mpt2sas_ctl_add_to_event_log(struct MPT2SAS_ADAPTER *ioc, |
870 | Mpi2EventNotificationReply_t *mpi_reply); | 887 | Mpi2EventNotificationReply_t *mpi_reply); |
871 | 888 | ||
872 | /* transport shared API */ | 889 | /* transport shared API */ |
873 | void mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, | 890 | u8 mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, |
874 | u8 msix_index, u32 reply); | 891 | u32 reply); |
875 | struct _sas_port *mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc, | 892 | struct _sas_port *mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc, |
876 | u16 handle, u16 parent_handle); | 893 | u16 handle, u16 parent_handle); |
877 | void mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address, | 894 | void mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address, |
@@ -885,6 +902,8 @@ void mpt2sas_transport_update_links(struct MPT2SAS_ADAPTER *ioc, u16 handle, | |||
885 | extern struct sas_function_template mpt2sas_transport_functions; | 902 | extern struct sas_function_template mpt2sas_transport_functions; |
886 | extern struct scsi_transport_template *mpt2sas_transport_template; | 903 | extern struct scsi_transport_template *mpt2sas_transport_template; |
887 | extern int scsi_internal_device_block(struct scsi_device *sdev); | 904 | extern int scsi_internal_device_block(struct scsi_device *sdev); |
905 | extern u8 mpt2sas_stm_zero_smid_handler(struct MPT2SAS_ADAPTER *ioc, | ||
906 | u8 msix_index, u32 reply); | ||
888 | extern int scsi_internal_device_unblock(struct scsi_device *sdev); | 907 | extern int scsi_internal_device_unblock(struct scsi_device *sdev); |
889 | 908 | ||
890 | #endif /* MPT2SAS_BASE_H_INCLUDED */ | 909 | #endif /* MPT2SAS_BASE_H_INCLUDED */ |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_config.c b/drivers/scsi/mpt2sas/mpt2sas_config.c index d79a4ddf26be..594a389c6526 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_config.c +++ b/drivers/scsi/mpt2sas/mpt2sas_config.c | |||
@@ -233,18 +233,19 @@ _config_free_config_dma_memory(struct MPT2SAS_ADAPTER *ioc, | |||
233 | * | 233 | * |
234 | * The callback handler when using _config_request. | 234 | * The callback handler when using _config_request. |
235 | * | 235 | * |
236 | * Return nothing. | 236 | * Return 1 meaning mf should be freed from _base_interrupt |
237 | * 0 means the mf is freed from this function. | ||
237 | */ | 238 | */ |
238 | void | 239 | u8 |
239 | mpt2sas_config_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | 240 | mpt2sas_config_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, |
240 | u32 reply) | 241 | u32 reply) |
241 | { | 242 | { |
242 | MPI2DefaultReply_t *mpi_reply; | 243 | MPI2DefaultReply_t *mpi_reply; |
243 | 244 | ||
244 | if (ioc->config_cmds.status == MPT2_CMD_NOT_USED) | 245 | if (ioc->config_cmds.status == MPT2_CMD_NOT_USED) |
245 | return; | 246 | return 1; |
246 | if (ioc->config_cmds.smid != smid) | 247 | if (ioc->config_cmds.smid != smid) |
247 | return; | 248 | return 1; |
248 | ioc->config_cmds.status |= MPT2_CMD_COMPLETE; | 249 | ioc->config_cmds.status |= MPT2_CMD_COMPLETE; |
249 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | 250 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); |
250 | if (mpi_reply) { | 251 | if (mpi_reply) { |
@@ -258,6 +259,7 @@ mpt2sas_config_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | |||
258 | #endif | 259 | #endif |
259 | ioc->config_cmds.smid = USHORT_MAX; | 260 | ioc->config_cmds.smid = USHORT_MAX; |
260 | complete(&ioc->config_cmds.done); | 261 | complete(&ioc->config_cmds.done); |
262 | return 1; | ||
261 | } | 263 | } |
262 | 264 | ||
263 | /** | 265 | /** |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c index 466e2f42367f..33463ace0d48 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c +++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c | |||
@@ -225,18 +225,19 @@ _ctl_display_some_debug(struct MPT2SAS_ADAPTER *ioc, u16 smid, | |||
225 | * | 225 | * |
226 | * The callback handler when using ioc->ctl_cb_idx. | 226 | * The callback handler when using ioc->ctl_cb_idx. |
227 | * | 227 | * |
228 | * Return nothing. | 228 | * Return 1 meaning mf should be freed from _base_interrupt |
229 | * 0 means the mf is freed from this function. | ||
229 | */ | 230 | */ |
230 | void | 231 | u8 |
231 | mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | 232 | mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, |
232 | u32 reply) | 233 | u32 reply) |
233 | { | 234 | { |
234 | MPI2DefaultReply_t *mpi_reply; | 235 | MPI2DefaultReply_t *mpi_reply; |
235 | 236 | ||
236 | if (ioc->ctl_cmds.status == MPT2_CMD_NOT_USED) | 237 | if (ioc->ctl_cmds.status == MPT2_CMD_NOT_USED) |
237 | return; | 238 | return 1; |
238 | if (ioc->ctl_cmds.smid != smid) | 239 | if (ioc->ctl_cmds.smid != smid) |
239 | return; | 240 | return 1; |
240 | ioc->ctl_cmds.status |= MPT2_CMD_COMPLETE; | 241 | ioc->ctl_cmds.status |= MPT2_CMD_COMPLETE; |
241 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | 242 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); |
242 | if (mpi_reply) { | 243 | if (mpi_reply) { |
@@ -248,6 +249,7 @@ mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | |||
248 | #endif | 249 | #endif |
249 | ioc->ctl_cmds.status &= ~MPT2_CMD_PENDING; | 250 | ioc->ctl_cmds.status &= ~MPT2_CMD_PENDING; |
250 | complete(&ioc->ctl_cmds.done); | 251 | complete(&ioc->ctl_cmds.done); |
252 | return 1; | ||
251 | } | 253 | } |
252 | 254 | ||
253 | /** | 255 | /** |
@@ -336,9 +338,10 @@ mpt2sas_ctl_add_to_event_log(struct MPT2SAS_ADAPTER *ioc, | |||
336 | * This function merely adds a new work task into ioc->firmware_event_thread. | 338 | * This function merely adds a new work task into ioc->firmware_event_thread. |
337 | * The tasks are worked from _firmware_event_work in user context. | 339 | * The tasks are worked from _firmware_event_work in user context. |
338 | * | 340 | * |
339 | * Return nothing. | 341 | * Return 1 meaning mf should be freed from _base_interrupt |
342 | * 0 means the mf is freed from this function. | ||
340 | */ | 343 | */ |
341 | void | 344 | u8 |
342 | mpt2sas_ctl_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, | 345 | mpt2sas_ctl_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, |
343 | u32 reply) | 346 | u32 reply) |
344 | { | 347 | { |
@@ -346,6 +349,7 @@ mpt2sas_ctl_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, | |||
346 | 349 | ||
347 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | 350 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); |
348 | mpt2sas_ctl_add_to_event_log(ioc, mpi_reply); | 351 | mpt2sas_ctl_add_to_event_log(ioc, mpi_reply); |
352 | return 1; | ||
349 | } | 353 | } |
350 | 354 | ||
351 | /** | 355 | /** |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index d4b003a618a1..9ec50729d535 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c | |||
@@ -79,6 +79,9 @@ static u8 transport_cb_idx = -1; | |||
79 | static u8 config_cb_idx = -1; | 79 | static u8 config_cb_idx = -1; |
80 | static int mpt_ids; | 80 | static int mpt_ids; |
81 | 81 | ||
82 | static u8 tm_tr_cb_idx = -1 ; | ||
83 | static u8 tm_sas_control_cb_idx = -1; | ||
84 | |||
82 | /* command line options */ | 85 | /* command line options */ |
83 | static u32 logging_level; | 86 | static u32 logging_level; |
84 | MODULE_PARM_DESC(logging_level, " bits for enabling additional logging info " | 87 | MODULE_PARM_DESC(logging_level, " bits for enabling additional logging info " |
@@ -1641,17 +1644,18 @@ _scsih_response_code(struct MPT2SAS_ADAPTER *ioc, u8 response_code) | |||
1641 | * | 1644 | * |
1642 | * The callback handler when using scsih_issue_tm. | 1645 | * The callback handler when using scsih_issue_tm. |
1643 | * | 1646 | * |
1644 | * Return nothing. | 1647 | * Return 1 meaning mf should be freed from _base_interrupt |
1648 | * 0 means the mf is freed from this function. | ||
1645 | */ | 1649 | */ |
1646 | static void | 1650 | static u8 |
1647 | _scsih_tm_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | 1651 | _scsih_tm_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) |
1648 | { | 1652 | { |
1649 | MPI2DefaultReply_t *mpi_reply; | 1653 | MPI2DefaultReply_t *mpi_reply; |
1650 | 1654 | ||
1651 | if (ioc->tm_cmds.status == MPT2_CMD_NOT_USED) | 1655 | if (ioc->tm_cmds.status == MPT2_CMD_NOT_USED) |
1652 | return; | 1656 | return 1; |
1653 | if (ioc->tm_cmds.smid != smid) | 1657 | if (ioc->tm_cmds.smid != smid) |
1654 | return; | 1658 | return 1; |
1655 | ioc->tm_cmds.status |= MPT2_CMD_COMPLETE; | 1659 | ioc->tm_cmds.status |= MPT2_CMD_COMPLETE; |
1656 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | 1660 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); |
1657 | if (mpi_reply) { | 1661 | if (mpi_reply) { |
@@ -1660,6 +1664,7 @@ _scsih_tm_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | |||
1660 | } | 1664 | } |
1661 | ioc->tm_cmds.status &= ~MPT2_CMD_PENDING; | 1665 | ioc->tm_cmds.status &= ~MPT2_CMD_PENDING; |
1662 | complete(&ioc->tm_cmds.done); | 1666 | complete(&ioc->tm_cmds.done); |
1667 | return 1; | ||
1663 | } | 1668 | } |
1664 | 1669 | ||
1665 | /** | 1670 | /** |
@@ -2312,6 +2317,231 @@ _scsih_block_io_to_children_attached_directly(struct MPT2SAS_ADAPTER *ioc, | |||
2312 | } | 2317 | } |
2313 | 2318 | ||
2314 | /** | 2319 | /** |
2320 | * _scsih_tm_tr_send - send task management request | ||
2321 | * @ioc: per adapter object | ||
2322 | * @handle: device handle | ||
2323 | * Context: interrupt time. | ||
2324 | * | ||
2325 | * This code is to initiate the device removal handshake protocal | ||
2326 | * with controller firmware. This function will issue target reset | ||
2327 | * using high priority request queue. It will send a sas iounit | ||
2328 | * controll request (MPI2_SAS_OP_REMOVE_DEVICE) from this completion. | ||
2329 | * | ||
2330 | * This is designed to send muliple task management request at the same | ||
2331 | * time to the fifo. If the fifo is full, we will append the request, | ||
2332 | * and process it in a future completion. | ||
2333 | */ | ||
2334 | static void | ||
2335 | _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle) | ||
2336 | { | ||
2337 | Mpi2SCSITaskManagementRequest_t *mpi_request; | ||
2338 | struct MPT2SAS_TARGET *sas_target_priv_data; | ||
2339 | u16 smid; | ||
2340 | struct _sas_device *sas_device; | ||
2341 | unsigned long flags; | ||
2342 | struct _tr_list *delayed_tr; | ||
2343 | |||
2344 | if (ioc->shost_recovery) { | ||
2345 | printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n", | ||
2346 | __func__, ioc->name); | ||
2347 | return; | ||
2348 | } | ||
2349 | |||
2350 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
2351 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | ||
2352 | if (!sas_device) { | ||
2353 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
2354 | printk(MPT2SAS_ERR_FMT "%s: failed finding sas_device\n", | ||
2355 | ioc->name, __func__); | ||
2356 | return; | ||
2357 | } | ||
2358 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
2359 | |||
2360 | /* skip is hidden raid component */ | ||
2361 | if (sas_device->hidden_raid_component) | ||
2362 | return; | ||
2363 | |||
2364 | smid = mpt2sas_base_get_smid_hpr(ioc, ioc->tm_tr_cb_idx); | ||
2365 | if (!smid) { | ||
2366 | delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC); | ||
2367 | if (!delayed_tr) | ||
2368 | return; | ||
2369 | INIT_LIST_HEAD(&delayed_tr->list); | ||
2370 | delayed_tr->handle = handle; | ||
2371 | delayed_tr->state = MPT2SAS_REQ_SAS_CNTRL; | ||
2372 | list_add_tail(&delayed_tr->list, | ||
2373 | &ioc->delayed_tr_list); | ||
2374 | if (sas_device->starget) | ||
2375 | dewtprintk(ioc, starget_printk(KERN_INFO, | ||
2376 | sas_device->starget, "DELAYED:tr:handle(0x%04x), " | ||
2377 | "(open)\n", sas_device->handle)); | ||
2378 | return; | ||
2379 | } | ||
2380 | |||
2381 | if (sas_device->starget && sas_device->starget->hostdata) { | ||
2382 | sas_target_priv_data = sas_device->starget->hostdata; | ||
2383 | sas_target_priv_data->tm_busy = 1; | ||
2384 | dewtprintk(ioc, starget_printk(KERN_INFO, sas_device->starget, | ||
2385 | "tr:handle(0x%04x), (open)\n", sas_device->handle)); | ||
2386 | } | ||
2387 | |||
2388 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
2389 | memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t)); | ||
2390 | mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; | ||
2391 | mpi_request->DevHandle = cpu_to_le16(handle); | ||
2392 | mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; | ||
2393 | sas_device->state |= MPTSAS_STATE_TR_SEND; | ||
2394 | sas_device->state |= MPT2SAS_REQ_SAS_CNTRL; | ||
2395 | mpt2sas_base_put_smid_hi_priority(ioc, smid); | ||
2396 | } | ||
2397 | |||
2398 | |||
2399 | |||
2400 | /** | ||
2401 | * _scsih_sas_control_complete - completion routine | ||
2402 | * @ioc: per adapter object | ||
2403 | * @smid: system request message index | ||
2404 | * @msix_index: MSIX table index supplied by the OS | ||
2405 | * @reply: reply message frame(lower 32bit addr) | ||
2406 | * Context: interrupt time. | ||
2407 | * | ||
2408 | * This is the sas iounit controll completion routine. | ||
2409 | * This code is part of the code to initiate the device removal | ||
2410 | * handshake protocal with controller firmware. | ||
2411 | * | ||
2412 | * Return 1 meaning mf should be freed from _base_interrupt | ||
2413 | * 0 means the mf is freed from this function. | ||
2414 | */ | ||
2415 | static u8 | ||
2416 | _scsih_sas_control_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, | ||
2417 | u8 msix_index, u32 reply) | ||
2418 | { | ||
2419 | unsigned long flags; | ||
2420 | u16 handle; | ||
2421 | struct _sas_device *sas_device; | ||
2422 | Mpi2SasIoUnitControlReply_t *mpi_reply = | ||
2423 | mpt2sas_base_get_reply_virt_addr(ioc, reply); | ||
2424 | |||
2425 | handle = le16_to_cpu(mpi_reply->DevHandle); | ||
2426 | |||
2427 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
2428 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | ||
2429 | if (!sas_device) { | ||
2430 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
2431 | printk(MPT2SAS_ERR_FMT "%s: failed finding sas_device\n", | ||
2432 | ioc->name, __func__); | ||
2433 | return 1; | ||
2434 | } | ||
2435 | sas_device->state |= MPTSAS_STATE_CNTRL_COMPLETE; | ||
2436 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
2437 | |||
2438 | if (sas_device->starget) | ||
2439 | dewtprintk(ioc, starget_printk(KERN_INFO, sas_device->starget, | ||
2440 | "sc_complete:handle(0x%04x), " | ||
2441 | "ioc_status(0x%04x), loginfo(0x%08x)\n", | ||
2442 | handle, le16_to_cpu(mpi_reply->IOCStatus), | ||
2443 | le32_to_cpu(mpi_reply->IOCLogInfo))); | ||
2444 | return 1; | ||
2445 | } | ||
2446 | |||
2447 | /** | ||
2448 | * _scsih_tm_tr_complete - | ||
2449 | * @ioc: per adapter object | ||
2450 | * @smid: system request message index | ||
2451 | * @msix_index: MSIX table index supplied by the OS | ||
2452 | * @reply: reply message frame(lower 32bit addr) | ||
2453 | * Context: interrupt time. | ||
2454 | * | ||
2455 | * This is the target reset completion routine. | ||
2456 | * This code is part of the code to initiate the device removal | ||
2457 | * handshake protocal with controller firmware. | ||
2458 | * It will send a sas iounit controll request (MPI2_SAS_OP_REMOVE_DEVICE) | ||
2459 | * | ||
2460 | * Return 1 meaning mf should be freed from _base_interrupt | ||
2461 | * 0 means the mf is freed from this function. | ||
2462 | */ | ||
2463 | static u8 | ||
2464 | _scsih_tm_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | ||
2465 | u32 reply) | ||
2466 | { | ||
2467 | unsigned long flags; | ||
2468 | u16 handle; | ||
2469 | struct _sas_device *sas_device; | ||
2470 | Mpi2SCSITaskManagementReply_t *mpi_reply = | ||
2471 | mpt2sas_base_get_reply_virt_addr(ioc, reply); | ||
2472 | Mpi2SasIoUnitControlRequest_t *mpi_request; | ||
2473 | u16 smid_sas_ctrl; | ||
2474 | struct MPT2SAS_TARGET *sas_target_priv_data; | ||
2475 | struct _tr_list *delayed_tr; | ||
2476 | u8 rc; | ||
2477 | |||
2478 | handle = le16_to_cpu(mpi_reply->DevHandle); | ||
2479 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
2480 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | ||
2481 | if (!sas_device) { | ||
2482 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
2483 | printk(MPT2SAS_ERR_FMT "%s: failed finding sas_device\n", | ||
2484 | ioc->name, __func__); | ||
2485 | return 1; | ||
2486 | } | ||
2487 | sas_device->state |= MPTSAS_STATE_TR_COMPLETE; | ||
2488 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
2489 | |||
2490 | if (sas_device->starget) | ||
2491 | dewtprintk(ioc, starget_printk(KERN_INFO, sas_device->starget, | ||
2492 | "tr_complete:handle(0x%04x), (%s) ioc_status(0x%04x), " | ||
2493 | "loginfo(0x%08x), completed(%d)\n", | ||
2494 | sas_device->handle, (sas_device->state & | ||
2495 | MPT2SAS_REQ_SAS_CNTRL) ? "open" : "active", | ||
2496 | le16_to_cpu(mpi_reply->IOCStatus), | ||
2497 | le32_to_cpu(mpi_reply->IOCLogInfo), | ||
2498 | le32_to_cpu(mpi_reply->TerminationCount))); | ||
2499 | |||
2500 | if (sas_device->starget && sas_device->starget->hostdata) { | ||
2501 | sas_target_priv_data = sas_device->starget->hostdata; | ||
2502 | sas_target_priv_data->tm_busy = 0; | ||
2503 | } | ||
2504 | |||
2505 | if (!list_empty(&ioc->delayed_tr_list)) { | ||
2506 | delayed_tr = list_entry(ioc->delayed_tr_list.next, | ||
2507 | struct _tr_list, list); | ||
2508 | mpt2sas_base_free_smid(ioc, smid); | ||
2509 | if (delayed_tr->state & MPT2SAS_REQ_SAS_CNTRL) | ||
2510 | _scsih_tm_tr_send(ioc, delayed_tr->handle); | ||
2511 | list_del(&delayed_tr->list); | ||
2512 | kfree(delayed_tr); | ||
2513 | rc = 0; /* tells base_interrupt not to free mf */ | ||
2514 | } else | ||
2515 | rc = 1; | ||
2516 | |||
2517 | |||
2518 | if (!(sas_device->state & MPT2SAS_REQ_SAS_CNTRL)) | ||
2519 | return rc; | ||
2520 | |||
2521 | if (ioc->shost_recovery) { | ||
2522 | printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n", | ||
2523 | __func__, ioc->name); | ||
2524 | return rc; | ||
2525 | } | ||
2526 | |||
2527 | smid_sas_ctrl = mpt2sas_base_get_smid(ioc, ioc->tm_sas_control_cb_idx); | ||
2528 | if (!smid_sas_ctrl) { | ||
2529 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | ||
2530 | ioc->name, __func__); | ||
2531 | return rc; | ||
2532 | } | ||
2533 | |||
2534 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid_sas_ctrl); | ||
2535 | memset(mpi_request, 0, sizeof(Mpi2SasIoUnitControlRequest_t)); | ||
2536 | mpi_request->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL; | ||
2537 | mpi_request->Operation = MPI2_SAS_OP_REMOVE_DEVICE; | ||
2538 | mpi_request->DevHandle = mpi_reply->DevHandle; | ||
2539 | sas_device->state |= MPTSAS_STATE_CNTRL_SEND; | ||
2540 | mpt2sas_base_put_smid_default(ioc, smid_sas_ctrl); | ||
2541 | return rc; | ||
2542 | } | ||
2543 | |||
2544 | /** | ||
2315 | * _scsih_check_topo_delete_events - sanity check on topo events | 2545 | * _scsih_check_topo_delete_events - sanity check on topo events |
2316 | * @ioc: per adapter object | 2546 | * @ioc: per adapter object |
2317 | * @event_data: the event data payload | 2547 | * @event_data: the event data payload |
@@ -2333,6 +2563,21 @@ _scsih_check_topo_delete_events(struct MPT2SAS_ADAPTER *ioc, | |||
2333 | u16 expander_handle; | 2563 | u16 expander_handle; |
2334 | struct _sas_node *sas_expander; | 2564 | struct _sas_node *sas_expander; |
2335 | unsigned long flags; | 2565 | unsigned long flags; |
2566 | int i, reason_code; | ||
2567 | u16 handle; | ||
2568 | |||
2569 | for (i = 0 ; i < event_data->NumEntries; i++) { | ||
2570 | if (event_data->PHY[i].PhyStatus & | ||
2571 | MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT) | ||
2572 | continue; | ||
2573 | handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle); | ||
2574 | if (!handle) | ||
2575 | continue; | ||
2576 | reason_code = event_data->PHY[i].PhyStatus & | ||
2577 | MPI2_EVENT_SAS_TOPO_RC_MASK; | ||
2578 | if (reason_code == MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING) | ||
2579 | _scsih_tm_tr_send(ioc, handle); | ||
2580 | } | ||
2336 | 2581 | ||
2337 | expander_handle = le16_to_cpu(event_data->ExpanderDevHandle); | 2582 | expander_handle = le16_to_cpu(event_data->ExpanderDevHandle); |
2338 | if (expander_handle < ioc->sas_hba.num_phys) { | 2583 | if (expander_handle < ioc->sas_hba.num_phys) { |
@@ -2915,11 +3160,12 @@ _scsih_smart_predicted_fault(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
2915 | * @msix_index: MSIX table index supplied by the OS | 3160 | * @msix_index: MSIX table index supplied by the OS |
2916 | * @reply: reply message frame(lower 32bit addr) | 3161 | * @reply: reply message frame(lower 32bit addr) |
2917 | * | 3162 | * |
2918 | * Callback handler when using scsih_qcmd. | 3163 | * Callback handler when using _scsih_qcmd. |
2919 | * | 3164 | * |
2920 | * Return nothing. | 3165 | * Return 1 meaning mf should be freed from _base_interrupt |
3166 | * 0 means the mf is freed from this function. | ||
2921 | */ | 3167 | */ |
2922 | static void | 3168 | static u8 |
2923 | _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | 3169 | _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) |
2924 | { | 3170 | { |
2925 | Mpi2SCSIIORequest_t *mpi_request; | 3171 | Mpi2SCSIIORequest_t *mpi_request; |
@@ -2936,7 +3182,7 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | |||
2936 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | 3182 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); |
2937 | scmd = _scsih_scsi_lookup_get(ioc, smid); | 3183 | scmd = _scsih_scsi_lookup_get(ioc, smid); |
2938 | if (scmd == NULL) | 3184 | if (scmd == NULL) |
2939 | return; | 3185 | return 1; |
2940 | 3186 | ||
2941 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | 3187 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); |
2942 | 3188 | ||
@@ -3092,6 +3338,7 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | |||
3092 | out: | 3338 | out: |
3093 | scsi_dma_unmap(scmd); | 3339 | scsi_dma_unmap(scmd); |
3094 | scmd->scsi_done(scmd); | 3340 | scmd->scsi_done(scmd); |
3341 | return 1; | ||
3095 | } | 3342 | } |
3096 | 3343 | ||
3097 | /** | 3344 | /** |
@@ -3623,6 +3870,12 @@ _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
3623 | if (ioc->remove_host) | 3870 | if (ioc->remove_host) |
3624 | goto out; | 3871 | goto out; |
3625 | 3872 | ||
3873 | if ((sas_device->state & MPTSAS_STATE_TR_COMPLETE)) { | ||
3874 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "\tskip " | ||
3875 | "target_reset handle(0x%04x)\n", ioc->name, handle)); | ||
3876 | goto skip_tr; | ||
3877 | } | ||
3878 | |||
3626 | /* Target Reset to flush out all the outstanding IO */ | 3879 | /* Target Reset to flush out all the outstanding IO */ |
3627 | device_handle = (sas_device->hidden_raid_component) ? | 3880 | device_handle = (sas_device->hidden_raid_component) ? |
3628 | sas_device->volume_handle : handle; | 3881 | sas_device->volume_handle : handle; |
@@ -3639,6 +3892,13 @@ _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
3639 | if (ioc->shost_recovery) | 3892 | if (ioc->shost_recovery) |
3640 | goto out; | 3893 | goto out; |
3641 | } | 3894 | } |
3895 | skip_tr: | ||
3896 | |||
3897 | if ((sas_device->state & MPTSAS_STATE_CNTRL_COMPLETE)) { | ||
3898 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "\tskip " | ||
3899 | "sas_cntrl handle(0x%04x)\n", ioc->name, handle)); | ||
3900 | goto out; | ||
3901 | } | ||
3642 | 3902 | ||
3643 | /* SAS_IO_UNIT_CNTR - send REMOVE_DEVICE */ | 3903 | /* SAS_IO_UNIT_CNTR - send REMOVE_DEVICE */ |
3644 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "sas_iounit: handle" | 3904 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "sas_iounit: handle" |
@@ -4829,6 +5089,10 @@ _scsih_mark_responding_sas_device(struct MPT2SAS_ADAPTER *ioc, u64 sas_address, | |||
4829 | if (sas_device->sas_address == sas_address && | 5089 | if (sas_device->sas_address == sas_address && |
4830 | sas_device->slot == slot && sas_device->starget) { | 5090 | sas_device->slot == slot && sas_device->starget) { |
4831 | sas_device->responding = 1; | 5091 | sas_device->responding = 1; |
5092 | sas_device->state = 0; | ||
5093 | starget = sas_device->starget; | ||
5094 | sas_target_priv_data = starget->hostdata; | ||
5095 | sas_target_priv_data->tm_busy = 0; | ||
4832 | starget_printk(KERN_INFO, sas_device->starget, | 5096 | starget_printk(KERN_INFO, sas_device->starget, |
4833 | "handle(0x%04x), sas_addr(0x%016llx), enclosure " | 5097 | "handle(0x%04x), sas_addr(0x%016llx), enclosure " |
4834 | "logical id(0x%016llx), slot(%d)\n", handle, | 5098 | "logical id(0x%016llx), slot(%d)\n", handle, |
@@ -4841,8 +5105,6 @@ _scsih_mark_responding_sas_device(struct MPT2SAS_ADAPTER *ioc, u64 sas_address, | |||
4841 | printk(KERN_INFO "\thandle changed from(0x%04x)!!!\n", | 5105 | printk(KERN_INFO "\thandle changed from(0x%04x)!!!\n", |
4842 | sas_device->handle); | 5106 | sas_device->handle); |
4843 | sas_device->handle = handle; | 5107 | sas_device->handle = handle; |
4844 | starget = sas_device->starget; | ||
4845 | sas_target_priv_data = starget->hostdata; | ||
4846 | sas_target_priv_data->handle = handle; | 5108 | sas_target_priv_data->handle = handle; |
4847 | goto out; | 5109 | goto out; |
4848 | } | 5110 | } |
@@ -5235,9 +5497,10 @@ _firmware_event_work(struct work_struct *work) | |||
5235 | * This function merely adds a new work task into ioc->firmware_event_thread. | 5497 | * This function merely adds a new work task into ioc->firmware_event_thread. |
5236 | * The tasks are worked from _firmware_event_work in user context. | 5498 | * The tasks are worked from _firmware_event_work in user context. |
5237 | * | 5499 | * |
5238 | * Return nothing. | 5500 | * Return 1 meaning mf should be freed from _base_interrupt |
5501 | * 0 means the mf is freed from this function. | ||
5239 | */ | 5502 | */ |
5240 | void | 5503 | u8 |
5241 | mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, | 5504 | mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, |
5242 | u32 reply) | 5505 | u32 reply) |
5243 | { | 5506 | { |
@@ -5250,11 +5513,11 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, | |||
5250 | spin_lock_irqsave(&ioc->fw_event_lock, flags); | 5513 | spin_lock_irqsave(&ioc->fw_event_lock, flags); |
5251 | if (ioc->fw_events_off || ioc->remove_host) { | 5514 | if (ioc->fw_events_off || ioc->remove_host) { |
5252 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); | 5515 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); |
5253 | return; | 5516 | return 1; |
5254 | } | 5517 | } |
5255 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); | 5518 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); |
5256 | 5519 | ||
5257 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | 5520 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); |
5258 | event = le16_to_cpu(mpi_reply->Event); | 5521 | event = le16_to_cpu(mpi_reply->Event); |
5259 | 5522 | ||
5260 | switch (event) { | 5523 | switch (event) { |
@@ -5268,7 +5531,7 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, | |||
5268 | if (baen_data->Primitive != | 5531 | if (baen_data->Primitive != |
5269 | MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT || | 5532 | MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT || |
5270 | ioc->broadcast_aen_busy) | 5533 | ioc->broadcast_aen_busy) |
5271 | return; | 5534 | return 1; |
5272 | ioc->broadcast_aen_busy = 1; | 5535 | ioc->broadcast_aen_busy = 1; |
5273 | break; | 5536 | break; |
5274 | } | 5537 | } |
@@ -5290,14 +5553,14 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, | |||
5290 | break; | 5553 | break; |
5291 | 5554 | ||
5292 | default: /* ignore the rest */ | 5555 | default: /* ignore the rest */ |
5293 | return; | 5556 | return 1; |
5294 | } | 5557 | } |
5295 | 5558 | ||
5296 | fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC); | 5559 | fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC); |
5297 | if (!fw_event) { | 5560 | if (!fw_event) { |
5298 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | 5561 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", |
5299 | ioc->name, __FILE__, __LINE__, __func__); | 5562 | ioc->name, __FILE__, __LINE__, __func__); |
5300 | return; | 5563 | return 1; |
5301 | } | 5564 | } |
5302 | fw_event->event_data = | 5565 | fw_event->event_data = |
5303 | kzalloc(mpi_reply->EventDataLength*4, GFP_ATOMIC); | 5566 | kzalloc(mpi_reply->EventDataLength*4, GFP_ATOMIC); |
@@ -5305,7 +5568,7 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, | |||
5305 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | 5568 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", |
5306 | ioc->name, __FILE__, __LINE__, __func__); | 5569 | ioc->name, __FILE__, __LINE__, __func__); |
5307 | kfree(fw_event); | 5570 | kfree(fw_event); |
5308 | return; | 5571 | return 1; |
5309 | } | 5572 | } |
5310 | 5573 | ||
5311 | memcpy(fw_event->event_data, mpi_reply->EventData, | 5574 | memcpy(fw_event->event_data, mpi_reply->EventData, |
@@ -5315,6 +5578,7 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, | |||
5315 | fw_event->VP_ID = mpi_reply->VP_ID; | 5578 | fw_event->VP_ID = mpi_reply->VP_ID; |
5316 | fw_event->event = event; | 5579 | fw_event->event = event; |
5317 | _scsih_fw_event_add(ioc, fw_event); | 5580 | _scsih_fw_event_add(ioc, fw_event); |
5581 | return 1; | ||
5318 | } | 5582 | } |
5319 | 5583 | ||
5320 | /* shost template */ | 5584 | /* shost template */ |
@@ -5574,7 +5838,7 @@ _scsih_probe_raid(struct MPT2SAS_ADAPTER *ioc) | |||
5574 | } | 5838 | } |
5575 | 5839 | ||
5576 | /** | 5840 | /** |
5577 | * _scsih_probe_sas - reporting raid volumes to sas transport | 5841 | * _scsih_probe_sas - reporting sas devices to sas transport |
5578 | * @ioc: per adapter object | 5842 | * @ioc: per adapter object |
5579 | * | 5843 | * |
5580 | * Called during initial loading of the driver. | 5844 | * Called during initial loading of the driver. |
@@ -5671,6 +5935,8 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
5671 | ioc->base_cb_idx = base_cb_idx; | 5935 | ioc->base_cb_idx = base_cb_idx; |
5672 | ioc->transport_cb_idx = transport_cb_idx; | 5936 | ioc->transport_cb_idx = transport_cb_idx; |
5673 | ioc->config_cb_idx = config_cb_idx; | 5937 | ioc->config_cb_idx = config_cb_idx; |
5938 | ioc->tm_tr_cb_idx = tm_tr_cb_idx; | ||
5939 | ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx; | ||
5674 | ioc->logging_level = logging_level; | 5940 | ioc->logging_level = logging_level; |
5675 | /* misc semaphores and spin locks */ | 5941 | /* misc semaphores and spin locks */ |
5676 | spin_lock_init(&ioc->ioc_reset_in_progress_lock); | 5942 | spin_lock_init(&ioc->ioc_reset_in_progress_lock); |
@@ -5686,6 +5952,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
5686 | INIT_LIST_HEAD(&ioc->fw_event_list); | 5952 | INIT_LIST_HEAD(&ioc->fw_event_list); |
5687 | INIT_LIST_HEAD(&ioc->raid_device_list); | 5953 | INIT_LIST_HEAD(&ioc->raid_device_list); |
5688 | INIT_LIST_HEAD(&ioc->sas_hba.sas_port_list); | 5954 | INIT_LIST_HEAD(&ioc->sas_hba.sas_port_list); |
5955 | INIT_LIST_HEAD(&ioc->delayed_tr_list); | ||
5689 | 5956 | ||
5690 | /* init shost parameters */ | 5957 | /* init shost parameters */ |
5691 | shost->max_cmd_len = 16; | 5958 | shost->max_cmd_len = 16; |
@@ -5702,6 +5969,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
5702 | 5969 | ||
5703 | scsi_host_set_prot(shost, SHOST_DIF_TYPE1_PROTECTION | 5970 | scsi_host_set_prot(shost, SHOST_DIF_TYPE1_PROTECTION |
5704 | | SHOST_DIF_TYPE3_PROTECTION); | 5971 | | SHOST_DIF_TYPE3_PROTECTION); |
5972 | scsi_host_set_guard(shost, SHOST_DIX_GUARD_CRC); | ||
5705 | 5973 | ||
5706 | /* event thread */ | 5974 | /* event thread */ |
5707 | snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name), | 5975 | snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name), |
@@ -5851,6 +6119,11 @@ _scsih_init(void) | |||
5851 | /* ctl module callback handler */ | 6119 | /* ctl module callback handler */ |
5852 | ctl_cb_idx = mpt2sas_base_register_callback_handler(mpt2sas_ctl_done); | 6120 | ctl_cb_idx = mpt2sas_base_register_callback_handler(mpt2sas_ctl_done); |
5853 | 6121 | ||
6122 | tm_tr_cb_idx = mpt2sas_base_register_callback_handler( | ||
6123 | _scsih_tm_tr_complete); | ||
6124 | tm_sas_control_cb_idx = mpt2sas_base_register_callback_handler( | ||
6125 | _scsih_sas_control_complete); | ||
6126 | |||
5854 | mpt2sas_ctl_init(); | 6127 | mpt2sas_ctl_init(); |
5855 | 6128 | ||
5856 | error = pci_register_driver(&scsih_driver); | 6129 | error = pci_register_driver(&scsih_driver); |
@@ -5881,6 +6154,9 @@ _scsih_exit(void) | |||
5881 | mpt2sas_base_release_callback_handler(config_cb_idx); | 6154 | mpt2sas_base_release_callback_handler(config_cb_idx); |
5882 | mpt2sas_base_release_callback_handler(ctl_cb_idx); | 6155 | mpt2sas_base_release_callback_handler(ctl_cb_idx); |
5883 | 6156 | ||
6157 | mpt2sas_base_release_callback_handler(tm_tr_cb_idx); | ||
6158 | mpt2sas_base_release_callback_handler(tm_sas_control_cb_idx); | ||
6159 | |||
5884 | mpt2sas_ctl_exit(); | 6160 | mpt2sas_ctl_exit(); |
5885 | } | 6161 | } |
5886 | 6162 | ||
diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c index 4b7201a1e867..8bc57e315ce8 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_transport.c +++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c | |||
@@ -218,9 +218,10 @@ _transport_set_identify(struct MPT2SAS_ADAPTER *ioc, u16 handle, | |||
218 | * Callback handler when sending internal generated transport cmds. | 218 | * Callback handler when sending internal generated transport cmds. |
219 | * The callback index passed is `ioc->transport_cb_idx` | 219 | * The callback index passed is `ioc->transport_cb_idx` |
220 | * | 220 | * |
221 | * Return nothing. | 221 | * Return 1 meaning mf should be freed from _base_interrupt |
222 | * 0 means the mf is freed from this function. | ||
222 | */ | 223 | */ |
223 | void | 224 | u8 |
224 | mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | 225 | mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, |
225 | u32 reply) | 226 | u32 reply) |
226 | { | 227 | { |
@@ -228,9 +229,9 @@ mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | |||
228 | 229 | ||
229 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | 230 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); |
230 | if (ioc->transport_cmds.status == MPT2_CMD_NOT_USED) | 231 | if (ioc->transport_cmds.status == MPT2_CMD_NOT_USED) |
231 | return; | 232 | return 1; |
232 | if (ioc->transport_cmds.smid != smid) | 233 | if (ioc->transport_cmds.smid != smid) |
233 | return; | 234 | return 1; |
234 | ioc->transport_cmds.status |= MPT2_CMD_COMPLETE; | 235 | ioc->transport_cmds.status |= MPT2_CMD_COMPLETE; |
235 | if (mpi_reply) { | 236 | if (mpi_reply) { |
236 | memcpy(ioc->transport_cmds.reply, mpi_reply, | 237 | memcpy(ioc->transport_cmds.reply, mpi_reply, |
@@ -239,6 +240,7 @@ mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | |||
239 | } | 240 | } |
240 | ioc->transport_cmds.status &= ~MPT2_CMD_PENDING; | 241 | ioc->transport_cmds.status &= ~MPT2_CMD_PENDING; |
241 | complete(&ioc->transport_cmds.done); | 242 | complete(&ioc->transport_cmds.done); |
243 | return 1; | ||
242 | } | 244 | } |
243 | 245 | ||
244 | /* report manufacture request structure */ | 246 | /* report manufacture request structure */ |