aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc
diff options
context:
space:
mode:
authorJames Smart <james.smart@emulex.com>2013-04-17 20:17:40 -0400
committerJames Bottomley <JBottomley@Parallels.com>2013-05-02 16:01:30 -0400
commita40fc5f0d052d468f66da5fab3be0adb6cb6443d (patch)
treef0e686c83a78ff12d32761e30a36eb8a2a425190 /drivers/scsi/lpfc
parentd5ce53b7dd497f8e5a5e4bbc736312b34fe452bd (diff)
[SCSI] lpfc 8.3.39: Reduced spinlock contention on SCSI buffer list
Signed-off-by: James Smart <james.smart@emulex.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r--drivers/scsi/lpfc/lpfc.h6
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c54
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c93
3 files changed, 102 insertions, 51 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 924ceaaf1336..2d2261f4eab0 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -813,8 +813,10 @@ struct lpfc_hba {
813 uint64_t bg_reftag_err_cnt; 813 uint64_t bg_reftag_err_cnt;
814 814
815 /* fastpath list. */ 815 /* fastpath list. */
816 spinlock_t scsi_buf_list_lock; 816 spinlock_t scsi_buf_list_get_lock; /* SCSI buf alloc list lock */
817 struct list_head lpfc_scsi_buf_list; 817 spinlock_t scsi_buf_list_put_lock; /* SCSI buf free list lock */
818 struct list_head lpfc_scsi_buf_list_get;
819 struct list_head lpfc_scsi_buf_list_put;
818 uint32_t total_scsi_bufs; 820 uint32_t total_scsi_bufs;
819 struct list_head lpfc_iocb_list; 821 struct list_head lpfc_iocb_list;
820 uint32_t total_iocbq_bufs; 822 uint32_t total_iocbq_bufs;
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 7bb89f49df9b..207d3ec05b83 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -911,9 +911,9 @@ lpfc_hba_down_post_s4(struct lpfc_hba *phba)
911 psb->pCmd = NULL; 911 psb->pCmd = NULL;
912 psb->status = IOSTAT_SUCCESS; 912 psb->status = IOSTAT_SUCCESS;
913 } 913 }
914 spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag); 914 spin_lock_irqsave(&phba->scsi_buf_list_put_lock, iflag);
915 list_splice(&aborts, &phba->lpfc_scsi_buf_list); 915 list_splice(&aborts, &phba->lpfc_scsi_buf_list_put);
916 spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag); 916 spin_unlock_irqrestore(&phba->scsi_buf_list_put_lock, iflag);
917 return 0; 917 return 0;
918} 918}
919 919
@@ -2854,16 +2854,30 @@ lpfc_scsi_free(struct lpfc_hba *phba)
2854 struct lpfc_iocbq *io, *io_next; 2854 struct lpfc_iocbq *io, *io_next;
2855 2855
2856 spin_lock_irq(&phba->hbalock); 2856 spin_lock_irq(&phba->hbalock);
2857
2857 /* Release all the lpfc_scsi_bufs maintained by this host. */ 2858 /* Release all the lpfc_scsi_bufs maintained by this host. */
2858 spin_lock(&phba->scsi_buf_list_lock); 2859
2859 list_for_each_entry_safe(sb, sb_next, &phba->lpfc_scsi_buf_list, list) { 2860 spin_lock(&phba->scsi_buf_list_put_lock);
2861 list_for_each_entry_safe(sb, sb_next, &phba->lpfc_scsi_buf_list_put,
2862 list) {
2863 list_del(&sb->list);
2864 pci_pool_free(phba->lpfc_scsi_dma_buf_pool, sb->data,
2865 sb->dma_handle);
2866 kfree(sb);
2867 phba->total_scsi_bufs--;
2868 }
2869 spin_unlock(&phba->scsi_buf_list_put_lock);
2870
2871 spin_lock(&phba->scsi_buf_list_get_lock);
2872 list_for_each_entry_safe(sb, sb_next, &phba->lpfc_scsi_buf_list_get,
2873 list) {
2860 list_del(&sb->list); 2874 list_del(&sb->list);
2861 pci_pool_free(phba->lpfc_scsi_dma_buf_pool, sb->data, 2875 pci_pool_free(phba->lpfc_scsi_dma_buf_pool, sb->data,
2862 sb->dma_handle); 2876 sb->dma_handle);
2863 kfree(sb); 2877 kfree(sb);
2864 phba->total_scsi_bufs--; 2878 phba->total_scsi_bufs--;
2865 } 2879 }
2866 spin_unlock(&phba->scsi_buf_list_lock); 2880 spin_unlock(&phba->scsi_buf_list_get_lock);
2867 2881
2868 /* Release all the lpfc_iocbq entries maintained by this host. */ 2882 /* Release all the lpfc_iocbq entries maintained by this host. */
2869 list_for_each_entry_safe(io, io_next, &phba->lpfc_iocb_list, list) { 2883 list_for_each_entry_safe(io, io_next, &phba->lpfc_iocb_list, list) {
@@ -2999,9 +3013,12 @@ lpfc_sli4_xri_sgl_update(struct lpfc_hba *phba)
2999 phba->sli4_hba.scsi_xri_cnt, 3013 phba->sli4_hba.scsi_xri_cnt,
3000 phba->sli4_hba.scsi_xri_max); 3014 phba->sli4_hba.scsi_xri_max);
3001 3015
3002 spin_lock_irq(&phba->scsi_buf_list_lock); 3016 spin_lock_irq(&phba->scsi_buf_list_get_lock);
3003 list_splice_init(&phba->lpfc_scsi_buf_list, &scsi_sgl_list); 3017 spin_lock_irq(&phba->scsi_buf_list_put_lock);
3004 spin_unlock_irq(&phba->scsi_buf_list_lock); 3018 list_splice_init(&phba->lpfc_scsi_buf_list_get, &scsi_sgl_list);
3019 list_splice(&phba->lpfc_scsi_buf_list_put, &scsi_sgl_list);
3020 spin_unlock_irq(&phba->scsi_buf_list_put_lock);
3021 spin_unlock_irq(&phba->scsi_buf_list_get_lock);
3005 3022
3006 if (phba->sli4_hba.scsi_xri_cnt > phba->sli4_hba.scsi_xri_max) { 3023 if (phba->sli4_hba.scsi_xri_cnt > phba->sli4_hba.scsi_xri_max) {
3007 /* max scsi xri shrinked below the allocated scsi buffers */ 3024 /* max scsi xri shrinked below the allocated scsi buffers */
@@ -3015,9 +3032,9 @@ lpfc_sli4_xri_sgl_update(struct lpfc_hba *phba)
3015 psb->dma_handle); 3032 psb->dma_handle);
3016 kfree(psb); 3033 kfree(psb);
3017 } 3034 }
3018 spin_lock_irq(&phba->scsi_buf_list_lock); 3035 spin_lock_irq(&phba->scsi_buf_list_get_lock);
3019 phba->sli4_hba.scsi_xri_cnt -= scsi_xri_cnt; 3036 phba->sli4_hba.scsi_xri_cnt -= scsi_xri_cnt;
3020 spin_unlock_irq(&phba->scsi_buf_list_lock); 3037 spin_unlock_irq(&phba->scsi_buf_list_get_lock);
3021 } 3038 }
3022 3039
3023 /* update xris associated to remaining allocated scsi buffers */ 3040 /* update xris associated to remaining allocated scsi buffers */
@@ -3035,9 +3052,12 @@ lpfc_sli4_xri_sgl_update(struct lpfc_hba *phba)
3035 psb->cur_iocbq.sli4_lxritag = lxri; 3052 psb->cur_iocbq.sli4_lxritag = lxri;
3036 psb->cur_iocbq.sli4_xritag = phba->sli4_hba.xri_ids[lxri]; 3053 psb->cur_iocbq.sli4_xritag = phba->sli4_hba.xri_ids[lxri];
3037 } 3054 }
3038 spin_lock_irq(&phba->scsi_buf_list_lock); 3055 spin_lock_irq(&phba->scsi_buf_list_get_lock);
3039 list_splice_init(&scsi_sgl_list, &phba->lpfc_scsi_buf_list); 3056 spin_lock_irq(&phba->scsi_buf_list_put_lock);
3040 spin_unlock_irq(&phba->scsi_buf_list_lock); 3057 list_splice_init(&scsi_sgl_list, &phba->lpfc_scsi_buf_list_get);
3058 INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list_put);
3059 spin_unlock_irq(&phba->scsi_buf_list_put_lock);
3060 spin_unlock_irq(&phba->scsi_buf_list_get_lock);
3041 3061
3042 return 0; 3062 return 0;
3043 3063
@@ -5334,8 +5354,10 @@ lpfc_setup_driver_resource_phase1(struct lpfc_hba *phba)
5334 init_waitqueue_head(&phba->work_waitq); 5354 init_waitqueue_head(&phba->work_waitq);
5335 5355
5336 /* Initialize the scsi buffer list used by driver for scsi IO */ 5356 /* Initialize the scsi buffer list used by driver for scsi IO */
5337 spin_lock_init(&phba->scsi_buf_list_lock); 5357 spin_lock_init(&phba->scsi_buf_list_get_lock);
5338 INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list); 5358 INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list_get);
5359 spin_lock_init(&phba->scsi_buf_list_put_lock);
5360 INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list_put);
5339 5361
5340 /* Initialize the fabric iocb list */ 5362 /* Initialize the fabric iocb list */
5341 INIT_LIST_HEAD(&phba->fabric_iocb_list); 5363 INIT_LIST_HEAD(&phba->fabric_iocb_list);
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index c79b4dc8aa4a..be11bb9cb176 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -899,9 +899,12 @@ lpfc_sli4_repost_scsi_sgl_list(struct lpfc_hba *phba)
899 int num_posted, rc = 0; 899 int num_posted, rc = 0;
900 900
901 /* get all SCSI buffers need to repost to a local list */ 901 /* get all SCSI buffers need to repost to a local list */
902 spin_lock_irq(&phba->scsi_buf_list_lock); 902 spin_lock_irq(&phba->scsi_buf_list_get_lock);
903 list_splice_init(&phba->lpfc_scsi_buf_list, &post_sblist); 903 spin_lock_irq(&phba->scsi_buf_list_put_lock);
904 spin_unlock_irq(&phba->scsi_buf_list_lock); 904 list_splice_init(&phba->lpfc_scsi_buf_list_get, &post_sblist);
905 list_splice(&phba->lpfc_scsi_buf_list_put, &post_sblist);
906 spin_unlock_irq(&phba->scsi_buf_list_put_lock);
907 spin_unlock_irq(&phba->scsi_buf_list_get_lock);
905 908
906 /* post the list of scsi buffer sgls to port if available */ 909 /* post the list of scsi buffer sgls to port if available */
907 if (!list_empty(&post_sblist)) { 910 if (!list_empty(&post_sblist)) {
@@ -1053,9 +1056,9 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc)
1053 1056
1054 /* add the scsi buffer to a post list */ 1057 /* add the scsi buffer to a post list */
1055 list_add_tail(&psb->list, &post_sblist); 1058 list_add_tail(&psb->list, &post_sblist);
1056 spin_lock_irq(&phba->scsi_buf_list_lock); 1059 spin_lock_irq(&phba->scsi_buf_list_get_lock);
1057 phba->sli4_hba.scsi_xri_cnt++; 1060 phba->sli4_hba.scsi_xri_cnt++;
1058 spin_unlock_irq(&phba->scsi_buf_list_lock); 1061 spin_unlock_irq(&phba->scsi_buf_list_get_lock);
1059 } 1062 }
1060 lpfc_printf_log(phba, KERN_INFO, LOG_BG, 1063 lpfc_printf_log(phba, KERN_INFO, LOG_BG,
1061 "3021 Allocate %d out of %d requested new SCSI " 1064 "3021 Allocate %d out of %d requested new SCSI "
@@ -1104,17 +1107,23 @@ static struct lpfc_scsi_buf*
1104lpfc_get_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) 1107lpfc_get_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
1105{ 1108{
1106 struct lpfc_scsi_buf * lpfc_cmd = NULL; 1109 struct lpfc_scsi_buf * lpfc_cmd = NULL;
1107 struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list; 1110 struct list_head *scsi_buf_list_get = &phba->lpfc_scsi_buf_list_get;
1108 unsigned long iflag = 0; 1111 unsigned long gflag = 0;
1109 1112 unsigned long pflag = 0;
1110 spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag); 1113
1111 list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list); 1114 spin_lock_irqsave(&phba->scsi_buf_list_get_lock, gflag);
1112 if (lpfc_cmd) { 1115 list_remove_head(scsi_buf_list_get, lpfc_cmd, struct lpfc_scsi_buf,
1113 lpfc_cmd->seg_cnt = 0; 1116 list);
1114 lpfc_cmd->nonsg_phys = 0; 1117 if (!lpfc_cmd) {
1115 lpfc_cmd->prot_seg_cnt = 0; 1118 spin_lock_irqsave(&phba->scsi_buf_list_put_lock, pflag);
1119 list_splice(&phba->lpfc_scsi_buf_list_put,
1120 &phba->lpfc_scsi_buf_list_get);
1121 INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list_put);
1122 list_remove_head(scsi_buf_list_get, lpfc_cmd,
1123 struct lpfc_scsi_buf, list);
1124 spin_unlock_irqrestore(&phba->scsi_buf_list_put_lock, pflag);
1116 } 1125 }
1117 spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag); 1126 spin_unlock_irqrestore(&phba->scsi_buf_list_get_lock, gflag);
1118 return lpfc_cmd; 1127 return lpfc_cmd;
1119} 1128}
1120/** 1129/**
@@ -1132,28 +1141,39 @@ static struct lpfc_scsi_buf*
1132lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) 1141lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
1133{ 1142{
1134 struct lpfc_scsi_buf *lpfc_cmd ; 1143 struct lpfc_scsi_buf *lpfc_cmd ;
1135 unsigned long iflag = 0; 1144 unsigned long gflag = 0;
1145 unsigned long pflag = 0;
1136 int found = 0; 1146 int found = 0;
1137 1147
1138 spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag); 1148 spin_lock_irqsave(&phba->scsi_buf_list_get_lock, gflag);
1139 list_for_each_entry(lpfc_cmd, &phba->lpfc_scsi_buf_list, 1149 list_for_each_entry(lpfc_cmd, &phba->lpfc_scsi_buf_list_get, list) {
1140 list) {
1141 if (lpfc_test_rrq_active(phba, ndlp, 1150 if (lpfc_test_rrq_active(phba, ndlp,
1142 lpfc_cmd->cur_iocbq.sli4_lxritag)) 1151 lpfc_cmd->cur_iocbq.sli4_lxritag))
1143 continue; 1152 continue;
1144 list_del(&lpfc_cmd->list); 1153 list_del(&lpfc_cmd->list);
1145 found = 1; 1154 found = 1;
1146 lpfc_cmd->seg_cnt = 0;
1147 lpfc_cmd->nonsg_phys = 0;
1148 lpfc_cmd->prot_seg_cnt = 0;
1149 break; 1155 break;
1150 } 1156 }
1151 spin_unlock_irqrestore(&phba->scsi_buf_list_lock, 1157 if (!found) {
1152 iflag); 1158 spin_lock_irqsave(&phba->scsi_buf_list_put_lock, pflag);
1159 list_splice(&phba->lpfc_scsi_buf_list_put,
1160 &phba->lpfc_scsi_buf_list_get);
1161 INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list_put);
1162 spin_unlock_irqrestore(&phba->scsi_buf_list_put_lock, pflag);
1163 list_for_each_entry(lpfc_cmd, &phba->lpfc_scsi_buf_list_get,
1164 list) {
1165 if (lpfc_test_rrq_active(
1166 phba, ndlp, lpfc_cmd->cur_iocbq.sli4_lxritag))
1167 continue;
1168 list_del(&lpfc_cmd->list);
1169 found = 1;
1170 break;
1171 }
1172 }
1173 spin_unlock_irqrestore(&phba->scsi_buf_list_get_lock, gflag);
1153 if (!found) 1174 if (!found)
1154 return NULL; 1175 return NULL;
1155 else 1176 return lpfc_cmd;
1156 return lpfc_cmd;
1157} 1177}
1158/** 1178/**
1159 * lpfc_get_scsi_buf - Get a scsi buffer from lpfc_scsi_buf_list of the HBA 1179 * lpfc_get_scsi_buf - Get a scsi buffer from lpfc_scsi_buf_list of the HBA
@@ -1185,10 +1205,14 @@ lpfc_release_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb)
1185{ 1205{
1186 unsigned long iflag = 0; 1206 unsigned long iflag = 0;
1187 1207
1188 spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag); 1208 psb->seg_cnt = 0;
1209 psb->nonsg_phys = 0;
1210 psb->prot_seg_cnt = 0;
1211
1212 spin_lock_irqsave(&phba->scsi_buf_list_put_lock, iflag);
1189 psb->pCmd = NULL; 1213 psb->pCmd = NULL;
1190 list_add_tail(&psb->list, &phba->lpfc_scsi_buf_list); 1214 list_add_tail(&psb->list, &phba->lpfc_scsi_buf_list_put);
1191 spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag); 1215 spin_unlock_irqrestore(&phba->scsi_buf_list_put_lock, iflag);
1192} 1216}
1193 1217
1194/** 1218/**
@@ -1206,6 +1230,10 @@ lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb)
1206{ 1230{
1207 unsigned long iflag = 0; 1231 unsigned long iflag = 0;
1208 1232
1233 psb->seg_cnt = 0;
1234 psb->nonsg_phys = 0;
1235 psb->prot_seg_cnt = 0;
1236
1209 if (psb->exch_busy) { 1237 if (psb->exch_busy) {
1210 spin_lock_irqsave(&phba->sli4_hba.abts_scsi_buf_list_lock, 1238 spin_lock_irqsave(&phba->sli4_hba.abts_scsi_buf_list_lock,
1211 iflag); 1239 iflag);
@@ -1215,11 +1243,10 @@ lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb)
1215 spin_unlock_irqrestore(&phba->sli4_hba.abts_scsi_buf_list_lock, 1243 spin_unlock_irqrestore(&phba->sli4_hba.abts_scsi_buf_list_lock,
1216 iflag); 1244 iflag);
1217 } else { 1245 } else {
1218
1219 spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
1220 psb->pCmd = NULL; 1246 psb->pCmd = NULL;
1221 list_add_tail(&psb->list, &phba->lpfc_scsi_buf_list); 1247 spin_lock_irqsave(&phba->scsi_buf_list_put_lock, iflag);
1222 spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag); 1248 list_add_tail(&psb->list, &phba->lpfc_scsi_buf_list_put);
1249 spin_unlock_irqrestore(&phba->scsi_buf_list_put_lock, iflag);
1223 } 1250 }
1224} 1251}
1225 1252