aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Reed <mdr@sgi.com>2006-07-31 13:19:50 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-08-06 16:48:31 -0400
commit3a0c56d801df6785b30e36c19e89d7e971c151da (patch)
tree03f311351e7ee56f5315f61e23e5ca3bddbe76b2
parent77d88ee275aeba5da447987f30401bbd4c901ca9 (diff)
[SCSI] mptfc: correct out of order event processing
This patch corrects a problem in mptfc which can result in targets being removed after executing an "lsiutil 99" reset of the fibre channel ports. The last rescan event was being processed before the setup reset work due to an inappropriate optimization in the event processing logic. Every rescan event is now queued for execution and the setup reset work now executes in the proper sequence. Signed-off-by: Michael Reed <mdr@sgi.com> Acked-by: Moore, Eric <Eric.Moore@lsil.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r--drivers/message/fusion/mptbase.h1
-rw-r--r--drivers/message/fusion/mptfc.c87
2 files changed, 34 insertions, 54 deletions
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index d4cb144ab402..c537d71c18e4 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -640,7 +640,6 @@ typedef struct _MPT_ADAPTER
640 struct work_struct fc_setup_reset_work; 640 struct work_struct fc_setup_reset_work;
641 struct list_head fc_rports; 641 struct list_head fc_rports;
642 spinlock_t fc_rescan_work_lock; 642 spinlock_t fc_rescan_work_lock;
643 int fc_rescan_work_count;
644 struct work_struct fc_rescan_work; 643 struct work_struct fc_rescan_work;
645 char fc_rescan_work_q_name[KOBJ_NAME_LEN]; 644 char fc_rescan_work_q_name[KOBJ_NAME_LEN];
646 struct workqueue_struct *fc_rescan_work_q; 645 struct workqueue_struct *fc_rescan_work_q;
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index 2144554a640d..85696f34c310 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -898,59 +898,45 @@ mptfc_rescan_devices(void *arg)
898{ 898{
899 MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; 899 MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
900 int ii; 900 int ii;
901 int work_to_do;
902 u64 pn; 901 u64 pn;
903 unsigned long flags;
904 struct mptfc_rport_info *ri; 902 struct mptfc_rport_info *ri;
905 903
906 do { 904 /* start by tagging all ports as missing */
907 /* start by tagging all ports as missing */ 905 list_for_each_entry(ri, &ioc->fc_rports, list) {
908 list_for_each_entry(ri, &ioc->fc_rports, list) { 906 if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
909 if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) { 907 ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING;
910 ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING;
911 }
912 } 908 }
909 }
913 910
914 /* 911 /*
915 * now rescan devices known to adapter, 912 * now rescan devices known to adapter,
916 * will reregister existing rports 913 * will reregister existing rports
917 */ 914 */
918 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { 915 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
919 (void) mptfc_GetFcPortPage0(ioc, ii); 916 (void) mptfc_GetFcPortPage0(ioc, ii);
920 mptfc_init_host_attr(ioc,ii); /* refresh */ 917 mptfc_init_host_attr(ioc, ii); /* refresh */
921 mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev); 918 mptfc_GetFcDevPage0(ioc, ii, mptfc_register_dev);
922 } 919 }
923 920
924 /* delete devices still missing */ 921 /* delete devices still missing */
925 list_for_each_entry(ri, &ioc->fc_rports, list) { 922 list_for_each_entry(ri, &ioc->fc_rports, list) {
926 /* if newly missing, delete it */ 923 /* if newly missing, delete it */
927 if (ri->flags & MPT_RPORT_INFO_FLAGS_MISSING) { 924 if (ri->flags & MPT_RPORT_INFO_FLAGS_MISSING) {
928 925
929 ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED| 926 ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|
930 MPT_RPORT_INFO_FLAGS_MISSING); 927 MPT_RPORT_INFO_FLAGS_MISSING);
931 fc_remote_port_delete(ri->rport); /* won't sleep */ 928 fc_remote_port_delete(ri->rport); /* won't sleep */
932 ri->rport = NULL; 929 ri->rport = NULL;
933 930
934 pn = (u64)ri->pg0.WWPN.High << 32 | 931 pn = (u64)ri->pg0.WWPN.High << 32 |
935 (u64)ri->pg0.WWPN.Low; 932 (u64)ri->pg0.WWPN.Low;
936 dfcprintk ((MYIOC_s_INFO_FMT 933 dfcprintk ((MYIOC_s_INFO_FMT
937 "mptfc_rescan.%d: %llx deleted\n", 934 "mptfc_rescan.%d: %llx deleted\n",
938 ioc->name, 935 ioc->name,
939 ioc->sh->host_no, 936 ioc->sh->host_no,
940 (unsigned long long)pn)); 937 (unsigned long long)pn));
941 }
942 } 938 }
943 939 }
944 /*
945 * allow multiple passes as target state
946 * might have changed during scan
947 */
948 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
949 if (ioc->fc_rescan_work_count > 2) /* only need one more */
950 ioc->fc_rescan_work_count = 2;
951 work_to_do = --ioc->fc_rescan_work_count;
952 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
953 } while (work_to_do);
954} 940}
955 941
956static int 942static int
@@ -1162,7 +1148,6 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1162 * by doing it via the workqueue, some locking is eliminated 1148 * by doing it via the workqueue, some locking is eliminated
1163 */ 1149 */
1164 1150
1165 ioc->fc_rescan_work_count = 1;
1166 queue_work(ioc->fc_rescan_work_q, &ioc->fc_rescan_work); 1151 queue_work(ioc->fc_rescan_work_q, &ioc->fc_rescan_work);
1167 flush_workqueue(ioc->fc_rescan_work_q); 1152 flush_workqueue(ioc->fc_rescan_work_q);
1168 1153
@@ -1205,10 +1190,8 @@ mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
1205 case MPI_EVENT_RESCAN: 1190 case MPI_EVENT_RESCAN:
1206 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); 1191 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1207 if (ioc->fc_rescan_work_q) { 1192 if (ioc->fc_rescan_work_q) {
1208 if (ioc->fc_rescan_work_count++ == 0) { 1193 queue_work(ioc->fc_rescan_work_q,
1209 queue_work(ioc->fc_rescan_work_q, 1194 &ioc->fc_rescan_work);
1210 &ioc->fc_rescan_work);
1211 }
1212 } 1195 }
1213 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); 1196 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1214 break; 1197 break;
@@ -1251,10 +1234,8 @@ mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
1251 mptfc_SetFcPortPage1_defaults(ioc); 1234 mptfc_SetFcPortPage1_defaults(ioc);
1252 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); 1235 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1253 if (ioc->fc_rescan_work_q) { 1236 if (ioc->fc_rescan_work_q) {
1254 if (ioc->fc_rescan_work_count++ == 0) { 1237 queue_work(ioc->fc_rescan_work_q,
1255 queue_work(ioc->fc_rescan_work_q, 1238 &ioc->fc_rescan_work);
1256 &ioc->fc_rescan_work);
1257 }
1258 } 1239 }
1259 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); 1240 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1260 } 1241 }