diff options
Diffstat (limited to 'drivers/scsi/mpt2sas/mpt2sas_scsih.c')
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_scsih.c | 343 |
1 files changed, 136 insertions, 207 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 1a96a00418a4..eda347c57979 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c | |||
@@ -931,31 +931,32 @@ _scsih_scsi_lookup_find_by_lun(struct MPT2SAS_ADAPTER *ioc, int id, | |||
931 | } | 931 | } |
932 | 932 | ||
933 | /** | 933 | /** |
934 | * _scsih_get_chain_buffer_dma - obtain block of chains (dma address) | 934 | * _scsih_get_chain_buffer_tracker - obtain chain tracker |
935 | * @ioc: per adapter object | 935 | * @ioc: per adapter object |
936 | * @smid: system request message index | 936 | * @smid: smid associated to an IO request |
937 | * | 937 | * |
938 | * Returns phys pointer to chain buffer. | 938 | * Returns chain tracker(from ioc->free_chain_list) |
939 | */ | 939 | */ |
940 | static dma_addr_t | 940 | static struct chain_tracker * |
941 | _scsih_get_chain_buffer_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid) | 941 | _scsih_get_chain_buffer_tracker(struct MPT2SAS_ADAPTER *ioc, u16 smid) |
942 | { | 942 | { |
943 | return ioc->chain_dma + ((smid - 1) * (ioc->request_sz * | 943 | struct chain_tracker *chain_req; |
944 | ioc->chains_needed_per_io)); | 944 | unsigned long flags; |
945 | } | ||
946 | 945 | ||
947 | /** | 946 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); |
948 | * _scsih_get_chain_buffer - obtain block of chains assigned to a mf request | 947 | if (list_empty(&ioc->free_chain_list)) { |
949 | * @ioc: per adapter object | 948 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); |
950 | * @smid: system request message index | 949 | printk(MPT2SAS_WARN_FMT "chain buffers not available\n", |
951 | * | 950 | ioc->name); |
952 | * Returns virt pointer to chain buffer. | 951 | return NULL; |
953 | */ | 952 | } |
954 | static void * | 953 | chain_req = list_entry(ioc->free_chain_list.next, |
955 | _scsih_get_chain_buffer(struct MPT2SAS_ADAPTER *ioc, u16 smid) | 954 | struct chain_tracker, tracker_list); |
956 | { | 955 | list_del_init(&chain_req->tracker_list); |
957 | return (void *)(ioc->chain + ((smid - 1) * (ioc->request_sz * | 956 | list_add_tail(&chain_req->tracker_list, |
958 | ioc->chains_needed_per_io))); | 957 | &ioc->scsi_lookup[smid - 1].chain_list); |
958 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
959 | return chain_req; | ||
959 | } | 960 | } |
960 | 961 | ||
961 | /** | 962 | /** |
@@ -986,6 +987,7 @@ _scsih_build_scatter_gather(struct MPT2SAS_ADAPTER *ioc, | |||
986 | u32 sgl_flags; | 987 | u32 sgl_flags; |
987 | u32 sgl_flags_last_element; | 988 | u32 sgl_flags_last_element; |
988 | u32 sgl_flags_end_buffer; | 989 | u32 sgl_flags_end_buffer; |
990 | struct chain_tracker *chain_req; | ||
989 | 991 | ||
990 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | 992 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); |
991 | 993 | ||
@@ -1033,8 +1035,11 @@ _scsih_build_scatter_gather(struct MPT2SAS_ADAPTER *ioc, | |||
1033 | 1035 | ||
1034 | /* initializing the chain flags and pointers */ | 1036 | /* initializing the chain flags and pointers */ |
1035 | chain_flags = MPI2_SGE_FLAGS_CHAIN_ELEMENT << MPI2_SGE_FLAGS_SHIFT; | 1037 | chain_flags = MPI2_SGE_FLAGS_CHAIN_ELEMENT << MPI2_SGE_FLAGS_SHIFT; |
1036 | chain = _scsih_get_chain_buffer(ioc, smid); | 1038 | chain_req = _scsih_get_chain_buffer_tracker(ioc, smid); |
1037 | chain_dma = _scsih_get_chain_buffer_dma(ioc, smid); | 1039 | if (!chain_req) |
1040 | return -1; | ||
1041 | chain = chain_req->chain_buffer; | ||
1042 | chain_dma = chain_req->chain_buffer_dma; | ||
1038 | do { | 1043 | do { |
1039 | sges_in_segment = (sges_left <= | 1044 | sges_in_segment = (sges_left <= |
1040 | ioc->max_sges_in_chain_message) ? sges_left : | 1045 | ioc->max_sges_in_chain_message) ? sges_left : |
@@ -1070,8 +1075,11 @@ _scsih_build_scatter_gather(struct MPT2SAS_ADAPTER *ioc, | |||
1070 | sges_in_segment--; | 1075 | sges_in_segment--; |
1071 | } | 1076 | } |
1072 | 1077 | ||
1073 | chain_dma += ioc->request_sz; | 1078 | chain_req = _scsih_get_chain_buffer_tracker(ioc, smid); |
1074 | chain += ioc->request_sz; | 1079 | if (!chain_req) |
1080 | return -1; | ||
1081 | chain = chain_req->chain_buffer; | ||
1082 | chain_dma = chain_req->chain_buffer_dma; | ||
1075 | } while (1); | 1083 | } while (1); |
1076 | 1084 | ||
1077 | 1085 | ||
@@ -1094,28 +1102,24 @@ _scsih_build_scatter_gather(struct MPT2SAS_ADAPTER *ioc, | |||
1094 | } | 1102 | } |
1095 | 1103 | ||
1096 | /** | 1104 | /** |
1097 | * _scsih_change_queue_depth - setting device queue depth | 1105 | * _scsih_adjust_queue_depth - setting device queue depth |
1098 | * @sdev: scsi device struct | 1106 | * @sdev: scsi device struct |
1099 | * @qdepth: requested queue depth | 1107 | * @qdepth: requested queue depth |
1100 | * @reason: calling context | ||
1101 | * | 1108 | * |
1102 | * Returns queue depth. | 1109 | * |
1110 | * Returns nothing | ||
1103 | */ | 1111 | */ |
1104 | static int | 1112 | static void |
1105 | _scsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason) | 1113 | _scsih_adjust_queue_depth(struct scsi_device *sdev, int qdepth) |
1106 | { | 1114 | { |
1107 | struct Scsi_Host *shost = sdev->host; | 1115 | struct Scsi_Host *shost = sdev->host; |
1108 | int max_depth; | 1116 | int max_depth; |
1109 | int tag_type; | ||
1110 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | 1117 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); |
1111 | struct MPT2SAS_DEVICE *sas_device_priv_data; | 1118 | struct MPT2SAS_DEVICE *sas_device_priv_data; |
1112 | struct MPT2SAS_TARGET *sas_target_priv_data; | 1119 | struct MPT2SAS_TARGET *sas_target_priv_data; |
1113 | struct _sas_device *sas_device; | 1120 | struct _sas_device *sas_device; |
1114 | unsigned long flags; | 1121 | unsigned long flags; |
1115 | 1122 | ||
1116 | if (reason != SCSI_QDEPTH_DEFAULT) | ||
1117 | return -EOPNOTSUPP; | ||
1118 | |||
1119 | max_depth = shost->can_queue; | 1123 | max_depth = shost->can_queue; |
1120 | 1124 | ||
1121 | /* limit max device queue for SATA to 32 */ | 1125 | /* limit max device queue for SATA to 32 */ |
@@ -1141,8 +1145,27 @@ _scsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason) | |||
1141 | max_depth = 1; | 1145 | max_depth = 1; |
1142 | if (qdepth > max_depth) | 1146 | if (qdepth > max_depth) |
1143 | qdepth = max_depth; | 1147 | qdepth = max_depth; |
1144 | tag_type = (qdepth == 1) ? 0 : MSG_SIMPLE_TAG; | 1148 | scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth); |
1145 | scsi_adjust_queue_depth(sdev, tag_type, qdepth); | 1149 | } |
1150 | |||
1151 | /** | ||
1152 | * _scsih_change_queue_depth - setting device queue depth | ||
1153 | * @sdev: scsi device struct | ||
1154 | * @qdepth: requested queue depth | ||
1155 | * @reason: SCSI_QDEPTH_DEFAULT/SCSI_QDEPTH_QFULL/SCSI_QDEPTH_RAMP_UP | ||
1156 | * (see include/scsi/scsi_host.h for definition) | ||
1157 | * | ||
1158 | * Returns queue depth. | ||
1159 | */ | ||
1160 | static int | ||
1161 | _scsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason) | ||
1162 | { | ||
1163 | if (reason == SCSI_QDEPTH_DEFAULT || reason == SCSI_QDEPTH_RAMP_UP) | ||
1164 | _scsih_adjust_queue_depth(sdev, qdepth); | ||
1165 | else if (reason == SCSI_QDEPTH_QFULL) | ||
1166 | scsi_track_queue_full(sdev, qdepth); | ||
1167 | else | ||
1168 | return -EOPNOTSUPP; | ||
1146 | 1169 | ||
1147 | if (sdev->inquiry_len > 7) | 1170 | if (sdev->inquiry_len > 7) |
1148 | sdev_printk(KERN_INFO, sdev, "qdepth(%d), tagged(%d), " | 1171 | sdev_printk(KERN_INFO, sdev, "qdepth(%d), tagged(%d), " |
@@ -2251,13 +2274,13 @@ _scsih_dev_reset(struct scsi_cmnd *scmd) | |||
2251 | 2274 | ||
2252 | struct scsi_target *starget = scmd->device->sdev_target; | 2275 | struct scsi_target *starget = scmd->device->sdev_target; |
2253 | 2276 | ||
2254 | starget_printk(KERN_INFO, starget, "attempting target reset! " | 2277 | starget_printk(KERN_INFO, starget, "attempting device reset! " |
2255 | "scmd(%p)\n", scmd); | 2278 | "scmd(%p)\n", scmd); |
2256 | _scsih_tm_display_info(ioc, scmd); | 2279 | _scsih_tm_display_info(ioc, scmd); |
2257 | 2280 | ||
2258 | sas_device_priv_data = scmd->device->hostdata; | 2281 | sas_device_priv_data = scmd->device->hostdata; |
2259 | if (!sas_device_priv_data || !sas_device_priv_data->sas_target) { | 2282 | if (!sas_device_priv_data || !sas_device_priv_data->sas_target) { |
2260 | starget_printk(KERN_INFO, starget, "target been deleted! " | 2283 | starget_printk(KERN_INFO, starget, "device been deleted! " |
2261 | "scmd(%p)\n", scmd); | 2284 | "scmd(%p)\n", scmd); |
2262 | scmd->result = DID_NO_CONNECT << 16; | 2285 | scmd->result = DID_NO_CONNECT << 16; |
2263 | scmd->scsi_done(scmd); | 2286 | scmd->scsi_done(scmd); |
@@ -2576,9 +2599,9 @@ _scsih_block_io_to_children_attached_to_ex(struct MPT2SAS_ADAPTER *ioc, | |||
2576 | &sas_expander->sas_port_list, port_list) { | 2599 | &sas_expander->sas_port_list, port_list) { |
2577 | 2600 | ||
2578 | if (mpt2sas_port->remote_identify.device_type == | 2601 | if (mpt2sas_port->remote_identify.device_type == |
2579 | MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER || | 2602 | SAS_EDGE_EXPANDER_DEVICE || |
2580 | mpt2sas_port->remote_identify.device_type == | 2603 | mpt2sas_port->remote_identify.device_type == |
2581 | MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER) { | 2604 | SAS_FANOUT_EXPANDER_DEVICE) { |
2582 | 2605 | ||
2583 | spin_lock_irqsave(&ioc->sas_node_lock, flags); | 2606 | spin_lock_irqsave(&ioc->sas_node_lock, flags); |
2584 | expander_sibling = | 2607 | expander_sibling = |
@@ -2715,9 +2738,10 @@ static u8 | |||
2715 | _scsih_sas_control_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, | 2738 | _scsih_sas_control_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, |
2716 | u8 msix_index, u32 reply) | 2739 | u8 msix_index, u32 reply) |
2717 | { | 2740 | { |
2741 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | ||
2718 | Mpi2SasIoUnitControlReply_t *mpi_reply = | 2742 | Mpi2SasIoUnitControlReply_t *mpi_reply = |
2719 | mpt2sas_base_get_reply_virt_addr(ioc, reply); | 2743 | mpt2sas_base_get_reply_virt_addr(ioc, reply); |
2720 | 2744 | #endif | |
2721 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT | 2745 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT |
2722 | "sc_complete:handle(0x%04x), (open) " | 2746 | "sc_complete:handle(0x%04x), (open) " |
2723 | "smid(%d), ioc_status(0x%04x), loginfo(0x%08x)\n", | 2747 | "smid(%d), ioc_status(0x%04x), loginfo(0x%08x)\n", |
@@ -3963,6 +3987,7 @@ _scsih_sas_host_refresh(struct MPT2SAS_ADAPTER *ioc) | |||
3963 | Mpi2ConfigReply_t mpi_reply; | 3987 | Mpi2ConfigReply_t mpi_reply; |
3964 | Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL; | 3988 | Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL; |
3965 | u16 attached_handle; | 3989 | u16 attached_handle; |
3990 | u8 link_rate; | ||
3966 | 3991 | ||
3967 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT | 3992 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT |
3968 | "updating handles for sas_host(0x%016llx)\n", | 3993 | "updating handles for sas_host(0x%016llx)\n", |
@@ -3984,15 +4009,17 @@ _scsih_sas_host_refresh(struct MPT2SAS_ADAPTER *ioc) | |||
3984 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) | 4009 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) |
3985 | goto out; | 4010 | goto out; |
3986 | for (i = 0; i < ioc->sas_hba.num_phys ; i++) { | 4011 | for (i = 0; i < ioc->sas_hba.num_phys ; i++) { |
4012 | link_rate = sas_iounit_pg0->PhyData[i].NegotiatedLinkRate >> 4; | ||
3987 | if (i == 0) | 4013 | if (i == 0) |
3988 | ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0-> | 4014 | ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0-> |
3989 | PhyData[0].ControllerDevHandle); | 4015 | PhyData[0].ControllerDevHandle); |
3990 | ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle; | 4016 | ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle; |
3991 | attached_handle = le16_to_cpu(sas_iounit_pg0->PhyData[i]. | 4017 | attached_handle = le16_to_cpu(sas_iounit_pg0->PhyData[i]. |
3992 | AttachedDevHandle); | 4018 | AttachedDevHandle); |
4019 | if (attached_handle && link_rate < MPI2_SAS_NEG_LINK_RATE_1_5) | ||
4020 | link_rate = MPI2_SAS_NEG_LINK_RATE_1_5; | ||
3993 | mpt2sas_transport_update_links(ioc, ioc->sas_hba.sas_address, | 4021 | mpt2sas_transport_update_links(ioc, ioc->sas_hba.sas_address, |
3994 | attached_handle, i, sas_iounit_pg0->PhyData[i]. | 4022 | attached_handle, i, link_rate); |
3995 | NegotiatedLinkRate >> 4); | ||
3996 | } | 4023 | } |
3997 | out: | 4024 | out: |
3998 | kfree(sas_iounit_pg0); | 4025 | kfree(sas_iounit_pg0); |
@@ -4336,14 +4363,14 @@ _scsih_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | |||
4336 | } | 4363 | } |
4337 | 4364 | ||
4338 | /** | 4365 | /** |
4339 | * _scsih_expander_remove - removing expander object | 4366 | * mpt2sas_expander_remove - removing expander object |
4340 | * @ioc: per adapter object | 4367 | * @ioc: per adapter object |
4341 | * @sas_address: expander sas_address | 4368 | * @sas_address: expander sas_address |
4342 | * | 4369 | * |
4343 | * Return nothing. | 4370 | * Return nothing. |
4344 | */ | 4371 | */ |
4345 | static void | 4372 | void |
4346 | _scsih_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address) | 4373 | mpt2sas_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address) |
4347 | { | 4374 | { |
4348 | struct _sas_node *sas_expander; | 4375 | struct _sas_node *sas_expander; |
4349 | unsigned long flags; | 4376 | unsigned long flags; |
@@ -4354,6 +4381,11 @@ _scsih_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address) | |||
4354 | spin_lock_irqsave(&ioc->sas_node_lock, flags); | 4381 | spin_lock_irqsave(&ioc->sas_node_lock, flags); |
4355 | sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc, | 4382 | sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc, |
4356 | sas_address); | 4383 | sas_address); |
4384 | if (!sas_expander) { | ||
4385 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | ||
4386 | return; | ||
4387 | } | ||
4388 | list_del(&sas_expander->list); | ||
4357 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | 4389 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); |
4358 | _scsih_expander_node_remove(ioc, sas_expander); | 4390 | _scsih_expander_node_remove(ioc, sas_expander); |
4359 | } | 4391 | } |
@@ -4643,6 +4675,33 @@ _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc, | |||
4643 | sas_device_backup.sas_address)); | 4675 | sas_device_backup.sas_address)); |
4644 | } | 4676 | } |
4645 | 4677 | ||
4678 | /** | ||
4679 | * mpt2sas_device_remove - removing device object | ||
4680 | * @ioc: per adapter object | ||
4681 | * @sas_address: expander sas_address | ||
4682 | * | ||
4683 | * Return nothing. | ||
4684 | */ | ||
4685 | void | ||
4686 | mpt2sas_device_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address) | ||
4687 | { | ||
4688 | struct _sas_device *sas_device; | ||
4689 | unsigned long flags; | ||
4690 | |||
4691 | if (ioc->shost_recovery) | ||
4692 | return; | ||
4693 | |||
4694 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
4695 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | ||
4696 | sas_address); | ||
4697 | if (!sas_device) { | ||
4698 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
4699 | return; | ||
4700 | } | ||
4701 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
4702 | _scsih_remove_device(ioc, sas_device); | ||
4703 | } | ||
4704 | |||
4646 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | 4705 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING |
4647 | /** | 4706 | /** |
4648 | * _scsih_sas_topology_change_event_debug - debug for topology event | 4707 | * _scsih_sas_topology_change_event_debug - debug for topology event |
@@ -4737,7 +4796,7 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, | |||
4737 | int i; | 4796 | int i; |
4738 | u16 parent_handle, handle; | 4797 | u16 parent_handle, handle; |
4739 | u16 reason_code; | 4798 | u16 reason_code; |
4740 | u8 phy_number; | 4799 | u8 phy_number, max_phys; |
4741 | struct _sas_node *sas_expander; | 4800 | struct _sas_node *sas_expander; |
4742 | struct _sas_device *sas_device; | 4801 | struct _sas_device *sas_device; |
4743 | u64 sas_address; | 4802 | u64 sas_address; |
@@ -4775,11 +4834,13 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, | |||
4775 | sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc, | 4834 | sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc, |
4776 | parent_handle); | 4835 | parent_handle); |
4777 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | 4836 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); |
4778 | if (sas_expander) | 4837 | if (sas_expander) { |
4779 | sas_address = sas_expander->sas_address; | 4838 | sas_address = sas_expander->sas_address; |
4780 | else if (parent_handle < ioc->sas_hba.num_phys) | 4839 | max_phys = sas_expander->num_phys; |
4840 | } else if (parent_handle < ioc->sas_hba.num_phys) { | ||
4781 | sas_address = ioc->sas_hba.sas_address; | 4841 | sas_address = ioc->sas_hba.sas_address; |
4782 | else | 4842 | max_phys = ioc->sas_hba.num_phys; |
4843 | } else | ||
4783 | return; | 4844 | return; |
4784 | 4845 | ||
4785 | /* handle siblings events */ | 4846 | /* handle siblings events */ |
@@ -4793,6 +4854,8 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, | |||
4793 | ioc->pci_error_recovery) | 4854 | ioc->pci_error_recovery) |
4794 | return; | 4855 | return; |
4795 | phy_number = event_data->StartPhyNum + i; | 4856 | phy_number = event_data->StartPhyNum + i; |
4857 | if (phy_number >= max_phys) | ||
4858 | continue; | ||
4796 | reason_code = event_data->PHY[i].PhyStatus & | 4859 | reason_code = event_data->PHY[i].PhyStatus & |
4797 | MPI2_EVENT_SAS_TOPO_RC_MASK; | 4860 | MPI2_EVENT_SAS_TOPO_RC_MASK; |
4798 | if ((event_data->PHY[i].PhyStatus & | 4861 | if ((event_data->PHY[i].PhyStatus & |
@@ -4844,7 +4907,7 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, | |||
4844 | /* handle expander removal */ | 4907 | /* handle expander removal */ |
4845 | if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING && | 4908 | if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING && |
4846 | sas_expander) | 4909 | sas_expander) |
4847 | _scsih_expander_remove(ioc, sas_address); | 4910 | mpt2sas_expander_remove(ioc, sas_address); |
4848 | 4911 | ||
4849 | } | 4912 | } |
4850 | 4913 | ||
@@ -5773,90 +5836,6 @@ _scsih_sas_ir_operation_status_event(struct MPT2SAS_ADAPTER *ioc, | |||
5773 | } | 5836 | } |
5774 | 5837 | ||
5775 | /** | 5838 | /** |
5776 | * _scsih_task_set_full - handle task set full | ||
5777 | * @ioc: per adapter object | ||
5778 | * @fw_event: The fw_event_work object | ||
5779 | * Context: user. | ||
5780 | * | ||
5781 | * Throttle back qdepth. | ||
5782 | */ | ||
5783 | static void | ||
5784 | _scsih_task_set_full(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work | ||
5785 | *fw_event) | ||
5786 | { | ||
5787 | unsigned long flags; | ||
5788 | struct _sas_device *sas_device; | ||
5789 | static struct _raid_device *raid_device; | ||
5790 | struct scsi_device *sdev; | ||
5791 | int depth; | ||
5792 | u16 current_depth; | ||
5793 | u16 handle; | ||
5794 | int id, channel; | ||
5795 | u64 sas_address; | ||
5796 | Mpi2EventDataTaskSetFull_t *event_data = fw_event->event_data; | ||
5797 | |||
5798 | current_depth = le16_to_cpu(event_data->CurrentDepth); | ||
5799 | handle = le16_to_cpu(event_data->DevHandle); | ||
5800 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
5801 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | ||
5802 | if (!sas_device) { | ||
5803 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
5804 | return; | ||
5805 | } | ||
5806 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
5807 | id = sas_device->id; | ||
5808 | channel = sas_device->channel; | ||
5809 | sas_address = sas_device->sas_address; | ||
5810 | |||
5811 | /* if hidden raid component, then change to volume characteristics */ | ||
5812 | if (test_bit(handle, ioc->pd_handles) && sas_device->volume_handle) { | ||
5813 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | ||
5814 | raid_device = _scsih_raid_device_find_by_handle( | ||
5815 | ioc, sas_device->volume_handle); | ||
5816 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | ||
5817 | if (raid_device) { | ||
5818 | id = raid_device->id; | ||
5819 | channel = raid_device->channel; | ||
5820 | handle = raid_device->handle; | ||
5821 | sas_address = raid_device->wwid; | ||
5822 | } | ||
5823 | } | ||
5824 | |||
5825 | if (ioc->logging_level & MPT_DEBUG_TASK_SET_FULL) | ||
5826 | starget_printk(KERN_INFO, sas_device->starget, "task set " | ||
5827 | "full: handle(0x%04x), sas_addr(0x%016llx), depth(%d)\n", | ||
5828 | handle, (unsigned long long)sas_address, current_depth); | ||
5829 | |||
5830 | shost_for_each_device(sdev, ioc->shost) { | ||
5831 | if (sdev->id == id && sdev->channel == channel) { | ||
5832 | if (current_depth > sdev->queue_depth) { | ||
5833 | if (ioc->logging_level & | ||
5834 | MPT_DEBUG_TASK_SET_FULL) | ||
5835 | sdev_printk(KERN_INFO, sdev, "strange " | ||
5836 | "observation, the queue depth is" | ||
5837 | " (%d) meanwhile fw queue depth " | ||
5838 | "is (%d)\n", sdev->queue_depth, | ||
5839 | current_depth); | ||
5840 | continue; | ||
5841 | } | ||
5842 | depth = scsi_track_queue_full(sdev, | ||
5843 | current_depth - 1); | ||
5844 | if (depth > 0) | ||
5845 | sdev_printk(KERN_INFO, sdev, "Queue depth " | ||
5846 | "reduced to (%d)\n", depth); | ||
5847 | else if (depth < 0) | ||
5848 | sdev_printk(KERN_INFO, sdev, "Tagged Command " | ||
5849 | "Queueing is being disabled\n"); | ||
5850 | else if (depth == 0) | ||
5851 | if (ioc->logging_level & | ||
5852 | MPT_DEBUG_TASK_SET_FULL) | ||
5853 | sdev_printk(KERN_INFO, sdev, | ||
5854 | "Queue depth not changed yet\n"); | ||
5855 | } | ||
5856 | } | ||
5857 | } | ||
5858 | |||
5859 | /** | ||
5860 | * _scsih_prep_device_scan - initialize parameters prior to device scan | 5839 | * _scsih_prep_device_scan - initialize parameters prior to device scan |
5861 | * @ioc: per adapter object | 5840 | * @ioc: per adapter object |
5862 | * | 5841 | * |
@@ -6219,7 +6198,7 @@ _scsih_remove_unresponding_sas_devices(struct MPT2SAS_ADAPTER *ioc) | |||
6219 | sas_expander->responding = 0; | 6198 | sas_expander->responding = 0; |
6220 | continue; | 6199 | continue; |
6221 | } | 6200 | } |
6222 | _scsih_expander_remove(ioc, sas_expander->sas_address); | 6201 | mpt2sas_expander_remove(ioc, sas_expander->sas_address); |
6223 | goto retry_expander_search; | 6202 | goto retry_expander_search; |
6224 | } | 6203 | } |
6225 | } | 6204 | } |
@@ -6343,9 +6322,6 @@ _firmware_event_work(struct work_struct *work) | |||
6343 | case MPI2_EVENT_IR_OPERATION_STATUS: | 6322 | case MPI2_EVENT_IR_OPERATION_STATUS: |
6344 | _scsih_sas_ir_operation_status_event(ioc, fw_event); | 6323 | _scsih_sas_ir_operation_status_event(ioc, fw_event); |
6345 | break; | 6324 | break; |
6346 | case MPI2_EVENT_TASK_SET_FULL: | ||
6347 | _scsih_task_set_full(ioc, fw_event); | ||
6348 | break; | ||
6349 | } | 6325 | } |
6350 | _scsih_fw_event_free(ioc, fw_event); | 6326 | _scsih_fw_event_free(ioc, fw_event); |
6351 | } | 6327 | } |
@@ -6415,7 +6391,6 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, | |||
6415 | case MPI2_EVENT_SAS_DISCOVERY: | 6391 | case MPI2_EVENT_SAS_DISCOVERY: |
6416 | case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE: | 6392 | case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE: |
6417 | case MPI2_EVENT_IR_PHYSICAL_DISK: | 6393 | case MPI2_EVENT_IR_PHYSICAL_DISK: |
6418 | case MPI2_EVENT_TASK_SET_FULL: | ||
6419 | break; | 6394 | break; |
6420 | 6395 | ||
6421 | default: /* ignore the rest */ | 6396 | default: /* ignore the rest */ |
@@ -6490,56 +6465,23 @@ static void | |||
6490 | _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc, | 6465 | _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc, |
6491 | struct _sas_node *sas_expander) | 6466 | struct _sas_node *sas_expander) |
6492 | { | 6467 | { |
6493 | struct _sas_port *mpt2sas_port; | 6468 | struct _sas_port *mpt2sas_port, *next; |
6494 | struct _sas_device *sas_device; | ||
6495 | struct _sas_node *expander_sibling; | ||
6496 | unsigned long flags; | ||
6497 | |||
6498 | if (!sas_expander) | ||
6499 | return; | ||
6500 | 6469 | ||
6501 | /* remove sibling ports attached to this expander */ | 6470 | /* remove sibling ports attached to this expander */ |
6502 | retry_device_search: | 6471 | list_for_each_entry_safe(mpt2sas_port, next, |
6503 | list_for_each_entry(mpt2sas_port, | ||
6504 | &sas_expander->sas_port_list, port_list) { | 6472 | &sas_expander->sas_port_list, port_list) { |
6473 | if (ioc->shost_recovery) | ||
6474 | return; | ||
6505 | if (mpt2sas_port->remote_identify.device_type == | 6475 | if (mpt2sas_port->remote_identify.device_type == |
6506 | SAS_END_DEVICE) { | 6476 | SAS_END_DEVICE) |
6507 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 6477 | mpt2sas_device_remove(ioc, |
6508 | sas_device = | 6478 | mpt2sas_port->remote_identify.sas_address); |
6509 | mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | 6479 | else if (mpt2sas_port->remote_identify.device_type == |
6510 | mpt2sas_port->remote_identify.sas_address); | 6480 | SAS_EDGE_EXPANDER_DEVICE || |
6511 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
6512 | if (!sas_device) | ||
6513 | continue; | ||
6514 | _scsih_remove_device(ioc, sas_device); | ||
6515 | if (ioc->shost_recovery) | ||
6516 | return; | ||
6517 | goto retry_device_search; | ||
6518 | } | ||
6519 | } | ||
6520 | |||
6521 | retry_expander_search: | ||
6522 | list_for_each_entry(mpt2sas_port, | ||
6523 | &sas_expander->sas_port_list, port_list) { | ||
6524 | |||
6525 | if (mpt2sas_port->remote_identify.device_type == | ||
6526 | MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER || | ||
6527 | mpt2sas_port->remote_identify.device_type == | 6481 | mpt2sas_port->remote_identify.device_type == |
6528 | MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER) { | 6482 | SAS_FANOUT_EXPANDER_DEVICE) |
6529 | 6483 | mpt2sas_expander_remove(ioc, | |
6530 | spin_lock_irqsave(&ioc->sas_node_lock, flags); | 6484 | mpt2sas_port->remote_identify.sas_address); |
6531 | expander_sibling = | ||
6532 | mpt2sas_scsih_expander_find_by_sas_address( | ||
6533 | ioc, mpt2sas_port->remote_identify.sas_address); | ||
6534 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | ||
6535 | if (!expander_sibling) | ||
6536 | continue; | ||
6537 | _scsih_expander_remove(ioc, | ||
6538 | expander_sibling->sas_address); | ||
6539 | if (ioc->shost_recovery) | ||
6540 | return; | ||
6541 | goto retry_expander_search; | ||
6542 | } | ||
6543 | } | 6485 | } |
6544 | 6486 | ||
6545 | mpt2sas_transport_port_remove(ioc, sas_expander->sas_address, | 6487 | mpt2sas_transport_port_remove(ioc, sas_expander->sas_address, |
@@ -6550,7 +6492,6 @@ _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc, | |||
6550 | sas_expander->handle, (unsigned long long) | 6492 | sas_expander->handle, (unsigned long long) |
6551 | sas_expander->sas_address); | 6493 | sas_expander->sas_address); |
6552 | 6494 | ||
6553 | list_del(&sas_expander->list); | ||
6554 | kfree(sas_expander->phy); | 6495 | kfree(sas_expander->phy); |
6555 | kfree(sas_expander); | 6496 | kfree(sas_expander); |
6556 | } | 6497 | } |
@@ -6668,9 +6609,7 @@ _scsih_remove(struct pci_dev *pdev) | |||
6668 | { | 6609 | { |
6669 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | 6610 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
6670 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | 6611 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); |
6671 | struct _sas_port *mpt2sas_port; | 6612 | struct _sas_port *mpt2sas_port, *next_port; |
6672 | struct _sas_device *sas_device; | ||
6673 | struct _sas_node *expander_sibling; | ||
6674 | struct _raid_device *raid_device, *next; | 6613 | struct _raid_device *raid_device, *next; |
6675 | struct MPT2SAS_TARGET *sas_target_priv_data; | 6614 | struct MPT2SAS_TARGET *sas_target_priv_data; |
6676 | struct workqueue_struct *wq; | 6615 | struct workqueue_struct *wq; |
@@ -6702,28 +6641,18 @@ _scsih_remove(struct pci_dev *pdev) | |||
6702 | } | 6641 | } |
6703 | 6642 | ||
6704 | /* free ports attached to the sas_host */ | 6643 | /* free ports attached to the sas_host */ |
6705 | retry_again: | 6644 | list_for_each_entry_safe(mpt2sas_port, next_port, |
6706 | list_for_each_entry(mpt2sas_port, | ||
6707 | &ioc->sas_hba.sas_port_list, port_list) { | 6645 | &ioc->sas_hba.sas_port_list, port_list) { |
6708 | if (mpt2sas_port->remote_identify.device_type == | 6646 | if (mpt2sas_port->remote_identify.device_type == |
6709 | SAS_END_DEVICE) { | 6647 | SAS_END_DEVICE) |
6710 | sas_device = | 6648 | mpt2sas_device_remove(ioc, |
6711 | mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | 6649 | mpt2sas_port->remote_identify.sas_address); |
6712 | mpt2sas_port->remote_identify.sas_address); | 6650 | else if (mpt2sas_port->remote_identify.device_type == |
6713 | if (sas_device) { | 6651 | SAS_EDGE_EXPANDER_DEVICE || |
6714 | _scsih_remove_device(ioc, sas_device); | 6652 | mpt2sas_port->remote_identify.device_type == |
6715 | goto retry_again; | 6653 | SAS_FANOUT_EXPANDER_DEVICE) |
6716 | } | 6654 | mpt2sas_expander_remove(ioc, |
6717 | } else { | ||
6718 | expander_sibling = | ||
6719 | mpt2sas_scsih_expander_find_by_sas_address(ioc, | ||
6720 | mpt2sas_port->remote_identify.sas_address); | 6655 | mpt2sas_port->remote_identify.sas_address); |
6721 | if (expander_sibling) { | ||
6722 | _scsih_expander_remove(ioc, | ||
6723 | expander_sibling->sas_address); | ||
6724 | goto retry_again; | ||
6725 | } | ||
6726 | } | ||
6727 | } | 6656 | } |
6728 | 6657 | ||
6729 | /* free phys attached to the sas_host */ | 6658 | /* free phys attached to the sas_host */ |