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