xref: /openbmc/linux/drivers/message/fusion/mptfc.c (revision 80d3ac77a84987d5132726f3d7cef342a280f7d9)
1 /*
2  *  linux/drivers/message/fusion/mptfc.c
3  *      For use with LSI Logic PCI chip/adapter(s)
4  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
5  *
6  *  Copyright (c) 1999-2005 LSI Logic Corporation
7  *  (mailto:mpt_linux_developer@lsil.com)
8  *
9  */
10 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11 /*
12     This program is free software; you can redistribute it and/or modify
13     it under the terms of the GNU General Public License as published by
14     the Free Software Foundation; version 2 of the License.
15 
16     This program is distributed in the hope that it will be useful,
17     but WITHOUT ANY WARRANTY; without even the implied warranty of
18     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19     GNU General Public License for more details.
20 
21     NO WARRANTY
22     THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
23     CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
24     LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
25     MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
26     solely responsible for determining the appropriateness of using and
27     distributing the Program and assumes all risks associated with its
28     exercise of rights under this Agreement, including but not limited to
29     the risks and costs of program errors, damage to or loss of data,
30     programs or equipment, and unavailability or interruption of operations.
31 
32     DISCLAIMER OF LIABILITY
33     NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
34     DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35     DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
36     ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
37     TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
38     USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
39     HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
40 
41     You should have received a copy of the GNU General Public License
42     along with this program; if not, write to the Free Software
43     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
44 */
45 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
46 #include "linux_compat.h"	/* linux-2.6 tweaks */
47 #include <linux/module.h>
48 #include <linux/kernel.h>
49 #include <linux/init.h>
50 #include <linux/errno.h>
51 #include <linux/kdev_t.h>
52 #include <linux/blkdev.h>
53 #include <linux/delay.h>	/* for mdelay */
54 #include <linux/interrupt.h>	/* needed for in_interrupt() proto */
55 #include <linux/reboot.h>	/* notifier code */
56 #include <linux/sched.h>
57 #include <linux/workqueue.h>
58 #include <linux/sort.h>
59 
60 #include <scsi/scsi.h>
61 #include <scsi/scsi_cmnd.h>
62 #include <scsi/scsi_device.h>
63 #include <scsi/scsi_host.h>
64 #include <scsi/scsi_tcq.h>
65 #include <scsi/scsi_transport_fc.h>
66 
67 #include "mptbase.h"
68 #include "mptscsih.h"
69 
70 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
71 #define my_NAME		"Fusion MPT FC Host driver"
72 #define my_VERSION	MPT_LINUX_VERSION_COMMON
73 #define MYNAM		"mptfc"
74 
75 MODULE_AUTHOR(MODULEAUTHOR);
76 MODULE_DESCRIPTION(my_NAME);
77 MODULE_LICENSE("GPL");
78 
79 /* Command line args */
80 static int mpt_pq_filter = 0;
81 module_param(mpt_pq_filter, int, 0);
82 MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1  (default=0)");
83 
84 #define MPTFC_DEV_LOSS_TMO (60)
85 static int mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;	/* reasonable default */
86 module_param(mptfc_dev_loss_tmo, int, 0);
87 MODULE_PARM_DESC(mptfc_dev_loss_tmo, " Initial time the driver programs the "
88     				     " transport to wait for an rport to "
89 				     " return following a device loss event."
90 				     "  Default=60.");
91 
92 static int	mptfcDoneCtx = -1;
93 static int	mptfcTaskCtx = -1;
94 static int	mptfcInternalCtx = -1; /* Used only for internal commands */
95 
96 static int mptfc_target_alloc(struct scsi_target *starget);
97 static int mptfc_slave_alloc(struct scsi_device *sdev);
98 static int mptfc_qcmd(struct scsi_cmnd *SCpnt,
99 		      void (*done)(struct scsi_cmnd *));
100 static void mptfc_target_destroy(struct scsi_target *starget);
101 static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout);
102 static void __devexit mptfc_remove(struct pci_dev *pdev);
103 
104 static struct scsi_host_template mptfc_driver_template = {
105 	.module				= THIS_MODULE,
106 	.proc_name			= "mptfc",
107 	.proc_info			= mptscsih_proc_info,
108 	.name				= "MPT FC Host",
109 	.info				= mptscsih_info,
110 	.queuecommand			= mptfc_qcmd,
111 	.target_alloc			= mptfc_target_alloc,
112 	.slave_alloc			= mptfc_slave_alloc,
113 	.slave_configure		= mptscsih_slave_configure,
114 	.target_destroy			= mptfc_target_destroy,
115 	.slave_destroy			= mptscsih_slave_destroy,
116 	.change_queue_depth 		= mptscsih_change_queue_depth,
117 	.eh_abort_handler		= mptscsih_abort,
118 	.eh_device_reset_handler	= mptscsih_dev_reset,
119 	.eh_bus_reset_handler		= mptscsih_bus_reset,
120 	.eh_host_reset_handler		= mptscsih_host_reset,
121 	.bios_param			= mptscsih_bios_param,
122 	.can_queue			= MPT_FC_CAN_QUEUE,
123 	.this_id			= -1,
124 	.sg_tablesize			= MPT_SCSI_SG_DEPTH,
125 	.max_sectors			= 8192,
126 	.cmd_per_lun			= 7,
127 	.use_clustering			= ENABLE_CLUSTERING,
128 };
129 
130 /****************************************************************************
131  * Supported hardware
132  */
133 
134 static struct pci_device_id mptfc_pci_table[] = {
135 	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC909,
136 		PCI_ANY_ID, PCI_ANY_ID },
137 	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919,
138 		PCI_ANY_ID, PCI_ANY_ID },
139 	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929,
140 		PCI_ANY_ID, PCI_ANY_ID },
141 	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919X,
142 		PCI_ANY_ID, PCI_ANY_ID },
143 	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929X,
144 		PCI_ANY_ID, PCI_ANY_ID },
145 	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC939X,
146 		PCI_ANY_ID, PCI_ANY_ID },
147 	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949X,
148 		PCI_ANY_ID, PCI_ANY_ID },
149 	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949ES,
150 		PCI_ANY_ID, PCI_ANY_ID },
151 	{0}	/* Terminating entry */
152 };
153 MODULE_DEVICE_TABLE(pci, mptfc_pci_table);
154 
155 static struct scsi_transport_template *mptfc_transport_template = NULL;
156 
157 static struct fc_function_template mptfc_transport_functions = {
158 	.dd_fcrport_size = 8,
159 	.show_host_node_name = 1,
160 	.show_host_port_name = 1,
161 	.show_host_supported_classes = 1,
162 	.show_host_port_id = 1,
163 	.show_rport_supported_classes = 1,
164 	.show_starget_node_name = 1,
165 	.show_starget_port_name = 1,
166 	.show_starget_port_id = 1,
167 	.set_rport_dev_loss_tmo = mptfc_set_rport_loss_tmo,
168 	.show_rport_dev_loss_tmo = 1,
169 
170 };
171 
172 /* FIXME! values controlling firmware RESCAN event
173  * need to be set low to allow dev_loss_tmo to
174  * work as expected.  Currently, firmware doesn't
175  * notify driver of RESCAN event until some number
176  * of seconds elapse.  This value can be set via
177  * lsiutil.
178  */
179 static void
180 mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
181 {
182 	if (timeout > 0)
183 		rport->dev_loss_tmo = timeout;
184 	else
185 		rport->dev_loss_tmo = mptfc_dev_loss_tmo;
186 }
187 
188 static int
189 mptfc_FcDevPage0_cmp_func(const void *a, const void *b)
190 {
191 	FCDevicePage0_t **aa = (FCDevicePage0_t **)a;
192 	FCDevicePage0_t **bb = (FCDevicePage0_t **)b;
193 
194 	if ((*aa)->CurrentBus == (*bb)->CurrentBus) {
195 		if ((*aa)->CurrentTargetID == (*bb)->CurrentTargetID)
196 			return 0;
197 		if ((*aa)->CurrentTargetID < (*bb)->CurrentTargetID)
198 			return -1;
199 		return 1;
200 	}
201 	if ((*aa)->CurrentBus < (*bb)->CurrentBus)
202 		return -1;
203 	return 1;
204 }
205 
206 static int
207 mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, int ioc_port,
208 	void(*func)(MPT_ADAPTER *ioc,int channel, FCDevicePage0_t *arg))
209 {
210 	ConfigPageHeader_t	 hdr;
211 	CONFIGPARMS		 cfg;
212 	FCDevicePage0_t		*ppage0_alloc, *fc;
213 	dma_addr_t		 page0_dma;
214 	int			 data_sz;
215 	int			 ii;
216 
217 	FCDevicePage0_t		*p0_array=NULL, *p_p0;
218 	FCDevicePage0_t		**pp0_array=NULL, **p_pp0;
219 
220 	int			 rc = -ENOMEM;
221 	U32			 port_id = 0xffffff;
222 	int			 num_targ = 0;
223 	int			 max_bus = ioc->facts.MaxBuses;
224 	int			 max_targ = ioc->facts.MaxDevices;
225 
226 	if (max_bus == 0 || max_targ == 0)
227 		goto out;
228 
229 	data_sz = sizeof(FCDevicePage0_t) * max_bus * max_targ;
230 	p_p0 = p0_array =  kzalloc(data_sz, GFP_KERNEL);
231 	if (!p0_array)
232 		goto out;
233 
234 	data_sz = sizeof(FCDevicePage0_t *) * max_bus * max_targ;
235 	p_pp0 = pp0_array = kzalloc(data_sz, GFP_KERNEL);
236 	if (!pp0_array)
237 		goto out;
238 
239 	do {
240 		/* Get FC Device Page 0 header */
241 		hdr.PageVersion = 0;
242 		hdr.PageLength = 0;
243 		hdr.PageNumber = 0;
244 		hdr.PageType = MPI_CONFIG_PAGETYPE_FC_DEVICE;
245 		cfg.cfghdr.hdr = &hdr;
246 		cfg.physAddr = -1;
247 		cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
248 		cfg.dir = 0;
249 		cfg.pageAddr = port_id;
250 		cfg.timeout = 0;
251 
252 		if ((rc = mpt_config(ioc, &cfg)) != 0)
253 			break;
254 
255 		if (hdr.PageLength <= 0)
256 			break;
257 
258 		data_sz = hdr.PageLength * 4;
259 		ppage0_alloc = pci_alloc_consistent(ioc->pcidev, data_sz,
260 		    					&page0_dma);
261 		rc = -ENOMEM;
262 		if (!ppage0_alloc)
263 			break;
264 
265 		cfg.physAddr = page0_dma;
266 		cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
267 
268 		if ((rc = mpt_config(ioc, &cfg)) == 0) {
269 			ppage0_alloc->PortIdentifier =
270 				le32_to_cpu(ppage0_alloc->PortIdentifier);
271 
272 			ppage0_alloc->WWNN.Low =
273 				le32_to_cpu(ppage0_alloc->WWNN.Low);
274 
275 			ppage0_alloc->WWNN.High =
276 				le32_to_cpu(ppage0_alloc->WWNN.High);
277 
278 			ppage0_alloc->WWPN.Low =
279 				le32_to_cpu(ppage0_alloc->WWPN.Low);
280 
281 			ppage0_alloc->WWPN.High =
282 				le32_to_cpu(ppage0_alloc->WWPN.High);
283 
284 			ppage0_alloc->BBCredit =
285 				le16_to_cpu(ppage0_alloc->BBCredit);
286 
287 			ppage0_alloc->MaxRxFrameSize =
288 				le16_to_cpu(ppage0_alloc->MaxRxFrameSize);
289 
290 			port_id = ppage0_alloc->PortIdentifier;
291 			num_targ++;
292 			*p_p0 = *ppage0_alloc;	/* save data */
293 			*p_pp0++ = p_p0++;	/* save addr */
294 		}
295 		pci_free_consistent(ioc->pcidev, data_sz,
296 		    			(u8 *) ppage0_alloc, page0_dma);
297 		if (rc != 0)
298 			break;
299 
300 	} while (port_id <= 0xff0000);
301 
302 	if (num_targ) {
303 		/* sort array */
304 		if (num_targ > 1)
305 			sort (pp0_array, num_targ, sizeof(FCDevicePage0_t *),
306 				mptfc_FcDevPage0_cmp_func, NULL);
307 		/* call caller's func for each targ */
308 		for (ii = 0; ii < num_targ;  ii++) {
309 			fc = *(pp0_array+ii);
310 			func(ioc, ioc_port, fc);
311 		}
312 	}
313 
314  out:
315 	if (pp0_array)
316 		kfree(pp0_array);
317 	if (p0_array)
318 		kfree(p0_array);
319 	return rc;
320 }
321 
322 static int
323 mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid)
324 {
325 	/* not currently usable */
326 	if (pg0->Flags & (MPI_FC_DEVICE_PAGE0_FLAGS_PLOGI_INVALID |
327 			  MPI_FC_DEVICE_PAGE0_FLAGS_PRLI_INVALID))
328 		return -1;
329 
330 	if (!(pg0->Flags & MPI_FC_DEVICE_PAGE0_FLAGS_TARGETID_BUS_VALID))
331 		return -1;
332 
333 	if (!(pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_TARGET))
334 		return -1;
335 
336 	/*
337 	 * board data structure already normalized to platform endianness
338 	 * shifted to avoid unaligned access on 64 bit architecture
339 	 */
340 	rid->node_name = ((u64)pg0->WWNN.High) << 32 | (u64)pg0->WWNN.Low;
341 	rid->port_name = ((u64)pg0->WWPN.High) << 32 | (u64)pg0->WWPN.Low;
342 	rid->port_id =   pg0->PortIdentifier;
343 	rid->roles = FC_RPORT_ROLE_UNKNOWN;
344 
345 	return 0;
346 }
347 
348 static void
349 mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
350 {
351 	struct fc_rport_identifiers rport_ids;
352 	struct fc_rport		*rport;
353 	struct mptfc_rport_info	*ri;
354 	int			new_ri = 1;
355 	u64			pn, nn;
356 	VirtTarget		*vtarget;
357 	u32			roles = FC_RPORT_ROLE_UNKNOWN;
358 
359 	if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0)
360 		return;
361 
362 	roles |= FC_RPORT_ROLE_FCP_TARGET;
363 	if (pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR)
364 		roles |= FC_RPORT_ROLE_FCP_INITIATOR;
365 
366 	/* scan list looking for a match */
367 	list_for_each_entry(ri, &ioc->fc_rports, list) {
368 		pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
369 		if (pn == rport_ids.port_name) {	/* match */
370 			list_move_tail(&ri->list, &ioc->fc_rports);
371 			new_ri = 0;
372 			break;
373 		}
374 	}
375 	if (new_ri) {	/* allocate one */
376 		ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL);
377 		if (!ri)
378 			return;
379 		list_add_tail(&ri->list, &ioc->fc_rports);
380 	}
381 
382 	ri->pg0 = *pg0;	/* add/update pg0 data */
383 	ri->flags &= ~MPT_RPORT_INFO_FLAGS_MISSING;
384 
385 	/* MPT_RPORT_INFO_FLAGS_REGISTERED - rport not previously deleted */
386 	if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) {
387 		ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED;
388 		rport = fc_remote_port_add(ioc->sh, channel, &rport_ids);
389 		if (rport) {
390 			ri->rport = rport;
391 			if (new_ri) /* may have been reset by user */
392 				rport->dev_loss_tmo = mptfc_dev_loss_tmo;
393 			/*
394 			 * if already mapped, remap here.  If not mapped,
395 			 * target_alloc will allocate vtarget and map,
396 			 * slave_alloc will fill in vdev from vtarget.
397 			 */
398 			if (ri->starget) {
399 				vtarget = ri->starget->hostdata;
400 				if (vtarget) {
401 					vtarget->target_id = pg0->CurrentTargetID;
402 					vtarget->bus_id = pg0->CurrentBus;
403 				}
404 			}
405 			*((struct mptfc_rport_info **)rport->dd_data) = ri;
406 			/* scan will be scheduled once rport becomes a target */
407 			fc_remote_port_rolechg(rport,roles);
408 
409 			pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
410 			nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low;
411 			dfcprintk ((MYIOC_s_INFO_FMT
412 				"mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "
413 				"rport tid %d, tmo %d\n",
414 					ioc->name,
415 					ioc->sh->host_no,
416 					pg0->PortIdentifier,
417 					(unsigned long long)nn,
418 					(unsigned long long)pn,
419 					pg0->CurrentTargetID,
420 					ri->rport->scsi_target_id,
421 					ri->rport->dev_loss_tmo));
422 		} else {
423 			list_del(&ri->list);
424 			kfree(ri);
425 			ri = NULL;
426 		}
427 	}
428 }
429 
430 /*
431  *	OS entry point to allow for host driver to free allocated memory
432  *	Called if no device present or device being unloaded
433  */
434 static void
435 mptfc_target_destroy(struct scsi_target *starget)
436 {
437 	struct fc_rport		*rport;
438 	struct mptfc_rport_info *ri;
439 
440 	rport = starget_to_rport(starget);
441 	if (rport) {
442 		ri = *((struct mptfc_rport_info **)rport->dd_data);
443 		if (ri)	/* better be! */
444 			ri->starget = NULL;
445 	}
446 	if (starget->hostdata)
447 		kfree(starget->hostdata);
448 	starget->hostdata = NULL;
449 }
450 
451 /*
452  *	OS entry point to allow host driver to alloc memory
453  *	for each scsi target. Called once per device the bus scan.
454  *	Return non-zero if allocation fails.
455  */
456 static int
457 mptfc_target_alloc(struct scsi_target *starget)
458 {
459 	VirtTarget		*vtarget;
460 	struct fc_rport		*rport;
461 	struct mptfc_rport_info *ri;
462 	int			rc;
463 
464 	vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
465 	if (!vtarget)
466 		return -ENOMEM;
467 	starget->hostdata = vtarget;
468 
469 	rc = -ENODEV;
470 	rport = starget_to_rport(starget);
471 	if (rport) {
472 		ri = *((struct mptfc_rport_info **)rport->dd_data);
473 		if (ri) {	/* better be! */
474 			vtarget->target_id = ri->pg0.CurrentTargetID;
475 			vtarget->bus_id = ri->pg0.CurrentBus;
476 			ri->starget = starget;
477 			rc = 0;
478 		}
479 	}
480 	if (rc != 0) {
481 		kfree(vtarget);
482 		starget->hostdata = NULL;
483 	}
484 
485 	return rc;
486 }
487 
488 /*
489  *	OS entry point to allow host driver to alloc memory
490  *	for each scsi device. Called once per device the bus scan.
491  *	Return non-zero if allocation fails.
492  *	Init memory once per LUN.
493  */
494 static int
495 mptfc_slave_alloc(struct scsi_device *sdev)
496 {
497 	MPT_SCSI_HOST		*hd;
498 	VirtTarget		*vtarget;
499 	VirtDevice		*vdev;
500 	struct scsi_target	*starget;
501 	struct fc_rport		*rport;
502 
503 
504 	starget = scsi_target(sdev);
505 	rport = starget_to_rport(starget);
506 
507 	if (!rport || fc_remote_port_chkready(rport))
508 		return -ENXIO;
509 
510 	hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
511 
512 	vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
513 	if (!vdev) {
514 		printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
515 				hd->ioc->name, sizeof(VirtDevice));
516 		return -ENOMEM;
517 	}
518 
519 
520 	sdev->hostdata = vdev;
521 	vtarget = starget->hostdata;
522 
523 	if (vtarget->num_luns == 0) {
524 		vtarget->ioc_id = hd->ioc->id;
525 		vtarget->tflags = MPT_TARGET_FLAGS_Q_YES |
526 		    		  MPT_TARGET_FLAGS_VALID_INQUIRY;
527 		hd->Targets[sdev->id] = vtarget;
528 	}
529 
530 	vdev->vtarget = vtarget;
531 	vdev->lun = sdev->lun;
532 
533 	vtarget->num_luns++;
534 
535 
536 #ifdef DMPT_DEBUG_FC
537 	{
538 	u64 nn, pn;
539 	struct mptfc_rport_info *ri;
540 	ri = *((struct mptfc_rport_info **)rport->dd_data);
541 	pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
542 	nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low;
543 	dfcprintk ((MYIOC_s_INFO_FMT
544 		"mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
545 	        "CurrentTargetID %d, %x %llx %llx\n",
546 		hd->ioc->name,
547 		sdev->host->host_no,
548 		vtarget->num_luns,
549 		sdev->id, ri->pg0.CurrentTargetID,
550 		ri->pg0.PortIdentifier,
551 		(unsigned long long)pn,
552 		(unsigned long long)nn));
553 	}
554 #endif
555 
556 	return 0;
557 }
558 
559 static int
560 mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
561 {
562 	struct mptfc_rport_info	*ri;
563 	struct fc_rport	*rport = starget_to_rport(scsi_target(SCpnt->device));
564 	int		err;
565 
566 	err = fc_remote_port_chkready(rport);
567 	if (unlikely(err)) {
568 		SCpnt->result = err;
569 		done(SCpnt);
570 		return 0;
571 	}
572 
573 	/* dd_data is null until finished adding target */
574 	ri = *((struct mptfc_rport_info **)rport->dd_data);
575 	if (unlikely(!ri)) {
576 		dfcprintk ((MYIOC_s_INFO_FMT
577 			"mptfc_qcmd.%d: %d:%d, dd_data is null.\n",
578 			((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name,
579 			((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no,
580 			SCpnt->device->id,SCpnt->device->lun));
581 		SCpnt->result = DID_IMM_RETRY << 16;
582 		done(SCpnt);
583 		return 0;
584 	}
585 
586 	err = mptscsih_qcmd(SCpnt,done);
587 #ifdef DMPT_DEBUG_FC
588 	if (unlikely(err)) {
589 		dfcprintk ((MYIOC_s_INFO_FMT
590 			"mptfc_qcmd.%d: %d:%d, mptscsih_qcmd returns non-zero.\n",
591 			((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name,
592 			((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no,
593 			SCpnt->device->id,SCpnt->device->lun));
594 	}
595 #endif
596 	return err;
597 }
598 
599 /*
600  *	mptfc_GetFcPortPage0 - Fetch FCPort config Page0.
601  *	@ioc: Pointer to MPT_ADAPTER structure
602  *	@portnum: IOC Port number
603  *
604  *	Return: 0 for success
605  *	-ENOMEM if no memory available
606  *		-EPERM if not allowed due to ISR context
607  *		-EAGAIN if no msg frames currently available
608  *		-EFAULT for non-successful reply or no reply (timeout)
609  *		-EINVAL portnum arg out of range (hardwired to two elements)
610  */
611 static int
612 mptfc_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
613 {
614 	ConfigPageHeader_t	 hdr;
615 	CONFIGPARMS		 cfg;
616 	FCPortPage0_t		*ppage0_alloc;
617 	FCPortPage0_t		*pp0dest;
618 	dma_addr_t		 page0_dma;
619 	int			 data_sz;
620 	int			 copy_sz;
621 	int			 rc;
622 	int			 count = 400;
623 
624 	if (portnum > 1)
625 		return -EINVAL;
626 
627 	/* Get FCPort Page 0 header */
628 	hdr.PageVersion = 0;
629 	hdr.PageLength = 0;
630 	hdr.PageNumber = 0;
631 	hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
632 	cfg.cfghdr.hdr = &hdr;
633 	cfg.physAddr = -1;
634 	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
635 	cfg.dir = 0;
636 	cfg.pageAddr = portnum;
637 	cfg.timeout = 0;
638 
639 	if ((rc = mpt_config(ioc, &cfg)) != 0)
640 		return rc;
641 
642 	if (hdr.PageLength == 0)
643 		return 0;
644 
645 	data_sz = hdr.PageLength * 4;
646 	rc = -ENOMEM;
647 	ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
648 	if (ppage0_alloc) {
649 
650  try_again:
651 		memset((u8 *)ppage0_alloc, 0, data_sz);
652 		cfg.physAddr = page0_dma;
653 		cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
654 
655 		if ((rc = mpt_config(ioc, &cfg)) == 0) {
656 			/* save the data */
657 			pp0dest = &ioc->fc_port_page0[portnum];
658 			copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz);
659 			memcpy(pp0dest, ppage0_alloc, copy_sz);
660 
661 			/*
662 			 *	Normalize endianness of structure data,
663 			 *	by byte-swapping all > 1 byte fields!
664 			 */
665 			pp0dest->Flags = le32_to_cpu(pp0dest->Flags);
666 			pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier);
667 			pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low);
668 			pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High);
669 			pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low);
670 			pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High);
671 			pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass);
672 			pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds);
673 			pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed);
674 			pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize);
675 			pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low);
676 			pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High);
677 			pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low);
678 			pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High);
679 			pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
680 			pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
681 
682 			/*
683 			 * if still doing discovery,
684 			 * hang loose a while until finished
685 			 */
686 			if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) {
687 				if (count-- > 0) {
688 					msleep_interruptible(100);
689 					goto try_again;
690 				}
691 				printk(MYIOC_s_INFO_FMT "Firmware discovery not"
692 							" complete.\n",
693 						ioc->name);
694 			}
695 		}
696 
697 		pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
698 	}
699 
700 	return rc;
701 }
702 
703 static void
704 mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum)
705 {
706 	unsigned class = 0, cos = 0;
707 
708 	/* don't know what to do as only one scsi (fc) host was allocated */
709 	if (portnum != 0)
710 		return;
711 
712 	class = ioc->fc_port_page0[portnum].SupportedServiceClass;
713 	if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_1)
714 		cos |= FC_COS_CLASS1;
715 	if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_2)
716 		cos |= FC_COS_CLASS2;
717 	if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_3)
718 		cos |= FC_COS_CLASS3;
719 
720 	fc_host_node_name(ioc->sh) =
721 	    	(u64)ioc->fc_port_page0[portnum].WWNN.High << 32
722 		    | (u64)ioc->fc_port_page0[portnum].WWNN.Low;
723 
724 	fc_host_port_name(ioc->sh) =
725 	    	(u64)ioc->fc_port_page0[portnum].WWPN.High << 32
726 		    | (u64)ioc->fc_port_page0[portnum].WWPN.Low;
727 
728 	fc_host_port_id(ioc->sh) = ioc->fc_port_page0[portnum].PortIdentifier;
729 
730 	fc_host_supported_classes(ioc->sh) = cos;
731 
732 	fc_host_tgtid_bind_type(ioc->sh) = FC_TGTID_BIND_BY_WWPN;
733 }
734 
735 static void
736 mptfc_rescan_devices(void *arg)
737 {
738 	MPT_ADAPTER		*ioc = (MPT_ADAPTER *)arg;
739 	int			ii;
740 	int			work_to_do;
741 	u64			pn;
742 	unsigned long		flags;
743 	struct mptfc_rport_info *ri;
744 
745 	do {
746 		/* start by tagging all ports as missing */
747 		list_for_each_entry(ri, &ioc->fc_rports, list) {
748 			if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
749 				ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING;
750 			}
751 		}
752 
753 		/*
754 		 * now rescan devices known to adapter,
755 		 * will reregister existing rports
756 		 */
757 		for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
758 			(void) mptfc_GetFcPortPage0(ioc, ii);
759 			mptfc_init_host_attr(ioc,ii);	/* refresh */
760 			mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);
761 		}
762 
763 		/* delete devices still missing */
764 		list_for_each_entry(ri, &ioc->fc_rports, list) {
765 			/* if newly missing, delete it */
766 			if (ri->flags & MPT_RPORT_INFO_FLAGS_MISSING) {
767 
768 				ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|
769 					       MPT_RPORT_INFO_FLAGS_MISSING);
770 				fc_remote_port_delete(ri->rport);	/* won't sleep */
771 				ri->rport = NULL;
772 
773 				pn = (u64)ri->pg0.WWPN.High << 32 |
774 				     (u64)ri->pg0.WWPN.Low;
775 				dfcprintk ((MYIOC_s_INFO_FMT
776 					"mptfc_rescan.%d: %llx deleted\n",
777 					ioc->name,
778 					ioc->sh->host_no,
779 					(unsigned long long)pn));
780 			}
781 		}
782 
783 		/*
784 		 * allow multiple passes as target state
785 		 * might have changed during scan
786 		 */
787 		spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
788 		if (ioc->fc_rescan_work_count > 2) 	/* only need one more */
789 			ioc->fc_rescan_work_count = 2;
790 		work_to_do = --ioc->fc_rescan_work_count;
791 		spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
792 	} while (work_to_do);
793 }
794 
795 static int
796 mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
797 {
798 	struct Scsi_Host	*sh;
799 	MPT_SCSI_HOST		*hd;
800 	MPT_ADAPTER 		*ioc;
801 	unsigned long		 flags;
802 	int			 ii;
803 	int			 numSGE = 0;
804 	int			 scale;
805 	int			 ioc_cap;
806 	int			error=0;
807 	int			r;
808 
809 	if ((r = mpt_attach(pdev,id)) != 0)
810 		return r;
811 
812 	ioc = pci_get_drvdata(pdev);
813 	ioc->DoneCtx = mptfcDoneCtx;
814 	ioc->TaskCtx = mptfcTaskCtx;
815 	ioc->InternalCtx = mptfcInternalCtx;
816 
817 	/*  Added sanity check on readiness of the MPT adapter.
818 	 */
819 	if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
820 		printk(MYIOC_s_WARN_FMT
821 		  "Skipping because it's not operational!\n",
822 		  ioc->name);
823 		error = -ENODEV;
824 		goto out_mptfc_probe;
825 	}
826 
827 	if (!ioc->active) {
828 		printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
829 		  ioc->name);
830 		error = -ENODEV;
831 		goto out_mptfc_probe;
832 	}
833 
834 	/*  Sanity check - ensure at least 1 port is INITIATOR capable
835 	 */
836 	ioc_cap = 0;
837 	for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
838 		if (ioc->pfacts[ii].ProtocolFlags &
839 		    MPI_PORTFACTS_PROTOCOL_INITIATOR)
840 			ioc_cap ++;
841 	}
842 
843 	if (!ioc_cap) {
844 		printk(MYIOC_s_WARN_FMT
845 			"Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
846 			ioc->name, ioc);
847 		return -ENODEV;
848 	}
849 
850 	sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));
851 
852 	if (!sh) {
853 		printk(MYIOC_s_WARN_FMT
854 			"Unable to register controller with SCSI subsystem\n",
855 			ioc->name);
856 		error = -1;
857 		goto out_mptfc_probe;
858         }
859 
860 	spin_lock_init(&ioc->fc_rescan_work_lock);
861 	INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc);
862 
863 	spin_lock_irqsave(&ioc->FreeQlock, flags);
864 
865 	/* Attach the SCSI Host to the IOC structure
866 	 */
867 	ioc->sh = sh;
868 
869 	sh->io_port = 0;
870 	sh->n_io_port = 0;
871 	sh->irq = 0;
872 
873 	/* set 16 byte cdb's */
874 	sh->max_cmd_len = 16;
875 
876 	sh->max_id = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
877 
878 	sh->max_lun = MPT_LAST_LUN + 1;
879 	sh->max_channel = 0;
880 	sh->this_id = ioc->pfacts[0].PortSCSIID;
881 
882 	/* Required entry.
883 	 */
884 	sh->unique_id = ioc->id;
885 
886 	/* Verify that we won't exceed the maximum
887 	 * number of chain buffers
888 	 * We can optimize:  ZZ = req_sz/sizeof(SGE)
889 	 * For 32bit SGE's:
890 	 *  numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
891 	 *               + (req_sz - 64)/sizeof(SGE)
892 	 * A slightly different algorithm is required for
893 	 * 64bit SGEs.
894 	 */
895 	scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
896 	if (sizeof(dma_addr_t) == sizeof(u64)) {
897 		numSGE = (scale - 1) *
898 		  (ioc->facts.MaxChainDepth-1) + scale +
899 		  (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
900 		  sizeof(u32));
901 	} else {
902 		numSGE = 1 + (scale - 1) *
903 		  (ioc->facts.MaxChainDepth-1) + scale +
904 		  (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
905 		  sizeof(u32));
906 	}
907 
908 	if (numSGE < sh->sg_tablesize) {
909 		/* Reset this value */
910 		dprintk((MYIOC_s_INFO_FMT
911 		  "Resetting sg_tablesize to %d from %d\n",
912 		  ioc->name, numSGE, sh->sg_tablesize));
913 		sh->sg_tablesize = numSGE;
914 	}
915 
916 	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
917 
918 	hd = (MPT_SCSI_HOST *) sh->hostdata;
919 	hd->ioc = ioc;
920 
921 	/* SCSI needs scsi_cmnd lookup table!
922 	 * (with size equal to req_depth*PtrSz!)
923 	 */
924 	hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
925 	if (!hd->ScsiLookup) {
926 		error = -ENOMEM;
927 		goto out_mptfc_probe;
928 	}
929 
930 	dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
931 		 ioc->name, hd->ScsiLookup));
932 
933 	/* Allocate memory for the device structures.
934 	 * A non-Null pointer at an offset
935 	 * indicates a device exists.
936 	 * max_id = 1 + maximum id (hosts.h)
937 	 */
938 	hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
939 	if (!hd->Targets) {
940 		error = -ENOMEM;
941 		goto out_mptfc_probe;
942 	}
943 
944 	dprintk((KERN_INFO "  vdev @ %p\n", hd->Targets));
945 
946 	/* Clear the TM flags
947 	 */
948 	hd->tmPending = 0;
949 	hd->tmState = TM_STATE_NONE;
950 	hd->resetPending = 0;
951 	hd->abortSCpnt = NULL;
952 
953 	/* Clear the pointer used to store
954 	 * single-threaded commands, i.e., those
955 	 * issued during a bus scan, dv and
956 	 * configuration pages.
957 	 */
958 	hd->cmdPtr = NULL;
959 
960 	/* Initialize this SCSI Hosts' timers
961 	 * To use, set the timer expires field
962 	 * and add_timer
963 	 */
964 	init_timer(&hd->timer);
965 	hd->timer.data = (unsigned long) hd;
966 	hd->timer.function = mptscsih_timer_expired;
967 
968 	hd->mpt_pq_filter = mpt_pq_filter;
969 
970 	ddvprintk((MYIOC_s_INFO_FMT
971 		"mpt_pq_filter %x\n",
972 		ioc->name,
973 		mpt_pq_filter));
974 
975 	init_waitqueue_head(&hd->scandv_waitq);
976 	hd->scandv_wait_done = 0;
977 	hd->last_queue_full = 0;
978 
979 	sh->transportt = mptfc_transport_template;
980 	error = scsi_add_host (sh, &ioc->pcidev->dev);
981 	if(error) {
982 		dprintk((KERN_ERR MYNAM
983 		  "scsi_add_host failed\n"));
984 		goto out_mptfc_probe;
985 	}
986 
987 	/* initialize workqueue */
988 
989 	snprintf(ioc->fc_rescan_work_q_name, KOBJ_NAME_LEN, "mptfc_wq_%d",
990 		sh->host_no);
991 	ioc->fc_rescan_work_q =
992 		create_singlethread_workqueue(ioc->fc_rescan_work_q_name);
993 	if (!ioc->fc_rescan_work_q)
994 		goto out_mptfc_probe;
995 
996 	/*
997 	 *  Pre-fetch FC port WWN and stuff...
998 	 *  (FCPortPage0_t stuff)
999 	 */
1000 	for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1001 		(void) mptfc_GetFcPortPage0(ioc, ii);
1002 	}
1003 
1004 	/*
1005 	 * scan for rports -
1006 	 *	by doing it via the workqueue, some locking is eliminated
1007 	 */
1008 
1009 	ioc->fc_rescan_work_count = 1;
1010 	queue_work(ioc->fc_rescan_work_q, &ioc->fc_rescan_work);
1011 	flush_workqueue(ioc->fc_rescan_work_q);
1012 
1013 	return 0;
1014 
1015 out_mptfc_probe:
1016 
1017 	mptscsih_remove(pdev);
1018 	return error;
1019 }
1020 
1021 static struct pci_driver mptfc_driver = {
1022 	.name		= "mptfc",
1023 	.id_table	= mptfc_pci_table,
1024 	.probe		= mptfc_probe,
1025 	.remove		= __devexit_p(mptfc_remove),
1026 	.shutdown	= mptscsih_shutdown,
1027 #ifdef CONFIG_PM
1028 	.suspend	= mptscsih_suspend,
1029 	.resume		= mptscsih_resume,
1030 #endif
1031 };
1032 
1033 static int
1034 mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
1035 {
1036 	MPT_SCSI_HOST *hd;
1037 	u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
1038 	unsigned long flags;
1039 	int rc=1;
1040 
1041 	devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
1042 			ioc->name, event));
1043 
1044 	if (ioc->sh == NULL ||
1045 		((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
1046 		return 1;
1047 
1048 	switch (event) {
1049 	case MPI_EVENT_RESCAN:
1050 		spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1051 		if (ioc->fc_rescan_work_q) {
1052 			if (ioc->fc_rescan_work_count++ == 0) {
1053 				queue_work(ioc->fc_rescan_work_q,
1054 					   &ioc->fc_rescan_work);
1055 			}
1056 		}
1057 		spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1058 		break;
1059 	default:
1060 		rc = mptscsih_event_process(ioc,pEvReply);
1061 		break;
1062 	}
1063 	return rc;
1064 }
1065 
1066 static int
1067 mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
1068 {
1069 	int		rc;
1070 	unsigned long	flags;
1071 
1072 	rc = mptscsih_ioc_reset(ioc,reset_phase);
1073 	if (rc == 0)
1074 		return rc;
1075 
1076 
1077 	dtmprintk((KERN_WARNING MYNAM
1078 		": IOC %s_reset routed to FC host driver!\n",
1079 		reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
1080 		reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
1081 
1082 	if (reset_phase == MPT_IOC_SETUP_RESET) {
1083 	}
1084 
1085 	else if (reset_phase == MPT_IOC_PRE_RESET) {
1086 	}
1087 
1088 	else {	/* MPT_IOC_POST_RESET */
1089 		spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1090 		if (ioc->fc_rescan_work_q) {
1091 			if (ioc->fc_rescan_work_count++ == 0) {
1092 				queue_work(ioc->fc_rescan_work_q,
1093 					   &ioc->fc_rescan_work);
1094 			}
1095 		}
1096 		spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1097 	}
1098 	return 1;
1099 }
1100 
1101 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1102 /**
1103  *	mptfc_init - Register MPT adapter(s) as SCSI host(s) with
1104  *	linux scsi mid-layer.
1105  *
1106  *	Returns 0 for success, non-zero for failure.
1107  */
1108 static int __init
1109 mptfc_init(void)
1110 {
1111 	int error;
1112 
1113 	show_mptmod_ver(my_NAME, my_VERSION);
1114 
1115 	/* sanity check module parameter */
1116 	if (mptfc_dev_loss_tmo == 0)
1117 		mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;
1118 
1119 	mptfc_transport_template =
1120 		fc_attach_transport(&mptfc_transport_functions);
1121 
1122 	if (!mptfc_transport_template)
1123 		return -ENODEV;
1124 
1125 	mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER);
1126 	mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER);
1127 	mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER);
1128 
1129 	if (mpt_event_register(mptfcDoneCtx, mptfc_event_process) == 0) {
1130 		devtverboseprintk((KERN_INFO MYNAM
1131 		  ": Registered for IOC event notifications\n"));
1132 	}
1133 
1134 	if (mpt_reset_register(mptfcDoneCtx, mptfc_ioc_reset) == 0) {
1135 		dprintk((KERN_INFO MYNAM
1136 		  ": Registered for IOC reset notifications\n"));
1137 	}
1138 
1139 	error = pci_register_driver(&mptfc_driver);
1140 	if (error)
1141 		fc_release_transport(mptfc_transport_template);
1142 
1143 	return error;
1144 }
1145 
1146 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1147 /**
1148  *	mptfc_remove - Removed fc infrastructure for devices
1149  *	@pdev: Pointer to pci_dev structure
1150  *
1151  */
1152 static void __devexit
1153 mptfc_remove(struct pci_dev *pdev)
1154 {
1155 	MPT_ADAPTER		*ioc = pci_get_drvdata(pdev);
1156 	struct mptfc_rport_info	*p, *n;
1157 	struct workqueue_struct *work_q;
1158 	unsigned long		flags;
1159 
1160 	/* destroy workqueue */
1161 	if ((work_q=ioc->fc_rescan_work_q)) {
1162 		spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1163 		ioc->fc_rescan_work_q = NULL;
1164 		spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1165 		destroy_workqueue(work_q);
1166 	}
1167 
1168 	fc_remove_host(ioc->sh);
1169 
1170 	list_for_each_entry_safe(p, n, &ioc->fc_rports, list) {
1171 		list_del(&p->list);
1172 		kfree(p);
1173 	}
1174 
1175 	mptscsih_remove(pdev);
1176 }
1177 
1178 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1179 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1180 /**
1181  *	mptfc_exit - Unregisters MPT adapter(s)
1182  *
1183  */
1184 static void __exit
1185 mptfc_exit(void)
1186 {
1187 	pci_unregister_driver(&mptfc_driver);
1188 	fc_release_transport(mptfc_transport_template);
1189 
1190 	mpt_reset_deregister(mptfcDoneCtx);
1191 	dprintk((KERN_INFO MYNAM
1192 	  ": Deregistered for IOC reset notifications\n"));
1193 
1194 	mpt_event_deregister(mptfcDoneCtx);
1195 	dprintk((KERN_INFO MYNAM
1196 	  ": Deregistered for IOC event notifications\n"));
1197 
1198 	mpt_deregister(mptfcInternalCtx);
1199 	mpt_deregister(mptfcTaskCtx);
1200 	mpt_deregister(mptfcDoneCtx);
1201 }
1202 
1203 module_init(mptfc_init);
1204 module_exit(mptfc_exit);
1205