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