Blame view

drivers/message/fusion/mptfc.c 41.8 KB
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1
2
  /*
   *  linux/drivers/message/fusion/mptfc.c
f36789e22   Prakash, Sathya   [SCSI] mpt fusion...
3
4
   *      For use with LSI PCI chip/adapter(s)
   *      running LSI Fusion MPT (Message Passing Technology) firmware.
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
5
   *
cddc0ab71   Prakash, Sathya   [SCSI] mpt fusion...
6
   *  Copyright (c) 1999-2008 LSI Corporation
16d201016   Eric Moore   [SCSI] mpt fusion...
7
   *  (mailto:DL-MPTFusionLinux@lsi.com)
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
   *
   */
  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  /*
      This program is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published by
      the Free Software Foundation; version 2 of the License.
  
      This program is distributed in the hope that it will be useful,
      but WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      GNU General Public License for more details.
  
      NO WARRANTY
      THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
      CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
      LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
      MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
      solely responsible for determining the appropriateness of using and
      distributing the Program and assumes all risks associated with its
      exercise of rights under this Agreement, including but not limited to
      the risks and costs of program errors, damage to or loss of data,
      programs or equipment, and unavailability or interruption of operations.
  
      DISCLAIMER OF LIABILITY
      NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
      DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
      ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
      TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
      USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
      HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
  
      You should have received a copy of the GNU General Public License
      along with this program; if not, write to the Free Software
      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
46
47
48
49
50
51
52
53
54
  #include <linux/module.h>
  #include <linux/kernel.h>
  #include <linux/init.h>
  #include <linux/errno.h>
  #include <linux/kdev_t.h>
  #include <linux/blkdev.h>
  #include <linux/delay.h>	/* for mdelay */
  #include <linux/interrupt.h>	/* needed for in_interrupt() proto */
  #include <linux/reboot.h>	/* notifier code */
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
55
  #include <linux/workqueue.h>
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
56
  #include <linux/sort.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
57
  #include <linux/slab.h>
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
58
59
60
61
62
63
  
  #include <scsi/scsi.h>
  #include <scsi/scsi_cmnd.h>
  #include <scsi/scsi_device.h>
  #include <scsi/scsi_host.h>
  #include <scsi/scsi_tcq.h>
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
64
  #include <scsi/scsi_transport_fc.h>
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
65
66
67
68
69
70
71
72
73
74
75
76
  
  #include "mptbase.h"
  #include "mptscsih.h"
  
  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  #define my_NAME		"Fusion MPT FC Host driver"
  #define my_VERSION	MPT_LINUX_VERSION_COMMON
  #define MYNAM		"mptfc"
  
  MODULE_AUTHOR(MODULEAUTHOR);
  MODULE_DESCRIPTION(my_NAME);
  MODULE_LICENSE("GPL");
9f4203b35   Eric Moore   [SCSI] fusion: MO...
77
  MODULE_VERSION(my_VERSION);
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
78
79
  
  /* Command line args */
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
80
81
82
83
84
85
86
  #define MPTFC_DEV_LOSS_TMO (60)
  static int mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;	/* reasonable default */
  module_param(mptfc_dev_loss_tmo, int, 0);
  MODULE_PARM_DESC(mptfc_dev_loss_tmo, " Initial time the driver programs the "
      				     " transport to wait for an rport to "
  				     " return following a device loss event."
  				     "  Default=60.");
793955f54   Eric Moore   [SCSI] fusion - G...
87
88
89
90
91
  /* scsi-mid layer global parmeter is max_report_luns, which is 511 */
  #define MPTFC_MAX_LUN (16895)
  static int max_lun = MPTFC_MAX_LUN;
  module_param(max_lun, int, 0);
  MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
f606f5718   Prakash, Sathya   [SCSI] mpt fusion...
92
93
94
  static u8	mptfcDoneCtx = MPT_MAX_PROTOCOL_DRIVERS;
  static u8	mptfcTaskCtx = MPT_MAX_PROTOCOL_DRIVERS;
  static u8	mptfcInternalCtx = MPT_MAX_PROTOCOL_DRIVERS;
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
95

3bc7bf1d1   Michael Reed   [SCSI] fusion: FC...
96
97
  static int mptfc_target_alloc(struct scsi_target *starget);
  static int mptfc_slave_alloc(struct scsi_device *sdev);
f281233d3   Jeff Garzik   SCSI host lock pu...
98
  static int mptfc_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *SCpnt);
3bc7bf1d1   Michael Reed   [SCSI] fusion: FC...
99
  static void mptfc_target_destroy(struct scsi_target *starget);
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
100
101
  static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout);
  static void __devexit mptfc_remove(struct pci_dev *pdev);
35508e46a   Michael Reed   [SCSI] mptfc: sta...
102
103
104
105
  static int mptfc_abort(struct scsi_cmnd *SCpnt);
  static int mptfc_dev_reset(struct scsi_cmnd *SCpnt);
  static int mptfc_bus_reset(struct scsi_cmnd *SCpnt);
  static int mptfc_host_reset(struct scsi_cmnd *SCpnt);
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
106

2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
107
  static struct scsi_host_template mptfc_driver_template = {
f78496da6   Moore, Eric Dean   [SCSI] mptfusion ...
108
  	.module				= THIS_MODULE,
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
109
110
111
112
  	.proc_name			= "mptfc",
  	.proc_info			= mptscsih_proc_info,
  	.name				= "MPT FC Host",
  	.info				= mptscsih_info,
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
113
  	.queuecommand			= mptfc_qcmd,
3bc7bf1d1   Michael Reed   [SCSI] fusion: FC...
114
  	.target_alloc			= mptfc_target_alloc,
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
115
  	.slave_alloc			= mptfc_slave_alloc,
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
116
  	.slave_configure		= mptscsih_slave_configure,
3bc7bf1d1   Michael Reed   [SCSI] fusion: FC...
117
  	.target_destroy			= mptfc_target_destroy,
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
118
  	.slave_destroy			= mptscsih_slave_destroy,
6e3815ba3   Moore, Eric Dean   [SCSI] - mptfusio...
119
  	.change_queue_depth 		= mptscsih_change_queue_depth,
35508e46a   Michael Reed   [SCSI] mptfc: sta...
120
121
122
123
  	.eh_abort_handler		= mptfc_abort,
  	.eh_device_reset_handler	= mptfc_dev_reset,
  	.eh_bus_reset_handler		= mptfc_bus_reset,
  	.eh_host_reset_handler		= mptfc_host_reset,
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
124
125
126
127
128
129
130
  	.bios_param			= mptscsih_bios_param,
  	.can_queue			= MPT_FC_CAN_QUEUE,
  	.this_id			= -1,
  	.sg_tablesize			= MPT_SCSI_SG_DEPTH,
  	.max_sectors			= 8192,
  	.cmd_per_lun			= 7,
  	.use_clustering			= ENABLE_CLUSTERING,
edb9068d0   Prakash, Sathya   [SCSI] mpt fusion...
131
  	.shost_attrs			= mptscsih_host_attrs,
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
132
133
134
135
136
137
138
  };
  
  /****************************************************************************
   * Supported hardware
   */
  
  static struct pci_device_id mptfc_pci_table[] = {
87cf89866   Eric Moore   [SCSI] mptsas: Ad...
139
  	{ PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC909,
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
140
  		PCI_ANY_ID, PCI_ANY_ID },
87cf89866   Eric Moore   [SCSI] mptsas: Ad...
141
  	{ PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC919,
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
142
  		PCI_ANY_ID, PCI_ANY_ID },
87cf89866   Eric Moore   [SCSI] mptsas: Ad...
143
  	{ PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC929,
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
144
  		PCI_ANY_ID, PCI_ANY_ID },
87cf89866   Eric Moore   [SCSI] mptsas: Ad...
145
  	{ PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC919X,
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
146
  		PCI_ANY_ID, PCI_ANY_ID },
87cf89866   Eric Moore   [SCSI] mptsas: Ad...
147
  	{ PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC929X,
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
148
  		PCI_ANY_ID, PCI_ANY_ID },
87cf89866   Eric Moore   [SCSI] mptsas: Ad...
149
  	{ PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC939X,
3fadc59d6   Moore, Eric Dean   [SCSI] fusion - A...
150
  		PCI_ANY_ID, PCI_ANY_ID },
87cf89866   Eric Moore   [SCSI] mptsas: Ad...
151
  	{ PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC949X,
3fadc59d6   Moore, Eric Dean   [SCSI] fusion - A...
152
  		PCI_ANY_ID, PCI_ANY_ID },
87cf89866   Eric Moore   [SCSI] mptsas: Ad...
153
  	{ PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC949E,
6d5b0c315   Moore, Eric   [SCSI] fusion - a...
154
  		PCI_ANY_ID, PCI_ANY_ID },
ef1d8df72   Prakash, Sathya   [SCSI] mpt fusion...
155
156
  	{ PCI_VENDOR_ID_BROCADE, MPI_MANUFACTPAGE_DEVICEID_FC949E,
  		PCI_ANY_ID, PCI_ANY_ID },
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
157
158
159
  	{0}	/* Terminating entry */
  };
  MODULE_DEVICE_TABLE(pci, mptfc_pci_table);
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
160
  static struct scsi_transport_template *mptfc_transport_template = NULL;
03fbcbcd5   Adrian Bunk   [SCSI] drivers/me...
161
  static struct fc_function_template mptfc_transport_functions = {
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
162
163
164
165
166
167
168
169
170
171
172
  	.dd_fcrport_size = 8,
  	.show_host_node_name = 1,
  	.show_host_port_name = 1,
  	.show_host_supported_classes = 1,
  	.show_host_port_id = 1,
  	.show_rport_supported_classes = 1,
  	.show_starget_node_name = 1,
  	.show_starget_port_name = 1,
  	.show_starget_port_id = 1,
  	.set_rport_dev_loss_tmo = mptfc_set_rport_loss_tmo,
  	.show_rport_dev_loss_tmo = 1,
5d947f2b7   Michael Reed   [SCSI] mptfc: add...
173
174
175
176
177
178
179
  	.show_host_supported_speeds = 1,
  	.show_host_maxframe_size = 1,
  	.show_host_speed = 1,
  	.show_host_fabric_name = 1,
  	.show_host_port_type = 1,
  	.show_host_port_state = 1,
  	.show_host_symbolic_name = 1,
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
180
  };
35508e46a   Michael Reed   [SCSI] mptfc: sta...
181
182
183
184
185
  static int
  mptfc_block_error_handler(struct scsi_cmnd *SCpnt,
  			  int (*func)(struct scsi_cmnd *SCpnt),
  			  const char *caller)
  {
d6ecdd638   Prakash, Sathya   [SCSI] mpt fusion...
186
  	MPT_SCSI_HOST		*hd;
35508e46a   Michael Reed   [SCSI] mptfc: sta...
187
188
189
190
191
  	struct scsi_device	*sdev = SCpnt->device;
  	struct Scsi_Host	*shost = sdev->host;
  	struct fc_rport		*rport = starget_to_rport(scsi_target(sdev));
  	unsigned long		flags;
  	int			ready;
e80b002bf   Eric Moore   [SCSI] mpt fusion...
192
  	MPT_ADAPTER 		*ioc;
03cb3829e   Michael Reed   [SCSI] fusion: ho...
193
  	int			loops = 40;	/* seconds */
35508e46a   Michael Reed   [SCSI] mptfc: sta...
194

e7eae9f6e   Eric Moore   [SCSI] mpt fusion...
195
  	hd = shost_priv(SCpnt->device->host);
e80b002bf   Eric Moore   [SCSI] mpt fusion...
196
  	ioc = hd->ioc;
35508e46a   Michael Reed   [SCSI] mptfc: sta...
197
  	spin_lock_irqsave(shost->host_lock, flags);
03cb3829e   Michael Reed   [SCSI] fusion: ho...
198
199
  	while ((ready = fc_remote_port_chkready(rport) >> 16) == DID_IMM_RETRY
  	 || (loops > 0 && ioc->active == 0)) {
35508e46a   Michael Reed   [SCSI] mptfc: sta...
200
  		spin_unlock_irqrestore(shost->host_lock, flags);
e80b002bf   Eric Moore   [SCSI] mpt fusion...
201
  		dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
35508e46a   Michael Reed   [SCSI] mptfc: sta...
202
  			"mptfc_block_error_handler.%d: %d:%d, port status is "
03cb3829e   Michael Reed   [SCSI] fusion: ho...
203
204
  			"%x, active flag %d, deferring %s recovery.
  ",
e7eae9f6e   Eric Moore   [SCSI] mpt fusion...
205
  			ioc->name, ioc->sh->host_no,
03cb3829e   Michael Reed   [SCSI] fusion: ho...
206
207
  			SCpnt->device->id, SCpnt->device->lun,
  			ready, ioc->active, caller));
35508e46a   Michael Reed   [SCSI] mptfc: sta...
208
209
  		msleep(1000);
  		spin_lock_irqsave(shost->host_lock, flags);
03cb3829e   Michael Reed   [SCSI] fusion: ho...
210
  		loops --;
35508e46a   Michael Reed   [SCSI] mptfc: sta...
211
212
  	}
  	spin_unlock_irqrestore(shost->host_lock, flags);
03cb3829e   Michael Reed   [SCSI] fusion: ho...
213
214
  	if (ready == DID_NO_CONNECT || !SCpnt->device->hostdata
  	 || ioc->active == 0) {
e80b002bf   Eric Moore   [SCSI] mpt fusion...
215
  		dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
35508e46a   Michael Reed   [SCSI] mptfc: sta...
216
  			"%s.%d: %d:%d, failing recovery, "
03cb3829e   Michael Reed   [SCSI] fusion: ho...
217
218
  			"port state %x, active %d, vdevice %p.
  ", caller,
e7eae9f6e   Eric Moore   [SCSI] mpt fusion...
219
  			ioc->name, ioc->sh->host_no,
29dd3609f   Eric Moore   [SCSI] mpt fusion...
220
  			SCpnt->device->id, SCpnt->device->lun, ready,
03cb3829e   Michael Reed   [SCSI] fusion: ho...
221
  			ioc->active, SCpnt->device->hostdata));
35508e46a   Michael Reed   [SCSI] mptfc: sta...
222
223
  		return FAILED;
  	}
e80b002bf   Eric Moore   [SCSI] mpt fusion...
224
  	dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
35508e46a   Michael Reed   [SCSI] mptfc: sta...
225
226
  		"%s.%d: %d:%d, executing recovery.
  ", caller,
e7eae9f6e   Eric Moore   [SCSI] mpt fusion...
227
  		ioc->name, ioc->sh->host_no,
29dd3609f   Eric Moore   [SCSI] mpt fusion...
228
  		SCpnt->device->id, SCpnt->device->lun));
35508e46a   Michael Reed   [SCSI] mptfc: sta...
229
230
231
232
233
234
235
  	return (*func)(SCpnt);
  }
  
  static int
  mptfc_abort(struct scsi_cmnd *SCpnt)
  {
  	return
cadbd4a5e   Harvey Harrison   [SCSI] replace __...
236
  	    mptfc_block_error_handler(SCpnt, mptscsih_abort, __func__);
35508e46a   Michael Reed   [SCSI] mptfc: sta...
237
238
239
240
241
242
  }
  
  static int
  mptfc_dev_reset(struct scsi_cmnd *SCpnt)
  {
  	return
cadbd4a5e   Harvey Harrison   [SCSI] replace __...
243
  	    mptfc_block_error_handler(SCpnt, mptscsih_dev_reset, __func__);
35508e46a   Michael Reed   [SCSI] mptfc: sta...
244
245
246
247
248
249
  }
  
  static int
  mptfc_bus_reset(struct scsi_cmnd *SCpnt)
  {
  	return
cadbd4a5e   Harvey Harrison   [SCSI] replace __...
250
  	    mptfc_block_error_handler(SCpnt, mptscsih_bus_reset, __func__);
35508e46a   Michael Reed   [SCSI] mptfc: sta...
251
252
253
254
255
256
  }
  
  static int
  mptfc_host_reset(struct scsi_cmnd *SCpnt)
  {
  	return
cadbd4a5e   Harvey Harrison   [SCSI] replace __...
257
  	    mptfc_block_error_handler(SCpnt, mptscsih_host_reset, __func__);
35508e46a   Michael Reed   [SCSI] mptfc: sta...
258
  }
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
  static void
  mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
  {
  	if (timeout > 0)
  		rport->dev_loss_tmo = timeout;
  	else
  		rport->dev_loss_tmo = mptfc_dev_loss_tmo;
  }
  
  static int
  mptfc_FcDevPage0_cmp_func(const void *a, const void *b)
  {
  	FCDevicePage0_t **aa = (FCDevicePage0_t **)a;
  	FCDevicePage0_t **bb = (FCDevicePage0_t **)b;
  
  	if ((*aa)->CurrentBus == (*bb)->CurrentBus) {
  		if ((*aa)->CurrentTargetID == (*bb)->CurrentTargetID)
  			return 0;
  		if ((*aa)->CurrentTargetID < (*bb)->CurrentTargetID)
  			return -1;
  		return 1;
  	}
  	if ((*aa)->CurrentBus < (*bb)->CurrentBus)
  		return -1;
  	return 1;
  }
  
  static int
  mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, int ioc_port,
  	void(*func)(MPT_ADAPTER *ioc,int channel, FCDevicePage0_t *arg))
  {
  	ConfigPageHeader_t	 hdr;
  	CONFIGPARMS		 cfg;
  	FCDevicePage0_t		*ppage0_alloc, *fc;
  	dma_addr_t		 page0_dma;
  	int			 data_sz;
  	int			 ii;
  
  	FCDevicePage0_t		*p0_array=NULL, *p_p0;
  	FCDevicePage0_t		**pp0_array=NULL, **p_pp0;
  
  	int			 rc = -ENOMEM;
  	U32			 port_id = 0xffffff;
  	int			 num_targ = 0;
  	int			 max_bus = ioc->facts.MaxBuses;
793955f54   Eric Moore   [SCSI] fusion - G...
304
  	int			 max_targ;
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
305

793955f54   Eric Moore   [SCSI] fusion - G...
306
  	max_targ = (ioc->facts.MaxDevices == 0) ? 256 : ioc->facts.MaxDevices;
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
  
  	data_sz = sizeof(FCDevicePage0_t) * max_bus * max_targ;
  	p_p0 = p0_array =  kzalloc(data_sz, GFP_KERNEL);
  	if (!p0_array)
  		goto out;
  
  	data_sz = sizeof(FCDevicePage0_t *) * max_bus * max_targ;
  	p_pp0 = pp0_array = kzalloc(data_sz, GFP_KERNEL);
  	if (!pp0_array)
  		goto out;
  
  	do {
  		/* Get FC Device Page 0 header */
  		hdr.PageVersion = 0;
  		hdr.PageLength = 0;
  		hdr.PageNumber = 0;
  		hdr.PageType = MPI_CONFIG_PAGETYPE_FC_DEVICE;
  		cfg.cfghdr.hdr = &hdr;
  		cfg.physAddr = -1;
  		cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
  		cfg.dir = 0;
  		cfg.pageAddr = port_id;
  		cfg.timeout = 0;
  
  		if ((rc = mpt_config(ioc, &cfg)) != 0)
  			break;
  
  		if (hdr.PageLength <= 0)
  			break;
  
  		data_sz = hdr.PageLength * 4;
  		ppage0_alloc = pci_alloc_consistent(ioc->pcidev, data_sz,
  		    					&page0_dma);
  		rc = -ENOMEM;
  		if (!ppage0_alloc)
  			break;
  
  		cfg.physAddr = page0_dma;
  		cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
  
  		if ((rc = mpt_config(ioc, &cfg)) == 0) {
  			ppage0_alloc->PortIdentifier =
  				le32_to_cpu(ppage0_alloc->PortIdentifier);
  
  			ppage0_alloc->WWNN.Low =
  				le32_to_cpu(ppage0_alloc->WWNN.Low);
  
  			ppage0_alloc->WWNN.High =
  				le32_to_cpu(ppage0_alloc->WWNN.High);
  
  			ppage0_alloc->WWPN.Low =
  				le32_to_cpu(ppage0_alloc->WWPN.Low);
  
  			ppage0_alloc->WWPN.High =
  				le32_to_cpu(ppage0_alloc->WWPN.High);
  
  			ppage0_alloc->BBCredit =
  				le16_to_cpu(ppage0_alloc->BBCredit);
  
  			ppage0_alloc->MaxRxFrameSize =
  				le16_to_cpu(ppage0_alloc->MaxRxFrameSize);
  
  			port_id = ppage0_alloc->PortIdentifier;
  			num_targ++;
  			*p_p0 = *ppage0_alloc;	/* save data */
  			*p_pp0++ = p_p0++;	/* save addr */
  		}
  		pci_free_consistent(ioc->pcidev, data_sz,
  		    			(u8 *) ppage0_alloc, page0_dma);
  		if (rc != 0)
  			break;
  
  	} while (port_id <= 0xff0000);
  
  	if (num_targ) {
  		/* sort array */
  		if (num_targ > 1)
  			sort (pp0_array, num_targ, sizeof(FCDevicePage0_t *),
  				mptfc_FcDevPage0_cmp_func, NULL);
  		/* call caller's func for each targ */
  		for (ii = 0; ii < num_targ;  ii++) {
  			fc = *(pp0_array+ii);
  			func(ioc, ioc_port, fc);
  		}
  	}
  
   out:
8f7607803   Jesper Juhl   [PATCH] Remove re...
394
395
  	kfree(pp0_array);
  	kfree(p0_array);
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
  	return rc;
  }
  
  static int
  mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid)
  {
  	/* not currently usable */
  	if (pg0->Flags & (MPI_FC_DEVICE_PAGE0_FLAGS_PLOGI_INVALID |
  			  MPI_FC_DEVICE_PAGE0_FLAGS_PRLI_INVALID))
  		return -1;
  
  	if (!(pg0->Flags & MPI_FC_DEVICE_PAGE0_FLAGS_TARGETID_BUS_VALID))
  		return -1;
  
  	if (!(pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_TARGET))
  		return -1;
  
  	/*
  	 * board data structure already normalized to platform endianness
  	 * shifted to avoid unaligned access on 64 bit architecture
  	 */
  	rid->node_name = ((u64)pg0->WWNN.High) << 32 | (u64)pg0->WWNN.Low;
  	rid->port_name = ((u64)pg0->WWPN.High) << 32 | (u64)pg0->WWPN.Low;
  	rid->port_id =   pg0->PortIdentifier;
  	rid->roles = FC_RPORT_ROLE_UNKNOWN;
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
421
422
423
424
425
426
427
428
429
430
  
  	return 0;
  }
  
  static void
  mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
  {
  	struct fc_rport_identifiers rport_ids;
  	struct fc_rport		*rport;
  	struct mptfc_rport_info	*ri;
3bc7bf1d1   Michael Reed   [SCSI] fusion: FC...
431
  	int			new_ri = 1;
65207fedc   Moore, Eric   [SCSI] - fusion -...
432
  	u64			pn, nn;
3bc7bf1d1   Michael Reed   [SCSI] fusion: FC...
433
  	VirtTarget		*vtarget;
6dd727da9   mdr@sgi.com   [SCSI] mptfc: rac...
434
  	u32			roles = FC_RPORT_ROLE_UNKNOWN;
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
435
436
437
  
  	if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0)
  		return;
6dd727da9   mdr@sgi.com   [SCSI] mptfc: rac...
438
439
440
  	roles |= FC_RPORT_ROLE_FCP_TARGET;
  	if (pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR)
  		roles |= FC_RPORT_ROLE_FCP_INITIATOR;
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
441
  	/* scan list looking for a match */
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
442
  	list_for_each_entry(ri, &ioc->fc_rports, list) {
3bc7bf1d1   Michael Reed   [SCSI] fusion: FC...
443
444
  		pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
  		if (pn == rport_ids.port_name) {	/* match */
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
445
  			list_move_tail(&ri->list, &ioc->fc_rports);
3bc7bf1d1   Michael Reed   [SCSI] fusion: FC...
446
  			new_ri = 0;
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
447
448
449
  			break;
  		}
  	}
3bc7bf1d1   Michael Reed   [SCSI] fusion: FC...
450
  	if (new_ri) {	/* allocate one */
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
451
452
453
  		ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL);
  		if (!ri)
  			return;
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
454
455
456
457
458
  		list_add_tail(&ri->list, &ioc->fc_rports);
  	}
  
  	ri->pg0 = *pg0;	/* add/update pg0 data */
  	ri->flags &= ~MPT_RPORT_INFO_FLAGS_MISSING;
3bc7bf1d1   Michael Reed   [SCSI] fusion: FC...
459
  	/* MPT_RPORT_INFO_FLAGS_REGISTERED - rport not previously deleted */
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
460
461
  	if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) {
  		ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED;
3bc7bf1d1   Michael Reed   [SCSI] fusion: FC...
462
  		rport = fc_remote_port_add(ioc->sh, channel, &rport_ids);
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
463
  		if (rport) {
3bc7bf1d1   Michael Reed   [SCSI] fusion: FC...
464
465
466
  			ri->rport = rport;
  			if (new_ri) /* may have been reset by user */
  				rport->dev_loss_tmo = mptfc_dev_loss_tmo;
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
467
468
  			/*
  			 * if already mapped, remap here.  If not mapped,
3bc7bf1d1   Michael Reed   [SCSI] fusion: FC...
469
  			 * target_alloc will allocate vtarget and map,
a69de507a   Eric Moore   [SCSI] mpt fusion...
470
  			 * slave_alloc will fill in vdevice from vtarget.
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
471
  			 */
3bc7bf1d1   Michael Reed   [SCSI] fusion: FC...
472
473
474
  			if (ri->starget) {
  				vtarget = ri->starget->hostdata;
  				if (vtarget) {
793955f54   Eric Moore   [SCSI] fusion - G...
475
476
  					vtarget->id = pg0->CurrentTargetID;
  					vtarget->channel = pg0->CurrentBus;
08f5c5c23   Kashyap, Desai   [SCSI] mptfusion:...
477
  					vtarget->deleted = 0;
3bc7bf1d1   Michael Reed   [SCSI] fusion: FC...
478
  				}
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
479
  			}
65207fedc   Moore, Eric   [SCSI] - fusion -...
480
  			*((struct mptfc_rport_info **)rport->dd_data) = ri;
6dd727da9   mdr@sgi.com   [SCSI] mptfc: rac...
481
482
  			/* scan will be scheduled once rport becomes a target */
  			fc_remote_port_rolechg(rport,roles);
65207fedc   Moore, Eric   [SCSI] - fusion -...
483
484
485
  
  			pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
  			nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low;
d6ecdd638   Prakash, Sathya   [SCSI] mpt fusion...
486
  			dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
3bc7bf1d1   Michael Reed   [SCSI] fusion: FC...
487
  				"mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
488
489
  				"rport tid %d, tmo %d
  ",
3bc7bf1d1   Michael Reed   [SCSI] fusion: FC...
490
  					ioc->name,
914c2d8e5   Moore, Eric   [SCSI] fusion - r...
491
  					ioc->sh->host_no,
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
492
  					pg0->PortIdentifier,
65207fedc   Moore, Eric   [SCSI] - fusion -...
493
494
  					(unsigned long long)nn,
  					(unsigned long long)pn,
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
495
496
  					pg0->CurrentTargetID,
  					ri->rport->scsi_target_id,
3bc7bf1d1   Michael Reed   [SCSI] fusion: FC...
497
  					ri->rport->dev_loss_tmo));
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
498
499
500
501
502
503
  		} else {
  			list_del(&ri->list);
  			kfree(ri);
  			ri = NULL;
  		}
  	}
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
504
  }
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
505
  /*
3bc7bf1d1   Michael Reed   [SCSI] fusion: FC...
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
   *	OS entry point to allow for host driver to free allocated memory
   *	Called if no device present or device being unloaded
   */
  static void
  mptfc_target_destroy(struct scsi_target *starget)
  {
  	struct fc_rport		*rport;
  	struct mptfc_rport_info *ri;
  
  	rport = starget_to_rport(starget);
  	if (rport) {
  		ri = *((struct mptfc_rport_info **)rport->dd_data);
  		if (ri)	/* better be! */
  			ri->starget = NULL;
  	}
  	if (starget->hostdata)
  		kfree(starget->hostdata);
  	starget->hostdata = NULL;
  }
  
  /*
   *	OS entry point to allow host driver to alloc memory
   *	for each scsi target. Called once per device the bus scan.
   *	Return non-zero if allocation fails.
   */
  static int
  mptfc_target_alloc(struct scsi_target *starget)
  {
  	VirtTarget		*vtarget;
  	struct fc_rport		*rport;
  	struct mptfc_rport_info *ri;
  	int			rc;
  
  	vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
  	if (!vtarget)
  		return -ENOMEM;
  	starget->hostdata = vtarget;
  
  	rc = -ENODEV;
  	rport = starget_to_rport(starget);
  	if (rport) {
  		ri = *((struct mptfc_rport_info **)rport->dd_data);
  		if (ri) {	/* better be! */
793955f54   Eric Moore   [SCSI] fusion - G...
549
550
  			vtarget->id = ri->pg0.CurrentTargetID;
  			vtarget->channel = ri->pg0.CurrentBus;
3bc7bf1d1   Michael Reed   [SCSI] fusion: FC...
551
  			ri->starget = starget;
3bc7bf1d1   Michael Reed   [SCSI] fusion: FC...
552
553
554
555
556
557
558
559
560
561
  			rc = 0;
  		}
  	}
  	if (rc != 0) {
  		kfree(vtarget);
  		starget->hostdata = NULL;
  	}
  
  	return rc;
  }
d6ecdd638   Prakash, Sathya   [SCSI] mpt fusion...
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
  /*
   *	mptfc_dump_lun_info
   *	@ioc
   *	@rport
   *	@sdev
   *
   */
  static void
  mptfc_dump_lun_info(MPT_ADAPTER *ioc, struct fc_rport *rport, struct scsi_device *sdev,
  		VirtTarget *vtarget)
  {
  	u64 nn, pn;
  	struct mptfc_rport_info *ri;
  
  	ri = *((struct mptfc_rport_info **)rport->dd_data);
  	pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
  	nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low;
  	dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
  		"mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
  		"CurrentTargetID %d, %x %llx %llx
  ",
  		ioc->name,
  		sdev->host->host_no,
  		vtarget->num_luns,
  		sdev->id, ri->pg0.CurrentTargetID,
  		ri->pg0.PortIdentifier,
  		(unsigned long long)pn,
  		(unsigned long long)nn));
  }
3bc7bf1d1   Michael Reed   [SCSI] fusion: FC...
591
592
  
  /*
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
593
594
595
596
   *	OS entry point to allow host driver to alloc memory
   *	for each scsi device. Called once per device the bus scan.
   *	Return non-zero if allocation fails.
   *	Init memory once per LUN.
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
597
   */
03fbcbcd5   Adrian Bunk   [SCSI] drivers/me...
598
  static int
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
599
600
601
602
  mptfc_slave_alloc(struct scsi_device *sdev)
  {
  	MPT_SCSI_HOST		*hd;
  	VirtTarget		*vtarget;
a69de507a   Eric Moore   [SCSI] mpt fusion...
603
  	VirtDevice		*vdevice;
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
604
605
  	struct scsi_target	*starget;
  	struct fc_rport		*rport;
e80b002bf   Eric Moore   [SCSI] mpt fusion...
606
  	MPT_ADAPTER 		*ioc;
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
607

65207fedc   Moore, Eric   [SCSI] - fusion -...
608
609
  	starget = scsi_target(sdev);
  	rport = starget_to_rport(starget);
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
610
611
612
  
  	if (!rport || fc_remote_port_chkready(rport))
  		return -ENXIO;
e7eae9f6e   Eric Moore   [SCSI] mpt fusion...
613
  	hd = shost_priv(sdev->host);
e80b002bf   Eric Moore   [SCSI] mpt fusion...
614
  	ioc = hd->ioc;
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
615

a69de507a   Eric Moore   [SCSI] mpt fusion...
616
617
  	vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
  	if (!vdevice) {
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
618
619
  		printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!
  ",
e80b002bf   Eric Moore   [SCSI] mpt fusion...
620
  				ioc->name, sizeof(VirtDevice));
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
621
622
  		return -ENOMEM;
  	}
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
623

05e8ec17f   Michael Reed   [SCSI] mptfusion ...
624

a69de507a   Eric Moore   [SCSI] mpt fusion...
625
  	sdev->hostdata = vdevice;
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
626
  	vtarget = starget->hostdata;
3bc7bf1d1   Michael Reed   [SCSI] fusion: FC...
627

05e8ec17f   Michael Reed   [SCSI] mptfusion ...
628
  	if (vtarget->num_luns == 0) {
e80b002bf   Eric Moore   [SCSI] mpt fusion...
629
  		vtarget->ioc_id = ioc->id;
ba856d32f   Eric Moore   [SCSI] mptfusion:...
630
  		vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
631
  	}
a69de507a   Eric Moore   [SCSI] mpt fusion...
632
633
  	vdevice->vtarget = vtarget;
  	vdevice->lun = sdev->lun;
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
634

05e8ec17f   Michael Reed   [SCSI] mptfusion ...
635
  	vtarget->num_luns++;
65207fedc   Moore, Eric   [SCSI] - fusion -...
636

e80b002bf   Eric Moore   [SCSI] mpt fusion...
637
  	mptfc_dump_lun_info(ioc, rport, sdev, vtarget);
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
638
639
640
641
642
  
  	return 0;
  }
  
  static int
f281233d3   Jeff Garzik   SCSI host lock pu...
643
  mptfc_qcmd_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
644
  {
3bc7bf1d1   Michael Reed   [SCSI] fusion: FC...
645
  	struct mptfc_rport_info	*ri;
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
646
647
  	struct fc_rport	*rport = starget_to_rport(scsi_target(SCpnt->device));
  	int		err;
a69de507a   Eric Moore   [SCSI] mpt fusion...
648
  	VirtDevice	*vdevice = SCpnt->device->hostdata;
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
649

a69de507a   Eric Moore   [SCSI] mpt fusion...
650
  	if (!vdevice || !vdevice->vtarget) {
793955f54   Eric Moore   [SCSI] fusion - G...
651
  		SCpnt->result = DID_NO_CONNECT << 16;
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
652
653
654
  		done(SCpnt);
  		return 0;
  	}
65207fedc   Moore, Eric   [SCSI] - fusion -...
655

793955f54   Eric Moore   [SCSI] fusion - G...
656
657
658
  	err = fc_remote_port_chkready(rport);
  	if (unlikely(err)) {
  		SCpnt->result = err;
35508e46a   Michael Reed   [SCSI] mptfc: sta...
659
660
661
  		done(SCpnt);
  		return 0;
  	}
65207fedc   Moore, Eric   [SCSI] - fusion -...
662
  	/* dd_data is null until finished adding target */
3bc7bf1d1   Michael Reed   [SCSI] fusion: FC...
663
  	ri = *((struct mptfc_rport_info **)rport->dd_data);
65207fedc   Moore, Eric   [SCSI] - fusion -...
664
  	if (unlikely(!ri)) {
65207fedc   Moore, Eric   [SCSI] - fusion -...
665
666
667
668
  		SCpnt->result = DID_IMM_RETRY << 16;
  		done(SCpnt);
  		return 0;
  	}
3bc7bf1d1   Michael Reed   [SCSI] fusion: FC...
669

d6ecdd638   Prakash, Sathya   [SCSI] mpt fusion...
670
  	return mptscsih_qcmd(SCpnt,done);
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
671
  }
f281233d3   Jeff Garzik   SCSI host lock pu...
672
  static DEF_SCSI_QCMD(mptfc_qcmd)
80d3ac77a   Michael Reed   [SCSI] mptfusion:...
673
  /*
eb5329f40   Prakash, Sathya   [SCSI] mpt fusion...
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
   *	mptfc_display_port_link_speed - displaying link speed
   *	@ioc: Pointer to MPT_ADAPTER structure
   *	@portnum: IOC Port number
   *	@pp0dest: port page0 data payload
   *
   */
  static void
  mptfc_display_port_link_speed(MPT_ADAPTER *ioc, int portnum, FCPortPage0_t *pp0dest)
  {
  	u8	old_speed, new_speed, state;
  	char	*old, *new;
  
  	if (portnum >= 2)
  		return;
  
  	old_speed = ioc->fc_link_speed[portnum];
  	new_speed = pp0dest->CurrentSpeed;
  	state = pp0dest->PortState;
  
  	if (state != MPI_FCPORTPAGE0_PORTSTATE_OFFLINE &&
  	    new_speed != MPI_FCPORTPAGE0_CURRENT_SPEED_UKNOWN) {
  
  		old = old_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT ? "1 Gbps" :
  		       old_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT ? "2 Gbps" :
  			old_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT ? "4 Gbps" :
  			 "Unknown";
  		new = new_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT ? "1 Gbps" :
  		       new_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT ? "2 Gbps" :
  			new_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT ? "4 Gbps" :
  			 "Unknown";
  		if (old_speed == 0)
  			printk(MYIOC_s_NOTE_FMT
  				"FC Link Established, Speed = %s
  ",
  				ioc->name, new);
  		else if (old_speed != new_speed)
  			printk(MYIOC_s_WARN_FMT
  				"FC Link Speed Change, Old Speed = %s, New Speed = %s
  ",
  				ioc->name, old, new);
  
  		ioc->fc_link_speed[portnum] = new_speed;
  	}
  }
  
  /*
80d3ac77a   Michael Reed   [SCSI] mptfusion:...
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
   *	mptfc_GetFcPortPage0 - Fetch FCPort config Page0.
   *	@ioc: Pointer to MPT_ADAPTER structure
   *	@portnum: IOC Port number
   *
   *	Return: 0 for success
   *	-ENOMEM if no memory available
   *		-EPERM if not allowed due to ISR context
   *		-EAGAIN if no msg frames currently available
   *		-EFAULT for non-successful reply or no reply (timeout)
   *		-EINVAL portnum arg out of range (hardwired to two elements)
   */
  static int
  mptfc_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
  {
  	ConfigPageHeader_t	 hdr;
  	CONFIGPARMS		 cfg;
  	FCPortPage0_t		*ppage0_alloc;
  	FCPortPage0_t		*pp0dest;
  	dma_addr_t		 page0_dma;
  	int			 data_sz;
  	int			 copy_sz;
  	int			 rc;
  	int			 count = 400;
  
  	if (portnum > 1)
  		return -EINVAL;
  
  	/* Get FCPort Page 0 header */
  	hdr.PageVersion = 0;
  	hdr.PageLength = 0;
  	hdr.PageNumber = 0;
  	hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
  	cfg.cfghdr.hdr = &hdr;
  	cfg.physAddr = -1;
  	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
  	cfg.dir = 0;
  	cfg.pageAddr = portnum;
  	cfg.timeout = 0;
  
  	if ((rc = mpt_config(ioc, &cfg)) != 0)
  		return rc;
  
  	if (hdr.PageLength == 0)
  		return 0;
  
  	data_sz = hdr.PageLength * 4;
  	rc = -ENOMEM;
  	ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
  	if (ppage0_alloc) {
  
   try_again:
  		memset((u8 *)ppage0_alloc, 0, data_sz);
  		cfg.physAddr = page0_dma;
  		cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
  
  		if ((rc = mpt_config(ioc, &cfg)) == 0) {
  			/* save the data */
  			pp0dest = &ioc->fc_port_page0[portnum];
  			copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz);
  			memcpy(pp0dest, ppage0_alloc, copy_sz);
  
  			/*
  			 *	Normalize endianness of structure data,
  			 *	by byte-swapping all > 1 byte fields!
  			 */
  			pp0dest->Flags = le32_to_cpu(pp0dest->Flags);
  			pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier);
  			pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low);
  			pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High);
  			pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low);
  			pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High);
  			pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass);
  			pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds);
  			pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed);
  			pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize);
  			pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low);
  			pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High);
  			pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low);
  			pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High);
  			pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
  			pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
  
  			/*
  			 * if still doing discovery,
  			 * hang loose a while until finished
  			 */
77d88ee27   Michael Reed   [SCSI] mptfc: pro...
806
807
808
809
  			if ((pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) ||
  			    (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_ONLINE &&
  			     (pp0dest->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_TYPE_MASK)
  			      == MPI_FCPORTPAGE0_FLAGS_ATTACH_NO_INIT)) {
80d3ac77a   Michael Reed   [SCSI] mptfusion:...
810
  				if (count-- > 0) {
d6be06c84   Michael Reed   [SCSI] mptfc: abo...
811
  					msleep(100);
80d3ac77a   Michael Reed   [SCSI] mptfusion:...
812
813
814
815
816
817
818
  					goto try_again;
  				}
  				printk(MYIOC_s_INFO_FMT "Firmware discovery not"
  							" complete.
  ",
  						ioc->name);
  			}
eb5329f40   Prakash, Sathya   [SCSI] mpt fusion...
819
  			mptfc_display_port_link_speed(ioc, portnum, pp0dest);
80d3ac77a   Michael Reed   [SCSI] mptfusion:...
820
821
822
823
824
825
826
  		}
  
  		pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
  	}
  
  	return rc;
  }
ca2f938ef   Michael Reed   [SCSI] mptfc: set...
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
  static int
  mptfc_WriteFcPortPage1(MPT_ADAPTER *ioc, int portnum)
  {
  	ConfigPageHeader_t	 hdr;
  	CONFIGPARMS		 cfg;
  	int			 rc;
  
  	if (portnum > 1)
  		return -EINVAL;
  
  	if (!(ioc->fc_data.fc_port_page1[portnum].data))
  		return -EINVAL;
  
  	/* get fcport page 1 header */
  	hdr.PageVersion = 0;
  	hdr.PageLength = 0;
  	hdr.PageNumber = 1;
  	hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
  	cfg.cfghdr.hdr = &hdr;
  	cfg.physAddr = -1;
  	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
  	cfg.dir = 0;
  	cfg.pageAddr = portnum;
  	cfg.timeout = 0;
  
  	if ((rc = mpt_config(ioc, &cfg)) != 0)
  		return rc;
  
  	if (hdr.PageLength == 0)
  		return -ENODEV;
  
  	if (hdr.PageLength*4 != ioc->fc_data.fc_port_page1[portnum].pg_sz)
  		return -EINVAL;
  
  	cfg.physAddr = ioc->fc_data.fc_port_page1[portnum].dma;
  	cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
  	cfg.dir = 1;
  
  	rc = mpt_config(ioc, &cfg);
  
  	return rc;
  }
  
  static int
  mptfc_GetFcPortPage1(MPT_ADAPTER *ioc, int portnum)
  {
  	ConfigPageHeader_t	 hdr;
  	CONFIGPARMS		 cfg;
  	FCPortPage1_t		*page1_alloc;
  	dma_addr_t		 page1_dma;
  	int			 data_sz;
  	int			 rc;
  
  	if (portnum > 1)
  		return -EINVAL;
  
  	/* get fcport page 1 header */
  	hdr.PageVersion = 0;
  	hdr.PageLength = 0;
  	hdr.PageNumber = 1;
  	hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
  	cfg.cfghdr.hdr = &hdr;
  	cfg.physAddr = -1;
  	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
  	cfg.dir = 0;
  	cfg.pageAddr = portnum;
  	cfg.timeout = 0;
  
  	if ((rc = mpt_config(ioc, &cfg)) != 0)
  		return rc;
  
  	if (hdr.PageLength == 0)
  		return -ENODEV;
  
  start_over:
  
  	if (ioc->fc_data.fc_port_page1[portnum].data == NULL) {
  		data_sz = hdr.PageLength * 4;
  		if (data_sz < sizeof(FCPortPage1_t))
  			data_sz = sizeof(FCPortPage1_t);
  
  		page1_alloc = (FCPortPage1_t *) pci_alloc_consistent(ioc->pcidev,
  						data_sz,
  						&page1_dma);
  		if (!page1_alloc)
  			return -ENOMEM;
  	}
  	else {
  		page1_alloc = ioc->fc_data.fc_port_page1[portnum].data;
  		page1_dma = ioc->fc_data.fc_port_page1[portnum].dma;
  		data_sz = ioc->fc_data.fc_port_page1[portnum].pg_sz;
  		if (hdr.PageLength * 4 > data_sz) {
  			ioc->fc_data.fc_port_page1[portnum].data = NULL;
  			pci_free_consistent(ioc->pcidev, data_sz, (u8 *)
  				page1_alloc, page1_dma);
  			goto start_over;
  		}
  	}
  
  	memset(page1_alloc,0,data_sz);
  
  	cfg.physAddr = page1_dma;
  	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
  
  	if ((rc = mpt_config(ioc, &cfg)) == 0) {
  		ioc->fc_data.fc_port_page1[portnum].data = page1_alloc;
  		ioc->fc_data.fc_port_page1[portnum].pg_sz = data_sz;
  		ioc->fc_data.fc_port_page1[portnum].dma = page1_dma;
  	}
  	else {
  		ioc->fc_data.fc_port_page1[portnum].data = NULL;
  		pci_free_consistent(ioc->pcidev, data_sz, (u8 *)
  			page1_alloc, page1_dma);
  	}
  
  	return rc;
  }
  
  static void
  mptfc_SetFcPortPage1_defaults(MPT_ADAPTER *ioc)
  {
  	int		ii;
  	FCPortPage1_t	*pp1;
  
  	#define MPTFC_FW_DEVICE_TIMEOUT	(1)
  	#define MPTFC_FW_IO_PEND_TIMEOUT (1)
  	#define ON_FLAGS  (MPI_FCPORTPAGE1_FLAGS_IMMEDIATE_ERROR_REPLY)
  	#define OFF_FLAGS (MPI_FCPORTPAGE1_FLAGS_VERBOSE_RESCAN_EVENTS)
  
  	for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) {
  		if (mptfc_GetFcPortPage1(ioc, ii) != 0)
  			continue;
  		pp1 = ioc->fc_data.fc_port_page1[ii].data;
  		if ((pp1->InitiatorDeviceTimeout == MPTFC_FW_DEVICE_TIMEOUT)
  		 && (pp1->InitiatorIoPendTimeout == MPTFC_FW_IO_PEND_TIMEOUT)
  		 && ((pp1->Flags & ON_FLAGS) == ON_FLAGS)
  		 && ((pp1->Flags & OFF_FLAGS) == 0))
  			continue;
  		pp1->InitiatorDeviceTimeout = MPTFC_FW_DEVICE_TIMEOUT;
  		pp1->InitiatorIoPendTimeout = MPTFC_FW_IO_PEND_TIMEOUT;
  		pp1->Flags &= ~OFF_FLAGS;
  		pp1->Flags |= ON_FLAGS;
  		mptfc_WriteFcPortPage1(ioc, ii);
  	}
  }
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
972
973
974
  static void
  mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum)
  {
5d947f2b7   Michael Reed   [SCSI] mptfc: add...
975
976
977
978
979
980
981
982
  	unsigned	class = 0;
  	unsigned	cos = 0;
  	unsigned	speed;
  	unsigned	port_type;
  	unsigned	port_state;
  	FCPortPage0_t	*pp0;
  	struct Scsi_Host *sh;
  	char		*sn;
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
983
984
985
986
  
  	/* don't know what to do as only one scsi (fc) host was allocated */
  	if (portnum != 0)
  		return;
5d947f2b7   Michael Reed   [SCSI] mptfc: add...
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
  	pp0 = &ioc->fc_port_page0[portnum];
  	sh = ioc->sh;
  
  	sn = fc_host_symbolic_name(sh);
  	snprintf(sn, FC_SYMBOLIC_NAME_SIZE, "%s %s%08xh",
  	    ioc->prod_name,
  	    MPT_FW_REV_MAGIC_ID_STRING,
  	    ioc->facts.FWVersion.Word);
  
  	fc_host_tgtid_bind_type(sh) = FC_TGTID_BIND_BY_WWPN;
  
  	fc_host_maxframe_size(sh) = pp0->MaxFrameSize;
  
  	fc_host_node_name(sh) =
  	    	(u64)pp0->WWNN.High << 32 | (u64)pp0->WWNN.Low;
  
  	fc_host_port_name(sh) =
  	    	(u64)pp0->WWPN.High << 32 | (u64)pp0->WWPN.Low;
  
  	fc_host_port_id(sh) = pp0->PortIdentifier;
  
  	class = pp0->SupportedServiceClass;
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
1009
1010
1011
1012
1013
1014
  	if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_1)
  		cos |= FC_COS_CLASS1;
  	if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_2)
  		cos |= FC_COS_CLASS2;
  	if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_3)
  		cos |= FC_COS_CLASS3;
5d947f2b7   Michael Reed   [SCSI] mptfc: add...
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
  	fc_host_supported_classes(sh) = cos;
  
  	if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT)
  		speed = FC_PORTSPEED_1GBIT;
  	else if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT)
  		speed = FC_PORTSPEED_2GBIT;
  	else if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT)
  		speed = FC_PORTSPEED_4GBIT;
  	else if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_10GBIT)
  		speed = FC_PORTSPEED_10GBIT;
  	else
  		speed = FC_PORTSPEED_UNKNOWN;
  	fc_host_speed(sh) = speed;
  
  	speed = 0;
  	if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_1GBIT_SPEED)
  		speed |= FC_PORTSPEED_1GBIT;
  	if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_2GBIT_SPEED)
  		speed |= FC_PORTSPEED_2GBIT;
  	if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_4GBIT_SPEED)
  		speed |= FC_PORTSPEED_4GBIT;
  	if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_10GBIT_SPEED)
  		speed |= FC_PORTSPEED_10GBIT;
  	fc_host_supported_speeds(sh) = speed;
  
  	port_state = FC_PORTSTATE_UNKNOWN;
  	if (pp0->PortState == MPI_FCPORTPAGE0_PORTSTATE_ONLINE)
  		port_state = FC_PORTSTATE_ONLINE;
  	else if (pp0->PortState == MPI_FCPORTPAGE0_PORTSTATE_OFFLINE)
  		port_state = FC_PORTSTATE_LINKDOWN;
  	fc_host_port_state(sh) = port_state;
  
  	port_type = FC_PORTTYPE_UNKNOWN;
  	if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_POINT_TO_POINT)
  		port_type = FC_PORTTYPE_PTP;
  	else if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_PRIVATE_LOOP)
  		port_type = FC_PORTTYPE_LPORT;
  	else if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_PUBLIC_LOOP)
  		port_type = FC_PORTTYPE_NLPORT;
  	else if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_FABRIC_DIRECT)
  		port_type = FC_PORTTYPE_NPORT;
  	fc_host_port_type(sh) = port_type;
  
  	fc_host_fabric_name(sh) =
  	    (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_FABRIC_WWN_VALID) ?
  		(u64) pp0->FabricWWNN.High << 32 | (u64) pp0->FabricWWPN.Low :
  		(u64)pp0->WWNN.High << 32 | (u64)pp0->WWNN.Low;
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
1062

05e8ec17f   Michael Reed   [SCSI] mptfusion ...
1063
1064
1065
  }
  
  static void
eb5329f40   Prakash, Sathya   [SCSI] mpt fusion...
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
  mptfc_link_status_change(struct work_struct *work)
  {
  	MPT_ADAPTER             *ioc =
  		container_of(work, MPT_ADAPTER, fc_rescan_work);
  	int ii;
  
  	for (ii=0; ii < ioc->facts.NumberOfPorts; ii++)
  		(void) mptfc_GetFcPortPage0(ioc, ii);
  
  }
  
  static void
c4028958b   David Howells   WorkStruct: make ...
1078
  mptfc_setup_reset(struct work_struct *work)
419835e28   Michael Reed   [SCSI] mptfc: fix...
1079
  {
c4028958b   David Howells   WorkStruct: make ...
1080
1081
  	MPT_ADAPTER		*ioc =
  		container_of(work, MPT_ADAPTER, fc_setup_reset_work);
419835e28   Michael Reed   [SCSI] mptfc: fix...
1082
1083
  	u64			pn;
  	struct mptfc_rport_info *ri;
08f5c5c23   Kashyap, Desai   [SCSI] mptfusion:...
1084
1085
  	struct scsi_target      *starget;
  	VirtTarget              *vtarget;
419835e28   Michael Reed   [SCSI] mptfc: fix...
1086
1087
1088
1089
1090
1091
1092
  
  	/* reset about to happen, delete (block) all rports */
  	list_for_each_entry(ri, &ioc->fc_rports, list) {
  		if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
  			ri->flags &= ~MPT_RPORT_INFO_FLAGS_REGISTERED;
  			fc_remote_port_delete(ri->rport);	/* won't sleep */
  			ri->rport = NULL;
08f5c5c23   Kashyap, Desai   [SCSI] mptfusion:...
1093
1094
1095
1096
1097
1098
  			starget = ri->starget;
  			if (starget) {
  				vtarget = starget->hostdata;
  				if (vtarget)
  					vtarget->deleted = 1;
  			}
419835e28   Michael Reed   [SCSI] mptfc: fix...
1099
1100
1101
  
  			pn = (u64)ri->pg0.WWPN.High << 32 |
  			     (u64)ri->pg0.WWPN.Low;
d6ecdd638   Prakash, Sathya   [SCSI] mpt fusion...
1102
  			dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
419835e28   Michael Reed   [SCSI] mptfc: fix...
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
  				"mptfc_setup_reset.%d: %llx deleted
  ",
  				ioc->name,
  				ioc->sh->host_no,
  				(unsigned long long)pn));
  		}
  	}
  }
  
  static void
c4028958b   David Howells   WorkStruct: make ...
1113
  mptfc_rescan_devices(struct work_struct *work)
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
1114
  {
c4028958b   David Howells   WorkStruct: make ...
1115
1116
  	MPT_ADAPTER		*ioc =
  		container_of(work, MPT_ADAPTER, fc_rescan_work);
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
1117
  	int			ii;
65207fedc   Moore, Eric   [SCSI] - fusion -...
1118
  	u64			pn;
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
1119
  	struct mptfc_rport_info *ri;
08f5c5c23   Kashyap, Desai   [SCSI] mptfusion:...
1120
1121
  	struct scsi_target      *starget;
  	VirtTarget              *vtarget;
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
1122

3a0c56d80   Michael Reed   [SCSI] mptfc: cor...
1123
1124
1125
1126
  	/* start by tagging all ports as missing */
  	list_for_each_entry(ri, &ioc->fc_rports, list) {
  		if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
  			ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING;
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
1127
  		}
3a0c56d80   Michael Reed   [SCSI] mptfc: cor...
1128
  	}
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
1129

3a0c56d80   Michael Reed   [SCSI] mptfc: cor...
1130
1131
1132
1133
1134
1135
1136
1137
1138
  	/*
  	 * now rescan devices known to adapter,
  	 * will reregister existing rports
  	 */
  	for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
  		(void) mptfc_GetFcPortPage0(ioc, ii);
  		mptfc_init_host_attr(ioc, ii);	/* refresh */
  		mptfc_GetFcDevPage0(ioc, ii, mptfc_register_dev);
  	}
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
1139

3a0c56d80   Michael Reed   [SCSI] mptfc: cor...
1140
1141
1142
1143
  	/* delete devices still missing */
  	list_for_each_entry(ri, &ioc->fc_rports, list) {
  		/* if newly missing, delete it */
  		if (ri->flags & MPT_RPORT_INFO_FLAGS_MISSING) {
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
1144

3a0c56d80   Michael Reed   [SCSI] mptfc: cor...
1145
1146
1147
1148
  			ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|
  				       MPT_RPORT_INFO_FLAGS_MISSING);
  			fc_remote_port_delete(ri->rport);	/* won't sleep */
  			ri->rport = NULL;
08f5c5c23   Kashyap, Desai   [SCSI] mptfusion:...
1149
1150
1151
1152
1153
1154
  			starget = ri->starget;
  			if (starget) {
  				vtarget = starget->hostdata;
  				if (vtarget)
  					vtarget->deleted = 1;
  			}
65207fedc   Moore, Eric   [SCSI] - fusion -...
1155

3a0c56d80   Michael Reed   [SCSI] mptfc: cor...
1156
1157
  			pn = (u64)ri->pg0.WWPN.High << 32 |
  			     (u64)ri->pg0.WWPN.Low;
d6ecdd638   Prakash, Sathya   [SCSI] mpt fusion...
1158
  			dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
3a0c56d80   Michael Reed   [SCSI] mptfc: cor...
1159
1160
1161
1162
1163
  				"mptfc_rescan.%d: %llx deleted
  ",
  				ioc->name,
  				ioc->sh->host_no,
  				(unsigned long long)pn));
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
1164
  		}
3a0c56d80   Michael Reed   [SCSI] mptfc: cor...
1165
  	}
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
1166
  }
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1167
1168
1169
1170
1171
1172
1173
  static int
  mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
  {
  	struct Scsi_Host	*sh;
  	MPT_SCSI_HOST		*hd;
  	MPT_ADAPTER 		*ioc;
  	unsigned long		 flags;
1ca00bb79   Christoph Hellwig   [SCSI] fusion: kz...
1174
  	int			 ii;
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1175
1176
1177
  	int			 numSGE = 0;
  	int			 scale;
  	int			 ioc_cap;
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1178
1179
  	int			error=0;
  	int			r;
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
1180

2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1181
1182
  	if ((r = mpt_attach(pdev,id)) != 0)
  		return r;
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
1183

2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1184
  	ioc = pci_get_drvdata(pdev);
d335cc38c   Moore, Eric Dean   [SCSI] mptfusion:...
1185
1186
1187
  	ioc->DoneCtx = mptfcDoneCtx;
  	ioc->TaskCtx = mptfcTaskCtx;
  	ioc->InternalCtx = mptfcInternalCtx;
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1188
1189
1190
1191
1192
1193
1194
1195
  
  	/*  Added sanity check on readiness of the MPT adapter.
  	 */
  	if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
  		printk(MYIOC_s_WARN_FMT
  		  "Skipping because it's not operational!
  ",
  		  ioc->name);
7acec1e75   Moore, Eric Dean   [SCSI] mptfusion ...
1196
1197
  		error = -ENODEV;
  		goto out_mptfc_probe;
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1198
1199
1200
1201
1202
1203
  	}
  
  	if (!ioc->active) {
  		printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!
  ",
  		  ioc->name);
7acec1e75   Moore, Eric Dean   [SCSI] mptfusion ...
1204
1205
  		error = -ENODEV;
  		goto out_mptfc_probe;
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
  	}
  
  	/*  Sanity check - ensure at least 1 port is INITIATOR capable
  	 */
  	ioc_cap = 0;
  	for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
  		if (ioc->pfacts[ii].ProtocolFlags &
  		    MPI_PORTFACTS_PROTOCOL_INITIATOR)
  			ioc_cap ++;
  	}
  
  	if (!ioc_cap) {
  		printk(MYIOC_s_WARN_FMT
  			"Skipping ioc=%p because SCSI Initiator mode is NOT enabled!
  ",
  			ioc->name, ioc);
793955f54   Eric Moore   [SCSI] fusion - G...
1222
  		return 0;
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1223
1224
1225
1226
1227
1228
1229
1230
1231
  	}
  
  	sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));
  
  	if (!sh) {
  		printk(MYIOC_s_WARN_FMT
  			"Unable to register controller with SCSI subsystem
  ",
  			ioc->name);
7acec1e75   Moore, Eric Dean   [SCSI] mptfusion ...
1232
1233
  		error = -1;
  		goto out_mptfc_probe;
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1234
          }
80d3ac77a   Michael Reed   [SCSI] mptfusion:...
1235
  	spin_lock_init(&ioc->fc_rescan_work_lock);
c4028958b   David Howells   WorkStruct: make ...
1236
1237
  	INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices);
  	INIT_WORK(&ioc->fc_setup_reset_work, mptfc_setup_reset);
eb5329f40   Prakash, Sathya   [SCSI] mpt fusion...
1238
  	INIT_WORK(&ioc->fc_lsc_work, mptfc_link_status_change);
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
1239

2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
  	spin_lock_irqsave(&ioc->FreeQlock, flags);
  
  	/* Attach the SCSI Host to the IOC structure
  	 */
  	ioc->sh = sh;
  
  	sh->io_port = 0;
  	sh->n_io_port = 0;
  	sh->irq = 0;
  
  	/* set 16 byte cdb's */
  	sh->max_cmd_len = 16;
793955f54   Eric Moore   [SCSI] fusion - G...
1252
1253
  	sh->max_id = ioc->pfacts->MaxDevices;
  	sh->max_lun = max_lun;
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1254

2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
  	/* Required entry.
  	 */
  	sh->unique_id = ioc->id;
  
  	/* Verify that we won't exceed the maximum
  	 * number of chain buffers
  	 * We can optimize:  ZZ = req_sz/sizeof(SGE)
  	 * For 32bit SGE's:
  	 *  numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
  	 *               + (req_sz - 64)/sizeof(SGE)
  	 * A slightly different algorithm is required for
  	 * 64bit SGEs.
  	 */
14d0f0b06   Kashyap, Desai   [SCSI] mpt fusion...
1268
1269
  	scale = ioc->req_sz/ioc->SGE_size;
  	if (ioc->sg_addr_size == sizeof(u64)) {
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1270
1271
  		numSGE = (scale - 1) *
  		  (ioc->facts.MaxChainDepth-1) + scale +
14d0f0b06   Kashyap, Desai   [SCSI] mpt fusion...
1272
  		  (ioc->req_sz - 60) / ioc->SGE_size;
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1273
1274
1275
  	} else {
  		numSGE = 1 + (scale - 1) *
  		  (ioc->facts.MaxChainDepth-1) + scale +
14d0f0b06   Kashyap, Desai   [SCSI] mpt fusion...
1276
  		  (ioc->req_sz - 64) / ioc->SGE_size;
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1277
1278
1279
1280
  	}
  
  	if (numSGE < sh->sg_tablesize) {
  		/* Reset this value */
d6ecdd638   Prakash, Sathya   [SCSI] mpt fusion...
1281
  		dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1282
1283
1284
1285
1286
  		  "Resetting sg_tablesize to %d from %d
  ",
  		  ioc->name, numSGE, sh->sg_tablesize));
  		sh->sg_tablesize = numSGE;
  	}
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1287
  	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
e7eae9f6e   Eric Moore   [SCSI] mpt fusion...
1288
  	hd = shost_priv(sh);
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1289
1290
1291
1292
1293
  	hd->ioc = ioc;
  
  	/* SCSI needs scsi_cmnd lookup table!
  	 * (with size equal to req_depth*PtrSz!)
  	 */
e8206381f   Eric Moore   [SCSI] mpt fusion...
1294
1295
  	ioc->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
  	if (!ioc->ScsiLookup) {
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1296
  		error = -ENOMEM;
7acec1e75   Moore, Eric Dean   [SCSI] mptfusion ...
1297
  		goto out_mptfc_probe;
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1298
  	}
e8206381f   Eric Moore   [SCSI] mpt fusion...
1299
  	spin_lock_init(&ioc->scsi_lookup_lock);
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1300

d6ecdd638   Prakash, Sathya   [SCSI] mpt fusion...
1301
1302
  	dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p
  ",
e8206381f   Eric Moore   [SCSI] mpt fusion...
1303
  		 ioc->name, ioc->ScsiLookup));
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1304

2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1305
  	hd->last_queue_full = 0;
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
1306
  	sh->transportt = mptfc_transport_template;
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1307
1308
  	error = scsi_add_host (sh, &ioc->pcidev->dev);
  	if(error) {
29dd3609f   Eric Moore   [SCSI] mpt fusion...
1309
1310
1311
  		dprintk(ioc, printk(MYIOC_s_ERR_FMT
  		  "scsi_add_host failed
  ", ioc->name));
7acec1e75   Moore, Eric Dean   [SCSI] mptfusion ...
1312
  		goto out_mptfc_probe;
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1313
  	}
65207fedc   Moore, Eric   [SCSI] - fusion -...
1314
  	/* initialize workqueue */
aab0de245   Kay Sievers   driver core: remo...
1315
1316
  	snprintf(ioc->fc_rescan_work_q_name, sizeof(ioc->fc_rescan_work_q_name),
  		 "mptfc_wq_%d", sh->host_no);
65207fedc   Moore, Eric   [SCSI] - fusion -...
1317
1318
1319
1320
1321
1322
  	ioc->fc_rescan_work_q =
  		create_singlethread_workqueue(ioc->fc_rescan_work_q_name);
  	if (!ioc->fc_rescan_work_q)
  		goto out_mptfc_probe;
  
  	/*
80d3ac77a   Michael Reed   [SCSI] mptfusion:...
1323
1324
1325
1326
1327
1328
  	 *  Pre-fetch FC port WWN and stuff...
  	 *  (FCPortPage0_t stuff)
  	 */
  	for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
  		(void) mptfc_GetFcPortPage0(ioc, ii);
  	}
ca2f938ef   Michael Reed   [SCSI] mptfc: set...
1329
  	mptfc_SetFcPortPage1_defaults(ioc);
80d3ac77a   Michael Reed   [SCSI] mptfusion:...
1330
1331
  
  	/*
65207fedc   Moore, Eric   [SCSI] - fusion -...
1332
1333
1334
  	 * scan for rports -
  	 *	by doing it via the workqueue, some locking is eliminated
  	 */
65207fedc   Moore, Eric   [SCSI] - fusion -...
1335
1336
  	queue_work(ioc->fc_rescan_work_q, &ioc->fc_rescan_work);
  	flush_workqueue(ioc->fc_rescan_work_q);
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
1337

2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1338
  	return 0;
7acec1e75   Moore, Eric Dean   [SCSI] mptfusion ...
1339
  out_mptfc_probe:
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1340
1341
1342
1343
1344
1345
1346
1347
1348
  
  	mptscsih_remove(pdev);
  	return error;
  }
  
  static struct pci_driver mptfc_driver = {
  	.name		= "mptfc",
  	.id_table	= mptfc_pci_table,
  	.probe		= mptfc_probe,
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
1349
  	.remove		= __devexit_p(mptfc_remove),
d18c3db58   Greg Kroah-Hartman   [PATCH] PCI: make...
1350
  	.shutdown	= mptscsih_shutdown,
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1351
1352
1353
1354
1355
  #ifdef CONFIG_PM
  	.suspend	= mptscsih_suspend,
  	.resume		= mptscsih_resume,
  #endif
  };
80d3ac77a   Michael Reed   [SCSI] mptfusion:...
1356
1357
1358
1359
1360
1361
1362
  static int
  mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
  {
  	MPT_SCSI_HOST *hd;
  	u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
  	unsigned long flags;
  	int rc=1;
ffb7fef32   Kashyap, Desai   [SCSI] mptfusion:...
1363
1364
  	if (ioc->bus_type != FC)
  		return 0;
d6ecdd638   Prakash, Sathya   [SCSI] mpt fusion...
1365
1366
  	devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MPT event (=%02Xh) routed to SCSI host driver!
  ",
80d3ac77a   Michael Reed   [SCSI] mptfusion:...
1367
1368
1369
  			ioc->name, event));
  
  	if (ioc->sh == NULL ||
e7eae9f6e   Eric Moore   [SCSI] mpt fusion...
1370
  		((hd = shost_priv(ioc->sh)) == NULL))
80d3ac77a   Michael Reed   [SCSI] mptfusion:...
1371
1372
1373
1374
1375
1376
  		return 1;
  
  	switch (event) {
  	case MPI_EVENT_RESCAN:
  		spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
  		if (ioc->fc_rescan_work_q) {
3a0c56d80   Michael Reed   [SCSI] mptfc: cor...
1377
1378
  			queue_work(ioc->fc_rescan_work_q,
  				   &ioc->fc_rescan_work);
80d3ac77a   Michael Reed   [SCSI] mptfusion:...
1379
1380
1381
  		}
  		spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
  		break;
eb5329f40   Prakash, Sathya   [SCSI] mpt fusion...
1382
1383
1384
1385
1386
1387
1388
1389
  	case MPI_EVENT_LINK_STATUS_CHANGE:
  		spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
  		if (ioc->fc_rescan_work_q) {
  			queue_work(ioc->fc_rescan_work_q,
  				   &ioc->fc_lsc_work);
  		}
  		spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
  		break;
80d3ac77a   Michael Reed   [SCSI] mptfusion:...
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
  	default:
  		rc = mptscsih_event_process(ioc,pEvReply);
  		break;
  	}
  	return rc;
  }
  
  static int
  mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
  {
  	int		rc;
  	unsigned long	flags;
  
  	rc = mptscsih_ioc_reset(ioc,reset_phase);
ffb7fef32   Kashyap, Desai   [SCSI] mptfusion:...
1404
  	if ((ioc->bus_type != FC) || (!rc))
80d3ac77a   Michael Reed   [SCSI] mptfusion:...
1405
  		return rc;
d6ecdd638   Prakash, Sathya   [SCSI] mpt fusion...
1406
1407
1408
  	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
  		": IOC %s_reset routed to FC host driver!
  ",ioc->name,
80d3ac77a   Michael Reed   [SCSI] mptfusion:...
1409
1410
1411
1412
  		reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
  		reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
  
  	if (reset_phase == MPT_IOC_SETUP_RESET) {
419835e28   Michael Reed   [SCSI] mptfc: fix...
1413
1414
1415
1416
1417
1418
  		spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
  		if (ioc->fc_rescan_work_q) {
  			queue_work(ioc->fc_rescan_work_q,
  				   &ioc->fc_setup_reset_work);
  		}
  		spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
80d3ac77a   Michael Reed   [SCSI] mptfusion:...
1419
1420
1421
1422
1423
1424
  	}
  
  	else if (reset_phase == MPT_IOC_PRE_RESET) {
  	}
  
  	else {	/* MPT_IOC_POST_RESET */
ca2f938ef   Michael Reed   [SCSI] mptfc: set...
1425
  		mptfc_SetFcPortPage1_defaults(ioc);
80d3ac77a   Michael Reed   [SCSI] mptfusion:...
1426
1427
  		spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
  		if (ioc->fc_rescan_work_q) {
3a0c56d80   Michael Reed   [SCSI] mptfc: cor...
1428
1429
  			queue_work(ioc->fc_rescan_work_q,
  				   &ioc->fc_rescan_work);
80d3ac77a   Michael Reed   [SCSI] mptfusion:...
1430
1431
1432
1433
1434
  		}
  		spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
  	}
  	return 1;
  }
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1435
1436
  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  /**
d9489fb60   Randy Dunlap   [PATCH] kernel-do...
1437
   *	mptfc_init - Register MPT adapter(s) as SCSI host(s) with SCSI mid-layer.
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1438
1439
1440
1441
1442
1443
   *
   *	Returns 0 for success, non-zero for failure.
   */
  static int __init
  mptfc_init(void)
  {
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
1444
  	int error;
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1445
1446
  
  	show_mptmod_ver(my_NAME, my_VERSION);
ca2f938ef   Michael Reed   [SCSI] mptfc: set...
1447
1448
  	/* sanity check module parameters */
  	if (mptfc_dev_loss_tmo <= 0)
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
1449
1450
1451
1452
1453
1454
1455
  		mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;
  
  	mptfc_transport_template =
  		fc_attach_transport(&mptfc_transport_functions);
  
  	if (!mptfc_transport_template)
  		return -ENODEV;
213aaca3e   Kashyap, Desai   [SCSI] mptfusion:...
1456
1457
1458
1459
1460
1461
  	mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER,
  	    "mptscsih_scandv_complete");
  	mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER,
  	    "mptscsih_scandv_complete");
  	mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER,
  	    "mptscsih_scandv_complete");
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1462

d6ecdd638   Prakash, Sathya   [SCSI] mpt fusion...
1463
1464
  	mpt_event_register(mptfcDoneCtx, mptfc_event_process);
  	mpt_reset_register(mptfcDoneCtx, mptfc_ioc_reset);
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1465

05e8ec17f   Michael Reed   [SCSI] mptfusion ...
1466
  	error = pci_register_driver(&mptfc_driver);
3bc7bf1d1   Michael Reed   [SCSI] fusion: FC...
1467
  	if (error)
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
1468
  		fc_release_transport(mptfc_transport_template);
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
1469
1470
1471
1472
1473
1474
  
  	return error;
  }
  
  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  /**
d9489fb60   Randy Dunlap   [PATCH] kernel-do...
1475
   *	mptfc_remove - Remove fc infrastructure for devices
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
1476
1477
1478
   *	@pdev: Pointer to pci_dev structure
   *
   */
3bc7bf1d1   Michael Reed   [SCSI] fusion: FC...
1479
1480
  static void __devexit
  mptfc_remove(struct pci_dev *pdev)
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
1481
  {
65207fedc   Moore, Eric   [SCSI] - fusion -...
1482
1483
1484
1485
  	MPT_ADAPTER		*ioc = pci_get_drvdata(pdev);
  	struct mptfc_rport_info	*p, *n;
  	struct workqueue_struct *work_q;
  	unsigned long		flags;
ca2f938ef   Michael Reed   [SCSI] mptfc: set...
1486
  	int			ii;
65207fedc   Moore, Eric   [SCSI] - fusion -...
1487
1488
1489
1490
1491
1492
1493
1494
  
  	/* destroy workqueue */
  	if ((work_q=ioc->fc_rescan_work_q)) {
  		spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
  		ioc->fc_rescan_work_q = NULL;
  		spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
  		destroy_workqueue(work_q);
  	}
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
1495
1496
1497
1498
1499
1500
1501
  
  	fc_remove_host(ioc->sh);
  
  	list_for_each_entry_safe(p, n, &ioc->fc_rports, list) {
  		list_del(&p->list);
  		kfree(p);
  	}
ca2f938ef   Michael Reed   [SCSI] mptfc: set...
1502
1503
1504
1505
1506
1507
1508
1509
1510
  	for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) {
  		if (ioc->fc_data.fc_port_page1[ii].data) {
  			pci_free_consistent(ioc->pcidev,
  				ioc->fc_data.fc_port_page1[ii].pg_sz,
  				(u8 *) ioc->fc_data.fc_port_page1[ii].data,
  				ioc->fc_data.fc_port_page1[ii].dma);
  			ioc->fc_data.fc_port_page1[ii].data = NULL;
  		}
  	}
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
1511
  	mptscsih_remove(pdev);
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
  }
  
  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  /**
   *	mptfc_exit - Unregisters MPT adapter(s)
   *
   */
  static void __exit
  mptfc_exit(void)
  {
  	pci_unregister_driver(&mptfc_driver);
05e8ec17f   Michael Reed   [SCSI] mptfusion ...
1524
  	fc_release_transport(mptfc_transport_template);
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1525
  	mpt_reset_deregister(mptfcDoneCtx);
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1526
  	mpt_event_deregister(mptfcDoneCtx);
2496af394   Moore, Eric Dean   [SCSI] mptfusion:...
1527
1528
1529
1530
1531
1532
1533
1534
  
  	mpt_deregister(mptfcInternalCtx);
  	mpt_deregister(mptfcTaskCtx);
  	mpt_deregister(mptfcDoneCtx);
  }
  
  module_init(mptfc_init);
  module_exit(mptfc_exit);