Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  *  linux/drivers/message/fusion/mptfc.c
0003  *      For use with LSI PCI chip/adapter(s)
0004  *      running LSI Fusion MPT (Message Passing Technology) firmware.
0005  *
0006  *  Copyright (c) 1999-2008 LSI Corporation
0007  *  (mailto:DL-MPTFusionLinux@lsi.com)
0008  *
0009  */
0010 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
0011 /*
0012     This program is free software; you can redistribute it and/or modify
0013     it under the terms of the GNU General Public License as published by
0014     the Free Software Foundation; version 2 of the License.
0015 
0016     This program is distributed in the hope that it will be useful,
0017     but WITHOUT ANY WARRANTY; without even the implied warranty of
0018     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0019     GNU General Public License for more details.
0020 
0021     NO WARRANTY
0022     THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
0023     CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
0024     LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
0025     MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
0026     solely responsible for determining the appropriateness of using and
0027     distributing the Program and assumes all risks associated with its
0028     exercise of rights under this Agreement, including but not limited to
0029     the risks and costs of program errors, damage to or loss of data,
0030     programs or equipment, and unavailability or interruption of operations.
0031 
0032     DISCLAIMER OF LIABILITY
0033     NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
0034     DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
0035     DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
0036     ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
0037     TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
0038     USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
0039     HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
0040 
0041     You should have received a copy of the GNU General Public License
0042     along with this program; if not, write to the Free Software
0043     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0044 */
0045 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
0046 #include <linux/module.h>
0047 #include <linux/kernel.h>
0048 #include <linux/init.h>
0049 #include <linux/errno.h>
0050 #include <linux/kdev_t.h>
0051 #include <linux/blkdev.h>
0052 #include <linux/delay.h>    /* for mdelay */
0053 #include <linux/interrupt.h>
0054 #include <linux/reboot.h>   /* notifier code */
0055 #include <linux/workqueue.h>
0056 #include <linux/sort.h>
0057 #include <linux/slab.h>
0058 
0059 #include <scsi/scsi.h>
0060 #include <scsi/scsi_cmnd.h>
0061 #include <scsi/scsi_device.h>
0062 #include <scsi/scsi_host.h>
0063 #include <scsi/scsi_tcq.h>
0064 #include <scsi/scsi_transport_fc.h>
0065 
0066 #include "mptbase.h"
0067 #include "mptscsih.h"
0068 
0069 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
0070 #define my_NAME     "Fusion MPT FC Host driver"
0071 #define my_VERSION  MPT_LINUX_VERSION_COMMON
0072 #define MYNAM       "mptfc"
0073 
0074 MODULE_AUTHOR(MODULEAUTHOR);
0075 MODULE_DESCRIPTION(my_NAME);
0076 MODULE_LICENSE("GPL");
0077 MODULE_VERSION(my_VERSION);
0078 
0079 /* Command line args */
0080 #define MPTFC_DEV_LOSS_TMO (60)
0081 static int mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO; /* reasonable default */
0082 module_param(mptfc_dev_loss_tmo, int, 0);
0083 MODULE_PARM_DESC(mptfc_dev_loss_tmo, " Initial time the driver programs the "
0084                          " transport to wait for an rport to "
0085                      " return following a device loss event."
0086                      "  Default=60.");
0087 
0088 /* scsi-mid layer global parmeter is max_report_luns, which is 511 */
0089 #define MPTFC_MAX_LUN (16895)
0090 static int max_lun = MPTFC_MAX_LUN;
0091 module_param(max_lun, int, 0);
0092 MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
0093 
0094 static u8   mptfcDoneCtx = MPT_MAX_PROTOCOL_DRIVERS;
0095 static u8   mptfcTaskCtx = MPT_MAX_PROTOCOL_DRIVERS;
0096 static u8   mptfcInternalCtx = MPT_MAX_PROTOCOL_DRIVERS;
0097 
0098 static int mptfc_target_alloc(struct scsi_target *starget);
0099 static int mptfc_slave_alloc(struct scsi_device *sdev);
0100 static int mptfc_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *SCpnt);
0101 static void mptfc_target_destroy(struct scsi_target *starget);
0102 static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout);
0103 static void mptfc_remove(struct pci_dev *pdev);
0104 static int mptfc_abort(struct scsi_cmnd *SCpnt);
0105 static int mptfc_dev_reset(struct scsi_cmnd *SCpnt);
0106 static int mptfc_bus_reset(struct scsi_cmnd *SCpnt);
0107 
0108 static struct scsi_host_template mptfc_driver_template = {
0109     .module             = THIS_MODULE,
0110     .proc_name          = "mptfc",
0111     .show_info          = mptscsih_show_info,
0112     .name               = "MPT FC Host",
0113     .info               = mptscsih_info,
0114     .queuecommand           = mptfc_qcmd,
0115     .target_alloc           = mptfc_target_alloc,
0116     .slave_alloc            = mptfc_slave_alloc,
0117     .slave_configure        = mptscsih_slave_configure,
0118     .target_destroy         = mptfc_target_destroy,
0119     .slave_destroy          = mptscsih_slave_destroy,
0120     .change_queue_depth         = mptscsih_change_queue_depth,
0121     .eh_timed_out           = fc_eh_timed_out,
0122     .eh_abort_handler       = mptfc_abort,
0123     .eh_device_reset_handler    = mptfc_dev_reset,
0124     .eh_bus_reset_handler       = mptfc_bus_reset,
0125     .eh_host_reset_handler      = mptscsih_host_reset,
0126     .bios_param         = mptscsih_bios_param,
0127     .can_queue          = MPT_FC_CAN_QUEUE,
0128     .this_id            = -1,
0129     .sg_tablesize           = MPT_SCSI_SG_DEPTH,
0130     .max_sectors            = 8192,
0131     .cmd_per_lun            = 7,
0132     .shost_groups           = mptscsih_host_attr_groups,
0133 };
0134 
0135 /****************************************************************************
0136  * Supported hardware
0137  */
0138 
0139 static struct pci_device_id mptfc_pci_table[] = {
0140     { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC909,
0141         PCI_ANY_ID, PCI_ANY_ID },
0142     { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC919,
0143         PCI_ANY_ID, PCI_ANY_ID },
0144     { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC929,
0145         PCI_ANY_ID, PCI_ANY_ID },
0146     { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC919X,
0147         PCI_ANY_ID, PCI_ANY_ID },
0148     { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC929X,
0149         PCI_ANY_ID, PCI_ANY_ID },
0150     { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC939X,
0151         PCI_ANY_ID, PCI_ANY_ID },
0152     { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC949X,
0153         PCI_ANY_ID, PCI_ANY_ID },
0154     { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC949E,
0155         PCI_ANY_ID, PCI_ANY_ID },
0156     { PCI_VENDOR_ID_BROCADE, MPI_MANUFACTPAGE_DEVICEID_FC949E,
0157         PCI_ANY_ID, PCI_ANY_ID },
0158     {0} /* Terminating entry */
0159 };
0160 MODULE_DEVICE_TABLE(pci, mptfc_pci_table);
0161 
0162 static struct scsi_transport_template *mptfc_transport_template = NULL;
0163 
0164 static struct fc_function_template mptfc_transport_functions = {
0165     .dd_fcrport_size = 8,
0166     .show_host_node_name = 1,
0167     .show_host_port_name = 1,
0168     .show_host_supported_classes = 1,
0169     .show_host_port_id = 1,
0170     .show_rport_supported_classes = 1,
0171     .show_starget_node_name = 1,
0172     .show_starget_port_name = 1,
0173     .show_starget_port_id = 1,
0174     .set_rport_dev_loss_tmo = mptfc_set_rport_loss_tmo,
0175     .show_rport_dev_loss_tmo = 1,
0176     .show_host_supported_speeds = 1,
0177     .show_host_maxframe_size = 1,
0178     .show_host_speed = 1,
0179     .show_host_fabric_name = 1,
0180     .show_host_port_type = 1,
0181     .show_host_port_state = 1,
0182     .show_host_symbolic_name = 1,
0183 };
0184 
0185 static int
0186 mptfc_block_error_handler(struct scsi_cmnd *SCpnt,
0187               int (*func)(struct scsi_cmnd *SCpnt),
0188               const char *caller)
0189 {
0190     MPT_SCSI_HOST       *hd;
0191     struct scsi_device  *sdev = SCpnt->device;
0192     struct Scsi_Host    *shost = sdev->host;
0193     struct fc_rport     *rport = starget_to_rport(scsi_target(sdev));
0194     unsigned long       flags;
0195     int         ready;
0196     MPT_ADAPTER         *ioc;
0197     int         loops = 40; /* seconds */
0198 
0199     hd = shost_priv(SCpnt->device->host);
0200     ioc = hd->ioc;
0201     spin_lock_irqsave(shost->host_lock, flags);
0202     while ((ready = fc_remote_port_chkready(rport) >> 16) == DID_IMM_RETRY
0203      || (loops > 0 && ioc->active == 0)) {
0204         spin_unlock_irqrestore(shost->host_lock, flags);
0205         dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
0206             "mptfc_block_error_handler.%d: %d:%llu, port status is "
0207             "%x, active flag %d, deferring %s recovery.\n",
0208             ioc->name, ioc->sh->host_no,
0209             SCpnt->device->id, SCpnt->device->lun,
0210             ready, ioc->active, caller));
0211         msleep(1000);
0212         spin_lock_irqsave(shost->host_lock, flags);
0213         loops --;
0214     }
0215     spin_unlock_irqrestore(shost->host_lock, flags);
0216 
0217     if (ready == DID_NO_CONNECT || !SCpnt->device->hostdata
0218      || ioc->active == 0) {
0219         dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
0220             "%s.%d: %d:%llu, failing recovery, "
0221             "port state %x, active %d, vdevice %p.\n", caller,
0222             ioc->name, ioc->sh->host_no,
0223             SCpnt->device->id, SCpnt->device->lun, ready,
0224             ioc->active, SCpnt->device->hostdata));
0225         return FAILED;
0226     }
0227     dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
0228         "%s.%d: %d:%llu, executing recovery.\n", caller,
0229         ioc->name, ioc->sh->host_no,
0230         SCpnt->device->id, SCpnt->device->lun));
0231     return (*func)(SCpnt);
0232 }
0233 
0234 static int
0235 mptfc_abort(struct scsi_cmnd *SCpnt)
0236 {
0237     return
0238         mptfc_block_error_handler(SCpnt, mptscsih_abort, __func__);
0239 }
0240 
0241 static int
0242 mptfc_dev_reset(struct scsi_cmnd *SCpnt)
0243 {
0244     return
0245         mptfc_block_error_handler(SCpnt, mptscsih_dev_reset, __func__);
0246 }
0247 
0248 static int
0249 mptfc_bus_reset(struct scsi_cmnd *SCpnt)
0250 {
0251     return
0252         mptfc_block_error_handler(SCpnt, mptscsih_bus_reset, __func__);
0253 }
0254 
0255 static void
0256 mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
0257 {
0258     if (timeout > 0)
0259         rport->dev_loss_tmo = timeout;
0260     else
0261         rport->dev_loss_tmo = mptfc_dev_loss_tmo;
0262 }
0263 
0264 static int
0265 mptfc_FcDevPage0_cmp_func(const void *a, const void *b)
0266 {
0267     FCDevicePage0_t **aa = (FCDevicePage0_t **)a;
0268     FCDevicePage0_t **bb = (FCDevicePage0_t **)b;
0269 
0270     if ((*aa)->CurrentBus == (*bb)->CurrentBus) {
0271         if ((*aa)->CurrentTargetID == (*bb)->CurrentTargetID)
0272             return 0;
0273         if ((*aa)->CurrentTargetID < (*bb)->CurrentTargetID)
0274             return -1;
0275         return 1;
0276     }
0277     if ((*aa)->CurrentBus < (*bb)->CurrentBus)
0278         return -1;
0279     return 1;
0280 }
0281 
0282 static int
0283 mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, int ioc_port,
0284     void(*func)(MPT_ADAPTER *ioc,int channel, FCDevicePage0_t *arg))
0285 {
0286     ConfigPageHeader_t   hdr;
0287     CONFIGPARMS      cfg;
0288     FCDevicePage0_t     *ppage0_alloc, *fc;
0289     dma_addr_t       page0_dma;
0290     int          data_sz;
0291     int          ii;
0292 
0293     FCDevicePage0_t     *p0_array=NULL, *p_p0;
0294     FCDevicePage0_t     **pp0_array=NULL, **p_pp0;
0295 
0296     int          rc = -ENOMEM;
0297     U32          port_id = 0xffffff;
0298     int          num_targ = 0;
0299     int          max_bus = ioc->facts.MaxBuses;
0300     int          max_targ;
0301 
0302     max_targ = (ioc->facts.MaxDevices == 0) ? 256 : ioc->facts.MaxDevices;
0303 
0304     data_sz = sizeof(FCDevicePage0_t) * max_bus * max_targ;
0305     p_p0 = p0_array =  kzalloc(data_sz, GFP_KERNEL);
0306     if (!p0_array)
0307         goto out;
0308 
0309     data_sz = sizeof(FCDevicePage0_t *) * max_bus * max_targ;
0310     p_pp0 = pp0_array = kzalloc(data_sz, GFP_KERNEL);
0311     if (!pp0_array)
0312         goto out;
0313 
0314     do {
0315         /* Get FC Device Page 0 header */
0316         hdr.PageVersion = 0;
0317         hdr.PageLength = 0;
0318         hdr.PageNumber = 0;
0319         hdr.PageType = MPI_CONFIG_PAGETYPE_FC_DEVICE;
0320         cfg.cfghdr.hdr = &hdr;
0321         cfg.physAddr = -1;
0322         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
0323         cfg.dir = 0;
0324         cfg.pageAddr = port_id;
0325         cfg.timeout = 0;
0326 
0327         if ((rc = mpt_config(ioc, &cfg)) != 0)
0328             break;
0329 
0330         if (hdr.PageLength <= 0)
0331             break;
0332 
0333         data_sz = hdr.PageLength * 4;
0334         ppage0_alloc = dma_alloc_coherent(&ioc->pcidev->dev, data_sz,
0335                           &page0_dma, GFP_KERNEL);
0336         rc = -ENOMEM;
0337         if (!ppage0_alloc)
0338             break;
0339 
0340         cfg.physAddr = page0_dma;
0341         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
0342 
0343         if ((rc = mpt_config(ioc, &cfg)) == 0) {
0344             ppage0_alloc->PortIdentifier =
0345                 le32_to_cpu(ppage0_alloc->PortIdentifier);
0346 
0347             ppage0_alloc->WWNN.Low =
0348                 le32_to_cpu(ppage0_alloc->WWNN.Low);
0349 
0350             ppage0_alloc->WWNN.High =
0351                 le32_to_cpu(ppage0_alloc->WWNN.High);
0352 
0353             ppage0_alloc->WWPN.Low =
0354                 le32_to_cpu(ppage0_alloc->WWPN.Low);
0355 
0356             ppage0_alloc->WWPN.High =
0357                 le32_to_cpu(ppage0_alloc->WWPN.High);
0358 
0359             ppage0_alloc->BBCredit =
0360                 le16_to_cpu(ppage0_alloc->BBCredit);
0361 
0362             ppage0_alloc->MaxRxFrameSize =
0363                 le16_to_cpu(ppage0_alloc->MaxRxFrameSize);
0364 
0365             port_id = ppage0_alloc->PortIdentifier;
0366             num_targ++;
0367             *p_p0 = *ppage0_alloc;  /* save data */
0368             *p_pp0++ = p_p0++;  /* save addr */
0369         }
0370         dma_free_coherent(&ioc->pcidev->dev, data_sz,
0371                   ppage0_alloc, page0_dma);
0372         if (rc != 0)
0373             break;
0374 
0375     } while (port_id <= 0xff0000);
0376 
0377     if (num_targ) {
0378         /* sort array */
0379         if (num_targ > 1)
0380             sort (pp0_array, num_targ, sizeof(FCDevicePage0_t *),
0381                 mptfc_FcDevPage0_cmp_func, NULL);
0382         /* call caller's func for each targ */
0383         for (ii = 0; ii < num_targ;  ii++) {
0384             fc = *(pp0_array+ii);
0385             func(ioc, ioc_port, fc);
0386         }
0387     }
0388 
0389  out:
0390     kfree(pp0_array);
0391     kfree(p0_array);
0392     return rc;
0393 }
0394 
0395 static int
0396 mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid)
0397 {
0398     /* not currently usable */
0399     if (pg0->Flags & (MPI_FC_DEVICE_PAGE0_FLAGS_PLOGI_INVALID |
0400               MPI_FC_DEVICE_PAGE0_FLAGS_PRLI_INVALID))
0401         return -1;
0402 
0403     if (!(pg0->Flags & MPI_FC_DEVICE_PAGE0_FLAGS_TARGETID_BUS_VALID))
0404         return -1;
0405 
0406     if (!(pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_TARGET))
0407         return -1;
0408 
0409     /*
0410      * board data structure already normalized to platform endianness
0411      * shifted to avoid unaligned access on 64 bit architecture
0412      */
0413     rid->node_name = ((u64)pg0->WWNN.High) << 32 | (u64)pg0->WWNN.Low;
0414     rid->port_name = ((u64)pg0->WWPN.High) << 32 | (u64)pg0->WWPN.Low;
0415     rid->port_id =   pg0->PortIdentifier;
0416     rid->roles = FC_RPORT_ROLE_UNKNOWN;
0417 
0418     return 0;
0419 }
0420 
0421 static void
0422 mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
0423 {
0424     struct fc_rport_identifiers rport_ids;
0425     struct fc_rport     *rport;
0426     struct mptfc_rport_info *ri;
0427     int         new_ri = 1;
0428     u64         pn, nn;
0429     VirtTarget      *vtarget;
0430     u32         roles = FC_RPORT_ROLE_UNKNOWN;
0431 
0432     if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0)
0433         return;
0434 
0435     roles |= FC_RPORT_ROLE_FCP_TARGET;
0436     if (pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR)
0437         roles |= FC_RPORT_ROLE_FCP_INITIATOR;
0438 
0439     /* scan list looking for a match */
0440     list_for_each_entry(ri, &ioc->fc_rports, list) {
0441         pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
0442         if (pn == rport_ids.port_name) {    /* match */
0443             list_move_tail(&ri->list, &ioc->fc_rports);
0444             new_ri = 0;
0445             break;
0446         }
0447     }
0448     if (new_ri) {   /* allocate one */
0449         ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL);
0450         if (!ri)
0451             return;
0452         list_add_tail(&ri->list, &ioc->fc_rports);
0453     }
0454 
0455     ri->pg0 = *pg0; /* add/update pg0 data */
0456     ri->flags &= ~MPT_RPORT_INFO_FLAGS_MISSING;
0457 
0458     /* MPT_RPORT_INFO_FLAGS_REGISTERED - rport not previously deleted */
0459     if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) {
0460         ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED;
0461         rport = fc_remote_port_add(ioc->sh, channel, &rport_ids);
0462         if (rport) {
0463             ri->rport = rport;
0464             if (new_ri) /* may have been reset by user */
0465                 rport->dev_loss_tmo = mptfc_dev_loss_tmo;
0466             /*
0467              * if already mapped, remap here.  If not mapped,
0468              * target_alloc will allocate vtarget and map,
0469              * slave_alloc will fill in vdevice from vtarget.
0470              */
0471             if (ri->starget) {
0472                 vtarget = ri->starget->hostdata;
0473                 if (vtarget) {
0474                     vtarget->id = pg0->CurrentTargetID;
0475                     vtarget->channel = pg0->CurrentBus;
0476                     vtarget->deleted = 0;
0477                 }
0478             }
0479             *((struct mptfc_rport_info **)rport->dd_data) = ri;
0480             /* scan will be scheduled once rport becomes a target */
0481             fc_remote_port_rolechg(rport,roles);
0482 
0483             pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
0484             nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low;
0485             dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
0486                 "mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "
0487                 "rport tid %d, tmo %d\n",
0488                     ioc->name,
0489                     ioc->sh->host_no,
0490                     pg0->PortIdentifier,
0491                     (unsigned long long)nn,
0492                     (unsigned long long)pn,
0493                     pg0->CurrentTargetID,
0494                     ri->rport->scsi_target_id,
0495                     ri->rport->dev_loss_tmo));
0496         } else {
0497             list_del(&ri->list);
0498             kfree(ri);
0499             ri = NULL;
0500         }
0501     }
0502 }
0503 
0504 /*
0505  *  OS entry point to allow for host driver to free allocated memory
0506  *  Called if no device present or device being unloaded
0507  */
0508 static void
0509 mptfc_target_destroy(struct scsi_target *starget)
0510 {
0511     struct fc_rport     *rport;
0512     struct mptfc_rport_info *ri;
0513 
0514     rport = starget_to_rport(starget);
0515     if (rport) {
0516         ri = *((struct mptfc_rport_info **)rport->dd_data);
0517         if (ri) /* better be! */
0518             ri->starget = NULL;
0519     }
0520     kfree(starget->hostdata);
0521     starget->hostdata = NULL;
0522 }
0523 
0524 /*
0525  *  OS entry point to allow host driver to alloc memory
0526  *  for each scsi target. Called once per device the bus scan.
0527  *  Return non-zero if allocation fails.
0528  */
0529 static int
0530 mptfc_target_alloc(struct scsi_target *starget)
0531 {
0532     VirtTarget      *vtarget;
0533     struct fc_rport     *rport;
0534     struct mptfc_rport_info *ri;
0535     int         rc;
0536 
0537     vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
0538     if (!vtarget)
0539         return -ENOMEM;
0540     starget->hostdata = vtarget;
0541 
0542     rc = -ENODEV;
0543     rport = starget_to_rport(starget);
0544     if (rport) {
0545         ri = *((struct mptfc_rport_info **)rport->dd_data);
0546         if (ri) {   /* better be! */
0547             vtarget->id = ri->pg0.CurrentTargetID;
0548             vtarget->channel = ri->pg0.CurrentBus;
0549             ri->starget = starget;
0550             rc = 0;
0551         }
0552     }
0553     if (rc != 0) {
0554         kfree(vtarget);
0555         starget->hostdata = NULL;
0556     }
0557 
0558     return rc;
0559 }
0560 /*
0561  *  mptfc_dump_lun_info
0562  *  @ioc
0563  *  @rport
0564  *  @sdev
0565  *
0566  */
0567 static void
0568 mptfc_dump_lun_info(MPT_ADAPTER *ioc, struct fc_rport *rport, struct scsi_device *sdev,
0569         VirtTarget *vtarget)
0570 {
0571     u64 nn, pn;
0572     struct mptfc_rport_info *ri;
0573 
0574     ri = *((struct mptfc_rport_info **)rport->dd_data);
0575     pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
0576     nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low;
0577     dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
0578         "mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
0579         "CurrentTargetID %d, %x %llx %llx\n",
0580         ioc->name,
0581         sdev->host->host_no,
0582         vtarget->num_luns,
0583         sdev->id, ri->pg0.CurrentTargetID,
0584         ri->pg0.PortIdentifier,
0585         (unsigned long long)pn,
0586         (unsigned long long)nn));
0587 }
0588 
0589 
0590 /*
0591  *  OS entry point to allow host driver to alloc memory
0592  *  for each scsi device. Called once per device the bus scan.
0593  *  Return non-zero if allocation fails.
0594  *  Init memory once per LUN.
0595  */
0596 static int
0597 mptfc_slave_alloc(struct scsi_device *sdev)
0598 {
0599     MPT_SCSI_HOST       *hd;
0600     VirtTarget      *vtarget;
0601     VirtDevice      *vdevice;
0602     struct scsi_target  *starget;
0603     struct fc_rport     *rport;
0604     MPT_ADAPTER         *ioc;
0605 
0606     starget = scsi_target(sdev);
0607     rport = starget_to_rport(starget);
0608 
0609     if (!rport || fc_remote_port_chkready(rport))
0610         return -ENXIO;
0611 
0612     hd = shost_priv(sdev->host);
0613     ioc = hd->ioc;
0614 
0615     vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
0616     if (!vdevice) {
0617         printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
0618                 ioc->name, sizeof(VirtDevice));
0619         return -ENOMEM;
0620     }
0621 
0622 
0623     sdev->hostdata = vdevice;
0624     vtarget = starget->hostdata;
0625 
0626     if (vtarget->num_luns == 0) {
0627         vtarget->ioc_id = ioc->id;
0628         vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
0629     }
0630 
0631     vdevice->vtarget = vtarget;
0632     vdevice->lun = sdev->lun;
0633 
0634     vtarget->num_luns++;
0635 
0636 
0637     mptfc_dump_lun_info(ioc, rport, sdev, vtarget);
0638 
0639     return 0;
0640 }
0641 
0642 static int
0643 mptfc_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *SCpnt)
0644 {
0645     struct mptfc_rport_info *ri;
0646     struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device));
0647     int     err;
0648     VirtDevice  *vdevice = SCpnt->device->hostdata;
0649 
0650     if (!vdevice || !vdevice->vtarget) {
0651         SCpnt->result = DID_NO_CONNECT << 16;
0652         scsi_done(SCpnt);
0653         return 0;
0654     }
0655 
0656     err = fc_remote_port_chkready(rport);
0657     if (unlikely(err)) {
0658         SCpnt->result = err;
0659         scsi_done(SCpnt);
0660         return 0;
0661     }
0662 
0663     /* dd_data is null until finished adding target */
0664     ri = *((struct mptfc_rport_info **)rport->dd_data);
0665     if (unlikely(!ri)) {
0666         SCpnt->result = DID_IMM_RETRY << 16;
0667         scsi_done(SCpnt);
0668         return 0;
0669     }
0670 
0671     return mptscsih_qcmd(SCpnt);
0672 }
0673 
0674 /*
0675  *  mptfc_display_port_link_speed - displaying link speed
0676  *  @ioc: Pointer to MPT_ADAPTER structure
0677  *  @portnum: IOC Port number
0678  *  @pp0dest: port page0 data payload
0679  *
0680  */
0681 static void
0682 mptfc_display_port_link_speed(MPT_ADAPTER *ioc, int portnum, FCPortPage0_t *pp0dest)
0683 {
0684     u8  old_speed, new_speed, state;
0685     char    *old, *new;
0686 
0687     if (portnum >= 2)
0688         return;
0689 
0690     old_speed = ioc->fc_link_speed[portnum];
0691     new_speed = pp0dest->CurrentSpeed;
0692     state = pp0dest->PortState;
0693 
0694     if (state != MPI_FCPORTPAGE0_PORTSTATE_OFFLINE &&
0695         new_speed != MPI_FCPORTPAGE0_CURRENT_SPEED_UNKNOWN) {
0696 
0697         old = old_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT ? "1 Gbps" :
0698                old_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT ? "2 Gbps" :
0699             old_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT ? "4 Gbps" :
0700              "Unknown";
0701         new = new_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT ? "1 Gbps" :
0702                new_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT ? "2 Gbps" :
0703             new_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT ? "4 Gbps" :
0704              "Unknown";
0705         if (old_speed == 0)
0706             printk(MYIOC_s_NOTE_FMT
0707                 "FC Link Established, Speed = %s\n",
0708                 ioc->name, new);
0709         else if (old_speed != new_speed)
0710             printk(MYIOC_s_WARN_FMT
0711                 "FC Link Speed Change, Old Speed = %s, New Speed = %s\n",
0712                 ioc->name, old, new);
0713 
0714         ioc->fc_link_speed[portnum] = new_speed;
0715     }
0716 }
0717 
0718 /*
0719  *  mptfc_GetFcPortPage0 - Fetch FCPort config Page0.
0720  *  @ioc: Pointer to MPT_ADAPTER structure
0721  *  @portnum: IOC Port number
0722  *
0723  *  Return: 0 for success
0724  *  -ENOMEM if no memory available
0725  *      -EPERM if not allowed due to ISR context
0726  *      -EAGAIN if no msg frames currently available
0727  *      -EFAULT for non-successful reply or no reply (timeout)
0728  *      -EINVAL portnum arg out of range (hardwired to two elements)
0729  */
0730 static int
0731 mptfc_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
0732 {
0733     ConfigPageHeader_t   hdr;
0734     CONFIGPARMS      cfg;
0735     FCPortPage0_t       *ppage0_alloc;
0736     FCPortPage0_t       *pp0dest;
0737     dma_addr_t       page0_dma;
0738     int          data_sz;
0739     int          copy_sz;
0740     int          rc;
0741     int          count = 400;
0742 
0743     if (portnum > 1)
0744         return -EINVAL;
0745 
0746     /* Get FCPort Page 0 header */
0747     hdr.PageVersion = 0;
0748     hdr.PageLength = 0;
0749     hdr.PageNumber = 0;
0750     hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
0751     cfg.cfghdr.hdr = &hdr;
0752     cfg.physAddr = -1;
0753     cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
0754     cfg.dir = 0;
0755     cfg.pageAddr = portnum;
0756     cfg.timeout = 0;
0757 
0758     if ((rc = mpt_config(ioc, &cfg)) != 0)
0759         return rc;
0760 
0761     if (hdr.PageLength == 0)
0762         return 0;
0763 
0764     data_sz = hdr.PageLength * 4;
0765     rc = -ENOMEM;
0766     ppage0_alloc = dma_alloc_coherent(&ioc->pcidev->dev, data_sz,
0767                       &page0_dma, GFP_KERNEL);
0768     if (ppage0_alloc) {
0769 
0770  try_again:
0771         memset((u8 *)ppage0_alloc, 0, data_sz);
0772         cfg.physAddr = page0_dma;
0773         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
0774 
0775         if ((rc = mpt_config(ioc, &cfg)) == 0) {
0776             /* save the data */
0777             pp0dest = &ioc->fc_port_page0[portnum];
0778             copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz);
0779             memcpy(pp0dest, ppage0_alloc, copy_sz);
0780 
0781             /*
0782              *  Normalize endianness of structure data,
0783              *  by byte-swapping all > 1 byte fields!
0784              */
0785             pp0dest->Flags = le32_to_cpu(pp0dest->Flags);
0786             pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier);
0787             pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low);
0788             pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High);
0789             pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low);
0790             pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High);
0791             pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass);
0792             pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds);
0793             pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed);
0794             pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize);
0795             pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low);
0796             pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High);
0797             pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low);
0798             pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High);
0799             pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
0800             pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
0801 
0802             /*
0803              * if still doing discovery,
0804              * hang loose a while until finished
0805              */
0806             if ((pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) ||
0807                 (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_ONLINE &&
0808                  (pp0dest->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_TYPE_MASK)
0809                   == MPI_FCPORTPAGE0_FLAGS_ATTACH_NO_INIT)) {
0810                 if (count-- > 0) {
0811                     msleep(100);
0812                     goto try_again;
0813                 }
0814                 printk(MYIOC_s_INFO_FMT "Firmware discovery not"
0815                             " complete.\n",
0816                         ioc->name);
0817             }
0818             mptfc_display_port_link_speed(ioc, portnum, pp0dest);
0819         }
0820 
0821         dma_free_coherent(&ioc->pcidev->dev, data_sz, ppage0_alloc,
0822                   page0_dma);
0823     }
0824 
0825     return rc;
0826 }
0827 
0828 static int
0829 mptfc_WriteFcPortPage1(MPT_ADAPTER *ioc, int portnum)
0830 {
0831     ConfigPageHeader_t   hdr;
0832     CONFIGPARMS      cfg;
0833     int          rc;
0834 
0835     if (portnum > 1)
0836         return -EINVAL;
0837 
0838     if (!(ioc->fc_data.fc_port_page1[portnum].data))
0839         return -EINVAL;
0840 
0841     /* get fcport page 1 header */
0842     hdr.PageVersion = 0;
0843     hdr.PageLength = 0;
0844     hdr.PageNumber = 1;
0845     hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
0846     cfg.cfghdr.hdr = &hdr;
0847     cfg.physAddr = -1;
0848     cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
0849     cfg.dir = 0;
0850     cfg.pageAddr = portnum;
0851     cfg.timeout = 0;
0852 
0853     if ((rc = mpt_config(ioc, &cfg)) != 0)
0854         return rc;
0855 
0856     if (hdr.PageLength == 0)
0857         return -ENODEV;
0858 
0859     if (hdr.PageLength*4 != ioc->fc_data.fc_port_page1[portnum].pg_sz)
0860         return -EINVAL;
0861 
0862     cfg.physAddr = ioc->fc_data.fc_port_page1[portnum].dma;
0863     cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
0864     cfg.dir = 1;
0865 
0866     rc = mpt_config(ioc, &cfg);
0867 
0868     return rc;
0869 }
0870 
0871 static int
0872 mptfc_GetFcPortPage1(MPT_ADAPTER *ioc, int portnum)
0873 {
0874     ConfigPageHeader_t   hdr;
0875     CONFIGPARMS      cfg;
0876     FCPortPage1_t       *page1_alloc;
0877     dma_addr_t       page1_dma;
0878     int          data_sz;
0879     int          rc;
0880 
0881     if (portnum > 1)
0882         return -EINVAL;
0883 
0884     /* get fcport page 1 header */
0885     hdr.PageVersion = 0;
0886     hdr.PageLength = 0;
0887     hdr.PageNumber = 1;
0888     hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
0889     cfg.cfghdr.hdr = &hdr;
0890     cfg.physAddr = -1;
0891     cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
0892     cfg.dir = 0;
0893     cfg.pageAddr = portnum;
0894     cfg.timeout = 0;
0895 
0896     if ((rc = mpt_config(ioc, &cfg)) != 0)
0897         return rc;
0898 
0899     if (hdr.PageLength == 0)
0900         return -ENODEV;
0901 
0902 start_over:
0903 
0904     if (ioc->fc_data.fc_port_page1[portnum].data == NULL) {
0905         data_sz = hdr.PageLength * 4;
0906         if (data_sz < sizeof(FCPortPage1_t))
0907             data_sz = sizeof(FCPortPage1_t);
0908 
0909         page1_alloc = dma_alloc_coherent(&ioc->pcidev->dev, data_sz,
0910                          &page1_dma, GFP_KERNEL);
0911         if (!page1_alloc)
0912             return -ENOMEM;
0913     }
0914     else {
0915         page1_alloc = ioc->fc_data.fc_port_page1[portnum].data;
0916         page1_dma = ioc->fc_data.fc_port_page1[portnum].dma;
0917         data_sz = ioc->fc_data.fc_port_page1[portnum].pg_sz;
0918         if (hdr.PageLength * 4 > data_sz) {
0919             ioc->fc_data.fc_port_page1[portnum].data = NULL;
0920             dma_free_coherent(&ioc->pcidev->dev, data_sz,
0921                       page1_alloc, page1_dma);
0922             goto start_over;
0923         }
0924     }
0925 
0926     cfg.physAddr = page1_dma;
0927     cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
0928 
0929     if ((rc = mpt_config(ioc, &cfg)) == 0) {
0930         ioc->fc_data.fc_port_page1[portnum].data = page1_alloc;
0931         ioc->fc_data.fc_port_page1[portnum].pg_sz = data_sz;
0932         ioc->fc_data.fc_port_page1[portnum].dma = page1_dma;
0933     }
0934     else {
0935         ioc->fc_data.fc_port_page1[portnum].data = NULL;
0936         dma_free_coherent(&ioc->pcidev->dev, data_sz, page1_alloc,
0937                   page1_dma);
0938     }
0939 
0940     return rc;
0941 }
0942 
0943 static void
0944 mptfc_SetFcPortPage1_defaults(MPT_ADAPTER *ioc)
0945 {
0946     int     ii;
0947     FCPortPage1_t   *pp1;
0948 
0949     #define MPTFC_FW_DEVICE_TIMEOUT (1)
0950     #define MPTFC_FW_IO_PEND_TIMEOUT (1)
0951     #define ON_FLAGS  (MPI_FCPORTPAGE1_FLAGS_IMMEDIATE_ERROR_REPLY)
0952     #define OFF_FLAGS (MPI_FCPORTPAGE1_FLAGS_VERBOSE_RESCAN_EVENTS)
0953 
0954     for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) {
0955         if (mptfc_GetFcPortPage1(ioc, ii) != 0)
0956             continue;
0957         pp1 = ioc->fc_data.fc_port_page1[ii].data;
0958         if ((pp1->InitiatorDeviceTimeout == MPTFC_FW_DEVICE_TIMEOUT)
0959          && (pp1->InitiatorIoPendTimeout == MPTFC_FW_IO_PEND_TIMEOUT)
0960          && ((pp1->Flags & ON_FLAGS) == ON_FLAGS)
0961          && ((pp1->Flags & OFF_FLAGS) == 0))
0962             continue;
0963         pp1->InitiatorDeviceTimeout = MPTFC_FW_DEVICE_TIMEOUT;
0964         pp1->InitiatorIoPendTimeout = MPTFC_FW_IO_PEND_TIMEOUT;
0965         pp1->Flags &= ~OFF_FLAGS;
0966         pp1->Flags |= ON_FLAGS;
0967         mptfc_WriteFcPortPage1(ioc, ii);
0968     }
0969 }
0970 
0971 
0972 static void
0973 mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum)
0974 {
0975     unsigned    class = 0;
0976     unsigned    cos = 0;
0977     unsigned    speed;
0978     unsigned    port_type;
0979     unsigned    port_state;
0980     FCPortPage0_t   *pp0;
0981     struct Scsi_Host *sh;
0982     char        *sn;
0983 
0984     /* don't know what to do as only one scsi (fc) host was allocated */
0985     if (portnum != 0)
0986         return;
0987 
0988     pp0 = &ioc->fc_port_page0[portnum];
0989     sh = ioc->sh;
0990 
0991     sn = fc_host_symbolic_name(sh);
0992     snprintf(sn, FC_SYMBOLIC_NAME_SIZE, "%s %s%08xh",
0993         ioc->prod_name,
0994         MPT_FW_REV_MAGIC_ID_STRING,
0995         ioc->facts.FWVersion.Word);
0996 
0997     fc_host_tgtid_bind_type(sh) = FC_TGTID_BIND_BY_WWPN;
0998 
0999     fc_host_maxframe_size(sh) = pp0->MaxFrameSize;
1000 
1001     fc_host_node_name(sh) =
1002             (u64)pp0->WWNN.High << 32 | (u64)pp0->WWNN.Low;
1003 
1004     fc_host_port_name(sh) =
1005             (u64)pp0->WWPN.High << 32 | (u64)pp0->WWPN.Low;
1006 
1007     fc_host_port_id(sh) = pp0->PortIdentifier;
1008 
1009     class = pp0->SupportedServiceClass;
1010     if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_1)
1011         cos |= FC_COS_CLASS1;
1012     if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_2)
1013         cos |= FC_COS_CLASS2;
1014     if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_3)
1015         cos |= FC_COS_CLASS3;
1016     fc_host_supported_classes(sh) = cos;
1017 
1018     if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT)
1019         speed = FC_PORTSPEED_1GBIT;
1020     else if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT)
1021         speed = FC_PORTSPEED_2GBIT;
1022     else if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT)
1023         speed = FC_PORTSPEED_4GBIT;
1024     else if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_10GBIT)
1025         speed = FC_PORTSPEED_10GBIT;
1026     else
1027         speed = FC_PORTSPEED_UNKNOWN;
1028     fc_host_speed(sh) = speed;
1029 
1030     speed = 0;
1031     if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_1GBIT_SPEED)
1032         speed |= FC_PORTSPEED_1GBIT;
1033     if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_2GBIT_SPEED)
1034         speed |= FC_PORTSPEED_2GBIT;
1035     if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_4GBIT_SPEED)
1036         speed |= FC_PORTSPEED_4GBIT;
1037     if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_10GBIT_SPEED)
1038         speed |= FC_PORTSPEED_10GBIT;
1039     fc_host_supported_speeds(sh) = speed;
1040 
1041     port_state = FC_PORTSTATE_UNKNOWN;
1042     if (pp0->PortState == MPI_FCPORTPAGE0_PORTSTATE_ONLINE)
1043         port_state = FC_PORTSTATE_ONLINE;
1044     else if (pp0->PortState == MPI_FCPORTPAGE0_PORTSTATE_OFFLINE)
1045         port_state = FC_PORTSTATE_LINKDOWN;
1046     fc_host_port_state(sh) = port_state;
1047 
1048     port_type = FC_PORTTYPE_UNKNOWN;
1049     if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_POINT_TO_POINT)
1050         port_type = FC_PORTTYPE_PTP;
1051     else if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_PRIVATE_LOOP)
1052         port_type = FC_PORTTYPE_LPORT;
1053     else if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_PUBLIC_LOOP)
1054         port_type = FC_PORTTYPE_NLPORT;
1055     else if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_FABRIC_DIRECT)
1056         port_type = FC_PORTTYPE_NPORT;
1057     fc_host_port_type(sh) = port_type;
1058 
1059     fc_host_fabric_name(sh) =
1060         (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_FABRIC_WWN_VALID) ?
1061         (u64) pp0->FabricWWNN.High << 32 | (u64) pp0->FabricWWPN.Low :
1062         (u64)pp0->WWNN.High << 32 | (u64)pp0->WWNN.Low;
1063 
1064 }
1065 
1066 static void
1067 mptfc_link_status_change(struct work_struct *work)
1068 {
1069     MPT_ADAPTER             *ioc =
1070         container_of(work, MPT_ADAPTER, fc_rescan_work);
1071     int ii;
1072 
1073     for (ii=0; ii < ioc->facts.NumberOfPorts; ii++)
1074         (void) mptfc_GetFcPortPage0(ioc, ii);
1075 
1076 }
1077 
1078 static void
1079 mptfc_setup_reset(struct work_struct *work)
1080 {
1081     MPT_ADAPTER     *ioc =
1082         container_of(work, MPT_ADAPTER, fc_setup_reset_work);
1083     u64         pn;
1084     struct mptfc_rport_info *ri;
1085     struct scsi_target      *starget;
1086     VirtTarget              *vtarget;
1087 
1088     /* reset about to happen, delete (block) all rports */
1089     list_for_each_entry(ri, &ioc->fc_rports, list) {
1090         if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
1091             ri->flags &= ~MPT_RPORT_INFO_FLAGS_REGISTERED;
1092             fc_remote_port_delete(ri->rport);   /* won't sleep */
1093             ri->rport = NULL;
1094             starget = ri->starget;
1095             if (starget) {
1096                 vtarget = starget->hostdata;
1097                 if (vtarget)
1098                     vtarget->deleted = 1;
1099             }
1100 
1101             pn = (u64)ri->pg0.WWPN.High << 32 |
1102                  (u64)ri->pg0.WWPN.Low;
1103             dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
1104                 "mptfc_setup_reset.%d: %llx deleted\n",
1105                 ioc->name,
1106                 ioc->sh->host_no,
1107                 (unsigned long long)pn));
1108         }
1109     }
1110 }
1111 
1112 static void
1113 mptfc_rescan_devices(struct work_struct *work)
1114 {
1115     MPT_ADAPTER     *ioc =
1116         container_of(work, MPT_ADAPTER, fc_rescan_work);
1117     int         ii;
1118     u64         pn;
1119     struct mptfc_rport_info *ri;
1120     struct scsi_target      *starget;
1121     VirtTarget              *vtarget;
1122 
1123     /* start by tagging all ports as missing */
1124     list_for_each_entry(ri, &ioc->fc_rports, list) {
1125         if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
1126             ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING;
1127         }
1128     }
1129 
1130     /*
1131      * now rescan devices known to adapter,
1132      * will reregister existing rports
1133      */
1134     for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1135         (void) mptfc_GetFcPortPage0(ioc, ii);
1136         mptfc_init_host_attr(ioc, ii);  /* refresh */
1137         mptfc_GetFcDevPage0(ioc, ii, mptfc_register_dev);
1138     }
1139 
1140     /* delete devices still missing */
1141     list_for_each_entry(ri, &ioc->fc_rports, list) {
1142         /* if newly missing, delete it */
1143         if (ri->flags & MPT_RPORT_INFO_FLAGS_MISSING) {
1144 
1145             ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|
1146                        MPT_RPORT_INFO_FLAGS_MISSING);
1147             fc_remote_port_delete(ri->rport);   /* won't sleep */
1148             ri->rport = NULL;
1149             starget = ri->starget;
1150             if (starget) {
1151                 vtarget = starget->hostdata;
1152                 if (vtarget)
1153                     vtarget->deleted = 1;
1154             }
1155 
1156             pn = (u64)ri->pg0.WWPN.High << 32 |
1157                  (u64)ri->pg0.WWPN.Low;
1158             dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
1159                 "mptfc_rescan.%d: %llx deleted\n",
1160                 ioc->name,
1161                 ioc->sh->host_no,
1162                 (unsigned long long)pn));
1163         }
1164     }
1165 }
1166 
1167 static int
1168 mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1169 {
1170     struct Scsi_Host    *sh;
1171     MPT_SCSI_HOST       *hd;
1172     MPT_ADAPTER         *ioc;
1173     unsigned long        flags;
1174     int          ii;
1175     int          numSGE = 0;
1176     int          scale;
1177     int          ioc_cap;
1178     int         error=0;
1179     int         r;
1180 
1181     if ((r = mpt_attach(pdev,id)) != 0)
1182         return r;
1183 
1184     ioc = pci_get_drvdata(pdev);
1185     ioc->DoneCtx = mptfcDoneCtx;
1186     ioc->TaskCtx = mptfcTaskCtx;
1187     ioc->InternalCtx = mptfcInternalCtx;
1188 
1189     /*  Added sanity check on readiness of the MPT adapter.
1190      */
1191     if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
1192         printk(MYIOC_s_WARN_FMT
1193           "Skipping because it's not operational!\n",
1194           ioc->name);
1195         error = -ENODEV;
1196         goto out_mptfc_probe;
1197     }
1198 
1199     if (!ioc->active) {
1200         printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
1201           ioc->name);
1202         error = -ENODEV;
1203         goto out_mptfc_probe;
1204     }
1205 
1206     /*  Sanity check - ensure at least 1 port is INITIATOR capable
1207      */
1208     ioc_cap = 0;
1209     for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1210         if (ioc->pfacts[ii].ProtocolFlags &
1211             MPI_PORTFACTS_PROTOCOL_INITIATOR)
1212             ioc_cap ++;
1213     }
1214 
1215     if (!ioc_cap) {
1216         printk(MYIOC_s_WARN_FMT
1217             "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
1218             ioc->name, ioc);
1219         return 0;
1220     }
1221 
1222     sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));
1223 
1224     if (!sh) {
1225         printk(MYIOC_s_WARN_FMT
1226             "Unable to register controller with SCSI subsystem\n",
1227             ioc->name);
1228         error = -1;
1229         goto out_mptfc_probe;
1230         }
1231 
1232     spin_lock_init(&ioc->fc_rescan_work_lock);
1233     INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices);
1234     INIT_WORK(&ioc->fc_setup_reset_work, mptfc_setup_reset);
1235     INIT_WORK(&ioc->fc_lsc_work, mptfc_link_status_change);
1236 
1237     spin_lock_irqsave(&ioc->FreeQlock, flags);
1238 
1239     /* Attach the SCSI Host to the IOC structure
1240      */
1241     ioc->sh = sh;
1242 
1243     sh->io_port = 0;
1244     sh->n_io_port = 0;
1245     sh->irq = 0;
1246 
1247     /* set 16 byte cdb's */
1248     sh->max_cmd_len = 16;
1249 
1250     sh->max_id = ioc->pfacts->MaxDevices;
1251     sh->max_lun = max_lun;
1252 
1253     /* Required entry.
1254      */
1255     sh->unique_id = ioc->id;
1256 
1257     /* Verify that we won't exceed the maximum
1258      * number of chain buffers
1259      * We can optimize:  ZZ = req_sz/sizeof(SGE)
1260      * For 32bit SGE's:
1261      *  numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
1262      *               + (req_sz - 64)/sizeof(SGE)
1263      * A slightly different algorithm is required for
1264      * 64bit SGEs.
1265      */
1266     scale = ioc->req_sz/ioc->SGE_size;
1267     if (ioc->sg_addr_size == sizeof(u64)) {
1268         numSGE = (scale - 1) *
1269           (ioc->facts.MaxChainDepth-1) + scale +
1270           (ioc->req_sz - 60) / ioc->SGE_size;
1271     } else {
1272         numSGE = 1 + (scale - 1) *
1273           (ioc->facts.MaxChainDepth-1) + scale +
1274           (ioc->req_sz - 64) / ioc->SGE_size;
1275     }
1276 
1277     if (numSGE < sh->sg_tablesize) {
1278         /* Reset this value */
1279         dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1280           "Resetting sg_tablesize to %d from %d\n",
1281           ioc->name, numSGE, sh->sg_tablesize));
1282         sh->sg_tablesize = numSGE;
1283     }
1284 
1285     spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1286 
1287     hd = shost_priv(sh);
1288     hd->ioc = ioc;
1289 
1290     /* SCSI needs scsi_cmnd lookup table!
1291      * (with size equal to req_depth*PtrSz!)
1292      */
1293     ioc->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_KERNEL);
1294     if (!ioc->ScsiLookup) {
1295         error = -ENOMEM;
1296         goto out_mptfc_probe;
1297     }
1298     spin_lock_init(&ioc->scsi_lookup_lock);
1299 
1300     dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
1301          ioc->name, ioc->ScsiLookup));
1302 
1303     hd->last_queue_full = 0;
1304 
1305     sh->transportt = mptfc_transport_template;
1306     error = scsi_add_host (sh, &ioc->pcidev->dev);
1307     if(error) {
1308         dprintk(ioc, printk(MYIOC_s_ERR_FMT
1309           "scsi_add_host failed\n", ioc->name));
1310         goto out_mptfc_probe;
1311     }
1312 
1313     /* initialize workqueue */
1314 
1315     snprintf(ioc->fc_rescan_work_q_name, sizeof(ioc->fc_rescan_work_q_name),
1316          "mptfc_wq_%d", sh->host_no);
1317     ioc->fc_rescan_work_q =
1318         alloc_ordered_workqueue(ioc->fc_rescan_work_q_name,
1319                     WQ_MEM_RECLAIM);
1320     if (!ioc->fc_rescan_work_q) {
1321         error = -ENOMEM;
1322         goto out_mptfc_host;
1323     }
1324 
1325     /*
1326      *  Pre-fetch FC port WWN and stuff...
1327      *  (FCPortPage0_t stuff)
1328      */
1329     for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1330         (void) mptfc_GetFcPortPage0(ioc, ii);
1331     }
1332     mptfc_SetFcPortPage1_defaults(ioc);
1333 
1334     /*
1335      * scan for rports -
1336      *  by doing it via the workqueue, some locking is eliminated
1337      */
1338 
1339     queue_work(ioc->fc_rescan_work_q, &ioc->fc_rescan_work);
1340     flush_workqueue(ioc->fc_rescan_work_q);
1341 
1342     return 0;
1343 
1344 out_mptfc_host:
1345     scsi_remove_host(sh);
1346 
1347 out_mptfc_probe:
1348 
1349     mptscsih_remove(pdev);
1350     return error;
1351 }
1352 
1353 static struct pci_driver mptfc_driver = {
1354     .name       = "mptfc",
1355     .id_table   = mptfc_pci_table,
1356     .probe      = mptfc_probe,
1357     .remove     = mptfc_remove,
1358     .shutdown   = mptscsih_shutdown,
1359 #ifdef CONFIG_PM
1360     .suspend    = mptscsih_suspend,
1361     .resume     = mptscsih_resume,
1362 #endif
1363 };
1364 
1365 static int
1366 mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
1367 {
1368     MPT_SCSI_HOST *hd;
1369     u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
1370     unsigned long flags;
1371     int rc=1;
1372 
1373     if (ioc->bus_type != FC)
1374         return 0;
1375 
1376     devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
1377             ioc->name, event));
1378 
1379     if (ioc->sh == NULL ||
1380         ((hd = shost_priv(ioc->sh)) == NULL))
1381         return 1;
1382 
1383     switch (event) {
1384     case MPI_EVENT_RESCAN:
1385         spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1386         if (ioc->fc_rescan_work_q) {
1387             queue_work(ioc->fc_rescan_work_q,
1388                    &ioc->fc_rescan_work);
1389         }
1390         spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1391         break;
1392     case MPI_EVENT_LINK_STATUS_CHANGE:
1393         spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1394         if (ioc->fc_rescan_work_q) {
1395             queue_work(ioc->fc_rescan_work_q,
1396                    &ioc->fc_lsc_work);
1397         }
1398         spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1399         break;
1400     default:
1401         rc = mptscsih_event_process(ioc,pEvReply);
1402         break;
1403     }
1404     return rc;
1405 }
1406 
1407 static int
1408 mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
1409 {
1410     int     rc;
1411     unsigned long   flags;
1412 
1413     rc = mptscsih_ioc_reset(ioc,reset_phase);
1414     if ((ioc->bus_type != FC) || (!rc))
1415         return rc;
1416 
1417 
1418     dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1419         ": IOC %s_reset routed to FC host driver!\n",ioc->name,
1420         reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
1421         reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
1422 
1423     if (reset_phase == MPT_IOC_SETUP_RESET) {
1424         spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1425         if (ioc->fc_rescan_work_q) {
1426             queue_work(ioc->fc_rescan_work_q,
1427                    &ioc->fc_setup_reset_work);
1428         }
1429         spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1430     }
1431 
1432     else if (reset_phase == MPT_IOC_PRE_RESET) {
1433     }
1434 
1435     else {  /* MPT_IOC_POST_RESET */
1436         mptfc_SetFcPortPage1_defaults(ioc);
1437         spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1438         if (ioc->fc_rescan_work_q) {
1439             queue_work(ioc->fc_rescan_work_q,
1440                    &ioc->fc_rescan_work);
1441         }
1442         spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1443     }
1444     return 1;
1445 }
1446 
1447 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1448 /**
1449  *  mptfc_init - Register MPT adapter(s) as SCSI host(s) with SCSI mid-layer.
1450  *
1451  *  Returns 0 for success, non-zero for failure.
1452  */
1453 static int __init
1454 mptfc_init(void)
1455 {
1456     int error;
1457 
1458     show_mptmod_ver(my_NAME, my_VERSION);
1459 
1460     /* sanity check module parameters */
1461     if (mptfc_dev_loss_tmo <= 0)
1462         mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;
1463 
1464     mptfc_transport_template =
1465         fc_attach_transport(&mptfc_transport_functions);
1466 
1467     if (!mptfc_transport_template)
1468         return -ENODEV;
1469 
1470     mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER,
1471         "mptscsih_scandv_complete");
1472     mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER,
1473         "mptscsih_scandv_complete");
1474     mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER,
1475         "mptscsih_scandv_complete");
1476 
1477     mpt_event_register(mptfcDoneCtx, mptfc_event_process);
1478     mpt_reset_register(mptfcDoneCtx, mptfc_ioc_reset);
1479 
1480     error = pci_register_driver(&mptfc_driver);
1481     if (error)
1482         fc_release_transport(mptfc_transport_template);
1483 
1484     return error;
1485 }
1486 
1487 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1488 /**
1489  *  mptfc_remove - Remove fc infrastructure for devices
1490  *  @pdev: Pointer to pci_dev structure
1491  *
1492  */
1493 static void mptfc_remove(struct pci_dev *pdev)
1494 {
1495     MPT_ADAPTER     *ioc = pci_get_drvdata(pdev);
1496     struct mptfc_rport_info *p, *n;
1497     struct workqueue_struct *work_q;
1498     unsigned long       flags;
1499     int         ii;
1500 
1501     /* destroy workqueue */
1502     if ((work_q=ioc->fc_rescan_work_q)) {
1503         spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1504         ioc->fc_rescan_work_q = NULL;
1505         spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1506         destroy_workqueue(work_q);
1507     }
1508 
1509     fc_remove_host(ioc->sh);
1510 
1511     list_for_each_entry_safe(p, n, &ioc->fc_rports, list) {
1512         list_del(&p->list);
1513         kfree(p);
1514     }
1515 
1516     for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) {
1517         if (ioc->fc_data.fc_port_page1[ii].data) {
1518             dma_free_coherent(&ioc->pcidev->dev,
1519                       ioc->fc_data.fc_port_page1[ii].pg_sz,
1520                       ioc->fc_data.fc_port_page1[ii].data,
1521                       ioc->fc_data.fc_port_page1[ii].dma);
1522             ioc->fc_data.fc_port_page1[ii].data = NULL;
1523         }
1524     }
1525 
1526     scsi_remove_host(ioc->sh);
1527 
1528     mptscsih_remove(pdev);
1529 }
1530 
1531 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1532 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1533 /**
1534  *  mptfc_exit - Unregisters MPT adapter(s)
1535  *
1536  */
1537 static void __exit
1538 mptfc_exit(void)
1539 {
1540     pci_unregister_driver(&mptfc_driver);
1541     fc_release_transport(mptfc_transport_template);
1542 
1543     mpt_reset_deregister(mptfcDoneCtx);
1544     mpt_event_deregister(mptfcDoneCtx);
1545 
1546     mpt_deregister(mptfcInternalCtx);
1547     mpt_deregister(mptfcTaskCtx);
1548     mpt_deregister(mptfcDoneCtx);
1549 }
1550 
1551 module_init(mptfc_init);
1552 module_exit(mptfc_exit);