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