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