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