Version:  2.0.40 2.2.26 2.4.37 2.6.39 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15

Linux/drivers/message/fusion/mptfc.c

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

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us