xref: /linux/drivers/message/fusion/mptfc.c (revision dec52397)
1 /*
2  *  linux/drivers/message/fusion/mptfc.c
3  *      For use with LSI PCI chip/adapter(s)
4  *      running LSI Fusion MPT (Message Passing Technology) firmware.
5  *
6  *  Copyright (c) 1999-2008 LSI Corporation
7  *  (mailto:DL-MPTFusionLinux@lsi.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/module.h>
47 #include <linux/kernel.h>
48 #include <linux/init.h>
49 #include <linux/errno.h>
50 #include <linux/kdev_t.h>
51 #include <linux/blkdev.h>
52 #include <linux/delay.h>	/* for mdelay */
53 #include <linux/interrupt.h>
54 #include <linux/reboot.h>	/* notifier code */
55 #include <linux/workqueue.h>
56 #include <linux/sort.h>
57 #include <linux/slab.h>
58 
59 #include <scsi/scsi.h>
60 #include <scsi/scsi_cmnd.h>
61 #include <scsi/scsi_device.h>
62 #include <scsi/scsi_host.h>
63 #include <scsi/scsi_tcq.h>
64 #include <scsi/scsi_transport_fc.h>
65 
66 #include "mptbase.h"
67 #include "mptscsih.h"
68 
69 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
70 #define my_NAME		"Fusion MPT FC Host driver"
71 #define my_VERSION	MPT_LINUX_VERSION_COMMON
72 #define MYNAM		"mptfc"
73 
74 MODULE_AUTHOR(MODULEAUTHOR);
75 MODULE_DESCRIPTION(my_NAME);
76 MODULE_LICENSE("GPL");
77 MODULE_VERSION(my_VERSION);
78 
79 /* Command line args */
80 #define MPTFC_DEV_LOSS_TMO (60)
81 static int mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;	/* reasonable default */
82 module_param(mptfc_dev_loss_tmo, int, 0);
83 MODULE_PARM_DESC(mptfc_dev_loss_tmo, " Initial time the driver programs the "
84     				     " transport to wait for an rport to "
85 				     " return following a device loss event."
86 				     "  Default=60.");
87 
88 /* scsi-mid layer global parmeter is max_report_luns, which is 511 */
89 #define MPTFC_MAX_LUN (16895)
90 static int max_lun = MPTFC_MAX_LUN;
91 module_param(max_lun, int, 0);
92 MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
93 
94 static u8	mptfcDoneCtx = MPT_MAX_PROTOCOL_DRIVERS;
95 static u8	mptfcTaskCtx = MPT_MAX_PROTOCOL_DRIVERS;
96 static u8	mptfcInternalCtx = MPT_MAX_PROTOCOL_DRIVERS;
97 
98 static int mptfc_target_alloc(struct scsi_target *starget);
99 static int mptfc_slave_alloc(struct scsi_device *sdev);
100 static int mptfc_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *SCpnt);
101 static void mptfc_target_destroy(struct scsi_target *starget);
102 static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout);
103 static void mptfc_remove(struct pci_dev *pdev);
104 static int mptfc_abort(struct scsi_cmnd *SCpnt);
105 static int mptfc_dev_reset(struct scsi_cmnd *SCpnt);
106 static int mptfc_bus_reset(struct scsi_cmnd *SCpnt);
107 
108 static const struct scsi_host_template mptfc_driver_template = {
109 	.module				= THIS_MODULE,
110 	.proc_name			= "mptfc",
111 	.show_info			= mptscsih_show_info,
112 	.name				= "MPT FC Host",
113 	.info				= mptscsih_info,
114 	.queuecommand			= mptfc_qcmd,
115 	.target_alloc			= mptfc_target_alloc,
116 	.slave_alloc			= mptfc_slave_alloc,
117 	.slave_configure		= mptscsih_slave_configure,
118 	.target_destroy			= mptfc_target_destroy,
119 	.slave_destroy			= mptscsih_slave_destroy,
120 	.change_queue_depth 		= mptscsih_change_queue_depth,
121 	.eh_timed_out			= fc_eh_timed_out,
122 	.eh_abort_handler		= mptfc_abort,
123 	.eh_device_reset_handler	= mptfc_dev_reset,
124 	.eh_bus_reset_handler		= mptfc_bus_reset,
125 	.eh_host_reset_handler		= mptscsih_host_reset,
126 	.bios_param			= mptscsih_bios_param,
127 	.can_queue			= MPT_FC_CAN_QUEUE,
128 	.this_id			= -1,
129 	.sg_tablesize			= MPT_SCSI_SG_DEPTH,
130 	.max_sectors			= 8192,
131 	.cmd_per_lun			= 7,
132 	.dma_alignment			= 511,
133 	.shost_groups			= mptscsih_host_attr_groups,
134 };
135 
136 /****************************************************************************
137  * Supported hardware
138  */
139 
140 static struct pci_device_id mptfc_pci_table[] = {
141 	{ PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC909,
142 		PCI_ANY_ID, PCI_ANY_ID },
143 	{ PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC919,
144 		PCI_ANY_ID, PCI_ANY_ID },
145 	{ PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC929,
146 		PCI_ANY_ID, PCI_ANY_ID },
147 	{ PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC919X,
148 		PCI_ANY_ID, PCI_ANY_ID },
149 	{ PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC929X,
150 		PCI_ANY_ID, PCI_ANY_ID },
151 	{ PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC939X,
152 		PCI_ANY_ID, PCI_ANY_ID },
153 	{ PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC949X,
154 		PCI_ANY_ID, PCI_ANY_ID },
155 	{ PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC949E,
156 		PCI_ANY_ID, PCI_ANY_ID },
157 	{ PCI_VENDOR_ID_BROCADE, MPI_MANUFACTPAGE_DEVICEID_FC949E,
158 		PCI_ANY_ID, PCI_ANY_ID },
159 	{0}	/* Terminating entry */
160 };
161 MODULE_DEVICE_TABLE(pci, mptfc_pci_table);
162 
163 static struct scsi_transport_template *mptfc_transport_template = NULL;
164 
165 static struct fc_function_template mptfc_transport_functions = {
166 	.dd_fcrport_size = 8,
167 	.show_host_node_name = 1,
168 	.show_host_port_name = 1,
169 	.show_host_supported_classes = 1,
170 	.show_host_port_id = 1,
171 	.show_rport_supported_classes = 1,
172 	.show_starget_node_name = 1,
173 	.show_starget_port_name = 1,
174 	.show_starget_port_id = 1,
175 	.set_rport_dev_loss_tmo = mptfc_set_rport_loss_tmo,
176 	.show_rport_dev_loss_tmo = 1,
177 	.show_host_supported_speeds = 1,
178 	.show_host_maxframe_size = 1,
179 	.show_host_speed = 1,
180 	.show_host_fabric_name = 1,
181 	.show_host_port_type = 1,
182 	.show_host_port_state = 1,
183 	.show_host_symbolic_name = 1,
184 };
185 
186 static int
mptfc_block_error_handler(struct fc_rport * rport)187 mptfc_block_error_handler(struct fc_rport *rport)
188 {
189 	MPT_SCSI_HOST		*hd;
190 	struct Scsi_Host	*shost = rport_to_shost(rport);
191 	unsigned long		flags;
192 	int			ready;
193 	MPT_ADAPTER		*ioc;
194 	int			loops = 40;	/* seconds */
195 
196 	hd = shost_priv(shost);
197 	ioc = hd->ioc;
198 	spin_lock_irqsave(shost->host_lock, flags);
199 	while ((ready = fc_remote_port_chkready(rport) >> 16) == DID_IMM_RETRY
200 	 || (loops > 0 && ioc->active == 0)) {
201 		spin_unlock_irqrestore(shost->host_lock, flags);
202 		dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
203 			"mptfc_block_error_handler.%d: %s, port status is "
204 			"%x, active flag %d, deferring recovery.\n",
205 			ioc->name, ioc->sh->host_no,
206 			dev_name(&rport->dev), ready, ioc->active));
207 		msleep(1000);
208 		spin_lock_irqsave(shost->host_lock, flags);
209 		loops --;
210 	}
211 	spin_unlock_irqrestore(shost->host_lock, flags);
212 
213 	if (ready == DID_NO_CONNECT || ioc->active == 0) {
214 		dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
215 			"mpt_block_error_handler.%d: %s, failing recovery, "
216 			"port state %x, active %d.\n",
217 			ioc->name, ioc->sh->host_no,
218 			dev_name(&rport->dev), ready, ioc->active));
219 		return FAILED;
220 	}
221 	return SUCCESS;
222 }
223 
224 static int
mptfc_abort(struct scsi_cmnd * SCpnt)225 mptfc_abort(struct scsi_cmnd *SCpnt)
226 {
227 	struct Scsi_Host *shost = SCpnt->device->host;
228 	struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device));
229 	MPT_SCSI_HOST __maybe_unused *hd = shost_priv(shost);
230 	int rtn;
231 
232 	rtn = mptfc_block_error_handler(rport);
233 	if (rtn == SUCCESS) {
234 		dfcprintk (hd->ioc, printk(MYIOC_s_DEBUG_FMT
235 			"%s.%d: %d:%llu, executing recovery.\n", __func__,
236 			hd->ioc->name, shost->host_no,
237 			SCpnt->device->id, SCpnt->device->lun));
238 		rtn = mptscsih_abort(SCpnt);
239 	}
240 	return rtn;
241 }
242 
243 static int
mptfc_dev_reset(struct scsi_cmnd * SCpnt)244 mptfc_dev_reset(struct scsi_cmnd *SCpnt)
245 {
246 	struct Scsi_Host *shost = SCpnt->device->host;
247 	struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device));
248 	MPT_SCSI_HOST __maybe_unused *hd = shost_priv(shost);
249 	int rtn;
250 
251 	rtn = mptfc_block_error_handler(rport);
252 	if (rtn == SUCCESS) {
253 		dfcprintk (hd->ioc, printk(MYIOC_s_DEBUG_FMT
254 			"%s.%d: %d:%llu, executing recovery.\n", __func__,
255 			hd->ioc->name, shost->host_no,
256 			SCpnt->device->id, SCpnt->device->lun));
257 		rtn = mptscsih_dev_reset(SCpnt);
258 	}
259 	return rtn;
260 }
261 
262 static int
mptfc_bus_reset(struct scsi_cmnd * SCpnt)263 mptfc_bus_reset(struct scsi_cmnd *SCpnt)
264 {
265 	struct Scsi_Host *shost = SCpnt->device->host;
266 	MPT_SCSI_HOST __maybe_unused *hd = shost_priv(shost);
267 	int channel = SCpnt->device->channel;
268 	struct mptfc_rport_info *ri;
269 	int rtn = FAILED;
270 
271 	list_for_each_entry(ri, &hd->ioc->fc_rports, list) {
272 		if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
273 			VirtTarget *vtarget = ri->starget->hostdata;
274 
275 			if (!vtarget || vtarget->channel != channel)
276 				continue;
277 			rtn = fc_block_rport(ri->rport);
278 			if (rtn != 0)
279 				break;
280 		}
281 	}
282 	if (rtn == 0) {
283 		dfcprintk (hd->ioc, printk(MYIOC_s_DEBUG_FMT
284 			"%s.%d: %d:%llu, executing recovery.\n", __func__,
285 			hd->ioc->name, shost->host_no,
286 			SCpnt->device->id, SCpnt->device->lun));
287 		rtn = mptscsih_bus_reset(SCpnt);
288 	}
289 	return rtn;
290 }
291 
292 static void
mptfc_set_rport_loss_tmo(struct fc_rport * rport,uint32_t timeout)293 mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
294 {
295 	if (timeout > 0)
296 		rport->dev_loss_tmo = timeout;
297 	else
298 		rport->dev_loss_tmo = mptfc_dev_loss_tmo;
299 }
300 
301 static int
mptfc_FcDevPage0_cmp_func(const void * a,const void * b)302 mptfc_FcDevPage0_cmp_func(const void *a, const void *b)
303 {
304 	FCDevicePage0_t **aa = (FCDevicePage0_t **)a;
305 	FCDevicePage0_t **bb = (FCDevicePage0_t **)b;
306 
307 	if ((*aa)->CurrentBus == (*bb)->CurrentBus) {
308 		if ((*aa)->CurrentTargetID == (*bb)->CurrentTargetID)
309 			return 0;
310 		if ((*aa)->CurrentTargetID < (*bb)->CurrentTargetID)
311 			return -1;
312 		return 1;
313 	}
314 	if ((*aa)->CurrentBus < (*bb)->CurrentBus)
315 		return -1;
316 	return 1;
317 }
318 
319 static int
mptfc_GetFcDevPage0(MPT_ADAPTER * ioc,int ioc_port,void (* func)(MPT_ADAPTER * ioc,int channel,FCDevicePage0_t * arg))320 mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, int ioc_port,
321 	void(*func)(MPT_ADAPTER *ioc,int channel, FCDevicePage0_t *arg))
322 {
323 	ConfigPageHeader_t	 hdr;
324 	CONFIGPARMS		 cfg;
325 	FCDevicePage0_t		*ppage0_alloc, *fc;
326 	dma_addr_t		 page0_dma;
327 	int			 data_sz;
328 	int			 ii;
329 
330 	FCDevicePage0_t		*p0_array=NULL, *p_p0;
331 	FCDevicePage0_t		**pp0_array=NULL, **p_pp0;
332 
333 	int			 rc = -ENOMEM;
334 	U32			 port_id = 0xffffff;
335 	int			 num_targ = 0;
336 	int			 max_bus = ioc->facts.MaxBuses;
337 	int			 max_targ;
338 
339 	max_targ = (ioc->facts.MaxDevices == 0) ? 256 : ioc->facts.MaxDevices;
340 
341 	data_sz = sizeof(FCDevicePage0_t) * max_bus * max_targ;
342 	p_p0 = p0_array =  kzalloc(data_sz, GFP_KERNEL);
343 	if (!p0_array)
344 		goto out;
345 
346 	data_sz = sizeof(FCDevicePage0_t *) * max_bus * max_targ;
347 	p_pp0 = pp0_array = kzalloc(data_sz, GFP_KERNEL);
348 	if (!pp0_array)
349 		goto out;
350 
351 	do {
352 		/* Get FC Device Page 0 header */
353 		hdr.PageVersion = 0;
354 		hdr.PageLength = 0;
355 		hdr.PageNumber = 0;
356 		hdr.PageType = MPI_CONFIG_PAGETYPE_FC_DEVICE;
357 		cfg.cfghdr.hdr = &hdr;
358 		cfg.physAddr = -1;
359 		cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
360 		cfg.dir = 0;
361 		cfg.pageAddr = port_id;
362 		cfg.timeout = 0;
363 
364 		if ((rc = mpt_config(ioc, &cfg)) != 0)
365 			break;
366 
367 		if (hdr.PageLength <= 0)
368 			break;
369 
370 		data_sz = hdr.PageLength * 4;
371 		ppage0_alloc = dma_alloc_coherent(&ioc->pcidev->dev, data_sz,
372 						  &page0_dma, GFP_KERNEL);
373 		rc = -ENOMEM;
374 		if (!ppage0_alloc)
375 			break;
376 
377 		cfg.physAddr = page0_dma;
378 		cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
379 
380 		if ((rc = mpt_config(ioc, &cfg)) == 0) {
381 			ppage0_alloc->PortIdentifier =
382 				le32_to_cpu(ppage0_alloc->PortIdentifier);
383 
384 			ppage0_alloc->WWNN.Low =
385 				le32_to_cpu(ppage0_alloc->WWNN.Low);
386 
387 			ppage0_alloc->WWNN.High =
388 				le32_to_cpu(ppage0_alloc->WWNN.High);
389 
390 			ppage0_alloc->WWPN.Low =
391 				le32_to_cpu(ppage0_alloc->WWPN.Low);
392 
393 			ppage0_alloc->WWPN.High =
394 				le32_to_cpu(ppage0_alloc->WWPN.High);
395 
396 			ppage0_alloc->BBCredit =
397 				le16_to_cpu(ppage0_alloc->BBCredit);
398 
399 			ppage0_alloc->MaxRxFrameSize =
400 				le16_to_cpu(ppage0_alloc->MaxRxFrameSize);
401 
402 			port_id = ppage0_alloc->PortIdentifier;
403 			num_targ++;
404 			*p_p0 = *ppage0_alloc;	/* save data */
405 			*p_pp0++ = p_p0++;	/* save addr */
406 		}
407 		dma_free_coherent(&ioc->pcidev->dev, data_sz,
408 				  ppage0_alloc, page0_dma);
409 		if (rc != 0)
410 			break;
411 
412 	} while (port_id <= 0xff0000);
413 
414 	if (num_targ) {
415 		/* sort array */
416 		if (num_targ > 1)
417 			sort (pp0_array, num_targ, sizeof(FCDevicePage0_t *),
418 				mptfc_FcDevPage0_cmp_func, NULL);
419 		/* call caller's func for each targ */
420 		for (ii = 0; ii < num_targ;  ii++) {
421 			fc = *(pp0_array+ii);
422 			func(ioc, ioc_port, fc);
423 		}
424 	}
425 
426  out:
427 	kfree(pp0_array);
428 	kfree(p0_array);
429 	return rc;
430 }
431 
432 static int
mptfc_generate_rport_ids(FCDevicePage0_t * pg0,struct fc_rport_identifiers * rid)433 mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid)
434 {
435 	/* not currently usable */
436 	if (pg0->Flags & (MPI_FC_DEVICE_PAGE0_FLAGS_PLOGI_INVALID |
437 			  MPI_FC_DEVICE_PAGE0_FLAGS_PRLI_INVALID))
438 		return -1;
439 
440 	if (!(pg0->Flags & MPI_FC_DEVICE_PAGE0_FLAGS_TARGETID_BUS_VALID))
441 		return -1;
442 
443 	if (!(pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_TARGET))
444 		return -1;
445 
446 	/*
447 	 * board data structure already normalized to platform endianness
448 	 * shifted to avoid unaligned access on 64 bit architecture
449 	 */
450 	rid->node_name = ((u64)pg0->WWNN.High) << 32 | (u64)pg0->WWNN.Low;
451 	rid->port_name = ((u64)pg0->WWPN.High) << 32 | (u64)pg0->WWPN.Low;
452 	rid->port_id =   pg0->PortIdentifier;
453 	rid->roles = FC_RPORT_ROLE_UNKNOWN;
454 
455 	return 0;
456 }
457 
458 static void
mptfc_register_dev(MPT_ADAPTER * ioc,int channel,FCDevicePage0_t * pg0)459 mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
460 {
461 	struct fc_rport_identifiers rport_ids;
462 	struct fc_rport		*rport;
463 	struct mptfc_rport_info	*ri;
464 	int			new_ri = 1;
465 	u64			pn, nn;
466 	VirtTarget		*vtarget;
467 	u32			roles = FC_RPORT_ROLE_UNKNOWN;
468 
469 	if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0)
470 		return;
471 
472 	roles |= FC_RPORT_ROLE_FCP_TARGET;
473 	if (pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR)
474 		roles |= FC_RPORT_ROLE_FCP_INITIATOR;
475 
476 	/* scan list looking for a match */
477 	list_for_each_entry(ri, &ioc->fc_rports, list) {
478 		pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
479 		if (pn == rport_ids.port_name) {	/* match */
480 			list_move_tail(&ri->list, &ioc->fc_rports);
481 			new_ri = 0;
482 			break;
483 		}
484 	}
485 	if (new_ri) {	/* allocate one */
486 		ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL);
487 		if (!ri)
488 			return;
489 		list_add_tail(&ri->list, &ioc->fc_rports);
490 	}
491 
492 	ri->pg0 = *pg0;	/* add/update pg0 data */
493 	ri->flags &= ~MPT_RPORT_INFO_FLAGS_MISSING;
494 
495 	/* MPT_RPORT_INFO_FLAGS_REGISTERED - rport not previously deleted */
496 	if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) {
497 		ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED;
498 		rport = fc_remote_port_add(ioc->sh, channel, &rport_ids);
499 		if (rport) {
500 			ri->rport = rport;
501 			if (new_ri) /* may have been reset by user */
502 				rport->dev_loss_tmo = mptfc_dev_loss_tmo;
503 			/*
504 			 * if already mapped, remap here.  If not mapped,
505 			 * target_alloc will allocate vtarget and map,
506 			 * slave_alloc will fill in vdevice from vtarget.
507 			 */
508 			if (ri->starget) {
509 				vtarget = ri->starget->hostdata;
510 				if (vtarget) {
511 					vtarget->id = pg0->CurrentTargetID;
512 					vtarget->channel = pg0->CurrentBus;
513 					vtarget->deleted = 0;
514 				}
515 			}
516 			*((struct mptfc_rport_info **)rport->dd_data) = ri;
517 			/* scan will be scheduled once rport becomes a target */
518 			fc_remote_port_rolechg(rport,roles);
519 
520 			pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
521 			nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low;
522 			dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
523 				"mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "
524 				"rport tid %d, tmo %d\n",
525 					ioc->name,
526 					ioc->sh->host_no,
527 					pg0->PortIdentifier,
528 					(unsigned long long)nn,
529 					(unsigned long long)pn,
530 					pg0->CurrentTargetID,
531 					ri->rport->scsi_target_id,
532 					ri->rport->dev_loss_tmo));
533 		} else {
534 			list_del(&ri->list);
535 			kfree(ri);
536 			ri = NULL;
537 		}
538 	}
539 }
540 
541 /*
542  *	OS entry point to allow for host driver to free allocated memory
543  *	Called if no device present or device being unloaded
544  */
545 static void
mptfc_target_destroy(struct scsi_target * starget)546 mptfc_target_destroy(struct scsi_target *starget)
547 {
548 	struct fc_rport		*rport;
549 	struct mptfc_rport_info *ri;
550 
551 	rport = starget_to_rport(starget);
552 	if (rport) {
553 		ri = *((struct mptfc_rport_info **)rport->dd_data);
554 		if (ri)	/* better be! */
555 			ri->starget = NULL;
556 	}
557 	kfree(starget->hostdata);
558 	starget->hostdata = NULL;
559 }
560 
561 /*
562  *	OS entry point to allow host driver to alloc memory
563  *	for each scsi target. Called once per device the bus scan.
564  *	Return non-zero if allocation fails.
565  */
566 static int
mptfc_target_alloc(struct scsi_target * starget)567 mptfc_target_alloc(struct scsi_target *starget)
568 {
569 	VirtTarget		*vtarget;
570 	struct fc_rport		*rport;
571 	struct mptfc_rport_info *ri;
572 	int			rc;
573 
574 	vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
575 	if (!vtarget)
576 		return -ENOMEM;
577 	starget->hostdata = vtarget;
578 
579 	rc = -ENODEV;
580 	rport = starget_to_rport(starget);
581 	if (rport) {
582 		ri = *((struct mptfc_rport_info **)rport->dd_data);
583 		if (ri) {	/* better be! */
584 			vtarget->id = ri->pg0.CurrentTargetID;
585 			vtarget->channel = ri->pg0.CurrentBus;
586 			ri->starget = starget;
587 			rc = 0;
588 		}
589 	}
590 	if (rc != 0) {
591 		kfree(vtarget);
592 		starget->hostdata = NULL;
593 	}
594 
595 	return rc;
596 }
597 /*
598  *	mptfc_dump_lun_info
599  *	@ioc
600  *	@rport
601  *	@sdev
602  *
603  */
604 static void
mptfc_dump_lun_info(MPT_ADAPTER * ioc,struct fc_rport * rport,struct scsi_device * sdev,VirtTarget * vtarget)605 mptfc_dump_lun_info(MPT_ADAPTER *ioc, struct fc_rport *rport, struct scsi_device *sdev,
606 		VirtTarget *vtarget)
607 {
608 	u64 nn, pn;
609 	struct mptfc_rport_info *ri;
610 
611 	ri = *((struct mptfc_rport_info **)rport->dd_data);
612 	pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
613 	nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low;
614 	dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
615 		"mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
616 		"CurrentTargetID %d, %x %llx %llx\n",
617 		ioc->name,
618 		sdev->host->host_no,
619 		vtarget->num_luns,
620 		sdev->id, ri->pg0.CurrentTargetID,
621 		ri->pg0.PortIdentifier,
622 		(unsigned long long)pn,
623 		(unsigned long long)nn));
624 }
625 
626 
627 /*
628  *	OS entry point to allow host driver to alloc memory
629  *	for each scsi device. Called once per device the bus scan.
630  *	Return non-zero if allocation fails.
631  *	Init memory once per LUN.
632  */
633 static int
mptfc_slave_alloc(struct scsi_device * sdev)634 mptfc_slave_alloc(struct scsi_device *sdev)
635 {
636 	MPT_SCSI_HOST		*hd;
637 	VirtTarget		*vtarget;
638 	VirtDevice		*vdevice;
639 	struct scsi_target	*starget;
640 	struct fc_rport		*rport;
641 	MPT_ADAPTER 		*ioc;
642 
643 	starget = scsi_target(sdev);
644 	rport = starget_to_rport(starget);
645 
646 	if (!rport || fc_remote_port_chkready(rport))
647 		return -ENXIO;
648 
649 	hd = shost_priv(sdev->host);
650 	ioc = hd->ioc;
651 
652 	vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
653 	if (!vdevice) {
654 		printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
655 				ioc->name, sizeof(VirtDevice));
656 		return -ENOMEM;
657 	}
658 
659 
660 	sdev->hostdata = vdevice;
661 	vtarget = starget->hostdata;
662 
663 	if (vtarget->num_luns == 0) {
664 		vtarget->ioc_id = ioc->id;
665 		vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
666 	}
667 
668 	vdevice->vtarget = vtarget;
669 	vdevice->lun = sdev->lun;
670 
671 	vtarget->num_luns++;
672 
673 
674 	mptfc_dump_lun_info(ioc, rport, sdev, vtarget);
675 
676 	return 0;
677 }
678 
679 static int
mptfc_qcmd(struct Scsi_Host * shost,struct scsi_cmnd * SCpnt)680 mptfc_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *SCpnt)
681 {
682 	struct mptfc_rport_info	*ri;
683 	struct fc_rport	*rport = starget_to_rport(scsi_target(SCpnt->device));
684 	int		err;
685 	VirtDevice	*vdevice = SCpnt->device->hostdata;
686 
687 	if (!vdevice || !vdevice->vtarget) {
688 		SCpnt->result = DID_NO_CONNECT << 16;
689 		scsi_done(SCpnt);
690 		return 0;
691 	}
692 
693 	err = fc_remote_port_chkready(rport);
694 	if (unlikely(err)) {
695 		SCpnt->result = err;
696 		scsi_done(SCpnt);
697 		return 0;
698 	}
699 
700 	/* dd_data is null until finished adding target */
701 	ri = *((struct mptfc_rport_info **)rport->dd_data);
702 	if (unlikely(!ri)) {
703 		SCpnt->result = DID_IMM_RETRY << 16;
704 		scsi_done(SCpnt);
705 		return 0;
706 	}
707 
708 	return mptscsih_qcmd(SCpnt);
709 }
710 
711 /*
712  *	mptfc_display_port_link_speed - displaying link speed
713  *	@ioc: Pointer to MPT_ADAPTER structure
714  *	@portnum: IOC Port number
715  *	@pp0dest: port page0 data payload
716  *
717  */
718 static void
mptfc_display_port_link_speed(MPT_ADAPTER * ioc,int portnum,FCPortPage0_t * pp0dest)719 mptfc_display_port_link_speed(MPT_ADAPTER *ioc, int portnum, FCPortPage0_t *pp0dest)
720 {
721 	u8	old_speed, new_speed, state;
722 	char	*old, *new;
723 
724 	if (portnum >= 2)
725 		return;
726 
727 	old_speed = ioc->fc_link_speed[portnum];
728 	new_speed = pp0dest->CurrentSpeed;
729 	state = pp0dest->PortState;
730 
731 	if (state != MPI_FCPORTPAGE0_PORTSTATE_OFFLINE &&
732 	    new_speed != MPI_FCPORTPAGE0_CURRENT_SPEED_UNKNOWN) {
733 
734 		old = old_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT ? "1 Gbps" :
735 		       old_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT ? "2 Gbps" :
736 			old_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT ? "4 Gbps" :
737 			 "Unknown";
738 		new = new_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT ? "1 Gbps" :
739 		       new_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT ? "2 Gbps" :
740 			new_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT ? "4 Gbps" :
741 			 "Unknown";
742 		if (old_speed == 0)
743 			printk(MYIOC_s_NOTE_FMT
744 				"FC Link Established, Speed = %s\n",
745 				ioc->name, new);
746 		else if (old_speed != new_speed)
747 			printk(MYIOC_s_WARN_FMT
748 				"FC Link Speed Change, Old Speed = %s, New Speed = %s\n",
749 				ioc->name, old, new);
750 
751 		ioc->fc_link_speed[portnum] = new_speed;
752 	}
753 }
754 
755 /*
756  *	mptfc_GetFcPortPage0 - Fetch FCPort config Page0.
757  *	@ioc: Pointer to MPT_ADAPTER structure
758  *	@portnum: IOC Port number
759  *
760  *	Return: 0 for success
761  *	-ENOMEM if no memory available
762  *		-EPERM if not allowed due to ISR context
763  *		-EAGAIN if no msg frames currently available
764  *		-EFAULT for non-successful reply or no reply (timeout)
765  *		-EINVAL portnum arg out of range (hardwired to two elements)
766  */
767 static int
mptfc_GetFcPortPage0(MPT_ADAPTER * ioc,int portnum)768 mptfc_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
769 {
770 	ConfigPageHeader_t	 hdr;
771 	CONFIGPARMS		 cfg;
772 	FCPortPage0_t		*ppage0_alloc;
773 	FCPortPage0_t		*pp0dest;
774 	dma_addr_t		 page0_dma;
775 	int			 data_sz;
776 	int			 copy_sz;
777 	int			 rc;
778 	int			 count = 400;
779 
780 	if (portnum > 1)
781 		return -EINVAL;
782 
783 	/* Get FCPort Page 0 header */
784 	hdr.PageVersion = 0;
785 	hdr.PageLength = 0;
786 	hdr.PageNumber = 0;
787 	hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
788 	cfg.cfghdr.hdr = &hdr;
789 	cfg.physAddr = -1;
790 	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
791 	cfg.dir = 0;
792 	cfg.pageAddr = portnum;
793 	cfg.timeout = 0;
794 
795 	if ((rc = mpt_config(ioc, &cfg)) != 0)
796 		return rc;
797 
798 	if (hdr.PageLength == 0)
799 		return 0;
800 
801 	data_sz = hdr.PageLength * 4;
802 	rc = -ENOMEM;
803 	ppage0_alloc = dma_alloc_coherent(&ioc->pcidev->dev, data_sz,
804 					  &page0_dma, GFP_KERNEL);
805 	if (ppage0_alloc) {
806 
807  try_again:
808 		memset((u8 *)ppage0_alloc, 0, data_sz);
809 		cfg.physAddr = page0_dma;
810 		cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
811 
812 		if ((rc = mpt_config(ioc, &cfg)) == 0) {
813 			/* save the data */
814 			pp0dest = &ioc->fc_port_page0[portnum];
815 			copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz);
816 			memcpy(pp0dest, ppage0_alloc, copy_sz);
817 
818 			/*
819 			 *	Normalize endianness of structure data,
820 			 *	by byte-swapping all > 1 byte fields!
821 			 */
822 			pp0dest->Flags = le32_to_cpu(pp0dest->Flags);
823 			pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier);
824 			pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low);
825 			pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High);
826 			pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low);
827 			pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High);
828 			pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass);
829 			pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds);
830 			pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed);
831 			pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize);
832 			pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low);
833 			pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High);
834 			pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low);
835 			pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High);
836 			pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
837 			pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
838 
839 			/*
840 			 * if still doing discovery,
841 			 * hang loose a while until finished
842 			 */
843 			if ((pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) ||
844 			    (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_ONLINE &&
845 			     (pp0dest->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_TYPE_MASK)
846 			      == MPI_FCPORTPAGE0_FLAGS_ATTACH_NO_INIT)) {
847 				if (count-- > 0) {
848 					msleep(100);
849 					goto try_again;
850 				}
851 				printk(MYIOC_s_INFO_FMT "Firmware discovery not"
852 							" complete.\n",
853 						ioc->name);
854 			}
855 			mptfc_display_port_link_speed(ioc, portnum, pp0dest);
856 		}
857 
858 		dma_free_coherent(&ioc->pcidev->dev, data_sz, ppage0_alloc,
859 				  page0_dma);
860 	}
861 
862 	return rc;
863 }
864 
865 static int
mptfc_WriteFcPortPage1(MPT_ADAPTER * ioc,int portnum)866 mptfc_WriteFcPortPage1(MPT_ADAPTER *ioc, int portnum)
867 {
868 	ConfigPageHeader_t	 hdr;
869 	CONFIGPARMS		 cfg;
870 	int			 rc;
871 
872 	if (portnum > 1)
873 		return -EINVAL;
874 
875 	if (!(ioc->fc_data.fc_port_page1[portnum].data))
876 		return -EINVAL;
877 
878 	/* get fcport page 1 header */
879 	hdr.PageVersion = 0;
880 	hdr.PageLength = 0;
881 	hdr.PageNumber = 1;
882 	hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
883 	cfg.cfghdr.hdr = &hdr;
884 	cfg.physAddr = -1;
885 	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
886 	cfg.dir = 0;
887 	cfg.pageAddr = portnum;
888 	cfg.timeout = 0;
889 
890 	if ((rc = mpt_config(ioc, &cfg)) != 0)
891 		return rc;
892 
893 	if (hdr.PageLength == 0)
894 		return -ENODEV;
895 
896 	if (hdr.PageLength*4 != ioc->fc_data.fc_port_page1[portnum].pg_sz)
897 		return -EINVAL;
898 
899 	cfg.physAddr = ioc->fc_data.fc_port_page1[portnum].dma;
900 	cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
901 	cfg.dir = 1;
902 
903 	rc = mpt_config(ioc, &cfg);
904 
905 	return rc;
906 }
907 
908 static int
mptfc_GetFcPortPage1(MPT_ADAPTER * ioc,int portnum)909 mptfc_GetFcPortPage1(MPT_ADAPTER *ioc, int portnum)
910 {
911 	ConfigPageHeader_t	 hdr;
912 	CONFIGPARMS		 cfg;
913 	FCPortPage1_t		*page1_alloc;
914 	dma_addr_t		 page1_dma;
915 	int			 data_sz;
916 	int			 rc;
917 
918 	if (portnum > 1)
919 		return -EINVAL;
920 
921 	/* get fcport page 1 header */
922 	hdr.PageVersion = 0;
923 	hdr.PageLength = 0;
924 	hdr.PageNumber = 1;
925 	hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
926 	cfg.cfghdr.hdr = &hdr;
927 	cfg.physAddr = -1;
928 	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
929 	cfg.dir = 0;
930 	cfg.pageAddr = portnum;
931 	cfg.timeout = 0;
932 
933 	if ((rc = mpt_config(ioc, &cfg)) != 0)
934 		return rc;
935 
936 	if (hdr.PageLength == 0)
937 		return -ENODEV;
938 
939 start_over:
940 
941 	if (ioc->fc_data.fc_port_page1[portnum].data == NULL) {
942 		data_sz = hdr.PageLength * 4;
943 		if (data_sz < sizeof(FCPortPage1_t))
944 			data_sz = sizeof(FCPortPage1_t);
945 
946 		page1_alloc = dma_alloc_coherent(&ioc->pcidev->dev, data_sz,
947 						 &page1_dma, GFP_KERNEL);
948 		if (!page1_alloc)
949 			return -ENOMEM;
950 	}
951 	else {
952 		page1_alloc = ioc->fc_data.fc_port_page1[portnum].data;
953 		page1_dma = ioc->fc_data.fc_port_page1[portnum].dma;
954 		data_sz = ioc->fc_data.fc_port_page1[portnum].pg_sz;
955 		if (hdr.PageLength * 4 > data_sz) {
956 			ioc->fc_data.fc_port_page1[portnum].data = NULL;
957 			dma_free_coherent(&ioc->pcidev->dev, data_sz,
958 					  page1_alloc, page1_dma);
959 			goto start_over;
960 		}
961 	}
962 
963 	cfg.physAddr = page1_dma;
964 	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
965 
966 	if ((rc = mpt_config(ioc, &cfg)) == 0) {
967 		ioc->fc_data.fc_port_page1[portnum].data = page1_alloc;
968 		ioc->fc_data.fc_port_page1[portnum].pg_sz = data_sz;
969 		ioc->fc_data.fc_port_page1[portnum].dma = page1_dma;
970 	}
971 	else {
972 		ioc->fc_data.fc_port_page1[portnum].data = NULL;
973 		dma_free_coherent(&ioc->pcidev->dev, data_sz, page1_alloc,
974 				  page1_dma);
975 	}
976 
977 	return rc;
978 }
979 
980 static void
mptfc_SetFcPortPage1_defaults(MPT_ADAPTER * ioc)981 mptfc_SetFcPortPage1_defaults(MPT_ADAPTER *ioc)
982 {
983 	int		ii;
984 	FCPortPage1_t	*pp1;
985 
986 	#define MPTFC_FW_DEVICE_TIMEOUT	(1)
987 	#define MPTFC_FW_IO_PEND_TIMEOUT (1)
988 	#define ON_FLAGS  (MPI_FCPORTPAGE1_FLAGS_IMMEDIATE_ERROR_REPLY)
989 	#define OFF_FLAGS (MPI_FCPORTPAGE1_FLAGS_VERBOSE_RESCAN_EVENTS)
990 
991 	for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) {
992 		if (mptfc_GetFcPortPage1(ioc, ii) != 0)
993 			continue;
994 		pp1 = ioc->fc_data.fc_port_page1[ii].data;
995 		if ((pp1->InitiatorDeviceTimeout == MPTFC_FW_DEVICE_TIMEOUT)
996 		 && (pp1->InitiatorIoPendTimeout == MPTFC_FW_IO_PEND_TIMEOUT)
997 		 && ((pp1->Flags & ON_FLAGS) == ON_FLAGS)
998 		 && ((pp1->Flags & OFF_FLAGS) == 0))
999 			continue;
1000 		pp1->InitiatorDeviceTimeout = MPTFC_FW_DEVICE_TIMEOUT;
1001 		pp1->InitiatorIoPendTimeout = MPTFC_FW_IO_PEND_TIMEOUT;
1002 		pp1->Flags &= ~OFF_FLAGS;
1003 		pp1->Flags |= ON_FLAGS;
1004 		mptfc_WriteFcPortPage1(ioc, ii);
1005 	}
1006 }
1007 
1008 
1009 static void
mptfc_init_host_attr(MPT_ADAPTER * ioc,int portnum)1010 mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum)
1011 {
1012 	unsigned	class = 0;
1013 	unsigned	cos = 0;
1014 	unsigned	speed;
1015 	unsigned	port_type;
1016 	unsigned	port_state;
1017 	FCPortPage0_t	*pp0;
1018 	struct Scsi_Host *sh;
1019 	char		*sn;
1020 
1021 	/* don't know what to do as only one scsi (fc) host was allocated */
1022 	if (portnum != 0)
1023 		return;
1024 
1025 	pp0 = &ioc->fc_port_page0[portnum];
1026 	sh = ioc->sh;
1027 
1028 	sn = fc_host_symbolic_name(sh);
1029 	snprintf(sn, FC_SYMBOLIC_NAME_SIZE, "%s %s%08xh",
1030 	    ioc->prod_name,
1031 	    MPT_FW_REV_MAGIC_ID_STRING,
1032 	    ioc->facts.FWVersion.Word);
1033 
1034 	fc_host_tgtid_bind_type(sh) = FC_TGTID_BIND_BY_WWPN;
1035 
1036 	fc_host_maxframe_size(sh) = pp0->MaxFrameSize;
1037 
1038 	fc_host_node_name(sh) =
1039 	    	(u64)pp0->WWNN.High << 32 | (u64)pp0->WWNN.Low;
1040 
1041 	fc_host_port_name(sh) =
1042 	    	(u64)pp0->WWPN.High << 32 | (u64)pp0->WWPN.Low;
1043 
1044 	fc_host_port_id(sh) = pp0->PortIdentifier;
1045 
1046 	class = pp0->SupportedServiceClass;
1047 	if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_1)
1048 		cos |= FC_COS_CLASS1;
1049 	if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_2)
1050 		cos |= FC_COS_CLASS2;
1051 	if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_3)
1052 		cos |= FC_COS_CLASS3;
1053 	fc_host_supported_classes(sh) = cos;
1054 
1055 	if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT)
1056 		speed = FC_PORTSPEED_1GBIT;
1057 	else if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT)
1058 		speed = FC_PORTSPEED_2GBIT;
1059 	else if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT)
1060 		speed = FC_PORTSPEED_4GBIT;
1061 	else if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_10GBIT)
1062 		speed = FC_PORTSPEED_10GBIT;
1063 	else
1064 		speed = FC_PORTSPEED_UNKNOWN;
1065 	fc_host_speed(sh) = speed;
1066 
1067 	speed = 0;
1068 	if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_1GBIT_SPEED)
1069 		speed |= FC_PORTSPEED_1GBIT;
1070 	if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_2GBIT_SPEED)
1071 		speed |= FC_PORTSPEED_2GBIT;
1072 	if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_4GBIT_SPEED)
1073 		speed |= FC_PORTSPEED_4GBIT;
1074 	if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_10GBIT_SPEED)
1075 		speed |= FC_PORTSPEED_10GBIT;
1076 	fc_host_supported_speeds(sh) = speed;
1077 
1078 	port_state = FC_PORTSTATE_UNKNOWN;
1079 	if (pp0->PortState == MPI_FCPORTPAGE0_PORTSTATE_ONLINE)
1080 		port_state = FC_PORTSTATE_ONLINE;
1081 	else if (pp0->PortState == MPI_FCPORTPAGE0_PORTSTATE_OFFLINE)
1082 		port_state = FC_PORTSTATE_LINKDOWN;
1083 	fc_host_port_state(sh) = port_state;
1084 
1085 	port_type = FC_PORTTYPE_UNKNOWN;
1086 	if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_POINT_TO_POINT)
1087 		port_type = FC_PORTTYPE_PTP;
1088 	else if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_PRIVATE_LOOP)
1089 		port_type = FC_PORTTYPE_LPORT;
1090 	else if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_PUBLIC_LOOP)
1091 		port_type = FC_PORTTYPE_NLPORT;
1092 	else if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_FABRIC_DIRECT)
1093 		port_type = FC_PORTTYPE_NPORT;
1094 	fc_host_port_type(sh) = port_type;
1095 
1096 	fc_host_fabric_name(sh) =
1097 	    (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_FABRIC_WWN_VALID) ?
1098 		(u64) pp0->FabricWWNN.High << 32 | (u64) pp0->FabricWWPN.Low :
1099 		(u64)pp0->WWNN.High << 32 | (u64)pp0->WWNN.Low;
1100 
1101 }
1102 
1103 static void
mptfc_link_status_change(struct work_struct * work)1104 mptfc_link_status_change(struct work_struct *work)
1105 {
1106 	MPT_ADAPTER             *ioc =
1107 		container_of(work, MPT_ADAPTER, fc_rescan_work);
1108 	int ii;
1109 
1110 	for (ii=0; ii < ioc->facts.NumberOfPorts; ii++)
1111 		(void) mptfc_GetFcPortPage0(ioc, ii);
1112 
1113 }
1114 
1115 static void
mptfc_setup_reset(struct work_struct * work)1116 mptfc_setup_reset(struct work_struct *work)
1117 {
1118 	MPT_ADAPTER		*ioc =
1119 		container_of(work, MPT_ADAPTER, fc_setup_reset_work);
1120 	u64			pn;
1121 	struct mptfc_rport_info *ri;
1122 	struct scsi_target      *starget;
1123 	VirtTarget              *vtarget;
1124 
1125 	/* reset about to happen, delete (block) all rports */
1126 	list_for_each_entry(ri, &ioc->fc_rports, list) {
1127 		if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
1128 			ri->flags &= ~MPT_RPORT_INFO_FLAGS_REGISTERED;
1129 			fc_remote_port_delete(ri->rport);	/* won't sleep */
1130 			ri->rport = NULL;
1131 			starget = ri->starget;
1132 			if (starget) {
1133 				vtarget = starget->hostdata;
1134 				if (vtarget)
1135 					vtarget->deleted = 1;
1136 			}
1137 
1138 			pn = (u64)ri->pg0.WWPN.High << 32 |
1139 			     (u64)ri->pg0.WWPN.Low;
1140 			dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
1141 				"mptfc_setup_reset.%d: %llx deleted\n",
1142 				ioc->name,
1143 				ioc->sh->host_no,
1144 				(unsigned long long)pn));
1145 		}
1146 	}
1147 }
1148 
1149 static void
mptfc_rescan_devices(struct work_struct * work)1150 mptfc_rescan_devices(struct work_struct *work)
1151 {
1152 	MPT_ADAPTER		*ioc =
1153 		container_of(work, MPT_ADAPTER, fc_rescan_work);
1154 	int			ii;
1155 	u64			pn;
1156 	struct mptfc_rport_info *ri;
1157 	struct scsi_target      *starget;
1158 	VirtTarget              *vtarget;
1159 
1160 	/* start by tagging all ports as missing */
1161 	list_for_each_entry(ri, &ioc->fc_rports, list) {
1162 		if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
1163 			ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING;
1164 		}
1165 	}
1166 
1167 	/*
1168 	 * now rescan devices known to adapter,
1169 	 * will reregister existing rports
1170 	 */
1171 	for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1172 		(void) mptfc_GetFcPortPage0(ioc, ii);
1173 		mptfc_init_host_attr(ioc, ii);	/* refresh */
1174 		mptfc_GetFcDevPage0(ioc, ii, mptfc_register_dev);
1175 	}
1176 
1177 	/* delete devices still missing */
1178 	list_for_each_entry(ri, &ioc->fc_rports, list) {
1179 		/* if newly missing, delete it */
1180 		if (ri->flags & MPT_RPORT_INFO_FLAGS_MISSING) {
1181 
1182 			ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|
1183 				       MPT_RPORT_INFO_FLAGS_MISSING);
1184 			fc_remote_port_delete(ri->rport);	/* won't sleep */
1185 			ri->rport = NULL;
1186 			starget = ri->starget;
1187 			if (starget) {
1188 				vtarget = starget->hostdata;
1189 				if (vtarget)
1190 					vtarget->deleted = 1;
1191 			}
1192 
1193 			pn = (u64)ri->pg0.WWPN.High << 32 |
1194 			     (u64)ri->pg0.WWPN.Low;
1195 			dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
1196 				"mptfc_rescan.%d: %llx deleted\n",
1197 				ioc->name,
1198 				ioc->sh->host_no,
1199 				(unsigned long long)pn));
1200 		}
1201 	}
1202 }
1203 
1204 static int
mptfc_probe(struct pci_dev * pdev,const struct pci_device_id * id)1205 mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1206 {
1207 	struct Scsi_Host	*sh;
1208 	MPT_SCSI_HOST		*hd;
1209 	MPT_ADAPTER 		*ioc;
1210 	unsigned long		 flags;
1211 	int			 ii;
1212 	int			 numSGE = 0;
1213 	int			 scale;
1214 	int			 ioc_cap;
1215 	int			error=0;
1216 	int			r;
1217 
1218 	if ((r = mpt_attach(pdev,id)) != 0)
1219 		return r;
1220 
1221 	ioc = pci_get_drvdata(pdev);
1222 	ioc->DoneCtx = mptfcDoneCtx;
1223 	ioc->TaskCtx = mptfcTaskCtx;
1224 	ioc->InternalCtx = mptfcInternalCtx;
1225 
1226 	/*  Added sanity check on readiness of the MPT adapter.
1227 	 */
1228 	if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
1229 		printk(MYIOC_s_WARN_FMT
1230 		  "Skipping because it's not operational!\n",
1231 		  ioc->name);
1232 		error = -ENODEV;
1233 		goto out_mptfc_probe;
1234 	}
1235 
1236 	if (!ioc->active) {
1237 		printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
1238 		  ioc->name);
1239 		error = -ENODEV;
1240 		goto out_mptfc_probe;
1241 	}
1242 
1243 	/*  Sanity check - ensure at least 1 port is INITIATOR capable
1244 	 */
1245 	ioc_cap = 0;
1246 	for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1247 		if (ioc->pfacts[ii].ProtocolFlags &
1248 		    MPI_PORTFACTS_PROTOCOL_INITIATOR)
1249 			ioc_cap ++;
1250 	}
1251 
1252 	if (!ioc_cap) {
1253 		printk(MYIOC_s_WARN_FMT
1254 			"Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
1255 			ioc->name, ioc);
1256 		return 0;
1257 	}
1258 
1259 	sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));
1260 
1261 	if (!sh) {
1262 		printk(MYIOC_s_WARN_FMT
1263 			"Unable to register controller with SCSI subsystem\n",
1264 			ioc->name);
1265 		error = -1;
1266 		goto out_mptfc_probe;
1267         }
1268 
1269 	spin_lock_init(&ioc->fc_rescan_work_lock);
1270 	INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices);
1271 	INIT_WORK(&ioc->fc_setup_reset_work, mptfc_setup_reset);
1272 	INIT_WORK(&ioc->fc_lsc_work, mptfc_link_status_change);
1273 
1274 	spin_lock_irqsave(&ioc->FreeQlock, flags);
1275 
1276 	/* Attach the SCSI Host to the IOC structure
1277 	 */
1278 	ioc->sh = sh;
1279 
1280 	sh->io_port = 0;
1281 	sh->n_io_port = 0;
1282 	sh->irq = 0;
1283 
1284 	/* set 16 byte cdb's */
1285 	sh->max_cmd_len = 16;
1286 
1287 	sh->max_id = ioc->pfacts->MaxDevices;
1288 	sh->max_lun = max_lun;
1289 
1290 	/* Required entry.
1291 	 */
1292 	sh->unique_id = ioc->id;
1293 
1294 	/* Verify that we won't exceed the maximum
1295 	 * number of chain buffers
1296 	 * We can optimize:  ZZ = req_sz/sizeof(SGE)
1297 	 * For 32bit SGE's:
1298 	 *  numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
1299 	 *               + (req_sz - 64)/sizeof(SGE)
1300 	 * A slightly different algorithm is required for
1301 	 * 64bit SGEs.
1302 	 */
1303 	scale = ioc->req_sz/ioc->SGE_size;
1304 	if (ioc->sg_addr_size == sizeof(u64)) {
1305 		numSGE = (scale - 1) *
1306 		  (ioc->facts.MaxChainDepth-1) + scale +
1307 		  (ioc->req_sz - 60) / ioc->SGE_size;
1308 	} else {
1309 		numSGE = 1 + (scale - 1) *
1310 		  (ioc->facts.MaxChainDepth-1) + scale +
1311 		  (ioc->req_sz - 64) / ioc->SGE_size;
1312 	}
1313 
1314 	if (numSGE < sh->sg_tablesize) {
1315 		/* Reset this value */
1316 		dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1317 		  "Resetting sg_tablesize to %d from %d\n",
1318 		  ioc->name, numSGE, sh->sg_tablesize));
1319 		sh->sg_tablesize = numSGE;
1320 	}
1321 
1322 	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1323 
1324 	hd = shost_priv(sh);
1325 	hd->ioc = ioc;
1326 
1327 	/* SCSI needs scsi_cmnd lookup table!
1328 	 * (with size equal to req_depth*PtrSz!)
1329 	 */
1330 	ioc->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_KERNEL);
1331 	if (!ioc->ScsiLookup) {
1332 		error = -ENOMEM;
1333 		goto out_mptfc_probe;
1334 	}
1335 	spin_lock_init(&ioc->scsi_lookup_lock);
1336 
1337 	dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
1338 		 ioc->name, ioc->ScsiLookup));
1339 
1340 	hd->last_queue_full = 0;
1341 
1342 	sh->transportt = mptfc_transport_template;
1343 	error = scsi_add_host (sh, &ioc->pcidev->dev);
1344 	if(error) {
1345 		dprintk(ioc, printk(MYIOC_s_ERR_FMT
1346 		  "scsi_add_host failed\n", ioc->name));
1347 		goto out_mptfc_probe;
1348 	}
1349 
1350 	/* initialize workqueue */
1351 
1352 	ioc->fc_rescan_work_q = alloc_ordered_workqueue(
1353 		"mptfc_wq_%d", WQ_MEM_RECLAIM, sh->host_no);
1354 	if (!ioc->fc_rescan_work_q) {
1355 		error = -ENOMEM;
1356 		goto out_mptfc_host;
1357 	}
1358 
1359 	/*
1360 	 *  Pre-fetch FC port WWN and stuff...
1361 	 *  (FCPortPage0_t stuff)
1362 	 */
1363 	for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1364 		(void) mptfc_GetFcPortPage0(ioc, ii);
1365 	}
1366 	mptfc_SetFcPortPage1_defaults(ioc);
1367 
1368 	/*
1369 	 * scan for rports -
1370 	 *	by doing it via the workqueue, some locking is eliminated
1371 	 */
1372 
1373 	queue_work(ioc->fc_rescan_work_q, &ioc->fc_rescan_work);
1374 	flush_workqueue(ioc->fc_rescan_work_q);
1375 
1376 	return 0;
1377 
1378 out_mptfc_host:
1379 	scsi_remove_host(sh);
1380 
1381 out_mptfc_probe:
1382 
1383 	mptscsih_remove(pdev);
1384 	return error;
1385 }
1386 
1387 static struct pci_driver mptfc_driver = {
1388 	.name		= "mptfc",
1389 	.id_table	= mptfc_pci_table,
1390 	.probe		= mptfc_probe,
1391 	.remove		= mptfc_remove,
1392 	.shutdown	= mptscsih_shutdown,
1393 #ifdef CONFIG_PM
1394 	.suspend	= mptscsih_suspend,
1395 	.resume		= mptscsih_resume,
1396 #endif
1397 };
1398 
1399 static int
mptfc_event_process(MPT_ADAPTER * ioc,EventNotificationReply_t * pEvReply)1400 mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
1401 {
1402 	u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
1403 	unsigned long flags;
1404 	int rc=1;
1405 
1406 	if (ioc->bus_type != FC)
1407 		return 0;
1408 
1409 	devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
1410 			ioc->name, event));
1411 
1412 	if (ioc->sh == NULL || shost_priv(ioc->sh) == NULL)
1413 		return 1;
1414 
1415 	switch (event) {
1416 	case MPI_EVENT_RESCAN:
1417 		spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1418 		if (ioc->fc_rescan_work_q) {
1419 			queue_work(ioc->fc_rescan_work_q,
1420 				   &ioc->fc_rescan_work);
1421 		}
1422 		spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1423 		break;
1424 	case MPI_EVENT_LINK_STATUS_CHANGE:
1425 		spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1426 		if (ioc->fc_rescan_work_q) {
1427 			queue_work(ioc->fc_rescan_work_q,
1428 				   &ioc->fc_lsc_work);
1429 		}
1430 		spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1431 		break;
1432 	default:
1433 		rc = mptscsih_event_process(ioc,pEvReply);
1434 		break;
1435 	}
1436 	return rc;
1437 }
1438 
1439 static int
mptfc_ioc_reset(MPT_ADAPTER * ioc,int reset_phase)1440 mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
1441 {
1442 	int		rc;
1443 	unsigned long	flags;
1444 
1445 	rc = mptscsih_ioc_reset(ioc,reset_phase);
1446 	if ((ioc->bus_type != FC) || (!rc))
1447 		return rc;
1448 
1449 
1450 	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1451 		": IOC %s_reset routed to FC host driver!\n",ioc->name,
1452 		reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
1453 		reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
1454 
1455 	if (reset_phase == MPT_IOC_SETUP_RESET) {
1456 		spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1457 		if (ioc->fc_rescan_work_q) {
1458 			queue_work(ioc->fc_rescan_work_q,
1459 				   &ioc->fc_setup_reset_work);
1460 		}
1461 		spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1462 	}
1463 
1464 	else if (reset_phase == MPT_IOC_PRE_RESET) {
1465 	}
1466 
1467 	else {	/* MPT_IOC_POST_RESET */
1468 		mptfc_SetFcPortPage1_defaults(ioc);
1469 		spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1470 		if (ioc->fc_rescan_work_q) {
1471 			queue_work(ioc->fc_rescan_work_q,
1472 				   &ioc->fc_rescan_work);
1473 		}
1474 		spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1475 	}
1476 	return 1;
1477 }
1478 
1479 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1480 /**
1481  *	mptfc_init - Register MPT adapter(s) as SCSI host(s) with SCSI mid-layer.
1482  *
1483  *	Returns 0 for success, non-zero for failure.
1484  */
1485 static int __init
mptfc_init(void)1486 mptfc_init(void)
1487 {
1488 	int error;
1489 
1490 	show_mptmod_ver(my_NAME, my_VERSION);
1491 
1492 	/* sanity check module parameters */
1493 	if (mptfc_dev_loss_tmo <= 0)
1494 		mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;
1495 
1496 	mptfc_transport_template =
1497 		fc_attach_transport(&mptfc_transport_functions);
1498 
1499 	if (!mptfc_transport_template)
1500 		return -ENODEV;
1501 
1502 	mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER,
1503 	    "mptscsih_scandv_complete");
1504 	mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER,
1505 	    "mptscsih_scandv_complete");
1506 	mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER,
1507 	    "mptscsih_scandv_complete");
1508 
1509 	mpt_event_register(mptfcDoneCtx, mptfc_event_process);
1510 	mpt_reset_register(mptfcDoneCtx, mptfc_ioc_reset);
1511 
1512 	error = pci_register_driver(&mptfc_driver);
1513 	if (error)
1514 		fc_release_transport(mptfc_transport_template);
1515 
1516 	return error;
1517 }
1518 
1519 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1520 /**
1521  *	mptfc_remove - Remove fc infrastructure for devices
1522  *	@pdev: Pointer to pci_dev structure
1523  *
1524  */
mptfc_remove(struct pci_dev * pdev)1525 static void mptfc_remove(struct pci_dev *pdev)
1526 {
1527 	MPT_ADAPTER		*ioc = pci_get_drvdata(pdev);
1528 	struct mptfc_rport_info	*p, *n;
1529 	struct workqueue_struct *work_q;
1530 	unsigned long		flags;
1531 	int			ii;
1532 
1533 	/* destroy workqueue */
1534 	if ((work_q=ioc->fc_rescan_work_q)) {
1535 		spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1536 		ioc->fc_rescan_work_q = NULL;
1537 		spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1538 		destroy_workqueue(work_q);
1539 	}
1540 
1541 	fc_remove_host(ioc->sh);
1542 
1543 	list_for_each_entry_safe(p, n, &ioc->fc_rports, list) {
1544 		list_del(&p->list);
1545 		kfree(p);
1546 	}
1547 
1548 	for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) {
1549 		if (ioc->fc_data.fc_port_page1[ii].data) {
1550 			dma_free_coherent(&ioc->pcidev->dev,
1551 					  ioc->fc_data.fc_port_page1[ii].pg_sz,
1552 					  ioc->fc_data.fc_port_page1[ii].data,
1553 					  ioc->fc_data.fc_port_page1[ii].dma);
1554 			ioc->fc_data.fc_port_page1[ii].data = NULL;
1555 		}
1556 	}
1557 
1558 	scsi_remove_host(ioc->sh);
1559 
1560 	mptscsih_remove(pdev);
1561 }
1562 
1563 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1564 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1565 /**
1566  *	mptfc_exit - Unregisters MPT adapter(s)
1567  *
1568  */
1569 static void __exit
mptfc_exit(void)1570 mptfc_exit(void)
1571 {
1572 	pci_unregister_driver(&mptfc_driver);
1573 	fc_release_transport(mptfc_transport_template);
1574 
1575 	mpt_reset_deregister(mptfcDoneCtx);
1576 	mpt_event_deregister(mptfcDoneCtx);
1577 
1578 	mpt_deregister(mptfcInternalCtx);
1579 	mpt_deregister(mptfcTaskCtx);
1580 	mpt_deregister(mptfcDoneCtx);
1581 }
1582 
1583 module_init(mptfc_init);
1584 module_exit(mptfc_exit);
1585