[SCSI] mptfusion - fc transport attributes
[linux-2.6/libata-dev.git] / drivers / message / fusion / mptfc.c
bloba380fe105a226121484a868f226b5d5b386f6ac3
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.
6 * Copyright (c) 1999-2005 LSI Logic Corporation
7 * (mailto:mpt_linux_developer@lsil.com)
9 */
10 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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.
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.
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.
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
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
45 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
46 #include "linux_compat.h" /* linux-2.6 tweaks */
47 #include <linux/module.h>
48 #include <linux/kernel.h>
49 #include <linux/init.h>
50 #include <linux/errno.h>
51 #include <linux/kdev_t.h>
52 #include <linux/blkdev.h>
53 #include <linux/delay.h> /* for mdelay */
54 #include <linux/interrupt.h> /* needed for in_interrupt() proto */
55 #include <linux/reboot.h> /* notifier code */
56 #include <linux/sched.h>
57 #include <linux/workqueue.h>
58 #include <linux/sort.h>
60 #include <scsi/scsi.h>
61 #include <scsi/scsi_cmnd.h>
62 #include <scsi/scsi_device.h>
63 #include <scsi/scsi_host.h>
64 #include <scsi/scsi_tcq.h>
65 #include <scsi/scsi_transport_fc.h>
67 #include "mptbase.h"
68 #include "mptscsih.h"
70 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
71 #define my_NAME "Fusion MPT FC Host driver"
72 #define my_VERSION MPT_LINUX_VERSION_COMMON
73 #define MYNAM "mptfc"
75 MODULE_AUTHOR(MODULEAUTHOR);
76 MODULE_DESCRIPTION(my_NAME);
77 MODULE_LICENSE("GPL");
79 /* Command line args */
80 static int mpt_pq_filter = 0;
81 module_param(mpt_pq_filter, int, 0);
82 MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)");
84 #define MPTFC_DEV_LOSS_TMO (60)
85 static int mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO; /* reasonable default */
86 module_param(mptfc_dev_loss_tmo, int, 0);
87 MODULE_PARM_DESC(mptfc_dev_loss_tmo, " Initial time the driver programs the "
88 " transport to wait for an rport to "
89 " return following a device loss event."
90 " Default=60.");
92 static int mptfcDoneCtx = -1;
93 static int mptfcTaskCtx = -1;
94 static int mptfcInternalCtx = -1; /* Used only for internal commands */
96 int mptfc_slave_alloc(struct scsi_device *device);
97 static int mptfc_qcmd(struct scsi_cmnd *SCpnt,
98 void (*done)(struct scsi_cmnd *));
100 static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout);
101 static void __devexit mptfc_remove(struct pci_dev *pdev);
103 static struct scsi_host_template mptfc_driver_template = {
104 .module = THIS_MODULE,
105 .proc_name = "mptfc",
106 .proc_info = mptscsih_proc_info,
107 .name = "MPT FC Host",
108 .info = mptscsih_info,
109 .queuecommand = mptfc_qcmd,
110 .target_alloc = mptscsih_target_alloc,
111 .slave_alloc = mptfc_slave_alloc,
112 .slave_configure = mptscsih_slave_configure,
113 .target_destroy = mptscsih_target_destroy,
114 .slave_destroy = mptscsih_slave_destroy,
115 .change_queue_depth = mptscsih_change_queue_depth,
116 .eh_abort_handler = mptscsih_abort,
117 .eh_device_reset_handler = mptscsih_dev_reset,
118 .eh_bus_reset_handler = mptscsih_bus_reset,
119 .eh_host_reset_handler = mptscsih_host_reset,
120 .bios_param = mptscsih_bios_param,
121 .can_queue = MPT_FC_CAN_QUEUE,
122 .this_id = -1,
123 .sg_tablesize = MPT_SCSI_SG_DEPTH,
124 .max_sectors = 8192,
125 .cmd_per_lun = 7,
126 .use_clustering = ENABLE_CLUSTERING,
129 /****************************************************************************
130 * Supported hardware
133 static struct pci_device_id mptfc_pci_table[] = {
134 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC909,
135 PCI_ANY_ID, PCI_ANY_ID },
136 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919,
137 PCI_ANY_ID, PCI_ANY_ID },
138 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929,
139 PCI_ANY_ID, PCI_ANY_ID },
140 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919X,
141 PCI_ANY_ID, PCI_ANY_ID },
142 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929X,
143 PCI_ANY_ID, PCI_ANY_ID },
144 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC939X,
145 PCI_ANY_ID, PCI_ANY_ID },
146 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949X,
147 PCI_ANY_ID, PCI_ANY_ID },
148 {0} /* Terminating entry */
150 MODULE_DEVICE_TABLE(pci, mptfc_pci_table);
152 static struct scsi_transport_template *mptfc_transport_template = NULL;
154 struct fc_function_template mptfc_transport_functions = {
155 .dd_fcrport_size = 8,
156 .show_host_node_name = 1,
157 .show_host_port_name = 1,
158 .show_host_supported_classes = 1,
159 .show_host_port_id = 1,
160 .show_rport_supported_classes = 1,
161 .show_starget_node_name = 1,
162 .show_starget_port_name = 1,
163 .show_starget_port_id = 1,
164 .set_rport_dev_loss_tmo = mptfc_set_rport_loss_tmo,
165 .show_rport_dev_loss_tmo = 1,
169 /* FIXME! values controlling firmware RESCAN event
170 * need to be set low to allow dev_loss_tmo to
171 * work as expected. Currently, firmware doesn't
172 * notify driver of RESCAN event until some number
173 * of seconds elapse. This value can be set via
174 * lsiutil.
176 static void
177 mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
179 if (timeout > 0)
180 rport->dev_loss_tmo = timeout;
181 else
182 rport->dev_loss_tmo = mptfc_dev_loss_tmo;
185 static int
186 mptfc_FcDevPage0_cmp_func(const void *a, const void *b)
188 FCDevicePage0_t **aa = (FCDevicePage0_t **)a;
189 FCDevicePage0_t **bb = (FCDevicePage0_t **)b;
191 if ((*aa)->CurrentBus == (*bb)->CurrentBus) {
192 if ((*aa)->CurrentTargetID == (*bb)->CurrentTargetID)
193 return 0;
194 if ((*aa)->CurrentTargetID < (*bb)->CurrentTargetID)
195 return -1;
196 return 1;
198 if ((*aa)->CurrentBus < (*bb)->CurrentBus)
199 return -1;
200 return 1;
203 static int
204 mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, int ioc_port,
205 void(*func)(MPT_ADAPTER *ioc,int channel, FCDevicePage0_t *arg))
207 ConfigPageHeader_t hdr;
208 CONFIGPARMS cfg;
209 FCDevicePage0_t *ppage0_alloc, *fc;
210 dma_addr_t page0_dma;
211 int data_sz;
212 int ii;
214 FCDevicePage0_t *p0_array=NULL, *p_p0;
215 FCDevicePage0_t **pp0_array=NULL, **p_pp0;
217 int rc = -ENOMEM;
218 U32 port_id = 0xffffff;
219 int num_targ = 0;
220 int max_bus = ioc->facts.MaxBuses;
221 int max_targ = ioc->facts.MaxDevices;
223 if (max_bus == 0 || max_targ == 0)
224 goto out;
226 data_sz = sizeof(FCDevicePage0_t) * max_bus * max_targ;
227 p_p0 = p0_array = kzalloc(data_sz, GFP_KERNEL);
228 if (!p0_array)
229 goto out;
231 data_sz = sizeof(FCDevicePage0_t *) * max_bus * max_targ;
232 p_pp0 = pp0_array = kzalloc(data_sz, GFP_KERNEL);
233 if (!pp0_array)
234 goto out;
236 do {
237 /* Get FC Device Page 0 header */
238 hdr.PageVersion = 0;
239 hdr.PageLength = 0;
240 hdr.PageNumber = 0;
241 hdr.PageType = MPI_CONFIG_PAGETYPE_FC_DEVICE;
242 cfg.cfghdr.hdr = &hdr;
243 cfg.physAddr = -1;
244 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
245 cfg.dir = 0;
246 cfg.pageAddr = port_id;
247 cfg.timeout = 0;
249 if ((rc = mpt_config(ioc, &cfg)) != 0)
250 break;
252 if (hdr.PageLength <= 0)
253 break;
255 data_sz = hdr.PageLength * 4;
256 ppage0_alloc = pci_alloc_consistent(ioc->pcidev, data_sz,
257 &page0_dma);
258 rc = -ENOMEM;
259 if (!ppage0_alloc)
260 break;
262 cfg.physAddr = page0_dma;
263 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
265 if ((rc = mpt_config(ioc, &cfg)) == 0) {
266 ppage0_alloc->PortIdentifier =
267 le32_to_cpu(ppage0_alloc->PortIdentifier);
269 ppage0_alloc->WWNN.Low =
270 le32_to_cpu(ppage0_alloc->WWNN.Low);
272 ppage0_alloc->WWNN.High =
273 le32_to_cpu(ppage0_alloc->WWNN.High);
275 ppage0_alloc->WWPN.Low =
276 le32_to_cpu(ppage0_alloc->WWPN.Low);
278 ppage0_alloc->WWPN.High =
279 le32_to_cpu(ppage0_alloc->WWPN.High);
281 ppage0_alloc->BBCredit =
282 le16_to_cpu(ppage0_alloc->BBCredit);
284 ppage0_alloc->MaxRxFrameSize =
285 le16_to_cpu(ppage0_alloc->MaxRxFrameSize);
287 port_id = ppage0_alloc->PortIdentifier;
288 num_targ++;
289 *p_p0 = *ppage0_alloc; /* save data */
290 *p_pp0++ = p_p0++; /* save addr */
292 pci_free_consistent(ioc->pcidev, data_sz,
293 (u8 *) ppage0_alloc, page0_dma);
294 if (rc != 0)
295 break;
297 } while (port_id <= 0xff0000);
299 if (num_targ) {
300 /* sort array */
301 if (num_targ > 1)
302 sort (pp0_array, num_targ, sizeof(FCDevicePage0_t *),
303 mptfc_FcDevPage0_cmp_func, NULL);
304 /* call caller's func for each targ */
305 for (ii = 0; ii < num_targ; ii++) {
306 fc = *(pp0_array+ii);
307 func(ioc, ioc_port, fc);
311 out:
312 if (pp0_array)
313 kfree(pp0_array);
314 if (p0_array)
315 kfree(p0_array);
316 return rc;
319 static int
320 mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid)
322 /* not currently usable */
323 if (pg0->Flags & (MPI_FC_DEVICE_PAGE0_FLAGS_PLOGI_INVALID |
324 MPI_FC_DEVICE_PAGE0_FLAGS_PRLI_INVALID))
325 return -1;
327 if (!(pg0->Flags & MPI_FC_DEVICE_PAGE0_FLAGS_TARGETID_BUS_VALID))
328 return -1;
330 if (!(pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_TARGET))
331 return -1;
334 * board data structure already normalized to platform endianness
335 * shifted to avoid unaligned access on 64 bit architecture
337 rid->node_name = ((u64)pg0->WWNN.High) << 32 | (u64)pg0->WWNN.Low;
338 rid->port_name = ((u64)pg0->WWPN.High) << 32 | (u64)pg0->WWPN.Low;
339 rid->port_id = pg0->PortIdentifier;
340 rid->roles = FC_RPORT_ROLE_UNKNOWN;
341 rid->roles |= FC_RPORT_ROLE_FCP_TARGET;
342 if (pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR)
343 rid->roles |= FC_RPORT_ROLE_FCP_INITIATOR;
345 return 0;
348 static void
349 mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
351 struct fc_rport_identifiers rport_ids;
352 struct fc_rport *rport;
353 struct mptfc_rport_info *ri;
354 int match = 0;
355 u64 port_name;
356 unsigned long flags;
358 if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0)
359 return;
361 /* scan list looking for a match */
362 spin_lock_irqsave(&ioc->fc_rport_lock, flags);
363 list_for_each_entry(ri, &ioc->fc_rports, list) {
364 port_name = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
365 if (port_name == rport_ids.port_name) { /* match */
366 list_move_tail(&ri->list, &ioc->fc_rports);
367 match = 1;
368 break;
371 if (!match) { /* allocate one */
372 spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);
373 ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL);
374 if (!ri)
375 return;
376 spin_lock_irqsave(&ioc->fc_rport_lock, flags);
377 list_add_tail(&ri->list, &ioc->fc_rports);
380 ri->pg0 = *pg0; /* add/update pg0 data */
381 ri->flags &= ~MPT_RPORT_INFO_FLAGS_MISSING;
383 if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) {
384 ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED;
385 spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);
386 rport = fc_remote_port_add(ioc->sh,channel, &rport_ids);
387 spin_lock_irqsave(&ioc->fc_rport_lock, flags);
388 if (rport) {
389 if (*((struct mptfc_rport_info **)rport->dd_data) != ri) {
390 ri->flags &= ~MPT_RPORT_INFO_FLAGS_MAPPED_VDEV;
391 ri->vdev = NULL;
392 ri->rport = rport;
393 *((struct mptfc_rport_info **)rport->dd_data) = ri;
395 rport->dev_loss_tmo = mptfc_dev_loss_tmo;
397 * if already mapped, remap here. If not mapped,
398 * slave_alloc will allocate vdev and map
400 if (ri->flags & MPT_RPORT_INFO_FLAGS_MAPPED_VDEV) {
401 ri->vdev->target_id = ri->pg0.CurrentTargetID;
402 ri->vdev->bus_id = ri->pg0.CurrentBus;
403 ri->vdev->vtarget->target_id = ri->vdev->target_id;
404 ri->vdev->vtarget->bus_id = ri->vdev->bus_id;
406 #ifdef MPT_DEBUG
407 printk ("mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "
408 "rport tid %d, tmo %d\n",
409 ioc->sh->host_no,
410 pg0->PortIdentifier,
411 pg0->WWNN,
412 pg0->WWPN,
413 pg0->CurrentTargetID,
414 ri->rport->scsi_target_id,
415 ri->rport->dev_loss_tmo);
416 #endif
417 } else {
418 list_del(&ri->list);
419 kfree(ri);
420 ri = NULL;
423 spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
428 * OS entry point to allow host driver to alloc memory
429 * for each scsi device. Called once per device the bus scan.
430 * Return non-zero if allocation fails.
431 * Init memory once per LUN.
434 mptfc_slave_alloc(struct scsi_device *sdev)
436 MPT_SCSI_HOST *hd;
437 VirtTarget *vtarget;
438 VirtDevice *vdev;
439 struct scsi_target *starget;
440 struct fc_rport *rport;
441 struct mptfc_rport_info *ri;
442 unsigned long flags;
445 rport = starget_to_rport(scsi_target(sdev));
447 if (!rport || fc_remote_port_chkready(rport))
448 return -ENXIO;
450 hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
452 vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
453 if (!vdev) {
454 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
455 hd->ioc->name, sizeof(VirtDevice));
456 return -ENOMEM;
458 memset(vdev, 0, sizeof(VirtDevice));
460 spin_lock_irqsave(&hd->ioc->fc_rport_lock,flags);
462 if (!(ri = *((struct mptfc_rport_info **)rport->dd_data))) {
463 spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags);
464 kfree(vdev);
465 return -ENODEV;
468 sdev->hostdata = vdev;
469 starget = scsi_target(sdev);
470 vtarget = starget->hostdata;
471 if (vtarget->num_luns == 0) {
472 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES |
473 MPT_TARGET_FLAGS_VALID_INQUIRY;
474 hd->Targets[sdev->id] = vtarget;
477 vtarget->target_id = vdev->target_id;
478 vtarget->bus_id = vdev->bus_id;
480 vdev->vtarget = vtarget;
481 vdev->ioc_id = hd->ioc->id;
482 vdev->lun = sdev->lun;
483 vdev->target_id = ri->pg0.CurrentTargetID;
484 vdev->bus_id = ri->pg0.CurrentBus;
486 ri->flags |= MPT_RPORT_INFO_FLAGS_MAPPED_VDEV;
487 ri->vdev = vdev;
489 spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags);
491 vtarget->num_luns++;
493 #ifdef MPT_DEBUG
494 printk ("mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
495 "CurrentTargetID %d, %x %llx %llx\n",
496 sdev->host->host_no,
497 vtarget->num_luns,
498 sdev->id, ri->pg0.CurrentTargetID,
499 ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN);
500 #endif
502 return 0;
505 static int
506 mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
508 struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device));
509 int err;
511 err = fc_remote_port_chkready(rport);
512 if (unlikely(err)) {
513 SCpnt->result = err;
514 done(SCpnt);
515 return 0;
517 return mptscsih_qcmd(SCpnt,done);
520 static void
521 mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum)
523 unsigned class = 0, cos = 0;
525 /* don't know what to do as only one scsi (fc) host was allocated */
526 if (portnum != 0)
527 return;
529 class = ioc->fc_port_page0[portnum].SupportedServiceClass;
530 if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_1)
531 cos |= FC_COS_CLASS1;
532 if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_2)
533 cos |= FC_COS_CLASS2;
534 if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_3)
535 cos |= FC_COS_CLASS3;
537 fc_host_node_name(ioc->sh) =
538 (u64)ioc->fc_port_page0[portnum].WWNN.High << 32
539 | (u64)ioc->fc_port_page0[portnum].WWNN.Low;
541 fc_host_port_name(ioc->sh) =
542 (u64)ioc->fc_port_page0[portnum].WWPN.High << 32
543 | (u64)ioc->fc_port_page0[portnum].WWPN.Low;
545 fc_host_port_id(ioc->sh) = ioc->fc_port_page0[portnum].PortIdentifier;
547 fc_host_supported_classes(ioc->sh) = cos;
549 fc_host_tgtid_bind_type(ioc->sh) = FC_TGTID_BIND_BY_WWPN;
552 static void
553 mptfc_rescan_devices(void *arg)
555 MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
556 int ii;
557 int work_to_do;
558 unsigned long flags;
559 struct mptfc_rport_info *ri;
561 do {
562 /* start by tagging all ports as missing */
563 spin_lock_irqsave(&ioc->fc_rport_lock,flags);
564 list_for_each_entry(ri, &ioc->fc_rports, list) {
565 if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
566 ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING;
569 spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
572 * now rescan devices known to adapter,
573 * will reregister existing rports
575 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
576 (void) mptbase_GetFcPortPage0(ioc, ii);
577 mptfc_init_host_attr(ioc,ii); /* refresh */
578 mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);
581 /* delete devices still missing */
582 spin_lock_irqsave(&ioc->fc_rport_lock, flags);
583 list_for_each_entry(ri, &ioc->fc_rports, list) {
584 /* if newly missing, delete it */
585 if ((ri->flags & (MPT_RPORT_INFO_FLAGS_REGISTERED |
586 MPT_RPORT_INFO_FLAGS_MISSING))
587 == (MPT_RPORT_INFO_FLAGS_REGISTERED |
588 MPT_RPORT_INFO_FLAGS_MISSING)) {
590 ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|
591 MPT_RPORT_INFO_FLAGS_MISSING);
592 fc_remote_port_delete(ri->rport);
594 * remote port not really deleted 'cause
595 * binding is by WWPN and driver only
596 * registers FCP_TARGETs
598 #ifdef MPT_DEBUG
599 printk ("mptfc_rescan.%d: %llx deleted\n",
600 ioc->sh->host_no, ri->pg0.WWPN);
601 #endif
604 spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
607 * allow multiple passes as target state
608 * might have changed during scan
610 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
611 if (ioc->fc_rescan_work_count > 2) /* only need one more */
612 ioc->fc_rescan_work_count = 2;
613 work_to_do = --ioc->fc_rescan_work_count;
614 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
615 } while (work_to_do);
618 static int
619 mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
621 struct Scsi_Host *sh;
622 MPT_SCSI_HOST *hd;
623 MPT_ADAPTER *ioc;
624 unsigned long flags;
625 int ii;
626 int numSGE = 0;
627 int scale;
628 int ioc_cap;
629 int error=0;
630 int r;
632 if ((r = mpt_attach(pdev,id)) != 0)
633 return r;
635 ioc = pci_get_drvdata(pdev);
636 ioc->DoneCtx = mptfcDoneCtx;
637 ioc->TaskCtx = mptfcTaskCtx;
638 ioc->InternalCtx = mptfcInternalCtx;
640 /* Added sanity check on readiness of the MPT adapter.
642 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
643 printk(MYIOC_s_WARN_FMT
644 "Skipping because it's not operational!\n",
645 ioc->name);
646 error = -ENODEV;
647 goto out_mptfc_probe;
650 if (!ioc->active) {
651 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
652 ioc->name);
653 error = -ENODEV;
654 goto out_mptfc_probe;
657 /* Sanity check - ensure at least 1 port is INITIATOR capable
659 ioc_cap = 0;
660 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
661 if (ioc->pfacts[ii].ProtocolFlags &
662 MPI_PORTFACTS_PROTOCOL_INITIATOR)
663 ioc_cap ++;
666 if (!ioc_cap) {
667 printk(MYIOC_s_WARN_FMT
668 "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
669 ioc->name, ioc);
670 return -ENODEV;
673 sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));
675 if (!sh) {
676 printk(MYIOC_s_WARN_FMT
677 "Unable to register controller with SCSI subsystem\n",
678 ioc->name);
679 error = -1;
680 goto out_mptfc_probe;
683 INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc);
685 spin_lock_irqsave(&ioc->FreeQlock, flags);
687 /* Attach the SCSI Host to the IOC structure
689 ioc->sh = sh;
691 sh->io_port = 0;
692 sh->n_io_port = 0;
693 sh->irq = 0;
695 /* set 16 byte cdb's */
696 sh->max_cmd_len = 16;
698 sh->max_id = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
700 sh->max_lun = MPT_LAST_LUN + 1;
701 sh->max_channel = 0;
702 sh->this_id = ioc->pfacts[0].PortSCSIID;
704 /* Required entry.
706 sh->unique_id = ioc->id;
708 /* Verify that we won't exceed the maximum
709 * number of chain buffers
710 * We can optimize: ZZ = req_sz/sizeof(SGE)
711 * For 32bit SGE's:
712 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
713 * + (req_sz - 64)/sizeof(SGE)
714 * A slightly different algorithm is required for
715 * 64bit SGEs.
717 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
718 if (sizeof(dma_addr_t) == sizeof(u64)) {
719 numSGE = (scale - 1) *
720 (ioc->facts.MaxChainDepth-1) + scale +
721 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
722 sizeof(u32));
723 } else {
724 numSGE = 1 + (scale - 1) *
725 (ioc->facts.MaxChainDepth-1) + scale +
726 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
727 sizeof(u32));
730 if (numSGE < sh->sg_tablesize) {
731 /* Reset this value */
732 dprintk((MYIOC_s_INFO_FMT
733 "Resetting sg_tablesize to %d from %d\n",
734 ioc->name, numSGE, sh->sg_tablesize));
735 sh->sg_tablesize = numSGE;
738 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
740 hd = (MPT_SCSI_HOST *) sh->hostdata;
741 hd->ioc = ioc;
743 /* SCSI needs scsi_cmnd lookup table!
744 * (with size equal to req_depth*PtrSz!)
746 hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
747 if (!hd->ScsiLookup) {
748 error = -ENOMEM;
749 goto out_mptfc_probe;
752 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
753 ioc->name, hd->ScsiLookup));
755 /* Allocate memory for the device structures.
756 * A non-Null pointer at an offset
757 * indicates a device exists.
758 * max_id = 1 + maximum id (hosts.h)
760 hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
761 if (!hd->Targets) {
762 error = -ENOMEM;
763 goto out_mptfc_probe;
766 dprintk((KERN_INFO " vdev @ %p\n", hd->Targets));
768 /* Clear the TM flags
770 hd->tmPending = 0;
771 hd->tmState = TM_STATE_NONE;
772 hd->resetPending = 0;
773 hd->abortSCpnt = NULL;
775 /* Clear the pointer used to store
776 * single-threaded commands, i.e., those
777 * issued during a bus scan, dv and
778 * configuration pages.
780 hd->cmdPtr = NULL;
782 /* Initialize this SCSI Hosts' timers
783 * To use, set the timer expires field
784 * and add_timer
786 init_timer(&hd->timer);
787 hd->timer.data = (unsigned long) hd;
788 hd->timer.function = mptscsih_timer_expired;
790 hd->mpt_pq_filter = mpt_pq_filter;
792 ddvprintk((MYIOC_s_INFO_FMT
793 "mpt_pq_filter %x\n",
794 ioc->name,
795 mpt_pq_filter));
797 init_waitqueue_head(&hd->scandv_waitq);
798 hd->scandv_wait_done = 0;
799 hd->last_queue_full = 0;
801 sh->transportt = mptfc_transport_template;
802 error = scsi_add_host (sh, &ioc->pcidev->dev);
803 if(error) {
804 dprintk((KERN_ERR MYNAM
805 "scsi_add_host failed\n"));
806 goto out_mptfc_probe;
809 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
810 mptfc_init_host_attr(ioc,ii);
811 mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);
814 return 0;
816 out_mptfc_probe:
818 mptscsih_remove(pdev);
819 return error;
822 static struct pci_driver mptfc_driver = {
823 .name = "mptfc",
824 .id_table = mptfc_pci_table,
825 .probe = mptfc_probe,
826 .remove = __devexit_p(mptfc_remove),
827 .shutdown = mptscsih_shutdown,
828 #ifdef CONFIG_PM
829 .suspend = mptscsih_suspend,
830 .resume = mptscsih_resume,
831 #endif
834 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
836 * mptfc_init - Register MPT adapter(s) as SCSI host(s) with
837 * linux scsi mid-layer.
839 * Returns 0 for success, non-zero for failure.
841 static int __init
842 mptfc_init(void)
844 int error;
846 show_mptmod_ver(my_NAME, my_VERSION);
848 /* sanity check module parameter */
849 if (mptfc_dev_loss_tmo == 0)
850 mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;
852 mptfc_transport_template =
853 fc_attach_transport(&mptfc_transport_functions);
855 if (!mptfc_transport_template)
856 return -ENODEV;
858 mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER);
859 mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER);
860 mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER);
862 if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) {
863 devtprintk((KERN_INFO MYNAM
864 ": Registered for IOC event notifications\n"));
867 if (mpt_reset_register(mptfcDoneCtx, mptscsih_ioc_reset) == 0) {
868 dprintk((KERN_INFO MYNAM
869 ": Registered for IOC reset notifications\n"));
872 error = pci_register_driver(&mptfc_driver);
873 if (error) {
874 fc_release_transport(mptfc_transport_template);
877 return error;
880 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
882 * mptfc_remove - Removed fc infrastructure for devices
883 * @pdev: Pointer to pci_dev structure
886 static void __devexit mptfc_remove(struct pci_dev *pdev)
888 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
889 struct mptfc_rport_info *p, *n;
891 fc_remove_host(ioc->sh);
893 list_for_each_entry_safe(p, n, &ioc->fc_rports, list) {
894 list_del(&p->list);
895 kfree(p);
898 mptscsih_remove(pdev);
901 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
902 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
904 * mptfc_exit - Unregisters MPT adapter(s)
907 static void __exit
908 mptfc_exit(void)
910 pci_unregister_driver(&mptfc_driver);
911 fc_release_transport(mptfc_transport_template);
913 mpt_reset_deregister(mptfcDoneCtx);
914 dprintk((KERN_INFO MYNAM
915 ": Deregistered for IOC reset notifications\n"));
917 mpt_event_deregister(mptfcDoneCtx);
918 dprintk((KERN_INFO MYNAM
919 ": Deregistered for IOC event notifications\n"));
921 mpt_deregister(mptfcInternalCtx);
922 mpt_deregister(mptfcTaskCtx);
923 mpt_deregister(mptfcDoneCtx);
926 module_init(mptfc_init);
927 module_exit(mptfc_exit);