aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/message/fusion/mptbase.h4
-rw-r--r--drivers/message/fusion/mptfc.c89
2 files changed, 87 insertions, 6 deletions
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index c537d71c18e4..a4afad4ecab2 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -75,8 +75,8 @@
75#define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR 75#define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR
76#endif 76#endif
77 77
78#define MPT_LINUX_VERSION_COMMON "3.04.01" 78#define MPT_LINUX_VERSION_COMMON "3.04.02"
79#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.01" 79#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.02"
80#define WHAT_MAGIC_STRING "@" "(" "#" ")" 80#define WHAT_MAGIC_STRING "@" "(" "#" ")"
81 81
82#define show_mptmod_ver(s,ver) \ 82#define show_mptmod_ver(s,ver) \
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index e57bb035a021..1dd491773150 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -96,6 +96,10 @@ static int mptfc_qcmd(struct scsi_cmnd *SCpnt,
96static void mptfc_target_destroy(struct scsi_target *starget); 96static void mptfc_target_destroy(struct scsi_target *starget);
97static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout); 97static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout);
98static void __devexit mptfc_remove(struct pci_dev *pdev); 98static void __devexit mptfc_remove(struct pci_dev *pdev);
99static int mptfc_abort(struct scsi_cmnd *SCpnt);
100static int mptfc_dev_reset(struct scsi_cmnd *SCpnt);
101static int mptfc_bus_reset(struct scsi_cmnd *SCpnt);
102static int mptfc_host_reset(struct scsi_cmnd *SCpnt);
99 103
100static struct scsi_host_template mptfc_driver_template = { 104static struct scsi_host_template mptfc_driver_template = {
101 .module = THIS_MODULE, 105 .module = THIS_MODULE,
@@ -110,10 +114,10 @@ static struct scsi_host_template mptfc_driver_template = {
110 .target_destroy = mptfc_target_destroy, 114 .target_destroy = mptfc_target_destroy,
111 .slave_destroy = mptscsih_slave_destroy, 115 .slave_destroy = mptscsih_slave_destroy,
112 .change_queue_depth = mptscsih_change_queue_depth, 116 .change_queue_depth = mptscsih_change_queue_depth,
113 .eh_abort_handler = mptscsih_abort, 117 .eh_abort_handler = mptfc_abort,
114 .eh_device_reset_handler = mptscsih_dev_reset, 118 .eh_device_reset_handler = mptfc_dev_reset,
115 .eh_bus_reset_handler = mptscsih_bus_reset, 119 .eh_bus_reset_handler = mptfc_bus_reset,
116 .eh_host_reset_handler = mptscsih_host_reset, 120 .eh_host_reset_handler = mptfc_host_reset,
117 .bios_param = mptscsih_bios_param, 121 .bios_param = mptscsih_bios_param,
118 .can_queue = MPT_FC_CAN_QUEUE, 122 .can_queue = MPT_FC_CAN_QUEUE,
119 .this_id = -1, 123 .this_id = -1,
@@ -171,6 +175,77 @@ static struct fc_function_template mptfc_transport_functions = {
171 .show_host_symbolic_name = 1, 175 .show_host_symbolic_name = 1,
172}; 176};
173 177
178static int
179mptfc_block_error_handler(struct scsi_cmnd *SCpnt,
180 int (*func)(struct scsi_cmnd *SCpnt),
181 const char *caller)
182{
183 struct scsi_device *sdev = SCpnt->device;
184 struct Scsi_Host *shost = sdev->host;
185 struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
186 unsigned long flags;
187 int ready;
188
189 spin_lock_irqsave(shost->host_lock, flags);
190 while ((ready = fc_remote_port_chkready(rport) >> 16) == DID_IMM_RETRY) {
191 spin_unlock_irqrestore(shost->host_lock, flags);
192 dfcprintk ((MYIOC_s_INFO_FMT
193 "mptfc_block_error_handler.%d: %d:%d, port status is "
194 "DID_IMM_RETRY, deferring %s recovery.\n",
195 ((MPT_SCSI_HOST *) shost->hostdata)->ioc->name,
196 ((MPT_SCSI_HOST *) shost->hostdata)->ioc->sh->host_no,
197 SCpnt->device->id,SCpnt->device->lun,caller));
198 msleep(1000);
199 spin_lock_irqsave(shost->host_lock, flags);
200 }
201 spin_unlock_irqrestore(shost->host_lock, flags);
202
203 if (ready == DID_NO_CONNECT || !SCpnt->device->hostdata) {
204 dfcprintk ((MYIOC_s_INFO_FMT
205 "%s.%d: %d:%d, failing recovery, "
206 "port state %d, vdev %p.\n", caller,
207 ((MPT_SCSI_HOST *) shost->hostdata)->ioc->name,
208 ((MPT_SCSI_HOST *) shost->hostdata)->ioc->sh->host_no,
209 SCpnt->device->id,SCpnt->device->lun,ready,
210 SCpnt->device->hostdata));
211 return FAILED;
212 }
213 dfcprintk ((MYIOC_s_INFO_FMT
214 "%s.%d: %d:%d, executing recovery.\n", caller,
215 ((MPT_SCSI_HOST *) shost->hostdata)->ioc->name,
216 ((MPT_SCSI_HOST *) shost->hostdata)->ioc->sh->host_no,
217 SCpnt->device->id,SCpnt->device->lun));
218 return (*func)(SCpnt);
219}
220
221static int
222mptfc_abort(struct scsi_cmnd *SCpnt)
223{
224 return
225 mptfc_block_error_handler(SCpnt, mptscsih_abort, __FUNCTION__);
226}
227
228static int
229mptfc_dev_reset(struct scsi_cmnd *SCpnt)
230{
231 return
232 mptfc_block_error_handler(SCpnt, mptscsih_dev_reset, __FUNCTION__);
233}
234
235static int
236mptfc_bus_reset(struct scsi_cmnd *SCpnt)
237{
238 return
239 mptfc_block_error_handler(SCpnt, mptscsih_bus_reset, __FUNCTION__);
240}
241
242static int
243mptfc_host_reset(struct scsi_cmnd *SCpnt)
244{
245 return
246 mptfc_block_error_handler(SCpnt, mptscsih_host_reset, __FUNCTION__);
247}
248
174static void 249static void
175mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) 250mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
176{ 251{
@@ -562,6 +637,12 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
562 return 0; 637 return 0;
563 } 638 }
564 639
640 if (!SCpnt->device->hostdata) { /* vdev */
641 SCpnt->result = DID_NO_CONNECT << 16;
642 done(SCpnt);
643 return 0;
644 }
645
565 /* dd_data is null until finished adding target */ 646 /* dd_data is null until finished adding target */
566 ri = *((struct mptfc_rport_info **)rport->dd_data); 647 ri = *((struct mptfc_rport_info **)rport->dd_data);
567 if (unlikely(!ri)) { 648 if (unlikely(!ri)) {