aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJamie Wellnitz <Jamie.Wellnitz@emulex.com>2006-02-28 22:33:10 -0500
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-03-06 10:47:31 -0500
commit66a9ed66000d186933892ca5121e68a071d624ac (patch)
treec5aa2b1e2e819876a980e59f3cbd8d0a7761aeae
parent5fe9f5119378e75986ad90c783a7e085bf67703a (diff)
[PATCH] lpfc 8.1.3: Protect NPL lists with host lock
Protect NPL lists with host lock Symptoms: lpfc_findnode_rpi and lpfc_findnode_did can be called outside of the discovery thread context. We have to iterate through the NPL lists under the host lock and all add/del operations on those lists have to be done under host lock. Signed-off-by: Jamie Wellnitz <Jamie.Wellnitz@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c3
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c53
2 files changed, 26 insertions, 30 deletions
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 6e1a5162851c..090f4609d2af 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -3144,8 +3144,9 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba)
3144 3144
3145 if (cmd->ulpCommand == CMD_GEN_REQUEST64_CR) { 3145 if (cmd->ulpCommand == CMD_GEN_REQUEST64_CR) {
3146 struct lpfc_nodelist *ndlp; 3146 struct lpfc_nodelist *ndlp;
3147 3147 spin_unlock_irq(phba->host->host_lock);
3148 ndlp = lpfc_findnode_rpi(phba, cmd->ulpContext); 3148 ndlp = lpfc_findnode_rpi(phba, cmd->ulpContext);
3149 spin_lock_irq(phba->host->host_lock);
3149 remote_ID = ndlp->nlp_DID; 3150 remote_ID = ndlp->nlp_DID;
3150 if (cmd->un.elsreq64.bdl.ulpIoTag32) { 3151 if (cmd->un.elsreq64.bdl.ulpIoTag32) {
3151 lpfc_sli_issue_abort_iotag32(phba, 3152 lpfc_sli_issue_abort_iotag32(phba,
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index aa58ff0e3218..e7664a6bd251 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -1097,6 +1097,7 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
1097 if (list != NLP_NO_LIST) 1097 if (list != NLP_NO_LIST)
1098 return 0; 1098 return 0;
1099 1099
1100 spin_lock_irq(phba->host->host_lock);
1100 switch (nlp->nlp_flag & NLP_LIST_MASK) { 1101 switch (nlp->nlp_flag & NLP_LIST_MASK) {
1101 case NLP_NO_LIST: /* Not on any list */ 1102 case NLP_NO_LIST: /* Not on any list */
1102 break; 1103 break;
@@ -1123,10 +1124,8 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
1123 case NLP_UNMAPPED_LIST: 1124 case NLP_UNMAPPED_LIST:
1124 phba->fc_unmap_cnt--; 1125 phba->fc_unmap_cnt--;
1125 list_del(&nlp->nlp_listp); 1126 list_del(&nlp->nlp_listp);
1126 spin_lock_irq(phba->host->host_lock);
1127 nlp->nlp_flag &= ~NLP_TGT_NO_SCSIID; 1127 nlp->nlp_flag &= ~NLP_TGT_NO_SCSIID;
1128 nlp->nlp_type &= ~NLP_FC_NODE; 1128 nlp->nlp_type &= ~NLP_FC_NODE;
1129 spin_unlock_irq(phba->host->host_lock);
1130 phba->nport_event_cnt++; 1129 phba->nport_event_cnt++;
1131 if (nlp->rport) 1130 if (nlp->rport)
1132 rport_del = unmapped; 1131 rport_del = unmapped;
@@ -1144,20 +1143,18 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
1144 /* Stop delay tmo if taking node off NPR list */ 1143 /* Stop delay tmo if taking node off NPR list */
1145 if ((nlp->nlp_flag & NLP_DELAY_TMO) && 1144 if ((nlp->nlp_flag & NLP_DELAY_TMO) &&
1146 (list != NLP_NPR_LIST)) { 1145 (list != NLP_NPR_LIST)) {
1147 spin_lock_irq(phba->host->host_lock);
1148 nlp->nlp_flag &= ~NLP_DELAY_TMO; 1146 nlp->nlp_flag &= ~NLP_DELAY_TMO;
1149 spin_unlock_irq(phba->host->host_lock);
1150 nlp->nlp_last_elscmd = 0; 1147 nlp->nlp_last_elscmd = 0;
1148 spin_unlock_irq(phba->host->host_lock);
1151 del_timer_sync(&nlp->nlp_delayfunc); 1149 del_timer_sync(&nlp->nlp_delayfunc);
1150 spin_lock_irq(phba->host->host_lock);
1152 if (!list_empty(&nlp->els_retry_evt.evt_listp)) 1151 if (!list_empty(&nlp->els_retry_evt.evt_listp))
1153 list_del_init(&nlp->els_retry_evt.evt_listp); 1152 list_del_init(&nlp->els_retry_evt.evt_listp);
1154 } 1153 }
1155 break; 1154 break;
1156 } 1155 }
1157 1156
1158 spin_lock_irq(phba->host->host_lock);
1159 nlp->nlp_flag &= ~NLP_LIST_MASK; 1157 nlp->nlp_flag &= ~NLP_LIST_MASK;
1160 spin_unlock_irq(phba->host->host_lock);
1161 1158
1162 /* Add NPort <did> to <num> list */ 1159 /* Add NPort <did> to <num> list */
1163 lpfc_printf_log(phba, 1160 lpfc_printf_log(phba,
@@ -1169,46 +1166,38 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
1169 1166
1170 switch (list) { 1167 switch (list) {
1171 case NLP_NO_LIST: /* No list, just remove it */ 1168 case NLP_NO_LIST: /* No list, just remove it */
1169 spin_unlock_irq(phba->host->host_lock);
1172 lpfc_nlp_remove(phba, nlp); 1170 lpfc_nlp_remove(phba, nlp);
1171 spin_lock_irq(phba->host->host_lock);
1173 /* as node removed - stop further transport calls */ 1172 /* as node removed - stop further transport calls */
1174 rport_del = none; 1173 rport_del = none;
1175 break; 1174 break;
1176 case NLP_UNUSED_LIST: 1175 case NLP_UNUSED_LIST:
1177 spin_lock_irq(phba->host->host_lock);
1178 nlp->nlp_flag |= list; 1176 nlp->nlp_flag |= list;
1179 spin_unlock_irq(phba->host->host_lock);
1180 /* Put it at the end of the unused list */ 1177 /* Put it at the end of the unused list */
1181 list_add_tail(&nlp->nlp_listp, &phba->fc_unused_list); 1178 list_add_tail(&nlp->nlp_listp, &phba->fc_unused_list);
1182 phba->fc_unused_cnt++; 1179 phba->fc_unused_cnt++;
1183 break; 1180 break;
1184 case NLP_PLOGI_LIST: 1181 case NLP_PLOGI_LIST:
1185 spin_lock_irq(phba->host->host_lock);
1186 nlp->nlp_flag |= list; 1182 nlp->nlp_flag |= list;
1187 spin_unlock_irq(phba->host->host_lock);
1188 /* Put it at the end of the plogi list */ 1183 /* Put it at the end of the plogi list */
1189 list_add_tail(&nlp->nlp_listp, &phba->fc_plogi_list); 1184 list_add_tail(&nlp->nlp_listp, &phba->fc_plogi_list);
1190 phba->fc_plogi_cnt++; 1185 phba->fc_plogi_cnt++;
1191 break; 1186 break;
1192 case NLP_ADISC_LIST: 1187 case NLP_ADISC_LIST:
1193 spin_lock_irq(phba->host->host_lock);
1194 nlp->nlp_flag |= list; 1188 nlp->nlp_flag |= list;
1195 spin_unlock_irq(phba->host->host_lock);
1196 /* Put it at the end of the adisc list */ 1189 /* Put it at the end of the adisc list */
1197 list_add_tail(&nlp->nlp_listp, &phba->fc_adisc_list); 1190 list_add_tail(&nlp->nlp_listp, &phba->fc_adisc_list);
1198 phba->fc_adisc_cnt++; 1191 phba->fc_adisc_cnt++;
1199 break; 1192 break;
1200 case NLP_REGLOGIN_LIST: 1193 case NLP_REGLOGIN_LIST:
1201 spin_lock_irq(phba->host->host_lock);
1202 nlp->nlp_flag |= list; 1194 nlp->nlp_flag |= list;
1203 spin_unlock_irq(phba->host->host_lock);
1204 /* Put it at the end of the reglogin list */ 1195 /* Put it at the end of the reglogin list */
1205 list_add_tail(&nlp->nlp_listp, &phba->fc_reglogin_list); 1196 list_add_tail(&nlp->nlp_listp, &phba->fc_reglogin_list);
1206 phba->fc_reglogin_cnt++; 1197 phba->fc_reglogin_cnt++;
1207 break; 1198 break;
1208 case NLP_PRLI_LIST: 1199 case NLP_PRLI_LIST:
1209 spin_lock_irq(phba->host->host_lock);
1210 nlp->nlp_flag |= list; 1200 nlp->nlp_flag |= list;
1211 spin_unlock_irq(phba->host->host_lock);
1212 /* Put it at the end of the prli list */ 1201 /* Put it at the end of the prli list */
1213 list_add_tail(&nlp->nlp_listp, &phba->fc_prli_list); 1202 list_add_tail(&nlp->nlp_listp, &phba->fc_prli_list);
1214 phba->fc_prli_cnt++; 1203 phba->fc_prli_cnt++;
@@ -1217,19 +1206,17 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
1217 rport_add = unmapped; 1206 rport_add = unmapped;
1218 /* ensure all vestiges of "mapped" significance are gone */ 1207 /* ensure all vestiges of "mapped" significance are gone */
1219 nlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR); 1208 nlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR);
1220 spin_lock_irq(phba->host->host_lock);
1221 nlp->nlp_flag |= list; 1209 nlp->nlp_flag |= list;
1222 spin_unlock_irq(phba->host->host_lock);
1223 /* Put it at the end of the unmap list */ 1210 /* Put it at the end of the unmap list */
1224 list_add_tail(&nlp->nlp_listp, &phba->fc_nlpunmap_list); 1211 list_add_tail(&nlp->nlp_listp, &phba->fc_nlpunmap_list);
1225 phba->fc_unmap_cnt++; 1212 phba->fc_unmap_cnt++;
1226 phba->nport_event_cnt++; 1213 phba->nport_event_cnt++;
1227 /* stop nodev tmo if running */ 1214 /* stop nodev tmo if running */
1228 if (nlp->nlp_flag & NLP_NODEV_TMO) { 1215 if (nlp->nlp_flag & NLP_NODEV_TMO) {
1229 spin_lock_irq(phba->host->host_lock);
1230 nlp->nlp_flag &= ~NLP_NODEV_TMO; 1216 nlp->nlp_flag &= ~NLP_NODEV_TMO;
1231 spin_unlock_irq(phba->host->host_lock); 1217 spin_unlock_irq(phba->host->host_lock);
1232 del_timer_sync(&nlp->nlp_tmofunc); 1218 del_timer_sync(&nlp->nlp_tmofunc);
1219 spin_lock_irq(phba->host->host_lock);
1233 if (!list_empty(&nlp->nodev_timeout_evt.evt_listp)) 1220 if (!list_empty(&nlp->nodev_timeout_evt.evt_listp))
1234 list_del_init(&nlp->nodev_timeout_evt. 1221 list_del_init(&nlp->nodev_timeout_evt.
1235 evt_listp); 1222 evt_listp);
@@ -1239,9 +1226,7 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
1239 break; 1226 break;
1240 case NLP_MAPPED_LIST: 1227 case NLP_MAPPED_LIST:
1241 rport_add = mapped; 1228 rport_add = mapped;
1242 spin_lock_irq(phba->host->host_lock);
1243 nlp->nlp_flag |= list; 1229 nlp->nlp_flag |= list;
1244 spin_unlock_irq(phba->host->host_lock);
1245 /* Put it at the end of the map list */ 1230 /* Put it at the end of the map list */
1246 list_add_tail(&nlp->nlp_listp, &phba->fc_nlpmap_list); 1231 list_add_tail(&nlp->nlp_listp, &phba->fc_nlpmap_list);
1247 phba->fc_map_cnt++; 1232 phba->fc_map_cnt++;
@@ -1249,7 +1234,9 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
1249 /* stop nodev tmo if running */ 1234 /* stop nodev tmo if running */
1250 if (nlp->nlp_flag & NLP_NODEV_TMO) { 1235 if (nlp->nlp_flag & NLP_NODEV_TMO) {
1251 nlp->nlp_flag &= ~NLP_NODEV_TMO; 1236 nlp->nlp_flag &= ~NLP_NODEV_TMO;
1237 spin_unlock_irq(phba->host->host_lock);
1252 del_timer_sync(&nlp->nlp_tmofunc); 1238 del_timer_sync(&nlp->nlp_tmofunc);
1239 spin_lock_irq(phba->host->host_lock);
1253 if (!list_empty(&nlp->nodev_timeout_evt.evt_listp)) 1240 if (!list_empty(&nlp->nodev_timeout_evt.evt_listp))
1254 list_del_init(&nlp->nodev_timeout_evt. 1241 list_del_init(&nlp->nodev_timeout_evt.
1255 evt_listp); 1242 evt_listp);
@@ -1257,9 +1244,7 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
1257 } 1244 }
1258 break; 1245 break;
1259 case NLP_NPR_LIST: 1246 case NLP_NPR_LIST:
1260 spin_lock_irq(phba->host->host_lock);
1261 nlp->nlp_flag |= list; 1247 nlp->nlp_flag |= list;
1262 spin_unlock_irq(phba->host->host_lock);
1263 /* Put it at the end of the npr list */ 1248 /* Put it at the end of the npr list */
1264 list_add_tail(&nlp->nlp_listp, &phba->fc_npr_list); 1249 list_add_tail(&nlp->nlp_listp, &phba->fc_npr_list);
1265 phba->fc_npr_cnt++; 1250 phba->fc_npr_cnt++;
@@ -1268,15 +1253,15 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
1268 mod_timer(&nlp->nlp_tmofunc, 1253 mod_timer(&nlp->nlp_tmofunc,
1269 jiffies + HZ * phba->cfg_nodev_tmo); 1254 jiffies + HZ * phba->cfg_nodev_tmo);
1270 1255
1271 spin_lock_irq(phba->host->host_lock);
1272 nlp->nlp_flag |= NLP_NODEV_TMO; 1256 nlp->nlp_flag |= NLP_NODEV_TMO;
1273 nlp->nlp_flag &= ~NLP_RCV_PLOGI; 1257 nlp->nlp_flag &= ~NLP_RCV_PLOGI;
1274 spin_unlock_irq(phba->host->host_lock);
1275 break; 1258 break;
1276 case NLP_JUST_DQ: 1259 case NLP_JUST_DQ:
1277 break; 1260 break;
1278 } 1261 }
1279 1262
1263 spin_unlock_irq(phba->host->host_lock);
1264
1280 /* 1265 /*
1281 * We make all the calls into the transport after we have 1266 * We make all the calls into the transport after we have
1282 * moved the node between lists. This so that we don't 1267 * moved the node between lists. This so that we don't
@@ -1681,6 +1666,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did)
1681 struct lpfc_nodelist *ndlp, *next_ndlp; 1666 struct lpfc_nodelist *ndlp, *next_ndlp;
1682 uint32_t data1; 1667 uint32_t data1;
1683 1668
1669 spin_lock_irq(phba->host->host_lock);
1684 if (order & NLP_SEARCH_UNMAPPED) { 1670 if (order & NLP_SEARCH_UNMAPPED) {
1685 list_for_each_entry_safe(ndlp, next_ndlp, 1671 list_for_each_entry_safe(ndlp, next_ndlp,
1686 &phba->fc_nlpunmap_list, nlp_listp) { 1672 &phba->fc_nlpunmap_list, nlp_listp) {
@@ -1696,6 +1682,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did)
1696 phba->brd_no, 1682 phba->brd_no,
1697 ndlp, ndlp->nlp_DID, 1683 ndlp, ndlp->nlp_DID,
1698 ndlp->nlp_flag, data1); 1684 ndlp->nlp_flag, data1);
1685 spin_unlock_irq(phba->host->host_lock);
1699 return ndlp; 1686 return ndlp;
1700 } 1687 }
1701 } 1688 }
@@ -1717,6 +1704,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did)
1717 phba->brd_no, 1704 phba->brd_no,
1718 ndlp, ndlp->nlp_DID, 1705 ndlp, ndlp->nlp_DID,
1719 ndlp->nlp_flag, data1); 1706 ndlp->nlp_flag, data1);
1707 spin_unlock_irq(phba->host->host_lock);
1720 return ndlp; 1708 return ndlp;
1721 } 1709 }
1722 } 1710 }
@@ -1739,6 +1727,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did)
1739 phba->brd_no, 1727 phba->brd_no,
1740 ndlp, ndlp->nlp_DID, 1728 ndlp, ndlp->nlp_DID,
1741 ndlp->nlp_flag, data1); 1729 ndlp->nlp_flag, data1);
1730 spin_unlock_irq(phba->host->host_lock);
1742 return ndlp; 1731 return ndlp;
1743 } 1732 }
1744 } 1733 }
@@ -1783,6 +1772,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did)
1783 phba->brd_no, 1772 phba->brd_no,
1784 ndlp, ndlp->nlp_DID, 1773 ndlp, ndlp->nlp_DID,
1785 ndlp->nlp_flag, data1); 1774 ndlp->nlp_flag, data1);
1775 spin_unlock_irq(phba->host->host_lock);
1786 return ndlp; 1776 return ndlp;
1787 } 1777 }
1788 } 1778 }
@@ -1827,6 +1817,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did)
1827 phba->brd_no, 1817 phba->brd_no,
1828 ndlp, ndlp->nlp_DID, 1818 ndlp, ndlp->nlp_DID,
1829 ndlp->nlp_flag, data1); 1819 ndlp->nlp_flag, data1);
1820 spin_unlock_irq(phba->host->host_lock);
1830 return ndlp; 1821 return ndlp;
1831 } 1822 }
1832 } 1823 }
@@ -1849,11 +1840,14 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did)
1849 phba->brd_no, 1840 phba->brd_no,
1850 ndlp, ndlp->nlp_DID, 1841 ndlp, ndlp->nlp_DID,
1851 ndlp->nlp_flag, data1); 1842 ndlp->nlp_flag, data1);
1843 spin_unlock_irq(phba->host->host_lock);
1852 return ndlp; 1844 return ndlp;
1853 } 1845 }
1854 } 1846 }
1855 } 1847 }
1856 1848
1849 spin_unlock_irq(phba->host->host_lock);
1850
1857 /* FIND node did <did> NOT FOUND */ 1851 /* FIND node did <did> NOT FOUND */
1858 lpfc_printf_log(phba, 1852 lpfc_printf_log(phba,
1859 KERN_INFO, 1853 KERN_INFO,
@@ -1895,9 +1889,7 @@ lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did)
1895 */ 1889 */
1896 if (ndlp->nlp_flag & NLP_DELAY_TMO) { 1890 if (ndlp->nlp_flag & NLP_DELAY_TMO) {
1897 ndlp->nlp_flag &= ~NLP_DELAY_TMO; 1891 ndlp->nlp_flag &= ~NLP_DELAY_TMO;
1898 spin_unlock_irq(phba->host->host_lock);
1899 del_timer_sync(&ndlp->nlp_delayfunc); 1892 del_timer_sync(&ndlp->nlp_delayfunc);
1900 spin_lock_irq(phba->host->host_lock);
1901 if (!list_empty(&ndlp->els_retry_evt. 1893 if (!list_empty(&ndlp->els_retry_evt.
1902 evt_listp)) 1894 evt_listp))
1903 list_del_init(&ndlp->els_retry_evt. 1895 list_del_init(&ndlp->els_retry_evt.
@@ -2513,11 +2505,14 @@ lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi)
2513 &phba->fc_reglogin_list}; 2505 &phba->fc_reglogin_list};
2514 int i; 2506 int i;
2515 2507
2508 spin_lock_irq(phba->host->host_lock);
2516 for (i = 0; i < ARRAY_SIZE(lists); i++ ) 2509 for (i = 0; i < ARRAY_SIZE(lists); i++ )
2517 list_for_each_entry(ndlp, lists[i], nlp_listp) 2510 list_for_each_entry(ndlp, lists[i], nlp_listp)
2518 if (ndlp->nlp_rpi == rpi) 2511 if (ndlp->nlp_rpi == rpi) {
2512 spin_unlock_irq(phba->host->host_lock);
2519 return ndlp; 2513 return ndlp;
2520 2514 }
2515 spin_unlock_irq(phba->host->host_lock);
2521 return NULL; 2516 return NULL;
2522} 2517}
2523 2518