linux/drivers/scsi/mpt2sas/mpt2sas_transport.c
<<
>>
Prefs
   1/*
   2 * SAS Transport Layer for MPT (Message Passing Technology) based controllers
   3 *
   4 * This code is based on drivers/scsi/mpt2sas/mpt2_transport.c
   5 * Copyright (C) 2007-2010  LSI Corporation
   6 *  (mailto:DL-MPTFusionLinux@lsi.com)
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License
  10 * as published by the Free Software Foundation; either version 2
  11 * of the License, or (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * NO WARRANTY
  19 * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
  20 * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
  21 * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
  22 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
  23 * solely responsible for determining the appropriateness of using and
  24 * distributing the Program and assumes all risks associated with its
  25 * exercise of rights under this Agreement, including but not limited to
  26 * the risks and costs of program errors, damage to or loss of data,
  27 * programs or equipment, and unavailability or interruption of operations.
  28
  29 * DISCLAIMER OF LIABILITY
  30 * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
  31 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  32 * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
  33 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
  34 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  35 * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
  36 * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
  37
  38 * You should have received a copy of the GNU General Public License
  39 * along with this program; if not, write to the Free Software
  40 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
  41 * USA.
  42 */
  43
  44#include <linux/module.h>
  45#include <linux/kernel.h>
  46#include <linux/init.h>
  47#include <linux/errno.h>
  48#include <linux/sched.h>
  49#include <linux/workqueue.h>
  50#include <linux/delay.h>
  51#include <linux/pci.h>
  52#include <linux/slab.h>
  53
  54#include <scsi/scsi.h>
  55#include <scsi/scsi_cmnd.h>
  56#include <scsi/scsi_device.h>
  57#include <scsi/scsi_host.h>
  58#include <scsi/scsi_transport_sas.h>
  59#include <scsi/scsi_dbg.h>
  60
  61#include "mpt2sas_base.h"
  62/**
  63 * _transport_sas_node_find_by_sas_address - sas node search
  64 * @ioc: per adapter object
  65 * @sas_address: sas address of expander or sas host
  66 * Context: Calling function should acquire ioc->sas_node_lock.
  67 *
  68 * Search for either hba phys or expander device based on handle, then returns
  69 * the sas_node object.
  70 */
  71static struct _sas_node *
  72_transport_sas_node_find_by_sas_address(struct MPT2SAS_ADAPTER *ioc,
  73    u64 sas_address)
  74{
  75        if (ioc->sas_hba.sas_address == sas_address)
  76                return &ioc->sas_hba;
  77        else
  78                return mpt2sas_scsih_expander_find_by_sas_address(ioc,
  79                    sas_address);
  80}
  81
  82/**
  83 * _transport_convert_phy_link_rate -
  84 * @link_rate: link rate returned from mpt firmware
  85 *
  86 * Convert link_rate from mpi fusion into sas_transport form.
  87 */
  88static enum sas_linkrate
  89_transport_convert_phy_link_rate(u8 link_rate)
  90{
  91        enum sas_linkrate rc;
  92
  93        switch (link_rate) {
  94        case MPI2_SAS_NEG_LINK_RATE_1_5:
  95                rc = SAS_LINK_RATE_1_5_GBPS;
  96                break;
  97        case MPI2_SAS_NEG_LINK_RATE_3_0:
  98                rc = SAS_LINK_RATE_3_0_GBPS;
  99                break;
 100        case MPI2_SAS_NEG_LINK_RATE_6_0:
 101                rc = SAS_LINK_RATE_6_0_GBPS;
 102                break;
 103        case MPI2_SAS_NEG_LINK_RATE_PHY_DISABLED:
 104                rc = SAS_PHY_DISABLED;
 105                break;
 106        case MPI2_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED:
 107                rc = SAS_LINK_RATE_FAILED;
 108                break;
 109        case MPI2_SAS_NEG_LINK_RATE_PORT_SELECTOR:
 110                rc = SAS_SATA_PORT_SELECTOR;
 111                break;
 112        case MPI2_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS:
 113                rc = SAS_PHY_RESET_IN_PROGRESS;
 114                break;
 115        default:
 116        case MPI2_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE:
 117        case MPI2_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE:
 118                rc = SAS_LINK_RATE_UNKNOWN;
 119                break;
 120        }
 121        return rc;
 122}
 123
 124/**
 125 * _transport_set_identify - set identify for phys and end devices
 126 * @ioc: per adapter object
 127 * @handle: device handle
 128 * @identify: sas identify info
 129 *
 130 * Populates sas identify info.
 131 *
 132 * Returns 0 for success, non-zero for failure.
 133 */
 134static int
 135_transport_set_identify(struct MPT2SAS_ADAPTER *ioc, u16 handle,
 136    struct sas_identify *identify)
 137{
 138        Mpi2SasDevicePage0_t sas_device_pg0;
 139        Mpi2ConfigReply_t mpi_reply;
 140        u32 device_info;
 141        u32 ioc_status;
 142
 143        if (ioc->shost_recovery || ioc->pci_error_recovery) {
 144                printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
 145                    __func__, ioc->name);
 146                return -EFAULT;
 147        }
 148
 149        if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
 150            MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
 151                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
 152
 153                    ioc->name, __FILE__, __LINE__, __func__);
 154                return -ENXIO;
 155        }
 156
 157        ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
 158            MPI2_IOCSTATUS_MASK;
 159        if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
 160                printk(MPT2SAS_ERR_FMT "handle(0x%04x), ioc_status(0x%04x)"
 161                    "\nfailure at %s:%d/%s()!\n", ioc->name, handle, ioc_status,
 162                     __FILE__, __LINE__, __func__);
 163                return -EIO;
 164        }
 165
 166        memset(identify, 0, sizeof(struct sas_identify));
 167        device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
 168
 169        /* sas_address */
 170        identify->sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
 171
 172        /* phy number of the parent device this device is linked to */
 173        identify->phy_identifier = sas_device_pg0.PhyNum;
 174
 175        /* device_type */
 176        switch (device_info & MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
 177        case MPI2_SAS_DEVICE_INFO_NO_DEVICE:
 178                identify->device_type = SAS_PHY_UNUSED;
 179                break;
 180        case MPI2_SAS_DEVICE_INFO_END_DEVICE:
 181                identify->device_type = SAS_END_DEVICE;
 182                break;
 183        case MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER:
 184                identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
 185                break;
 186        case MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER:
 187                identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
 188                break;
 189        }
 190
 191        /* initiator_port_protocols */
 192        if (device_info & MPI2_SAS_DEVICE_INFO_SSP_INITIATOR)
 193                identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
 194        if (device_info & MPI2_SAS_DEVICE_INFO_STP_INITIATOR)
 195                identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
 196        if (device_info & MPI2_SAS_DEVICE_INFO_SMP_INITIATOR)
 197                identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
 198        if (device_info & MPI2_SAS_DEVICE_INFO_SATA_HOST)
 199                identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
 200
 201        /* target_port_protocols */
 202        if (device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET)
 203                identify->target_port_protocols |= SAS_PROTOCOL_SSP;
 204        if (device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET)
 205                identify->target_port_protocols |= SAS_PROTOCOL_STP;
 206        if (device_info & MPI2_SAS_DEVICE_INFO_SMP_TARGET)
 207                identify->target_port_protocols |= SAS_PROTOCOL_SMP;
 208        if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
 209                identify->target_port_protocols |= SAS_PROTOCOL_SATA;
 210
 211        return 0;
 212}
 213
 214/**
 215 * mpt2sas_transport_done -  internal transport layer callback handler.
 216 * @ioc: per adapter object
 217 * @smid: system request message index
 218 * @msix_index: MSIX table index supplied by the OS
 219 * @reply: reply message frame(lower 32bit addr)
 220 *
 221 * Callback handler when sending internal generated transport cmds.
 222 * The callback index passed is `ioc->transport_cb_idx`
 223 *
 224 * Return 1 meaning mf should be freed from _base_interrupt
 225 *        0 means the mf is freed from this function.
 226 */
 227u8
 228mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
 229    u32 reply)
 230{
 231        MPI2DefaultReply_t *mpi_reply;
 232
 233        mpi_reply =  mpt2sas_base_get_reply_virt_addr(ioc, reply);
 234        if (ioc->transport_cmds.status == MPT2_CMD_NOT_USED)
 235                return 1;
 236        if (ioc->transport_cmds.smid != smid)
 237                return 1;
 238        ioc->transport_cmds.status |= MPT2_CMD_COMPLETE;
 239        if (mpi_reply) {
 240                memcpy(ioc->transport_cmds.reply, mpi_reply,
 241                    mpi_reply->MsgLength*4);
 242                ioc->transport_cmds.status |= MPT2_CMD_REPLY_VALID;
 243        }
 244        ioc->transport_cmds.status &= ~MPT2_CMD_PENDING;
 245        complete(&ioc->transport_cmds.done);
 246        return 1;
 247}
 248
 249/* report manufacture request structure */
 250struct rep_manu_request{
 251        u8 smp_frame_type;
 252        u8 function;
 253        u8 reserved;
 254        u8 request_length;
 255};
 256
 257/* report manufacture reply structure */
 258struct rep_manu_reply{
 259        u8 smp_frame_type; /* 0x41 */
 260        u8 function; /* 0x01 */
 261        u8 function_result;
 262        u8 response_length;
 263        u16 expander_change_count;
 264        u8 reserved0[2];
 265        u8 sas_format;
 266        u8 reserved2[3];
 267        u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN];
 268        u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN];
 269        u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN];
 270        u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN];
 271        u16 component_id;
 272        u8 component_revision_id;
 273        u8 reserved3;
 274        u8 vendor_specific[8];
 275};
 276
 277/**
 278 * _transport_expander_report_manufacture - obtain SMP report_manufacture
 279 * @ioc: per adapter object
 280 * @sas_address: expander sas address
 281 * @edev: the sas_expander_device object
 282 *
 283 * Fills in the sas_expander_device object when SMP port is created.
 284 *
 285 * Returns 0 for success, non-zero for failure.
 286 */
 287static int
 288_transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc,
 289    u64 sas_address, struct sas_expander_device *edev)
 290{
 291        Mpi2SmpPassthroughRequest_t *mpi_request;
 292        Mpi2SmpPassthroughReply_t *mpi_reply;
 293        struct rep_manu_reply *manufacture_reply;
 294        struct rep_manu_request *manufacture_request;
 295        int rc;
 296        u16 smid;
 297        u32 ioc_state;
 298        unsigned long timeleft;
 299        void *psge;
 300        u32 sgl_flags;
 301        u8 issue_reset = 0;
 302        void *data_out = NULL;
 303        dma_addr_t data_out_dma;
 304        u32 sz;
 305        u16 wait_state_count;
 306
 307        if (ioc->shost_recovery || ioc->pci_error_recovery) {
 308                printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
 309                    __func__, ioc->name);
 310                return -EFAULT;
 311        }
 312
 313        mutex_lock(&ioc->transport_cmds.mutex);
 314
 315        if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
 316                printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n",
 317                    ioc->name, __func__);
 318                rc = -EAGAIN;
 319                goto out;
 320        }
 321        ioc->transport_cmds.status = MPT2_CMD_PENDING;
 322
 323        wait_state_count = 0;
 324        ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
 325        while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
 326                if (wait_state_count++ == 10) {
 327                        printk(MPT2SAS_ERR_FMT
 328                            "%s: failed due to ioc not operational\n",
 329                            ioc->name, __func__);
 330                        rc = -EFAULT;
 331                        goto out;
 332                }
 333                ssleep(1);
 334                ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
 335                printk(MPT2SAS_INFO_FMT "%s: waiting for "
 336                    "operational state(count=%d)\n", ioc->name,
 337                    __func__, wait_state_count);
 338        }
 339        if (wait_state_count)
 340                printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
 341                    ioc->name, __func__);
 342
 343        smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
 344        if (!smid) {
 345                printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
 346                    ioc->name, __func__);
 347                rc = -EAGAIN;
 348                goto out;
 349        }
 350
 351        rc = 0;
 352        mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
 353        ioc->transport_cmds.smid = smid;
 354
 355        sz = sizeof(struct rep_manu_request) + sizeof(struct rep_manu_reply);
 356        data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
 357
 358        if (!data_out) {
 359                printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
 360                    __LINE__, __func__);
 361                rc = -ENOMEM;
 362                mpt2sas_base_free_smid(ioc, smid);
 363                goto out;
 364        }
 365
 366        manufacture_request = data_out;
 367        manufacture_request->smp_frame_type = 0x40;
 368        manufacture_request->function = 1;
 369        manufacture_request->reserved = 0;
 370        manufacture_request->request_length = 0;
 371
 372        memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
 373        mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
 374        mpi_request->PhysicalPort = 0xFF;
 375        mpi_request->VF_ID = 0; /* TODO */
 376        mpi_request->VP_ID = 0;
 377        mpi_request->SASAddress = cpu_to_le64(sas_address);
 378        mpi_request->RequestDataLength =
 379            cpu_to_le16(sizeof(struct rep_manu_request));
 380        psge = &mpi_request->SGL;
 381
 382        /* WRITE sgel first */
 383        sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
 384            MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
 385        sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
 386        ioc->base_add_sg_single(psge, sgl_flags |
 387            sizeof(struct rep_manu_request), data_out_dma);
 388
 389        /* incr sgel */
 390        psge += ioc->sge_size;
 391
 392        /* READ sgel last */
 393        sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
 394            MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
 395            MPI2_SGE_FLAGS_END_OF_LIST);
 396        sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
 397        ioc->base_add_sg_single(psge, sgl_flags |
 398            sizeof(struct rep_manu_reply), data_out_dma +
 399            sizeof(struct rep_manu_request));
 400
 401        dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "report_manufacture - "
 402            "send to sas_addr(0x%016llx)\n", ioc->name,
 403            (unsigned long long)sas_address));
 404        init_completion(&ioc->transport_cmds.done);
 405        mpt2sas_base_put_smid_default(ioc, smid);
 406        timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
 407            10*HZ);
 408
 409        if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
 410                printk(MPT2SAS_ERR_FMT "%s: timeout\n",
 411                    ioc->name, __func__);
 412                _debug_dump_mf(mpi_request,
 413                    sizeof(Mpi2SmpPassthroughRequest_t)/4);
 414                if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
 415                        issue_reset = 1;
 416                goto issue_host_reset;
 417        }
 418
 419        dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "report_manufacture - "
 420            "complete\n", ioc->name));
 421
 422        if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
 423                u8 *tmp;
 424
 425                mpi_reply = ioc->transport_cmds.reply;
 426
 427                dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
 428                    "report_manufacture - reply data transfer size(%d)\n",
 429                    ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
 430
 431                if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
 432                    sizeof(struct rep_manu_reply))
 433                        goto out;
 434
 435                manufacture_reply = data_out + sizeof(struct rep_manu_request);
 436                strncpy(edev->vendor_id, manufacture_reply->vendor_id,
 437                     SAS_EXPANDER_VENDOR_ID_LEN);
 438                strncpy(edev->product_id, manufacture_reply->product_id,
 439                     SAS_EXPANDER_PRODUCT_ID_LEN);
 440                strncpy(edev->product_rev, manufacture_reply->product_rev,
 441                     SAS_EXPANDER_PRODUCT_REV_LEN);
 442                edev->level = manufacture_reply->sas_format & 1;
 443                if (edev->level) {
 444                        strncpy(edev->component_vendor_id,
 445                            manufacture_reply->component_vendor_id,
 446                             SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN);
 447                        tmp = (u8 *)&manufacture_reply->component_id;
 448                        edev->component_id = tmp[0] << 8 | tmp[1];
 449                        edev->component_revision_id =
 450                            manufacture_reply->component_revision_id;
 451                }
 452        } else
 453                dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
 454                    "report_manufacture - no reply\n", ioc->name));
 455
 456 issue_host_reset:
 457        if (issue_reset)
 458                mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
 459                    FORCE_BIG_HAMMER);
 460 out:
 461        ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
 462        if (data_out)
 463                pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
 464
 465        mutex_unlock(&ioc->transport_cmds.mutex);
 466        return rc;
 467}
 468
 469/**
 470 * _transport_delete_port - helper function to removing a port
 471 * @ioc: per adapter object
 472 * @mpt2sas_port: mpt2sas per port object
 473 *
 474 * Returns nothing.
 475 */
 476static void
 477_transport_delete_port(struct MPT2SAS_ADAPTER *ioc,
 478        struct _sas_port *mpt2sas_port)
 479{
 480        u64 sas_address = mpt2sas_port->remote_identify.sas_address;
 481        enum sas_device_type device_type =
 482            mpt2sas_port->remote_identify.device_type;
 483
 484        dev_printk(KERN_INFO, &mpt2sas_port->port->dev,
 485            "remove: sas_addr(0x%016llx)\n",
 486            (unsigned long long) sas_address);
 487
 488        ioc->logging_level |= MPT_DEBUG_TRANSPORT;
 489        if (device_type == SAS_END_DEVICE)
 490                mpt2sas_device_remove_by_sas_address(ioc, sas_address);
 491        else if (device_type == SAS_EDGE_EXPANDER_DEVICE ||
 492            device_type == SAS_FANOUT_EXPANDER_DEVICE)
 493                mpt2sas_expander_remove(ioc, sas_address);
 494        ioc->logging_level &= ~MPT_DEBUG_TRANSPORT;
 495}
 496
 497/**
 498 * _transport_delete_phy - helper function to removing single phy from port
 499 * @ioc: per adapter object
 500 * @mpt2sas_port: mpt2sas per port object
 501 * @mpt2sas_phy: mpt2sas per phy object
 502 *
 503 * Returns nothing.
 504 */
 505static void
 506_transport_delete_phy(struct MPT2SAS_ADAPTER *ioc,
 507        struct _sas_port *mpt2sas_port, struct _sas_phy *mpt2sas_phy)
 508{
 509        u64 sas_address = mpt2sas_port->remote_identify.sas_address;
 510
 511        dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
 512            "remove: sas_addr(0x%016llx), phy(%d)\n",
 513            (unsigned long long) sas_address, mpt2sas_phy->phy_id);
 514
 515        list_del(&mpt2sas_phy->port_siblings);
 516        mpt2sas_port->num_phys--;
 517        sas_port_delete_phy(mpt2sas_port->port, mpt2sas_phy->phy);
 518        mpt2sas_phy->phy_belongs_to_port = 0;
 519}
 520
 521/**
 522 * _transport_add_phy - helper function to adding single phy to port
 523 * @ioc: per adapter object
 524 * @mpt2sas_port: mpt2sas per port object
 525 * @mpt2sas_phy: mpt2sas per phy object
 526 *
 527 * Returns nothing.
 528 */
 529static void
 530_transport_add_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_port *mpt2sas_port,
 531        struct _sas_phy *mpt2sas_phy)
 532{
 533        u64 sas_address = mpt2sas_port->remote_identify.sas_address;
 534
 535        dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
 536            "add: sas_addr(0x%016llx), phy(%d)\n", (unsigned long long)
 537            sas_address, mpt2sas_phy->phy_id);
 538
 539        list_add_tail(&mpt2sas_phy->port_siblings, &mpt2sas_port->phy_list);
 540        mpt2sas_port->num_phys++;
 541        sas_port_add_phy(mpt2sas_port->port, mpt2sas_phy->phy);
 542        mpt2sas_phy->phy_belongs_to_port = 1;
 543}
 544
 545/**
 546 * _transport_add_phy_to_an_existing_port - adding new phy to existing port
 547 * @ioc: per adapter object
 548 * @sas_node: sas node object (either expander or sas host)
 549 * @mpt2sas_phy: mpt2sas per phy object
 550 * @sas_address: sas address of device/expander were phy needs to be added to
 551 *
 552 * Returns nothing.
 553 */
 554static void
 555_transport_add_phy_to_an_existing_port(struct MPT2SAS_ADAPTER *ioc,
 556struct _sas_node *sas_node, struct _sas_phy *mpt2sas_phy, u64 sas_address)
 557{
 558        struct _sas_port *mpt2sas_port;
 559        struct _sas_phy *phy_srch;
 560
 561        if (mpt2sas_phy->phy_belongs_to_port == 1)
 562                return;
 563
 564        list_for_each_entry(mpt2sas_port, &sas_node->sas_port_list,
 565            port_list) {
 566                if (mpt2sas_port->remote_identify.sas_address !=
 567                    sas_address)
 568                        continue;
 569                list_for_each_entry(phy_srch, &mpt2sas_port->phy_list,
 570                    port_siblings) {
 571                        if (phy_srch == mpt2sas_phy)
 572                                return;
 573                }
 574                _transport_add_phy(ioc, mpt2sas_port, mpt2sas_phy);
 575                        return;
 576        }
 577
 578}
 579
 580/**
 581 * _transport_del_phy_from_an_existing_port - delete phy from existing port
 582 * @ioc: per adapter object
 583 * @sas_node: sas node object (either expander or sas host)
 584 * @mpt2sas_phy: mpt2sas per phy object
 585 *
 586 * Returns nothing.
 587 */
 588static void
 589_transport_del_phy_from_an_existing_port(struct MPT2SAS_ADAPTER *ioc,
 590        struct _sas_node *sas_node, struct _sas_phy *mpt2sas_phy)
 591{
 592        struct _sas_port *mpt2sas_port, *next;
 593        struct _sas_phy *phy_srch;
 594
 595        if (mpt2sas_phy->phy_belongs_to_port == 0)
 596                return;
 597
 598        list_for_each_entry_safe(mpt2sas_port, next, &sas_node->sas_port_list,
 599            port_list) {
 600                list_for_each_entry(phy_srch, &mpt2sas_port->phy_list,
 601                    port_siblings) {
 602                        if (phy_srch != mpt2sas_phy)
 603                                continue;
 604                        if (mpt2sas_port->num_phys == 1)
 605                                _transport_delete_port(ioc, mpt2sas_port);
 606                        else
 607                                _transport_delete_phy(ioc, mpt2sas_port,
 608                                    mpt2sas_phy);
 609                        return;
 610                }
 611        }
 612}
 613
 614/**
 615 * _transport_sanity_check - sanity check when adding a new port
 616 * @ioc: per adapter object
 617 * @sas_node: sas node object (either expander or sas host)
 618 * @sas_address: sas address of device being added
 619 *
 620 * See the explanation above from _transport_delete_duplicate_port
 621 */
 622static void
 623_transport_sanity_check(struct MPT2SAS_ADAPTER *ioc, struct _sas_node *sas_node,
 624     u64 sas_address)
 625{
 626        int i;
 627
 628        for (i = 0; i < sas_node->num_phys; i++) {
 629                if (sas_node->phy[i].remote_identify.sas_address != sas_address)
 630                        continue;
 631                if (sas_node->phy[i].phy_belongs_to_port == 1)
 632                        _transport_del_phy_from_an_existing_port(ioc, sas_node,
 633                            &sas_node->phy[i]);
 634        }
 635}
 636
 637/**
 638 * mpt2sas_transport_port_add - insert port to the list
 639 * @ioc: per adapter object
 640 * @handle: handle of attached device
 641 * @sas_address: sas address of parent expander or sas host
 642 * Context: This function will acquire ioc->sas_node_lock.
 643 *
 644 * Adding new port object to the sas_node->sas_port_list.
 645 *
 646 * Returns mpt2sas_port.
 647 */
 648struct _sas_port *
 649mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc, u16 handle,
 650    u64 sas_address)
 651{
 652        struct _sas_phy *mpt2sas_phy, *next;
 653        struct _sas_port *mpt2sas_port;
 654        unsigned long flags;
 655        struct _sas_node *sas_node;
 656        struct sas_rphy *rphy;
 657        int i;
 658        struct sas_port *port;
 659
 660        mpt2sas_port = kzalloc(sizeof(struct _sas_port),
 661            GFP_KERNEL);
 662        if (!mpt2sas_port) {
 663                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
 664                    ioc->name, __FILE__, __LINE__, __func__);
 665                return NULL;
 666        }
 667
 668        INIT_LIST_HEAD(&mpt2sas_port->port_list);
 669        INIT_LIST_HEAD(&mpt2sas_port->phy_list);
 670        spin_lock_irqsave(&ioc->sas_node_lock, flags);
 671        sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
 672        spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 673
 674        if (!sas_node) {
 675                printk(MPT2SAS_ERR_FMT "%s: Could not find "
 676                    "parent sas_address(0x%016llx)!\n", ioc->name,
 677                    __func__, (unsigned long long)sas_address);
 678                goto out_fail;
 679        }
 680
 681        if ((_transport_set_identify(ioc, handle,
 682            &mpt2sas_port->remote_identify))) {
 683                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
 684                    ioc->name, __FILE__, __LINE__, __func__);
 685                goto out_fail;
 686        }
 687
 688        if (mpt2sas_port->remote_identify.device_type == SAS_PHY_UNUSED) {
 689                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
 690                    ioc->name, __FILE__, __LINE__, __func__);
 691                goto out_fail;
 692        }
 693
 694        _transport_sanity_check(ioc, sas_node,
 695            mpt2sas_port->remote_identify.sas_address);
 696
 697        for (i = 0; i < sas_node->num_phys; i++) {
 698                if (sas_node->phy[i].remote_identify.sas_address !=
 699                    mpt2sas_port->remote_identify.sas_address)
 700                        continue;
 701                list_add_tail(&sas_node->phy[i].port_siblings,
 702                    &mpt2sas_port->phy_list);
 703                mpt2sas_port->num_phys++;
 704        }
 705
 706        if (!mpt2sas_port->num_phys) {
 707                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
 708                    ioc->name, __FILE__, __LINE__, __func__);
 709                goto out_fail;
 710        }
 711
 712        port = sas_port_alloc_num(sas_node->parent_dev);
 713        if ((sas_port_add(port))) {
 714                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
 715                    ioc->name, __FILE__, __LINE__, __func__);
 716                goto out_fail;
 717        }
 718
 719        list_for_each_entry(mpt2sas_phy, &mpt2sas_port->phy_list,
 720            port_siblings) {
 721                if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
 722                        dev_printk(KERN_INFO, &port->dev, "add: handle(0x%04x)"
 723                            ", sas_addr(0x%016llx), phy(%d)\n", handle,
 724                            (unsigned long long)
 725                            mpt2sas_port->remote_identify.sas_address,
 726                            mpt2sas_phy->phy_id);
 727                sas_port_add_phy(port, mpt2sas_phy->phy);
 728                mpt2sas_phy->phy_belongs_to_port = 1;
 729        }
 730
 731        mpt2sas_port->port = port;
 732        if (mpt2sas_port->remote_identify.device_type == SAS_END_DEVICE)
 733                rphy = sas_end_device_alloc(port);
 734        else
 735                rphy = sas_expander_alloc(port,
 736                    mpt2sas_port->remote_identify.device_type);
 737
 738        rphy->identify = mpt2sas_port->remote_identify;
 739        if ((sas_rphy_add(rphy))) {
 740                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
 741                    ioc->name, __FILE__, __LINE__, __func__);
 742        }
 743        if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
 744                dev_printk(KERN_INFO, &rphy->dev, "add: handle(0x%04x), "
 745                    "sas_addr(0x%016llx)\n", handle,
 746                    (unsigned long long)
 747                    mpt2sas_port->remote_identify.sas_address);
 748        mpt2sas_port->rphy = rphy;
 749        spin_lock_irqsave(&ioc->sas_node_lock, flags);
 750        list_add_tail(&mpt2sas_port->port_list, &sas_node->sas_port_list);
 751        spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 752
 753        /* fill in report manufacture */
 754        if (mpt2sas_port->remote_identify.device_type ==
 755            MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER ||
 756            mpt2sas_port->remote_identify.device_type ==
 757            MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER)
 758                _transport_expander_report_manufacture(ioc,
 759                    mpt2sas_port->remote_identify.sas_address,
 760                    rphy_to_expander_device(rphy));
 761
 762        return mpt2sas_port;
 763
 764 out_fail:
 765        list_for_each_entry_safe(mpt2sas_phy, next, &mpt2sas_port->phy_list,
 766            port_siblings)
 767                list_del(&mpt2sas_phy->port_siblings);
 768        kfree(mpt2sas_port);
 769        return NULL;
 770}
 771
 772/**
 773 * mpt2sas_transport_port_remove - remove port from the list
 774 * @ioc: per adapter object
 775 * @sas_address: sas address of attached device
 776 * @sas_address_parent: sas address of parent expander or sas host
 777 * Context: This function will acquire ioc->sas_node_lock.
 778 *
 779 * Removing object and freeing associated memory from the
 780 * ioc->sas_port_list.
 781 *
 782 * Return nothing.
 783 */
 784void
 785mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
 786    u64 sas_address_parent)
 787{
 788        int i;
 789        unsigned long flags;
 790        struct _sas_port *mpt2sas_port, *next;
 791        struct _sas_node *sas_node;
 792        u8 found = 0;
 793        struct _sas_phy *mpt2sas_phy, *next_phy;
 794
 795        spin_lock_irqsave(&ioc->sas_node_lock, flags);
 796        sas_node = _transport_sas_node_find_by_sas_address(ioc,
 797            sas_address_parent);
 798        if (!sas_node) {
 799                spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 800                return;
 801        }
 802        list_for_each_entry_safe(mpt2sas_port, next, &sas_node->sas_port_list,
 803            port_list) {
 804                if (mpt2sas_port->remote_identify.sas_address != sas_address)
 805                        continue;
 806                found = 1;
 807                list_del(&mpt2sas_port->port_list);
 808                goto out;
 809        }
 810 out:
 811        if (!found) {
 812                spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 813                return;
 814        }
 815
 816        for (i = 0; i < sas_node->num_phys; i++) {
 817                if (sas_node->phy[i].remote_identify.sas_address == sas_address)
 818                        memset(&sas_node->phy[i].remote_identify, 0 ,
 819                            sizeof(struct sas_identify));
 820        }
 821
 822        spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 823        list_for_each_entry_safe(mpt2sas_phy, next_phy,
 824            &mpt2sas_port->phy_list, port_siblings) {
 825                if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
 826                        dev_printk(KERN_INFO, &mpt2sas_port->port->dev,
 827                            "remove: sas_addr(0x%016llx), phy(%d)\n",
 828                            (unsigned long long)
 829                            mpt2sas_port->remote_identify.sas_address,
 830                            mpt2sas_phy->phy_id);
 831                mpt2sas_phy->phy_belongs_to_port = 0;
 832                sas_port_delete_phy(mpt2sas_port->port, mpt2sas_phy->phy);
 833                list_del(&mpt2sas_phy->port_siblings);
 834        }
 835        sas_port_delete(mpt2sas_port->port);
 836        kfree(mpt2sas_port);
 837}
 838
 839/**
 840 * mpt2sas_transport_add_host_phy - report sas_host phy to transport
 841 * @ioc: per adapter object
 842 * @mpt2sas_phy: mpt2sas per phy object
 843 * @phy_pg0: sas phy page 0
 844 * @parent_dev: parent device class object
 845 *
 846 * Returns 0 for success, non-zero for failure.
 847 */
 848int
 849mpt2sas_transport_add_host_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
 850    *mpt2sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev)
 851{
 852        struct sas_phy *phy;
 853        int phy_index = mpt2sas_phy->phy_id;
 854
 855
 856        INIT_LIST_HEAD(&mpt2sas_phy->port_siblings);
 857        phy = sas_phy_alloc(parent_dev, phy_index);
 858        if (!phy) {
 859                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
 860                    ioc->name, __FILE__, __LINE__, __func__);
 861                return -1;
 862        }
 863        if ((_transport_set_identify(ioc, mpt2sas_phy->handle,
 864            &mpt2sas_phy->identify))) {
 865                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
 866                    ioc->name, __FILE__, __LINE__, __func__);
 867                return -1;
 868        }
 869        phy->identify = mpt2sas_phy->identify;
 870        mpt2sas_phy->attached_handle = le16_to_cpu(phy_pg0.AttachedDevHandle);
 871        if (mpt2sas_phy->attached_handle)
 872                _transport_set_identify(ioc, mpt2sas_phy->attached_handle,
 873                    &mpt2sas_phy->remote_identify);
 874        phy->identify.phy_identifier = mpt2sas_phy->phy_id;
 875        phy->negotiated_linkrate = _transport_convert_phy_link_rate(
 876            phy_pg0.NegotiatedLinkRate & MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
 877        phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
 878            phy_pg0.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
 879        phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
 880            phy_pg0.HwLinkRate >> 4);
 881        phy->minimum_linkrate = _transport_convert_phy_link_rate(
 882            phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
 883        phy->maximum_linkrate = _transport_convert_phy_link_rate(
 884            phy_pg0.ProgrammedLinkRate >> 4);
 885
 886        if ((sas_phy_add(phy))) {
 887                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
 888                    ioc->name, __FILE__, __LINE__, __func__);
 889                sas_phy_free(phy);
 890                return -1;
 891        }
 892        if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
 893                dev_printk(KERN_INFO, &phy->dev,
 894                    "add: handle(0x%04x), sas_addr(0x%016llx)\n"
 895                    "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
 896                    mpt2sas_phy->handle, (unsigned long long)
 897                    mpt2sas_phy->identify.sas_address,
 898                    mpt2sas_phy->attached_handle,
 899                    (unsigned long long)
 900                    mpt2sas_phy->remote_identify.sas_address);
 901        mpt2sas_phy->phy = phy;
 902        return 0;
 903}
 904
 905
 906/**
 907 * mpt2sas_transport_add_expander_phy - report expander phy to transport
 908 * @ioc: per adapter object
 909 * @mpt2sas_phy: mpt2sas per phy object
 910 * @expander_pg1: expander page 1
 911 * @parent_dev: parent device class object
 912 *
 913 * Returns 0 for success, non-zero for failure.
 914 */
 915int
 916mpt2sas_transport_add_expander_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
 917    *mpt2sas_phy, Mpi2ExpanderPage1_t expander_pg1, struct device *parent_dev)
 918{
 919        struct sas_phy *phy;
 920        int phy_index = mpt2sas_phy->phy_id;
 921
 922        INIT_LIST_HEAD(&mpt2sas_phy->port_siblings);
 923        phy = sas_phy_alloc(parent_dev, phy_index);
 924        if (!phy) {
 925                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
 926                    ioc->name, __FILE__, __LINE__, __func__);
 927                return -1;
 928        }
 929        if ((_transport_set_identify(ioc, mpt2sas_phy->handle,
 930            &mpt2sas_phy->identify))) {
 931                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
 932                    ioc->name, __FILE__, __LINE__, __func__);
 933                return -1;
 934        }
 935        phy->identify = mpt2sas_phy->identify;
 936        mpt2sas_phy->attached_handle =
 937            le16_to_cpu(expander_pg1.AttachedDevHandle);
 938        if (mpt2sas_phy->attached_handle)
 939                _transport_set_identify(ioc, mpt2sas_phy->attached_handle,
 940                    &mpt2sas_phy->remote_identify);
 941        phy->identify.phy_identifier = mpt2sas_phy->phy_id;
 942        phy->negotiated_linkrate = _transport_convert_phy_link_rate(
 943            expander_pg1.NegotiatedLinkRate &
 944            MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
 945        phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
 946            expander_pg1.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
 947        phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
 948            expander_pg1.HwLinkRate >> 4);
 949        phy->minimum_linkrate = _transport_convert_phy_link_rate(
 950            expander_pg1.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
 951        phy->maximum_linkrate = _transport_convert_phy_link_rate(
 952            expander_pg1.ProgrammedLinkRate >> 4);
 953
 954        if ((sas_phy_add(phy))) {
 955                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
 956                    ioc->name, __FILE__, __LINE__, __func__);
 957                sas_phy_free(phy);
 958                return -1;
 959        }
 960        if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
 961                dev_printk(KERN_INFO, &phy->dev,
 962                    "add: handle(0x%04x), sas_addr(0x%016llx)\n"
 963                    "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
 964                    mpt2sas_phy->handle, (unsigned long long)
 965                    mpt2sas_phy->identify.sas_address,
 966                    mpt2sas_phy->attached_handle,
 967                    (unsigned long long)
 968                    mpt2sas_phy->remote_identify.sas_address);
 969        mpt2sas_phy->phy = phy;
 970        return 0;
 971}
 972
 973/**
 974 * mpt2sas_transport_update_links - refreshing phy link changes
 975 * @ioc: per adapter object
 976 * @sas_address: sas address of parent expander or sas host
 977 * @handle: attached device handle
 978 * @phy_numberv: phy number
 979 * @link_rate: new link rate
 980 *
 981 * Returns nothing.
 982 */
 983void
 984mpt2sas_transport_update_links(struct MPT2SAS_ADAPTER *ioc,
 985     u64 sas_address, u16 handle, u8 phy_number, u8 link_rate)
 986{
 987        unsigned long flags;
 988        struct _sas_node *sas_node;
 989        struct _sas_phy *mpt2sas_phy;
 990
 991        if (ioc->shost_recovery || ioc->pci_error_recovery)
 992                return;
 993
 994        spin_lock_irqsave(&ioc->sas_node_lock, flags);
 995        sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
 996        if (!sas_node) {
 997                spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 998                return;
 999        }
1000
1001        mpt2sas_phy = &sas_node->phy[phy_number];
1002        mpt2sas_phy->attached_handle = handle;
1003        spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1004        if (handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5)) {
1005                _transport_set_identify(ioc, handle,
1006                    &mpt2sas_phy->remote_identify);
1007                _transport_add_phy_to_an_existing_port(ioc, sas_node,
1008                    mpt2sas_phy, mpt2sas_phy->remote_identify.sas_address);
1009        } else
1010                memset(&mpt2sas_phy->remote_identify, 0 , sizeof(struct
1011                    sas_identify));
1012
1013        if (mpt2sas_phy->phy)
1014                mpt2sas_phy->phy->negotiated_linkrate =
1015                    _transport_convert_phy_link_rate(link_rate);
1016
1017        if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
1018                dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
1019                    "refresh: parent sas_addr(0x%016llx),\n"
1020                    "\tlink_rate(0x%02x), phy(%d)\n"
1021                    "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
1022                    (unsigned long long)sas_address,
1023                    link_rate, phy_number, handle, (unsigned long long)
1024                    mpt2sas_phy->remote_identify.sas_address);
1025}
1026
1027static inline void *
1028phy_to_ioc(struct sas_phy *phy)
1029{
1030        struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
1031        return shost_priv(shost);
1032}
1033
1034static inline void *
1035rphy_to_ioc(struct sas_rphy *rphy)
1036{
1037        struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
1038        return shost_priv(shost);
1039}
1040
1041
1042/* report phy error log structure */
1043struct phy_error_log_request{
1044        u8 smp_frame_type; /* 0x40 */
1045        u8 function; /* 0x11 */
1046        u8 allocated_response_length;
1047        u8 request_length; /* 02 */
1048        u8 reserved_1[5];
1049        u8 phy_identifier;
1050        u8 reserved_2[2];
1051};
1052
1053/* report phy error log reply structure */
1054struct phy_error_log_reply{
1055        u8 smp_frame_type; /* 0x41 */
1056        u8 function; /* 0x11 */
1057        u8 function_result;
1058        u8 response_length;
1059        __be16 expander_change_count;
1060        u8 reserved_1[3];
1061        u8 phy_identifier;
1062        u8 reserved_2[2];
1063        __be32 invalid_dword;
1064        __be32 running_disparity_error;
1065        __be32 loss_of_dword_sync;
1066        __be32 phy_reset_problem;
1067};
1068
1069/**
1070 * _transport_get_expander_phy_error_log - return expander counters
1071 * @ioc: per adapter object
1072 * @phy: The sas phy object
1073 *
1074 * Returns 0 for success, non-zero for failure.
1075 *
1076 */
1077static int
1078_transport_get_expander_phy_error_log(struct MPT2SAS_ADAPTER *ioc,
1079    struct sas_phy *phy)
1080{
1081        Mpi2SmpPassthroughRequest_t *mpi_request;
1082        Mpi2SmpPassthroughReply_t *mpi_reply;
1083        struct phy_error_log_request *phy_error_log_request;
1084        struct phy_error_log_reply *phy_error_log_reply;
1085        int rc;
1086        u16 smid;
1087        u32 ioc_state;
1088        unsigned long timeleft;
1089        void *psge;
1090        u32 sgl_flags;
1091        u8 issue_reset = 0;
1092        void *data_out = NULL;
1093        dma_addr_t data_out_dma;
1094        u32 sz;
1095        u16 wait_state_count;
1096
1097        if (ioc->shost_recovery || ioc->pci_error_recovery) {
1098                printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
1099                    __func__, ioc->name);
1100                return -EFAULT;
1101        }
1102
1103        mutex_lock(&ioc->transport_cmds.mutex);
1104
1105        if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
1106                printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n",
1107                    ioc->name, __func__);
1108                rc = -EAGAIN;
1109                goto out;
1110        }
1111        ioc->transport_cmds.status = MPT2_CMD_PENDING;
1112
1113        wait_state_count = 0;
1114        ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1115        while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1116                if (wait_state_count++ == 10) {
1117                        printk(MPT2SAS_ERR_FMT
1118                            "%s: failed due to ioc not operational\n",
1119                            ioc->name, __func__);
1120                        rc = -EFAULT;
1121                        goto out;
1122                }
1123                ssleep(1);
1124                ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1125                printk(MPT2SAS_INFO_FMT "%s: waiting for "
1126                    "operational state(count=%d)\n", ioc->name,
1127                    __func__, wait_state_count);
1128        }
1129        if (wait_state_count)
1130                printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
1131                    ioc->name, __func__);
1132
1133        smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
1134        if (!smid) {
1135                printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
1136                    ioc->name, __func__);
1137                rc = -EAGAIN;
1138                goto out;
1139        }
1140
1141        mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
1142        ioc->transport_cmds.smid = smid;
1143
1144        sz = sizeof(struct phy_error_log_request) +
1145            sizeof(struct phy_error_log_reply);
1146        data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
1147        if (!data_out) {
1148                printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
1149                    __LINE__, __func__);
1150                rc = -ENOMEM;
1151                mpt2sas_base_free_smid(ioc, smid);
1152                goto out;
1153        }
1154
1155        rc = -EINVAL;
1156        memset(data_out, 0, sz);
1157        phy_error_log_request = data_out;
1158        phy_error_log_request->smp_frame_type = 0x40;
1159        phy_error_log_request->function = 0x11;
1160        phy_error_log_request->request_length = 2;
1161        phy_error_log_request->allocated_response_length = 0;
1162        phy_error_log_request->phy_identifier = phy->number;
1163
1164        memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
1165        mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
1166        mpi_request->PhysicalPort = 0xFF;
1167        mpi_request->VF_ID = 0; /* TODO */
1168        mpi_request->VP_ID = 0;
1169        mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
1170        mpi_request->RequestDataLength =
1171            cpu_to_le16(sizeof(struct phy_error_log_request));
1172        psge = &mpi_request->SGL;
1173
1174        /* WRITE sgel first */
1175        sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1176            MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
1177        sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1178        ioc->base_add_sg_single(psge, sgl_flags |
1179            sizeof(struct phy_error_log_request), data_out_dma);
1180
1181        /* incr sgel */
1182        psge += ioc->sge_size;
1183
1184        /* READ sgel last */
1185        sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1186            MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
1187            MPI2_SGE_FLAGS_END_OF_LIST);
1188        sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1189        ioc->base_add_sg_single(psge, sgl_flags |
1190            sizeof(struct phy_error_log_reply), data_out_dma +
1191            sizeof(struct phy_error_log_request));
1192
1193        dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_error_log - "
1194            "send to sas_addr(0x%016llx), phy(%d)\n", ioc->name,
1195            (unsigned long long)phy->identify.sas_address, phy->number));
1196        init_completion(&ioc->transport_cmds.done);
1197        mpt2sas_base_put_smid_default(ioc, smid);
1198        timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
1199            10*HZ);
1200
1201        if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
1202                printk(MPT2SAS_ERR_FMT "%s: timeout\n",
1203                    ioc->name, __func__);
1204                _debug_dump_mf(mpi_request,
1205                    sizeof(Mpi2SmpPassthroughRequest_t)/4);
1206                if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
1207                        issue_reset = 1;
1208                goto issue_host_reset;
1209        }
1210
1211        dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_error_log - "
1212            "complete\n", ioc->name));
1213
1214        if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
1215
1216                mpi_reply = ioc->transport_cmds.reply;
1217
1218                dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1219                    "phy_error_log - reply data transfer size(%d)\n",
1220                    ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
1221
1222                if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
1223                    sizeof(struct phy_error_log_reply))
1224                        goto out;
1225
1226                phy_error_log_reply = data_out +
1227                    sizeof(struct phy_error_log_request);
1228
1229                dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1230                    "phy_error_log - function_result(%d)\n",
1231                    ioc->name, phy_error_log_reply->function_result));
1232
1233                phy->invalid_dword_count =
1234                    be32_to_cpu(phy_error_log_reply->invalid_dword);
1235                phy->running_disparity_error_count =
1236                    be32_to_cpu(phy_error_log_reply->running_disparity_error);
1237                phy->loss_of_dword_sync_count =
1238                    be32_to_cpu(phy_error_log_reply->loss_of_dword_sync);
1239                phy->phy_reset_problem_count =
1240                    be32_to_cpu(phy_error_log_reply->phy_reset_problem);
1241                rc = 0;
1242        } else
1243                dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1244                    "phy_error_log - no reply\n", ioc->name));
1245
1246 issue_host_reset:
1247        if (issue_reset)
1248                mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1249                    FORCE_BIG_HAMMER);
1250 out:
1251        ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
1252        if (data_out)
1253                pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
1254
1255        mutex_unlock(&ioc->transport_cmds.mutex);
1256        return rc;
1257}
1258
1259/**
1260 * _transport_get_linkerrors - return phy counters for both hba and expanders
1261 * @phy: The sas phy object
1262 *
1263 * Returns 0 for success, non-zero for failure.
1264 *
1265 */
1266static int
1267_transport_get_linkerrors(struct sas_phy *phy)
1268{
1269        struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
1270        unsigned long flags;
1271        Mpi2ConfigReply_t mpi_reply;
1272        Mpi2SasPhyPage1_t phy_pg1;
1273
1274        spin_lock_irqsave(&ioc->sas_node_lock, flags);
1275        if (_transport_sas_node_find_by_sas_address(ioc,
1276            phy->identify.sas_address) == NULL) {
1277                spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1278                return -EINVAL;
1279        }
1280        spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1281
1282        if (phy->identify.sas_address != ioc->sas_hba.sas_address)
1283                return _transport_get_expander_phy_error_log(ioc, phy);
1284
1285        /* get hba phy error logs */
1286        if ((mpt2sas_config_get_phy_pg1(ioc, &mpi_reply, &phy_pg1,
1287                    phy->number))) {
1288                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1289                    ioc->name, __FILE__, __LINE__, __func__);
1290                return -ENXIO;
1291        }
1292
1293        if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
1294                printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status"
1295                    "(0x%04x), loginfo(0x%08x)\n", ioc->name,
1296                    phy->number, le16_to_cpu(mpi_reply.IOCStatus),
1297                    le32_to_cpu(mpi_reply.IOCLogInfo));
1298
1299        phy->invalid_dword_count = le32_to_cpu(phy_pg1.InvalidDwordCount);
1300        phy->running_disparity_error_count =
1301            le32_to_cpu(phy_pg1.RunningDisparityErrorCount);
1302        phy->loss_of_dword_sync_count =
1303            le32_to_cpu(phy_pg1.LossDwordSynchCount);
1304        phy->phy_reset_problem_count =
1305            le32_to_cpu(phy_pg1.PhyResetProblemCount);
1306        return 0;
1307}
1308
1309/**
1310 * _transport_get_enclosure_identifier -
1311 * @phy: The sas phy object
1312 *
1313 * Obtain the enclosure logical id for an expander.
1314 * Returns 0 for success, non-zero for failure.
1315 */
1316static int
1317_transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
1318{
1319        struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
1320        struct _sas_device *sas_device;
1321        unsigned long flags;
1322        int rc;
1323
1324        spin_lock_irqsave(&ioc->sas_device_lock, flags);
1325        sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
1326            rphy->identify.sas_address);
1327        if (sas_device) {
1328                *identifier = sas_device->enclosure_logical_id;
1329                rc = 0;
1330        } else {
1331                *identifier = 0;
1332                rc = -ENXIO;
1333        }
1334        spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1335        return rc;
1336}
1337
1338/**
1339 * _transport_get_bay_identifier -
1340 * @phy: The sas phy object
1341 *
1342 * Returns the slot id for a device that resides inside an enclosure.
1343 */
1344static int
1345_transport_get_bay_identifier(struct sas_rphy *rphy)
1346{
1347        struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
1348        struct _sas_device *sas_device;
1349        unsigned long flags;
1350        int rc;
1351
1352        spin_lock_irqsave(&ioc->sas_device_lock, flags);
1353        sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
1354            rphy->identify.sas_address);
1355        if (sas_device)
1356                rc = sas_device->slot;
1357        else
1358                rc = -ENXIO;
1359        spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1360        return rc;
1361}
1362
1363/* phy control request structure */
1364struct phy_control_request{
1365        u8 smp_frame_type; /* 0x40 */
1366        u8 function; /* 0x91 */
1367        u8 allocated_response_length;
1368        u8 request_length; /* 0x09 */
1369        u16 expander_change_count;
1370        u8 reserved_1[3];
1371        u8 phy_identifier;
1372        u8 phy_operation;
1373        u8 reserved_2[13];
1374        u64 attached_device_name;
1375        u8 programmed_min_physical_link_rate;
1376        u8 programmed_max_physical_link_rate;
1377        u8 reserved_3[6];
1378};
1379
1380/* phy control reply structure */
1381struct phy_control_reply{
1382        u8 smp_frame_type; /* 0x41 */
1383        u8 function; /* 0x11 */
1384        u8 function_result;
1385        u8 response_length;
1386};
1387
1388#define SMP_PHY_CONTROL_LINK_RESET      (0x01)
1389#define SMP_PHY_CONTROL_HARD_RESET      (0x02)
1390#define SMP_PHY_CONTROL_DISABLE         (0x03)
1391
1392/**
1393 * _transport_expander_phy_control - expander phy control
1394 * @ioc: per adapter object
1395 * @phy: The sas phy object
1396 *
1397 * Returns 0 for success, non-zero for failure.
1398 *
1399 */
1400static int
1401_transport_expander_phy_control(struct MPT2SAS_ADAPTER *ioc,
1402    struct sas_phy *phy, u8 phy_operation)
1403{
1404        Mpi2SmpPassthroughRequest_t *mpi_request;
1405        Mpi2SmpPassthroughReply_t *mpi_reply;
1406        struct phy_control_request *phy_control_request;
1407        struct phy_control_reply *phy_control_reply;
1408        int rc;
1409        u16 smid;
1410        u32 ioc_state;
1411        unsigned long timeleft;
1412        void *psge;
1413        u32 sgl_flags;
1414        u8 issue_reset = 0;
1415        void *data_out = NULL;
1416        dma_addr_t data_out_dma;
1417        u32 sz;
1418        u16 wait_state_count;
1419
1420        if (ioc->shost_recovery) {
1421                printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
1422                    __func__, ioc->name);
1423                return -EFAULT;
1424        }
1425
1426        mutex_lock(&ioc->transport_cmds.mutex);
1427
1428        if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
1429                printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n",
1430                    ioc->name, __func__);
1431                rc = -EAGAIN;
1432                goto out;
1433        }
1434        ioc->transport_cmds.status = MPT2_CMD_PENDING;
1435
1436        wait_state_count = 0;
1437        ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1438        while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1439                if (wait_state_count++ == 10) {
1440                        printk(MPT2SAS_ERR_FMT
1441                            "%s: failed due to ioc not operational\n",
1442                            ioc->name, __func__);
1443                        rc = -EFAULT;
1444                        goto out;
1445                }
1446                ssleep(1);
1447                ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1448                printk(MPT2SAS_INFO_FMT "%s: waiting for "
1449                    "operational state(count=%d)\n", ioc->name,
1450                    __func__, wait_state_count);
1451        }
1452        if (wait_state_count)
1453                printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
1454                    ioc->name, __func__);
1455
1456        smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
1457        if (!smid) {
1458                printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
1459                    ioc->name, __func__);
1460                rc = -EAGAIN;
1461                goto out;
1462        }
1463
1464        mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
1465        ioc->transport_cmds.smid = smid;
1466
1467        sz = sizeof(struct phy_control_request) +
1468            sizeof(struct phy_control_reply);
1469        data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
1470        if (!data_out) {
1471                printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
1472                    __LINE__, __func__);
1473                rc = -ENOMEM;
1474                mpt2sas_base_free_smid(ioc, smid);
1475                goto out;
1476        }
1477
1478        rc = -EINVAL;
1479        memset(data_out, 0, sz);
1480        phy_control_request = data_out;
1481        phy_control_request->smp_frame_type = 0x40;
1482        phy_control_request->function = 0x91;
1483        phy_control_request->request_length = 9;
1484        phy_control_request->allocated_response_length = 0;
1485        phy_control_request->phy_identifier = phy->number;
1486        phy_control_request->phy_operation = phy_operation;
1487        phy_control_request->programmed_min_physical_link_rate =
1488            phy->minimum_linkrate << 4;
1489        phy_control_request->programmed_max_physical_link_rate =
1490            phy->maximum_linkrate << 4;
1491
1492        memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
1493        mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
1494        mpi_request->PhysicalPort = 0xFF;
1495        mpi_request->VF_ID = 0; /* TODO */
1496        mpi_request->VP_ID = 0;
1497        mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
1498        mpi_request->RequestDataLength =
1499            cpu_to_le16(sizeof(struct phy_error_log_request));
1500        psge = &mpi_request->SGL;
1501
1502        /* WRITE sgel first */
1503        sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1504            MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
1505        sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1506        ioc->base_add_sg_single(psge, sgl_flags |
1507            sizeof(struct phy_control_request), data_out_dma);
1508
1509        /* incr sgel */
1510        psge += ioc->sge_size;
1511
1512        /* READ sgel last */
1513        sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1514            MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
1515            MPI2_SGE_FLAGS_END_OF_LIST);
1516        sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1517        ioc->base_add_sg_single(psge, sgl_flags |
1518            sizeof(struct phy_control_reply), data_out_dma +
1519            sizeof(struct phy_control_request));
1520
1521        dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_control - "
1522            "send to sas_addr(0x%016llx), phy(%d), opcode(%d)\n", ioc->name,
1523            (unsigned long long)phy->identify.sas_address, phy->number,
1524            phy_operation));
1525
1526        init_completion(&ioc->transport_cmds.done);
1527        mpt2sas_base_put_smid_default(ioc, smid);
1528        timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
1529            10*HZ);
1530
1531        if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
1532                printk(MPT2SAS_ERR_FMT "%s: timeout\n",
1533                    ioc->name, __func__);
1534                _debug_dump_mf(mpi_request,
1535                    sizeof(Mpi2SmpPassthroughRequest_t)/4);
1536                if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
1537                        issue_reset = 1;
1538                goto issue_host_reset;
1539        }
1540
1541        dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_control - "
1542            "complete\n", ioc->name));
1543
1544        if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
1545
1546                mpi_reply = ioc->transport_cmds.reply;
1547
1548                dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1549                    "phy_control - reply data transfer size(%d)\n",
1550                    ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
1551
1552                if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
1553                    sizeof(struct phy_control_reply))
1554                        goto out;
1555
1556                phy_control_reply = data_out +
1557                    sizeof(struct phy_control_request);
1558
1559                dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1560                    "phy_control - function_result(%d)\n",
1561                    ioc->name, phy_control_reply->function_result));
1562
1563                rc = 0;
1564        } else
1565                dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1566                    "phy_control - no reply\n", ioc->name));
1567
1568 issue_host_reset:
1569        if (issue_reset)
1570                mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1571                    FORCE_BIG_HAMMER);
1572 out:
1573        ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
1574        if (data_out)
1575                pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
1576
1577        mutex_unlock(&ioc->transport_cmds.mutex);
1578        return rc;
1579}
1580
1581/**
1582 * _transport_phy_reset -
1583 * @phy: The sas phy object
1584 * @hard_reset:
1585 *
1586 * Returns 0 for success, non-zero for failure.
1587 */
1588static int
1589_transport_phy_reset(struct sas_phy *phy, int hard_reset)
1590{
1591        struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
1592        Mpi2SasIoUnitControlReply_t mpi_reply;
1593        Mpi2SasIoUnitControlRequest_t mpi_request;
1594        unsigned long flags;
1595
1596        spin_lock_irqsave(&ioc->sas_node_lock, flags);
1597        if (_transport_sas_node_find_by_sas_address(ioc,
1598            phy->identify.sas_address) == NULL) {
1599                spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1600                return -EINVAL;
1601        }
1602        spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1603
1604        /* handle expander phys */
1605        if (phy->identify.sas_address != ioc->sas_hba.sas_address)
1606                return _transport_expander_phy_control(ioc, phy,
1607                    (hard_reset == 1) ? SMP_PHY_CONTROL_HARD_RESET :
1608                    SMP_PHY_CONTROL_LINK_RESET);
1609
1610        /* handle hba phys */
1611        memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlReply_t));
1612        mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
1613        mpi_request.Operation = hard_reset ?
1614            MPI2_SAS_OP_PHY_HARD_RESET : MPI2_SAS_OP_PHY_LINK_RESET;
1615        mpi_request.PhyNum = phy->number;
1616
1617        if ((mpt2sas_base_sas_iounit_control(ioc, &mpi_reply, &mpi_request))) {
1618                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1619                    ioc->name, __FILE__, __LINE__, __func__);
1620                return -ENXIO;
1621        }
1622
1623        if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
1624                printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status"
1625                    "(0x%04x), loginfo(0x%08x)\n", ioc->name,
1626                    phy->number, le16_to_cpu(mpi_reply.IOCStatus),
1627                    le32_to_cpu(mpi_reply.IOCLogInfo));
1628
1629        return 0;
1630}
1631
1632/**
1633 * _transport_phy_enable - enable/disable phys
1634 * @phy: The sas phy object
1635 * @enable: enable phy when true
1636 *
1637 * Only support sas_host direct attached phys.
1638 * Returns 0 for success, non-zero for failure.
1639 */
1640static int
1641_transport_phy_enable(struct sas_phy *phy, int enable)
1642{
1643        struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
1644        Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
1645        Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
1646        Mpi2ConfigReply_t mpi_reply;
1647        u16 ioc_status;
1648        u16 sz;
1649        int rc = 0;
1650        unsigned long flags;
1651        int i, discovery_active;
1652
1653        spin_lock_irqsave(&ioc->sas_node_lock, flags);
1654        if (_transport_sas_node_find_by_sas_address(ioc,
1655            phy->identify.sas_address) == NULL) {
1656                spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1657                return -EINVAL;
1658        }
1659        spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1660
1661        /* handle expander phys */
1662        if (phy->identify.sas_address != ioc->sas_hba.sas_address)
1663                return _transport_expander_phy_control(ioc, phy,
1664                    (enable == 1) ? SMP_PHY_CONTROL_LINK_RESET :
1665                    SMP_PHY_CONTROL_DISABLE);
1666
1667        /* handle hba phys */
1668
1669        /* read sas_iounit page 0 */
1670        sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys *
1671            sizeof(Mpi2SasIOUnit0PhyData_t));
1672        sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
1673        if (!sas_iounit_pg0) {
1674                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1675                    ioc->name, __FILE__, __LINE__, __func__);
1676                rc = -ENOMEM;
1677                goto out;
1678        }
1679        if ((mpt2sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
1680            sas_iounit_pg0, sz))) {
1681                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1682                    ioc->name, __FILE__, __LINE__, __func__);
1683                rc = -ENXIO;
1684                goto out;
1685        }
1686        ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1687            MPI2_IOCSTATUS_MASK;
1688        if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1689                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1690                    ioc->name, __FILE__, __LINE__, __func__);
1691                rc = -EIO;
1692                goto out;
1693        }
1694
1695        /* unable to enable/disable phys when when discovery is active */
1696        for (i = 0, discovery_active = 0; i < ioc->sas_hba.num_phys ; i++) {
1697                if (sas_iounit_pg0->PhyData[i].PortFlags &
1698                    MPI2_SASIOUNIT0_PORTFLAGS_DISCOVERY_IN_PROGRESS) {
1699                        printk(MPT2SAS_ERR_FMT "discovery is active on "
1700                            "port = %d, phy = %d: unable to enable/disable "
1701                            "phys, try again later!\n", ioc->name,
1702                            sas_iounit_pg0->PhyData[i].Port, i);
1703                        discovery_active = 1;
1704                }
1705        }
1706
1707        if (discovery_active) {
1708                rc = -EAGAIN;
1709                goto out;
1710        }
1711
1712        /* read sas_iounit page 1 */
1713        sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
1714            sizeof(Mpi2SasIOUnit1PhyData_t));
1715        sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
1716        if (!sas_iounit_pg1) {
1717                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1718                    ioc->name, __FILE__, __LINE__, __func__);
1719                rc = -ENOMEM;
1720                goto out;
1721        }
1722        if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
1723            sas_iounit_pg1, sz))) {
1724                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1725                    ioc->name, __FILE__, __LINE__, __func__);
1726                rc = -ENXIO;
1727                goto out;
1728        }
1729        ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1730            MPI2_IOCSTATUS_MASK;
1731        if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1732                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1733                    ioc->name, __FILE__, __LINE__, __func__);
1734                rc = -EIO;
1735                goto out;
1736        }
1737        /* copy Port/PortFlags/PhyFlags from page 0 */
1738        for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
1739                sas_iounit_pg1->PhyData[i].Port =
1740                    sas_iounit_pg0->PhyData[i].Port;
1741                sas_iounit_pg1->PhyData[i].PortFlags =
1742                    (sas_iounit_pg0->PhyData[i].PortFlags &
1743                    MPI2_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG);
1744                sas_iounit_pg1->PhyData[i].PhyFlags =
1745                    (sas_iounit_pg0->PhyData[i].PhyFlags &
1746                    (MPI2_SASIOUNIT0_PHYFLAGS_ZONING_ENABLED +
1747                    MPI2_SASIOUNIT0_PHYFLAGS_PHY_DISABLED));
1748        }
1749        if (enable)
1750                sas_iounit_pg1->PhyData[phy->number].PhyFlags
1751                    &= ~MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
1752        else
1753                sas_iounit_pg1->PhyData[phy->number].PhyFlags
1754                    |= MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
1755
1756        mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1, sz);
1757
1758        /* link reset */
1759        if (enable)
1760                _transport_phy_reset(phy, 0);
1761
1762 out:
1763        kfree(sas_iounit_pg1);
1764        kfree(sas_iounit_pg0);
1765        return rc;
1766}
1767
1768/**
1769 * _transport_phy_speed - set phy min/max link rates
1770 * @phy: The sas phy object
1771 * @rates: rates defined in sas_phy_linkrates
1772 *
1773 * Only support sas_host direct attached phys.
1774 * Returns 0 for success, non-zero for failure.
1775 */
1776static int
1777_transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
1778{
1779        struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
1780        Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
1781        Mpi2SasPhyPage0_t phy_pg0;
1782        Mpi2ConfigReply_t mpi_reply;
1783        u16 ioc_status;
1784        u16 sz;
1785        int i;
1786        int rc = 0;
1787        unsigned long flags;
1788
1789        spin_lock_irqsave(&ioc->sas_node_lock, flags);
1790        if (_transport_sas_node_find_by_sas_address(ioc,
1791            phy->identify.sas_address) == NULL) {
1792                spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1793                return -EINVAL;
1794        }
1795        spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1796
1797        if (!rates->minimum_linkrate)
1798                rates->minimum_linkrate = phy->minimum_linkrate;
1799        else if (rates->minimum_linkrate < phy->minimum_linkrate_hw)
1800                rates->minimum_linkrate = phy->minimum_linkrate_hw;
1801
1802        if (!rates->maximum_linkrate)
1803                rates->maximum_linkrate = phy->maximum_linkrate;
1804        else if (rates->maximum_linkrate > phy->maximum_linkrate_hw)
1805                rates->maximum_linkrate = phy->maximum_linkrate_hw;
1806
1807        /* handle expander phys */
1808        if (phy->identify.sas_address != ioc->sas_hba.sas_address) {
1809                phy->minimum_linkrate = rates->minimum_linkrate;
1810                phy->maximum_linkrate = rates->maximum_linkrate;
1811                return _transport_expander_phy_control(ioc, phy,
1812                    SMP_PHY_CONTROL_LINK_RESET);
1813        }
1814
1815        /* handle hba phys */
1816
1817        /* sas_iounit page 1 */
1818        sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
1819            sizeof(Mpi2SasIOUnit1PhyData_t));
1820        sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
1821        if (!sas_iounit_pg1) {
1822                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1823                    ioc->name, __FILE__, __LINE__, __func__);
1824                rc = -ENOMEM;
1825                goto out;
1826        }
1827        if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
1828            sas_iounit_pg1, sz))) {
1829                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1830                    ioc->name, __FILE__, __LINE__, __func__);
1831                rc = -ENXIO;
1832                goto out;
1833        }
1834        ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1835            MPI2_IOCSTATUS_MASK;
1836        if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1837                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1838                    ioc->name, __FILE__, __LINE__, __func__);
1839                rc = -EIO;
1840                goto out;
1841        }
1842
1843        for (i = 0; i < ioc->sas_hba.num_phys; i++) {
1844                if (phy->number != i) {
1845                        sas_iounit_pg1->PhyData[i].MaxMinLinkRate =
1846                            (ioc->sas_hba.phy[i].phy->minimum_linkrate +
1847                            (ioc->sas_hba.phy[i].phy->maximum_linkrate << 4));
1848                } else {
1849                        sas_iounit_pg1->PhyData[i].MaxMinLinkRate =
1850                            (rates->minimum_linkrate +
1851                            (rates->maximum_linkrate << 4));
1852                }
1853        }
1854
1855        if (mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1,
1856            sz)) {
1857                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1858                    ioc->name, __FILE__, __LINE__, __func__);
1859                rc = -ENXIO;
1860                goto out;
1861        }
1862
1863        /* link reset */
1864        _transport_phy_reset(phy, 0);
1865
1866        /* read phy page 0, then update the rates in the sas transport phy */
1867        if (!mpt2sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0,
1868            phy->number)) {
1869                phy->minimum_linkrate = _transport_convert_phy_link_rate(
1870                    phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
1871                phy->maximum_linkrate = _transport_convert_phy_link_rate(
1872                    phy_pg0.ProgrammedLinkRate >> 4);
1873                phy->negotiated_linkrate = _transport_convert_phy_link_rate(
1874                    phy_pg0.NegotiatedLinkRate &
1875                    MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
1876        }
1877
1878 out:
1879        kfree(sas_iounit_pg1);
1880        return rc;
1881}
1882
1883
1884/**
1885 * _transport_smp_handler - transport portal for smp passthru
1886 * @shost: shost object
1887 * @rphy: sas transport rphy object
1888 * @req:
1889 *
1890 * This used primarily for smp_utils.
1891 * Example:
1892 *           smp_rep_general /sys/class/bsg/expander-5:0
1893 */
1894static int
1895_transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
1896    struct request *req)
1897{
1898        struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
1899        Mpi2SmpPassthroughRequest_t *mpi_request;
1900        Mpi2SmpPassthroughReply_t *mpi_reply;
1901        int rc, i;
1902        u16 smid;
1903        u32 ioc_state;
1904        unsigned long timeleft;
1905        void *psge;
1906        u32 sgl_flags;
1907        u8 issue_reset = 0;
1908        dma_addr_t dma_addr_in = 0;
1909        dma_addr_t dma_addr_out = 0;
1910        dma_addr_t pci_dma_in = 0;
1911        dma_addr_t pci_dma_out = 0;
1912        void *pci_addr_in = NULL;
1913        void *pci_addr_out = NULL;
1914        u16 wait_state_count;
1915        struct request *rsp = req->next_rq;
1916        struct bio_vec *bvec = NULL;
1917
1918        if (!rsp) {
1919                printk(MPT2SAS_ERR_FMT "%s: the smp response space is "
1920                    "missing\n", ioc->name, __func__);
1921                return -EINVAL;
1922        }
1923        if (ioc->shost_recovery || ioc->pci_error_recovery) {
1924                printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
1925                    __func__, ioc->name);
1926                return -EFAULT;
1927        }
1928
1929        rc = mutex_lock_interruptible(&ioc->transport_cmds.mutex);
1930        if (rc)
1931                return rc;
1932
1933        if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
1934                printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n", ioc->name,
1935                    __func__);
1936                rc = -EAGAIN;
1937                goto out;
1938        }
1939        ioc->transport_cmds.status = MPT2_CMD_PENDING;
1940
1941        /* Check if the request is split across multiple segments */
1942        if (req->bio->bi_vcnt > 1) {
1943                u32 offset = 0;
1944
1945                /* Allocate memory and copy the request */
1946                pci_addr_out = pci_alloc_consistent(ioc->pdev,
1947                    blk_rq_bytes(req), &pci_dma_out);
1948                if (!pci_addr_out) {
1949                        printk(MPT2SAS_INFO_FMT "%s(): PCI Addr out = NULL\n",
1950                            ioc->name, __func__);
1951                        rc = -ENOMEM;
1952                        goto out;
1953                }
1954
1955                bio_for_each_segment(bvec, req->bio, i) {
1956                        memcpy(pci_addr_out + offset,
1957                            page_address(bvec->bv_page) + bvec->bv_offset,
1958                            bvec->bv_len);
1959                        offset += bvec->bv_len;
1960                }
1961        } else {
1962                dma_addr_out = pci_map_single(ioc->pdev, bio_data(req->bio),
1963                    blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL);
1964                if (!dma_addr_out) {
1965                        printk(MPT2SAS_INFO_FMT "%s(): DMA Addr out = NULL\n",
1966                            ioc->name, __func__);
1967                        rc = -ENOMEM;
1968                        goto free_pci;
1969                }
1970        }
1971
1972        /* Check if the response needs to be populated across
1973         * multiple segments */
1974        if (rsp->bio->bi_vcnt > 1) {
1975                pci_addr_in = pci_alloc_consistent(ioc->pdev, blk_rq_bytes(rsp),
1976                    &pci_dma_in);
1977                if (!pci_addr_in) {
1978                        printk(MPT2SAS_INFO_FMT "%s(): PCI Addr in = NULL\n",
1979                            ioc->name, __func__);
1980                        rc = -ENOMEM;
1981                        goto unmap;
1982                }
1983        } else {
1984                dma_addr_in =  pci_map_single(ioc->pdev, bio_data(rsp->bio),
1985                    blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL);
1986                if (!dma_addr_in) {
1987                        printk(MPT2SAS_INFO_FMT "%s(): DMA Addr in = NULL\n",
1988                            ioc->name, __func__);
1989                        rc = -ENOMEM;
1990                        goto unmap;
1991                }
1992        }
1993
1994        wait_state_count = 0;
1995        ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1996        while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1997                if (wait_state_count++ == 10) {
1998                        printk(MPT2SAS_ERR_FMT
1999                            "%s: failed due to ioc not operational\n",
2000                            ioc->name, __func__);
2001                        rc = -EFAULT;
2002                        goto unmap;
2003                }
2004                ssleep(1);
2005                ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
2006                printk(MPT2SAS_INFO_FMT "%s: waiting for "
2007                    "operational state(count=%d)\n", ioc->name,
2008                    __func__, wait_state_count);
2009        }
2010        if (wait_state_count)
2011                printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
2012                    ioc->name, __func__);
2013
2014        smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
2015        if (!smid) {
2016                printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
2017                    ioc->name, __func__);
2018                rc = -EAGAIN;
2019                goto unmap;
2020        }
2021
2022        rc = 0;
2023        mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
2024        ioc->transport_cmds.smid = smid;
2025
2026        memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
2027        mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
2028        mpi_request->PhysicalPort = 0xFF;
2029        mpi_request->VF_ID = 0; /* TODO */
2030        mpi_request->VP_ID = 0;
2031        mpi_request->SASAddress = (rphy) ?
2032            cpu_to_le64(rphy->identify.sas_address) :
2033            cpu_to_le64(ioc->sas_hba.sas_address);
2034        mpi_request->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4);
2035        psge = &mpi_request->SGL;
2036
2037        /* WRITE sgel first */
2038        sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
2039            MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
2040        sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
2041        if (req->bio->bi_vcnt > 1) {
2042                ioc->base_add_sg_single(psge, sgl_flags |
2043                    (blk_rq_bytes(req) - 4), pci_dma_out);
2044        } else {
2045                ioc->base_add_sg_single(psge, sgl_flags |
2046                    (blk_rq_bytes(req) - 4), dma_addr_out);
2047        }
2048
2049        /* incr sgel */
2050        psge += ioc->sge_size;
2051
2052        /* READ sgel last */
2053        sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
2054            MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
2055            MPI2_SGE_FLAGS_END_OF_LIST);
2056        sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
2057        if (rsp->bio->bi_vcnt > 1) {
2058                ioc->base_add_sg_single(psge, sgl_flags |
2059                    (blk_rq_bytes(rsp) + 4), pci_dma_in);
2060        } else {
2061                ioc->base_add_sg_single(psge, sgl_flags |
2062                    (blk_rq_bytes(rsp) + 4), dma_addr_in);
2063        }
2064
2065        dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "%s - "
2066            "sending smp request\n", ioc->name, __func__));
2067
2068        init_completion(&ioc->transport_cmds.done);
2069        mpt2sas_base_put_smid_default(ioc, smid);
2070        timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
2071            10*HZ);
2072
2073        if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
2074                printk(MPT2SAS_ERR_FMT "%s : timeout\n",
2075                    __func__, ioc->name);
2076                _debug_dump_mf(mpi_request,
2077                    sizeof(Mpi2SmpPassthroughRequest_t)/4);
2078                if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
2079                        issue_reset = 1;
2080                goto issue_host_reset;
2081        }
2082
2083        dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "%s - "
2084            "complete\n", ioc->name, __func__));
2085
2086        if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
2087
2088                mpi_reply = ioc->transport_cmds.reply;
2089
2090                dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
2091                    "%s - reply data transfer size(%d)\n",
2092                    ioc->name, __func__,
2093                    le16_to_cpu(mpi_reply->ResponseDataLength)));
2094
2095                memcpy(req->sense, mpi_reply, sizeof(*mpi_reply));
2096                req->sense_len = sizeof(*mpi_reply);
2097                req->resid_len = 0;
2098                rsp->resid_len -=
2099                    le16_to_cpu(mpi_reply->ResponseDataLength);
2100                /* check if the resp needs to be copied from the allocated
2101                 * pci mem */
2102                if (rsp->bio->bi_vcnt > 1) {
2103                        u32 offset = 0;
2104                        u32 bytes_to_copy =
2105                            le16_to_cpu(mpi_reply->ResponseDataLength);
2106                        bio_for_each_segment(bvec, rsp->bio, i) {
2107                                if (bytes_to_copy <= bvec->bv_len) {
2108                                        memcpy(page_address(bvec->bv_page) +
2109                                            bvec->bv_offset, pci_addr_in +
2110                                            offset, bytes_to_copy);
2111                                        break;
2112                                } else {
2113                                        memcpy(page_address(bvec->bv_page) +
2114                                            bvec->bv_offset, pci_addr_in +
2115                                            offset, bvec->bv_len);
2116                                        bytes_to_copy -= bvec->bv_len;
2117                                }
2118                                offset += bvec->bv_len;
2119                        }
2120                }
2121        } else {
2122                dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
2123                    "%s - no reply\n", ioc->name, __func__));
2124                rc = -ENXIO;
2125        }
2126
2127 issue_host_reset:
2128        if (issue_reset) {
2129                mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
2130                    FORCE_BIG_HAMMER);
2131                rc = -ETIMEDOUT;
2132        }
2133
2134 unmap:
2135        if (dma_addr_out)
2136                pci_unmap_single(ioc->pdev, dma_addr_out, blk_rq_bytes(req),
2137                    PCI_DMA_BIDIRECTIONAL);
2138        if (dma_addr_in)
2139                pci_unmap_single(ioc->pdev, dma_addr_in, blk_rq_bytes(rsp),
2140                    PCI_DMA_BIDIRECTIONAL);
2141
2142 free_pci:
2143        if (pci_addr_out)
2144                pci_free_consistent(ioc->pdev, blk_rq_bytes(req), pci_addr_out,
2145                    pci_dma_out);
2146
2147        if (pci_addr_in)
2148                pci_free_consistent(ioc->pdev, blk_rq_bytes(rsp), pci_addr_in,
2149                    pci_dma_in);
2150
2151 out:
2152        ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
2153        mutex_unlock(&ioc->transport_cmds.mutex);
2154        return rc;
2155}
2156
2157struct sas_function_template mpt2sas_transport_functions = {
2158        .get_linkerrors         = _transport_get_linkerrors,
2159        .get_enclosure_identifier = _transport_get_enclosure_identifier,
2160        .get_bay_identifier     = _transport_get_bay_identifier,
2161        .phy_reset              = _transport_phy_reset,
2162        .phy_enable             = _transport_phy_enable,
2163        .set_phy_speed          = _transport_phy_speed,
2164        .smp_handler            = _transport_smp_handler,
2165};
2166
2167struct scsi_transport_template *mpt2sas_transport_template;
2168