[SCSI] mpt fusion: Change call back indices to u8 from int
[safe/jmp/linux-2.6] / drivers / message / fusion / mptfc.c
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  *
6  *  Copyright (c) 1999-2007 LSI Logic Corporation
7  *  (mailto:DL-MPTFusionLinux@lsi.com)
8  *
9  */
10 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11 /*
12     This program is free software; you can redistribute it and/or modify
13     it under the terms of the GNU General Public License as published by
14     the Free Software Foundation; version 2 of the License.
15
16     This program is distributed in the hope that it will be useful,
17     but WITHOUT ANY WARRANTY; without even the implied warranty of
18     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19     GNU General Public License for more details.
20
21     NO WARRANTY
22     THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
23     CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
24     LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
25     MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
26     solely responsible for determining the appropriateness of using and
27     distributing the Program and assumes all risks associated with its
28     exercise of rights under this Agreement, including but not limited to
29     the risks and costs of program errors, damage to or loss of data,
30     programs or equipment, and unavailability or interruption of operations.
31
32     DISCLAIMER OF LIABILITY
33     NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
34     DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35     DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
36     ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
37     TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
38     USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
39     HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
40
41     You should have received a copy of the GNU General Public License
42     along with this program; if not, write to the Free Software
43     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
44 */
45 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
46 #include <linux/module.h>
47 #include <linux/kernel.h>
48 #include <linux/init.h>
49 #include <linux/errno.h>
50 #include <linux/kdev_t.h>
51 #include <linux/blkdev.h>
52 #include <linux/delay.h>        /* for mdelay */
53 #include <linux/interrupt.h>    /* needed for in_interrupt() proto */
54 #include <linux/reboot.h>       /* notifier code */
55 #include <linux/workqueue.h>
56 #include <linux/sort.h>
57
58 #include <scsi/scsi.h>
59 #include <scsi/scsi_cmnd.h>
60 #include <scsi/scsi_device.h>
61 #include <scsi/scsi_host.h>
62 #include <scsi/scsi_tcq.h>
63 #include <scsi/scsi_transport_fc.h>
64
65 #include "mptbase.h"
66 #include "mptscsih.h"
67
68 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
69 #define my_NAME         "Fusion MPT FC Host driver"
70 #define my_VERSION      MPT_LINUX_VERSION_COMMON
71 #define MYNAM           "mptfc"
72
73 MODULE_AUTHOR(MODULEAUTHOR);
74 MODULE_DESCRIPTION(my_NAME);
75 MODULE_LICENSE("GPL");
76 MODULE_VERSION(my_VERSION);
77
78 /* Command line args */
79 #define MPTFC_DEV_LOSS_TMO (60)
80 static int mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;     /* reasonable default */
81 module_param(mptfc_dev_loss_tmo, int, 0);
82 MODULE_PARM_DESC(mptfc_dev_loss_tmo, " Initial time the driver programs the "
83                                      " transport to wait for an rport to "
84                                      " return following a device loss event."
85                                      "  Default=60.");
86
87 /* scsi-mid layer global parmeter is max_report_luns, which is 511 */
88 #define MPTFC_MAX_LUN (16895)
89 static int max_lun = MPTFC_MAX_LUN;
90 module_param(max_lun, int, 0);
91 MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
92
93 static u8       mptfcDoneCtx = MPT_MAX_PROTOCOL_DRIVERS;
94 static u8       mptfcTaskCtx = MPT_MAX_PROTOCOL_DRIVERS;
95 static u8       mptfcInternalCtx = MPT_MAX_PROTOCOL_DRIVERS;
96
97 static int mptfc_target_alloc(struct scsi_target *starget);
98 static int mptfc_slave_alloc(struct scsi_device *sdev);
99 static int mptfc_qcmd(struct scsi_cmnd *SCpnt,
100                       void (*done)(struct scsi_cmnd *));
101 static void mptfc_target_destroy(struct scsi_target *starget);
102 static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout);
103 static void __devexit mptfc_remove(struct pci_dev *pdev);
104 static int mptfc_abort(struct scsi_cmnd *SCpnt);
105 static int mptfc_dev_reset(struct scsi_cmnd *SCpnt);
106 static int mptfc_bus_reset(struct scsi_cmnd *SCpnt);
107 static int mptfc_host_reset(struct scsi_cmnd *SCpnt);
108
109 static struct scsi_host_template mptfc_driver_template = {
110         .module                         = THIS_MODULE,
111         .proc_name                      = "mptfc",
112         .proc_info                      = mptscsih_proc_info,
113         .name                           = "MPT FC Host",
114         .info                           = mptscsih_info,
115         .queuecommand                   = mptfc_qcmd,
116         .target_alloc                   = mptfc_target_alloc,
117         .slave_alloc                    = mptfc_slave_alloc,
118         .slave_configure                = mptscsih_slave_configure,
119         .target_destroy                 = mptfc_target_destroy,
120         .slave_destroy                  = mptscsih_slave_destroy,
121         .change_queue_depth             = mptscsih_change_queue_depth,
122         .eh_abort_handler               = mptfc_abort,
123         .eh_device_reset_handler        = mptfc_dev_reset,
124         .eh_bus_reset_handler           = mptfc_bus_reset,
125         .eh_host_reset_handler          = mptfc_host_reset,
126         .bios_param                     = mptscsih_bios_param,
127         .can_queue                      = MPT_FC_CAN_QUEUE,
128         .this_id                        = -1,
129         .sg_tablesize                   = MPT_SCSI_SG_DEPTH,
130         .max_sectors                    = 8192,
131         .cmd_per_lun                    = 7,
132         .use_clustering                 = ENABLE_CLUSTERING,
133         .shost_attrs                    = mptscsih_host_attrs,
134 };
135
136 /****************************************************************************
137  * Supported hardware
138  */
139
140 static struct pci_device_id mptfc_pci_table[] = {
141         { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC909,
142                 PCI_ANY_ID, PCI_ANY_ID },
143         { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC919,
144                 PCI_ANY_ID, PCI_ANY_ID },
145         { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC929,
146                 PCI_ANY_ID, PCI_ANY_ID },
147         { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC919X,
148                 PCI_ANY_ID, PCI_ANY_ID },
149         { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC929X,
150                 PCI_ANY_ID, PCI_ANY_ID },
151         { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC939X,
152                 PCI_ANY_ID, PCI_ANY_ID },
153         { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC949X,
154                 PCI_ANY_ID, PCI_ANY_ID },
155         { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC949E,
156                 PCI_ANY_ID, PCI_ANY_ID },
157         { PCI_VENDOR_ID_BROCADE, MPI_MANUFACTPAGE_DEVICEID_FC949E,
158                 PCI_ANY_ID, PCI_ANY_ID },
159         {0}     /* Terminating entry */
160 };
161 MODULE_DEVICE_TABLE(pci, mptfc_pci_table);
162
163 static struct scsi_transport_template *mptfc_transport_template = NULL;
164
165 static struct fc_function_template mptfc_transport_functions = {
166         .dd_fcrport_size = 8,
167         .show_host_node_name = 1,
168         .show_host_port_name = 1,
169         .show_host_supported_classes = 1,
170         .show_host_port_id = 1,
171         .show_rport_supported_classes = 1,
172         .show_starget_node_name = 1,
173         .show_starget_port_name = 1,
174         .show_starget_port_id = 1,
175         .set_rport_dev_loss_tmo = mptfc_set_rport_loss_tmo,
176         .show_rport_dev_loss_tmo = 1,
177         .show_host_supported_speeds = 1,
178         .show_host_maxframe_size = 1,
179         .show_host_speed = 1,
180         .show_host_fabric_name = 1,
181         .show_host_port_type = 1,
182         .show_host_port_state = 1,
183         .show_host_symbolic_name = 1,
184 };
185
186 static int
187 mptfc_block_error_handler(struct scsi_cmnd *SCpnt,
188                           int (*func)(struct scsi_cmnd *SCpnt),
189                           const char *caller)
190 {
191         MPT_SCSI_HOST           *hd;
192         struct scsi_device      *sdev = SCpnt->device;
193         struct Scsi_Host        *shost = sdev->host;
194         struct fc_rport         *rport = starget_to_rport(scsi_target(sdev));
195         unsigned long           flags;
196         int                     ready;
197
198         hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
199         spin_lock_irqsave(shost->host_lock, flags);
200         while ((ready = fc_remote_port_chkready(rport) >> 16) == DID_IMM_RETRY) {
201                 spin_unlock_irqrestore(shost->host_lock, flags);
202                 dfcprintk (hd->ioc, printk(MYIOC_s_DEBUG_FMT
203                         "mptfc_block_error_handler.%d: %d:%d, port status is "
204                         "DID_IMM_RETRY, deferring %s recovery.\n",
205                         ((MPT_SCSI_HOST *) shost->hostdata)->ioc->name,
206                         ((MPT_SCSI_HOST *) shost->hostdata)->ioc->sh->host_no,
207                         SCpnt->device->id,SCpnt->device->lun,caller));
208                 msleep(1000);
209                 spin_lock_irqsave(shost->host_lock, flags);
210         }
211         spin_unlock_irqrestore(shost->host_lock, flags);
212
213         if (ready == DID_NO_CONNECT || !SCpnt->device->hostdata) {
214                 dfcprintk (hd->ioc, printk(MYIOC_s_DEBUG_FMT
215                         "%s.%d: %d:%d, failing recovery, "
216                         "port state %d, vdev %p.\n", caller,
217                         ((MPT_SCSI_HOST *) shost->hostdata)->ioc->name,
218                         ((MPT_SCSI_HOST *) shost->hostdata)->ioc->sh->host_no,
219                         SCpnt->device->id,SCpnt->device->lun,ready,
220                         SCpnt->device->hostdata));
221                 return FAILED;
222         }
223         dfcprintk (hd->ioc, printk(MYIOC_s_DEBUG_FMT
224                 "%s.%d: %d:%d, executing recovery.\n", caller,
225                 ((MPT_SCSI_HOST *) shost->hostdata)->ioc->name,
226                 ((MPT_SCSI_HOST *) shost->hostdata)->ioc->sh->host_no,
227                 SCpnt->device->id,SCpnt->device->lun));
228         return (*func)(SCpnt);
229 }
230
231 static int
232 mptfc_abort(struct scsi_cmnd *SCpnt)
233 {
234         return
235             mptfc_block_error_handler(SCpnt, mptscsih_abort, __FUNCTION__);
236 }
237
238 static int
239 mptfc_dev_reset(struct scsi_cmnd *SCpnt)
240 {
241         return
242             mptfc_block_error_handler(SCpnt, mptscsih_dev_reset, __FUNCTION__);
243 }
244
245 static int
246 mptfc_bus_reset(struct scsi_cmnd *SCpnt)
247 {
248         return
249             mptfc_block_error_handler(SCpnt, mptscsih_bus_reset, __FUNCTION__);
250 }
251
252 static int
253 mptfc_host_reset(struct scsi_cmnd *SCpnt)
254 {
255         return
256             mptfc_block_error_handler(SCpnt, mptscsih_host_reset, __FUNCTION__);
257 }
258
259 static void
260 mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
261 {
262         if (timeout > 0)
263                 rport->dev_loss_tmo = timeout;
264         else
265                 rport->dev_loss_tmo = mptfc_dev_loss_tmo;
266 }
267
268 static int
269 mptfc_FcDevPage0_cmp_func(const void *a, const void *b)
270 {
271         FCDevicePage0_t **aa = (FCDevicePage0_t **)a;
272         FCDevicePage0_t **bb = (FCDevicePage0_t **)b;
273
274         if ((*aa)->CurrentBus == (*bb)->CurrentBus) {
275                 if ((*aa)->CurrentTargetID == (*bb)->CurrentTargetID)
276                         return 0;
277                 if ((*aa)->CurrentTargetID < (*bb)->CurrentTargetID)
278                         return -1;
279                 return 1;
280         }
281         if ((*aa)->CurrentBus < (*bb)->CurrentBus)
282                 return -1;
283         return 1;
284 }
285
286 static int
287 mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, int ioc_port,
288         void(*func)(MPT_ADAPTER *ioc,int channel, FCDevicePage0_t *arg))
289 {
290         ConfigPageHeader_t       hdr;
291         CONFIGPARMS              cfg;
292         FCDevicePage0_t         *ppage0_alloc, *fc;
293         dma_addr_t               page0_dma;
294         int                      data_sz;
295         int                      ii;
296
297         FCDevicePage0_t         *p0_array=NULL, *p_p0;
298         FCDevicePage0_t         **pp0_array=NULL, **p_pp0;
299
300         int                      rc = -ENOMEM;
301         U32                      port_id = 0xffffff;
302         int                      num_targ = 0;
303         int                      max_bus = ioc->facts.MaxBuses;
304         int                      max_targ;
305
306         max_targ = (ioc->facts.MaxDevices == 0) ? 256 : ioc->facts.MaxDevices;
307
308         data_sz = sizeof(FCDevicePage0_t) * max_bus * max_targ;
309         p_p0 = p0_array =  kzalloc(data_sz, GFP_KERNEL);
310         if (!p0_array)
311                 goto out;
312
313         data_sz = sizeof(FCDevicePage0_t *) * max_bus * max_targ;
314         p_pp0 = pp0_array = kzalloc(data_sz, GFP_KERNEL);
315         if (!pp0_array)
316                 goto out;
317
318         do {
319                 /* Get FC Device Page 0 header */
320                 hdr.PageVersion = 0;
321                 hdr.PageLength = 0;
322                 hdr.PageNumber = 0;
323                 hdr.PageType = MPI_CONFIG_PAGETYPE_FC_DEVICE;
324                 cfg.cfghdr.hdr = &hdr;
325                 cfg.physAddr = -1;
326                 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
327                 cfg.dir = 0;
328                 cfg.pageAddr = port_id;
329                 cfg.timeout = 0;
330
331                 if ((rc = mpt_config(ioc, &cfg)) != 0)
332                         break;
333
334                 if (hdr.PageLength <= 0)
335                         break;
336
337                 data_sz = hdr.PageLength * 4;
338                 ppage0_alloc = pci_alloc_consistent(ioc->pcidev, data_sz,
339                                                         &page0_dma);
340                 rc = -ENOMEM;
341                 if (!ppage0_alloc)
342                         break;
343
344                 cfg.physAddr = page0_dma;
345                 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
346
347                 if ((rc = mpt_config(ioc, &cfg)) == 0) {
348                         ppage0_alloc->PortIdentifier =
349                                 le32_to_cpu(ppage0_alloc->PortIdentifier);
350
351                         ppage0_alloc->WWNN.Low =
352                                 le32_to_cpu(ppage0_alloc->WWNN.Low);
353
354                         ppage0_alloc->WWNN.High =
355                                 le32_to_cpu(ppage0_alloc->WWNN.High);
356
357                         ppage0_alloc->WWPN.Low =
358                                 le32_to_cpu(ppage0_alloc->WWPN.Low);
359
360                         ppage0_alloc->WWPN.High =
361                                 le32_to_cpu(ppage0_alloc->WWPN.High);
362
363                         ppage0_alloc->BBCredit =
364                                 le16_to_cpu(ppage0_alloc->BBCredit);
365
366                         ppage0_alloc->MaxRxFrameSize =
367                                 le16_to_cpu(ppage0_alloc->MaxRxFrameSize);
368
369                         port_id = ppage0_alloc->PortIdentifier;
370                         num_targ++;
371                         *p_p0 = *ppage0_alloc;  /* save data */
372                         *p_pp0++ = p_p0++;      /* save addr */
373                 }
374                 pci_free_consistent(ioc->pcidev, data_sz,
375                                         (u8 *) ppage0_alloc, page0_dma);
376                 if (rc != 0)
377                         break;
378
379         } while (port_id <= 0xff0000);
380
381         if (num_targ) {
382                 /* sort array */
383                 if (num_targ > 1)
384                         sort (pp0_array, num_targ, sizeof(FCDevicePage0_t *),
385                                 mptfc_FcDevPage0_cmp_func, NULL);
386                 /* call caller's func for each targ */
387                 for (ii = 0; ii < num_targ;  ii++) {
388                         fc = *(pp0_array+ii);
389                         func(ioc, ioc_port, fc);
390                 }
391         }
392
393  out:
394         kfree(pp0_array);
395         kfree(p0_array);
396         return rc;
397 }
398
399 static int
400 mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid)
401 {
402         /* not currently usable */
403         if (pg0->Flags & (MPI_FC_DEVICE_PAGE0_FLAGS_PLOGI_INVALID |
404                           MPI_FC_DEVICE_PAGE0_FLAGS_PRLI_INVALID))
405                 return -1;
406
407         if (!(pg0->Flags & MPI_FC_DEVICE_PAGE0_FLAGS_TARGETID_BUS_VALID))
408                 return -1;
409
410         if (!(pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_TARGET))
411                 return -1;
412
413         /*
414          * board data structure already normalized to platform endianness
415          * shifted to avoid unaligned access on 64 bit architecture
416          */
417         rid->node_name = ((u64)pg0->WWNN.High) << 32 | (u64)pg0->WWNN.Low;
418         rid->port_name = ((u64)pg0->WWPN.High) << 32 | (u64)pg0->WWPN.Low;
419         rid->port_id =   pg0->PortIdentifier;
420         rid->roles = FC_RPORT_ROLE_UNKNOWN;
421
422         return 0;
423 }
424
425 static void
426 mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
427 {
428         struct fc_rport_identifiers rport_ids;
429         struct fc_rport         *rport;
430         struct mptfc_rport_info *ri;
431         int                     new_ri = 1;
432         u64                     pn, nn;
433         VirtTarget              *vtarget;
434         u32                     roles = FC_RPORT_ROLE_UNKNOWN;
435
436         if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0)
437                 return;
438
439         roles |= FC_RPORT_ROLE_FCP_TARGET;
440         if (pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR)
441                 roles |= FC_RPORT_ROLE_FCP_INITIATOR;
442
443         /* scan list looking for a match */
444         list_for_each_entry(ri, &ioc->fc_rports, list) {
445                 pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
446                 if (pn == rport_ids.port_name) {        /* match */
447                         list_move_tail(&ri->list, &ioc->fc_rports);
448                         new_ri = 0;
449                         break;
450                 }
451         }
452         if (new_ri) {   /* allocate one */
453                 ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL);
454                 if (!ri)
455                         return;
456                 list_add_tail(&ri->list, &ioc->fc_rports);
457         }
458
459         ri->pg0 = *pg0; /* add/update pg0 data */
460         ri->flags &= ~MPT_RPORT_INFO_FLAGS_MISSING;
461
462         /* MPT_RPORT_INFO_FLAGS_REGISTERED - rport not previously deleted */
463         if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) {
464                 ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED;
465                 rport = fc_remote_port_add(ioc->sh, channel, &rport_ids);
466                 if (rport) {
467                         ri->rport = rport;
468                         if (new_ri) /* may have been reset by user */
469                                 rport->dev_loss_tmo = mptfc_dev_loss_tmo;
470                         /*
471                          * if already mapped, remap here.  If not mapped,
472                          * target_alloc will allocate vtarget and map,
473                          * slave_alloc will fill in vdev from vtarget.
474                          */
475                         if (ri->starget) {
476                                 vtarget = ri->starget->hostdata;
477                                 if (vtarget) {
478                                         vtarget->id = pg0->CurrentTargetID;
479                                         vtarget->channel = pg0->CurrentBus;
480                                 }
481                         }
482                         *((struct mptfc_rport_info **)rport->dd_data) = ri;
483                         /* scan will be scheduled once rport becomes a target */
484                         fc_remote_port_rolechg(rport,roles);
485
486                         pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
487                         nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low;
488                         dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
489                                 "mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "
490                                 "rport tid %d, tmo %d\n",
491                                         ioc->name,
492                                         ioc->sh->host_no,
493                                         pg0->PortIdentifier,
494                                         (unsigned long long)nn,
495                                         (unsigned long long)pn,
496                                         pg0->CurrentTargetID,
497                                         ri->rport->scsi_target_id,
498                                         ri->rport->dev_loss_tmo));
499                 } else {
500                         list_del(&ri->list);
501                         kfree(ri);
502                         ri = NULL;
503                 }
504         }
505 }
506
507 /*
508  *      OS entry point to allow for host driver to free allocated memory
509  *      Called if no device present or device being unloaded
510  */
511 static void
512 mptfc_target_destroy(struct scsi_target *starget)
513 {
514         struct fc_rport         *rport;
515         struct mptfc_rport_info *ri;
516
517         rport = starget_to_rport(starget);
518         if (rport) {
519                 ri = *((struct mptfc_rport_info **)rport->dd_data);
520                 if (ri) /* better be! */
521                         ri->starget = NULL;
522         }
523         if (starget->hostdata)
524                 kfree(starget->hostdata);
525         starget->hostdata = NULL;
526 }
527
528 /*
529  *      OS entry point to allow host driver to alloc memory
530  *      for each scsi target. Called once per device the bus scan.
531  *      Return non-zero if allocation fails.
532  */
533 static int
534 mptfc_target_alloc(struct scsi_target *starget)
535 {
536         VirtTarget              *vtarget;
537         struct fc_rport         *rport;
538         struct mptfc_rport_info *ri;
539         int                     rc;
540
541         vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
542         if (!vtarget)
543                 return -ENOMEM;
544         starget->hostdata = vtarget;
545
546         rc = -ENODEV;
547         rport = starget_to_rport(starget);
548         if (rport) {
549                 ri = *((struct mptfc_rport_info **)rport->dd_data);
550                 if (ri) {       /* better be! */
551                         vtarget->id = ri->pg0.CurrentTargetID;
552                         vtarget->channel = ri->pg0.CurrentBus;
553                         ri->starget = starget;
554                         rc = 0;
555                 }
556         }
557         if (rc != 0) {
558                 kfree(vtarget);
559                 starget->hostdata = NULL;
560         }
561
562         return rc;
563 }
564 /*
565  *      mptfc_dump_lun_info
566  *      @ioc
567  *      @rport
568  *      @sdev
569  *
570  */
571 static void
572 mptfc_dump_lun_info(MPT_ADAPTER *ioc, struct fc_rport *rport, struct scsi_device *sdev,
573                 VirtTarget *vtarget)
574 {
575         u64 nn, pn;
576         struct mptfc_rport_info *ri;
577
578         ri = *((struct mptfc_rport_info **)rport->dd_data);
579         pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
580         nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low;
581         dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
582                 "mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
583                 "CurrentTargetID %d, %x %llx %llx\n",
584                 ioc->name,
585                 sdev->host->host_no,
586                 vtarget->num_luns,
587                 sdev->id, ri->pg0.CurrentTargetID,
588                 ri->pg0.PortIdentifier,
589                 (unsigned long long)pn,
590                 (unsigned long long)nn));
591 }
592
593
594 /*
595  *      OS entry point to allow host driver to alloc memory
596  *      for each scsi device. Called once per device the bus scan.
597  *      Return non-zero if allocation fails.
598  *      Init memory once per LUN.
599  */
600 static int
601 mptfc_slave_alloc(struct scsi_device *sdev)
602 {
603         MPT_SCSI_HOST           *hd;
604         VirtTarget              *vtarget;
605         VirtDevice              *vdev;
606         struct scsi_target      *starget;
607         struct fc_rport         *rport;
608
609
610         starget = scsi_target(sdev);
611         rport = starget_to_rport(starget);
612
613         if (!rport || fc_remote_port_chkready(rport))
614                 return -ENXIO;
615
616         hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
617
618         vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
619         if (!vdev) {
620                 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
621                                 hd->ioc->name, sizeof(VirtDevice));
622                 return -ENOMEM;
623         }
624
625
626         sdev->hostdata = vdev;
627         vtarget = starget->hostdata;
628
629         if (vtarget->num_luns == 0) {
630                 vtarget->ioc_id = hd->ioc->id;
631                 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
632         }
633
634         vdev->vtarget = vtarget;
635         vdev->lun = sdev->lun;
636
637         vtarget->num_luns++;
638
639
640         mptfc_dump_lun_info(hd->ioc, rport, sdev, vtarget);
641
642         return 0;
643 }
644
645 static int
646 mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
647 {
648         struct mptfc_rport_info *ri;
649         struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device));
650         int             err;
651         VirtDevice      *vdev = SCpnt->device->hostdata;
652
653         if (!vdev || !vdev->vtarget) {
654                 SCpnt->result = DID_NO_CONNECT << 16;
655                 done(SCpnt);
656                 return 0;
657         }
658
659         err = fc_remote_port_chkready(rport);
660         if (unlikely(err)) {
661                 SCpnt->result = err;
662                 done(SCpnt);
663                 return 0;
664         }
665
666         /* dd_data is null until finished adding target */
667         ri = *((struct mptfc_rport_info **)rport->dd_data);
668         if (unlikely(!ri)) {
669                 SCpnt->result = DID_IMM_RETRY << 16;
670                 done(SCpnt);
671                 return 0;
672         }
673
674         return mptscsih_qcmd(SCpnt,done);
675 }
676
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  */
689 static int
690 mptfc_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                          */
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)) {
768                                 if (count-- > 0) {
769                                         msleep(100);
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
784 static int
785 mptfc_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
827 static int
828 mptfc_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
858 start_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
902 static void
903 mptfc_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
931 static void
932 mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum)
933 {
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;
942
943         /* don't know what to do as only one scsi (fc) host was allocated */
944         if (portnum != 0)
945                 return;
946
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;
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;
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;
1022
1023 }
1024
1025 static void
1026 mptfc_setup_reset(struct work_struct *work)
1027 {
1028         MPT_ADAPTER             *ioc =
1029                 container_of(work, MPT_ADAPTER, fc_setup_reset_work);
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 (ioc, printk(MYIOC_s_DEBUG_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
1051 static void
1052 mptfc_rescan_devices(struct work_struct *work)
1053 {
1054         MPT_ADAPTER             *ioc =
1055                 container_of(work, MPT_ADAPTER, fc_rescan_work);
1056         int                     ii;
1057         u64                     pn;
1058         struct mptfc_rport_info *ri;
1059
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;
1064                 }
1065         }
1066
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         }
1076
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) {
1081
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;
1086
1087                         pn = (u64)ri->pg0.WWPN.High << 32 |
1088                              (u64)ri->pg0.WWPN.Low;
1089                         dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
1090                                 "mptfc_rescan.%d: %llx deleted\n",
1091                                 ioc->name,
1092                                 ioc->sh->host_no,
1093                                 (unsigned long long)pn));
1094                 }
1095         }
1096 }
1097
1098 static int
1099 mptfc_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;
1105         int                      ii;
1106         int                      numSGE = 0;
1107         int                      scale;
1108         int                      ioc_cap;
1109         int                     error=0;
1110         int                     r;
1111
1112         if ((r = mpt_attach(pdev,id)) != 0)
1113                 return r;
1114
1115         ioc = pci_get_drvdata(pdev);
1116         ioc->DoneCtx = mptfcDoneCtx;
1117         ioc->TaskCtx = mptfcTaskCtx;
1118         ioc->InternalCtx = mptfcInternalCtx;
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);
1126                 error = -ENODEV;
1127                 goto out_mptfc_probe;
1128         }
1129
1130         if (!ioc->active) {
1131                 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
1132                   ioc->name);
1133                 error = -ENODEV;
1134                 goto out_mptfc_probe;
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);
1150                 return 0;
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);
1159                 error = -1;
1160                 goto out_mptfc_probe;
1161         }
1162
1163         spin_lock_init(&ioc->fc_rescan_work_lock);
1164         INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices);
1165         INIT_WORK(&ioc->fc_setup_reset_work, mptfc_setup_reset);
1166
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
1180         sh->max_id = ioc->pfacts->MaxDevices;
1181         sh->max_lun = max_lun;
1182
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(ioc, printk(MYIOC_s_DEBUG_FMT
1214                   "Resetting sg_tablesize to %d from %d\n",
1215                   ioc->name, numSGE, sh->sg_tablesize));
1216                 sh->sg_tablesize = numSGE;
1217         }
1218
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          */
1227         hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
1228         if (!hd->ScsiLookup) {
1229                 error = -ENOMEM;
1230                 goto out_mptfc_probe;
1231         }
1232
1233         dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
1234                  ioc->name, hd->ScsiLookup));
1235
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
1258         init_waitqueue_head(&hd->scandv_waitq);
1259         hd->scandv_wait_done = 0;
1260         hd->last_queue_full = 0;
1261
1262         sh->transportt = mptfc_transport_template;
1263         error = scsi_add_host (sh, &ioc->pcidev->dev);
1264         if(error) {
1265                 dprintk(ioc, printk(KERN_ERR MYNAM
1266                   "scsi_add_host failed\n"));
1267                 goto out_mptfc_probe;
1268         }
1269
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
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         }
1286         mptfc_SetFcPortPage1_defaults(ioc);
1287
1288         /*
1289          * scan for rports -
1290          *      by doing it via the workqueue, some locking is eliminated
1291          */
1292
1293         queue_work(ioc->fc_rescan_work_q, &ioc->fc_rescan_work);
1294         flush_workqueue(ioc->fc_rescan_work_q);
1295
1296         return 0;
1297
1298 out_mptfc_probe:
1299
1300         mptscsih_remove(pdev);
1301         return error;
1302 }
1303
1304 static struct pci_driver mptfc_driver = {
1305         .name           = "mptfc",
1306         .id_table       = mptfc_pci_table,
1307         .probe          = mptfc_probe,
1308         .remove         = __devexit_p(mptfc_remove),
1309         .shutdown       = mptscsih_shutdown,
1310 #ifdef CONFIG_PM
1311         .suspend        = mptscsih_suspend,
1312         .resume         = mptscsih_resume,
1313 #endif
1314 };
1315
1316 static int
1317 mptfc_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(ioc, printk(MYIOC_s_DEBUG_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) {
1335                         queue_work(ioc->fc_rescan_work_q,
1336                                    &ioc->fc_rescan_work);
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
1347 static int
1348 mptfc_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(ioc, printk(MYIOC_s_DEBUG_FMT
1359                 ": IOC %s_reset routed to FC host driver!\n",ioc->name,
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) {
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);
1370         }
1371
1372         else if (reset_phase == MPT_IOC_PRE_RESET) {
1373         }
1374
1375         else {  /* MPT_IOC_POST_RESET */
1376                 mptfc_SetFcPortPage1_defaults(ioc);
1377                 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1378                 if (ioc->fc_rescan_work_q) {
1379                         queue_work(ioc->fc_rescan_work_q,
1380                                    &ioc->fc_rescan_work);
1381                 }
1382                 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1383         }
1384         return 1;
1385 }
1386
1387 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1388 /**
1389  *      mptfc_init - Register MPT adapter(s) as SCSI host(s) with SCSI mid-layer.
1390  *
1391  *      Returns 0 for success, non-zero for failure.
1392  */
1393 static int __init
1394 mptfc_init(void)
1395 {
1396         int error;
1397
1398         show_mptmod_ver(my_NAME, my_VERSION);
1399
1400         /* sanity check module parameters */
1401         if (mptfc_dev_loss_tmo <= 0)
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
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
1414         mpt_event_register(mptfcDoneCtx, mptfc_event_process);
1415         mpt_reset_register(mptfcDoneCtx, mptfc_ioc_reset);
1416
1417         error = pci_register_driver(&mptfc_driver);
1418         if (error)
1419                 fc_release_transport(mptfc_transport_template);
1420
1421         return error;
1422 }
1423
1424 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1425 /**
1426  *      mptfc_remove - Remove fc infrastructure for devices
1427  *      @pdev: Pointer to pci_dev structure
1428  *
1429  */
1430 static void __devexit
1431 mptfc_remove(struct pci_dev *pdev)
1432 {
1433         MPT_ADAPTER             *ioc = pci_get_drvdata(pdev);
1434         struct mptfc_rport_info *p, *n;
1435         struct workqueue_struct *work_q;
1436         unsigned long           flags;
1437         int                     ii;
1438
1439         /* destroy workqueue */
1440         if ((work_q=ioc->fc_rescan_work_q)) {
1441                 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1442                 ioc->fc_rescan_work_q = NULL;
1443                 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1444                 destroy_workqueue(work_q);
1445         }
1446
1447         fc_remove_host(ioc->sh);
1448
1449         list_for_each_entry_safe(p, n, &ioc->fc_rports, list) {
1450                 list_del(&p->list);
1451                 kfree(p);
1452         }
1453
1454         for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) {
1455                 if (ioc->fc_data.fc_port_page1[ii].data) {
1456                         pci_free_consistent(ioc->pcidev,
1457                                 ioc->fc_data.fc_port_page1[ii].pg_sz,
1458                                 (u8 *) ioc->fc_data.fc_port_page1[ii].data,
1459                                 ioc->fc_data.fc_port_page1[ii].dma);
1460                         ioc->fc_data.fc_port_page1[ii].data = NULL;
1461                 }
1462         }
1463
1464         mptscsih_remove(pdev);
1465 }
1466
1467 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1468 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1469 /**
1470  *      mptfc_exit - Unregisters MPT adapter(s)
1471  *
1472  */
1473 static void __exit
1474 mptfc_exit(void)
1475 {
1476         pci_unregister_driver(&mptfc_driver);
1477         fc_release_transport(mptfc_transport_template);
1478
1479         mpt_reset_deregister(mptfcDoneCtx);
1480         mpt_event_deregister(mptfcDoneCtx);
1481
1482         mpt_deregister(mptfcInternalCtx);
1483         mpt_deregister(mptfcTaskCtx);
1484         mpt_deregister(mptfcDoneCtx);
1485 }
1486
1487 module_init(mptfc_init);
1488 module_exit(mptfc_exit);