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