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