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        void *psge;
 304        u8 issue_reset = 0;
 305        void *data_out = NULL;
 306        dma_addr_t data_out_dma;
 307        dma_addr_t data_in_dma;
 308        size_t data_in_sz;
 309        size_t data_out_sz;
 310        u16 wait_state_count;
 311
 312        if (ioc->shost_recovery || ioc->pci_error_recovery) {
 313                pr_info(MPT3SAS_FMT "%s: host reset in progress!\n",
 314                    __func__, ioc->name);
 315                return -EFAULT;
 316        }
 317
 318        mutex_lock(&ioc->transport_cmds.mutex);
 319
 320        if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) {
 321                pr_err(MPT3SAS_FMT "%s: transport_cmds in use\n",
 322                    ioc->name, __func__);
 323                rc = -EAGAIN;
 324                goto out;
 325        }
 326        ioc->transport_cmds.status = MPT3_CMD_PENDING;
 327
 328        wait_state_count = 0;
 329        ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
 330        while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
 331                if (wait_state_count++ == 10) {
 332                        pr_err(MPT3SAS_FMT
 333                            "%s: failed due to ioc not operational\n",
 334                            ioc->name, __func__);
 335                        rc = -EFAULT;
 336                        goto out;
 337                }
 338                ssleep(1);
 339                ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
 340                pr_info(MPT3SAS_FMT
 341                        "%s: waiting for operational state(count=%d)\n",
 342                        ioc->name, __func__, wait_state_count);
 343        }
 344        if (wait_state_count)
 345                pr_info(MPT3SAS_FMT "%s: ioc is operational\n",
 346                    ioc->name, __func__);
 347
 348        smid = mpt3sas_base_get_smid(ioc, ioc->transport_cb_idx);
 349        if (!smid) {
 350                pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
 351                    ioc->name, __func__);
 352                rc = -EAGAIN;
 353                goto out;
 354        }
 355
 356        rc = 0;
 357        mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
 358        ioc->transport_cmds.smid = smid;
 359
 360        data_out_sz = sizeof(struct rep_manu_request);
 361        data_in_sz = sizeof(struct rep_manu_reply);
 362        data_out = pci_alloc_consistent(ioc->pdev, data_out_sz + data_in_sz,
 363            &data_out_dma);
 364
 365        if (!data_out) {
 366                pr_err("failure at %s:%d/%s()!\n", __FILE__,
 367                    __LINE__, __func__);
 368                rc = -ENOMEM;
 369                mpt3sas_base_free_smid(ioc, smid);
 370                goto out;
 371        }
 372
 373        data_in_dma = data_out_dma + sizeof(struct rep_manu_request);
 374
 375        manufacture_request = data_out;
 376        manufacture_request->smp_frame_type = 0x40;
 377        manufacture_request->function = 1;
 378        manufacture_request->reserved = 0;
 379        manufacture_request->request_length = 0;
 380
 381        memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
 382        mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
 383        mpi_request->PhysicalPort = 0xFF;
 384        mpi_request->SASAddress = cpu_to_le64(sas_address);
 385        mpi_request->RequestDataLength = cpu_to_le16(data_out_sz);
 386        psge = &mpi_request->SGL;
 387
 388        ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma,
 389            data_in_sz);
 390
 391        dtransportprintk(ioc, pr_info(MPT3SAS_FMT
 392                "report_manufacture - send to sas_addr(0x%016llx)\n",
 393                ioc->name, (unsigned long long)sas_address));
 394        init_completion(&ioc->transport_cmds.done);
 395        ioc->put_smid_default(ioc, smid);
 396        wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ);
 397
 398        if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) {
 399                pr_err(MPT3SAS_FMT "%s: timeout\n",
 400                    ioc->name, __func__);
 401                _debug_dump_mf(mpi_request,
 402                    sizeof(Mpi2SmpPassthroughRequest_t)/4);
 403                if (!(ioc->transport_cmds.status & MPT3_CMD_RESET))
 404                        issue_reset = 1;
 405                goto issue_host_reset;
 406        }
 407
 408        dtransportprintk(ioc, pr_info(MPT3SAS_FMT
 409                "report_manufacture - complete\n", ioc->name));
 410
 411        if (ioc->transport_cmds.status & MPT3_CMD_REPLY_VALID) {
 412                u8 *tmp;
 413
 414                mpi_reply = ioc->transport_cmds.reply;
 415
 416                dtransportprintk(ioc, pr_info(MPT3SAS_FMT
 417                    "report_manufacture - reply data transfer size(%d)\n",
 418                    ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
 419
 420                if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
 421                    sizeof(struct rep_manu_reply))
 422                        goto out;
 423
 424                manufacture_reply = data_out + sizeof(struct rep_manu_request);
 425                strncpy(edev->vendor_id, manufacture_reply->vendor_id,
 426                     SAS_EXPANDER_VENDOR_ID_LEN);
 427                strncpy(edev->product_id, manufacture_reply->product_id,
 428                     SAS_EXPANDER_PRODUCT_ID_LEN);
 429                strncpy(edev->product_rev, manufacture_reply->product_rev,
 430                     SAS_EXPANDER_PRODUCT_REV_LEN);
 431                edev->level = manufacture_reply->sas_format & 1;
 432                if (edev->level) {
 433                        strncpy(edev->component_vendor_id,
 434                            manufacture_reply->component_vendor_id,
 435                             SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN);
 436                        tmp = (u8 *)&manufacture_reply->component_id;
 437                        edev->component_id = tmp[0] << 8 | tmp[1];
 438                        edev->component_revision_id =
 439                            manufacture_reply->component_revision_id;
 440                }
 441        } else
 442                dtransportprintk(ioc, pr_info(MPT3SAS_FMT
 443                    "report_manufacture - no reply\n", ioc->name));
 444
 445 issue_host_reset:
 446        if (issue_reset)
 447                mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
 448 out:
 449        ioc->transport_cmds.status = MPT3_CMD_NOT_USED;
 450        if (data_out)
 451                pci_free_consistent(ioc->pdev, data_out_sz + data_in_sz,
 452                    data_out, data_out_dma);
 453
 454        mutex_unlock(&ioc->transport_cmds.mutex);
 455        return rc;
 456}
 457
 458
 459/**
 460 * _transport_delete_port - helper function to removing a port
 461 * @ioc: per adapter object
 462 * @mpt3sas_port: mpt3sas per port object
 463 *
 464 * Returns nothing.
 465 */
 466static void
 467_transport_delete_port(struct MPT3SAS_ADAPTER *ioc,
 468        struct _sas_port *mpt3sas_port)
 469{
 470        u64 sas_address = mpt3sas_port->remote_identify.sas_address;
 471        enum sas_device_type device_type =
 472            mpt3sas_port->remote_identify.device_type;
 473
 474        dev_printk(KERN_INFO, &mpt3sas_port->port->dev,
 475            "remove: sas_addr(0x%016llx)\n",
 476            (unsigned long long) sas_address);
 477
 478        ioc->logging_level |= MPT_DEBUG_TRANSPORT;
 479        if (device_type == SAS_END_DEVICE)
 480                mpt3sas_device_remove_by_sas_address(ioc, sas_address);
 481        else if (device_type == SAS_EDGE_EXPANDER_DEVICE ||
 482            device_type == SAS_FANOUT_EXPANDER_DEVICE)
 483                mpt3sas_expander_remove(ioc, sas_address);
 484        ioc->logging_level &= ~MPT_DEBUG_TRANSPORT;
 485}
 486
 487/**
 488 * _transport_delete_phy - helper function to removing single phy from port
 489 * @ioc: per adapter object
 490 * @mpt3sas_port: mpt3sas per port object
 491 * @mpt3sas_phy: mpt3sas per phy object
 492 *
 493 * Returns nothing.
 494 */
 495static void
 496_transport_delete_phy(struct MPT3SAS_ADAPTER *ioc,
 497        struct _sas_port *mpt3sas_port, struct _sas_phy *mpt3sas_phy)
 498{
 499        u64 sas_address = mpt3sas_port->remote_identify.sas_address;
 500
 501        dev_printk(KERN_INFO, &mpt3sas_phy->phy->dev,
 502            "remove: sas_addr(0x%016llx), phy(%d)\n",
 503            (unsigned long long) sas_address, mpt3sas_phy->phy_id);
 504
 505        list_del(&mpt3sas_phy->port_siblings);
 506        mpt3sas_port->num_phys--;
 507        sas_port_delete_phy(mpt3sas_port->port, mpt3sas_phy->phy);
 508        mpt3sas_phy->phy_belongs_to_port = 0;
 509}
 510
 511/**
 512 * _transport_add_phy - helper function to adding single phy to port
 513 * @ioc: per adapter object
 514 * @mpt3sas_port: mpt3sas per port object
 515 * @mpt3sas_phy: mpt3sas per phy object
 516 *
 517 * Returns nothing.
 518 */
 519static void
 520_transport_add_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_port *mpt3sas_port,
 521        struct _sas_phy *mpt3sas_phy)
 522{
 523        u64 sas_address = mpt3sas_port->remote_identify.sas_address;
 524
 525        dev_printk(KERN_INFO, &mpt3sas_phy->phy->dev,
 526            "add: sas_addr(0x%016llx), phy(%d)\n", (unsigned long long)
 527            sas_address, mpt3sas_phy->phy_id);
 528
 529        list_add_tail(&mpt3sas_phy->port_siblings, &mpt3sas_port->phy_list);
 530        mpt3sas_port->num_phys++;
 531        sas_port_add_phy(mpt3sas_port->port, mpt3sas_phy->phy);
 532        mpt3sas_phy->phy_belongs_to_port = 1;
 533}
 534
 535/**
 536 * _transport_add_phy_to_an_existing_port - adding new phy to existing port
 537 * @ioc: per adapter object
 538 * @sas_node: sas node object (either expander or sas host)
 539 * @mpt3sas_phy: mpt3sas per phy object
 540 * @sas_address: sas address of device/expander were phy needs to be added to
 541 *
 542 * Returns nothing.
 543 */
 544static void
 545_transport_add_phy_to_an_existing_port(struct MPT3SAS_ADAPTER *ioc,
 546        struct _sas_node *sas_node, struct _sas_phy *mpt3sas_phy,
 547        u64 sas_address)
 548{
 549        struct _sas_port *mpt3sas_port;
 550        struct _sas_phy *phy_srch;
 551
 552        if (mpt3sas_phy->phy_belongs_to_port == 1)
 553                return;
 554
 555        list_for_each_entry(mpt3sas_port, &sas_node->sas_port_list,
 556            port_list) {
 557                if (mpt3sas_port->remote_identify.sas_address !=
 558                    sas_address)
 559                        continue;
 560                list_for_each_entry(phy_srch, &mpt3sas_port->phy_list,
 561                    port_siblings) {
 562                        if (phy_srch == mpt3sas_phy)
 563                                return;
 564                }
 565                _transport_add_phy(ioc, mpt3sas_port, mpt3sas_phy);
 566                        return;
 567        }
 568
 569}
 570
 571/**
 572 * _transport_del_phy_from_an_existing_port - delete phy from existing port
 573 * @ioc: per adapter object
 574 * @sas_node: sas node object (either expander or sas host)
 575 * @mpt3sas_phy: mpt3sas per phy object
 576 *
 577 * Returns nothing.
 578 */
 579static void
 580_transport_del_phy_from_an_existing_port(struct MPT3SAS_ADAPTER *ioc,
 581        struct _sas_node *sas_node, struct _sas_phy *mpt3sas_phy)
 582{
 583        struct _sas_port *mpt3sas_port, *next;
 584        struct _sas_phy *phy_srch;
 585
 586        if (mpt3sas_phy->phy_belongs_to_port == 0)
 587                return;
 588
 589        list_for_each_entry_safe(mpt3sas_port, next, &sas_node->sas_port_list,
 590            port_list) {
 591                list_for_each_entry(phy_srch, &mpt3sas_port->phy_list,
 592                    port_siblings) {
 593                        if (phy_srch != mpt3sas_phy)
 594                                continue;
 595
 596                        if (mpt3sas_port->num_phys == 1)
 597                                _transport_delete_port(ioc, mpt3sas_port);
 598                        else
 599                                _transport_delete_phy(ioc, mpt3sas_port,
 600                                    mpt3sas_phy);
 601                        return;
 602                }
 603        }
 604}
 605
 606/**
 607 * _transport_sanity_check - sanity check when adding a new port
 608 * @ioc: per adapter object
 609 * @sas_node: sas node object (either expander or sas host)
 610 * @sas_address: sas address of device being added
 611 *
 612 * See the explanation above from _transport_delete_duplicate_port
 613 */
 614static void
 615_transport_sanity_check(struct MPT3SAS_ADAPTER *ioc, struct _sas_node *sas_node,
 616        u64 sas_address)
 617{
 618        int i;
 619
 620        for (i = 0; i < sas_node->num_phys; i++) {
 621                if (sas_node->phy[i].remote_identify.sas_address != sas_address)
 622                        continue;
 623                if (sas_node->phy[i].phy_belongs_to_port == 1)
 624                        _transport_del_phy_from_an_existing_port(ioc, sas_node,
 625                            &sas_node->phy[i]);
 626        }
 627}
 628
 629/**
 630 * mpt3sas_transport_port_add - insert port to the list
 631 * @ioc: per adapter object
 632 * @handle: handle of attached device
 633 * @sas_address: sas address of parent expander or sas host
 634 * Context: This function will acquire ioc->sas_node_lock.
 635 *
 636 * Adding new port object to the sas_node->sas_port_list.
 637 *
 638 * Returns mpt3sas_port.
 639 */
 640struct _sas_port *
 641mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
 642        u64 sas_address)
 643{
 644        struct _sas_phy *mpt3sas_phy, *next;
 645        struct _sas_port *mpt3sas_port;
 646        unsigned long flags;
 647        struct _sas_node *sas_node;
 648        struct sas_rphy *rphy;
 649        struct _sas_device *sas_device = NULL;
 650        int i;
 651        struct sas_port *port;
 652
 653        mpt3sas_port = kzalloc(sizeof(struct _sas_port),
 654            GFP_KERNEL);
 655        if (!mpt3sas_port) {
 656                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
 657                    ioc->name, __FILE__, __LINE__, __func__);
 658                return NULL;
 659        }
 660
 661        INIT_LIST_HEAD(&mpt3sas_port->port_list);
 662        INIT_LIST_HEAD(&mpt3sas_port->phy_list);
 663        spin_lock_irqsave(&ioc->sas_node_lock, flags);
 664        sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
 665        spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 666
 667        if (!sas_node) {
 668                pr_err(MPT3SAS_FMT
 669                        "%s: Could not find parent sas_address(0x%016llx)!\n",
 670                        ioc->name, __func__, (unsigned long long)sas_address);
 671                goto out_fail;
 672        }
 673
 674        if ((_transport_set_identify(ioc, handle,
 675            &mpt3sas_port->remote_identify))) {
 676                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
 677                    ioc->name, __FILE__, __LINE__, __func__);
 678                goto out_fail;
 679        }
 680
 681        if (mpt3sas_port->remote_identify.device_type == SAS_PHY_UNUSED) {
 682                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
 683                    ioc->name, __FILE__, __LINE__, __func__);
 684                goto out_fail;
 685        }
 686
 687        _transport_sanity_check(ioc, sas_node,
 688            mpt3sas_port->remote_identify.sas_address);
 689
 690        for (i = 0; i < sas_node->num_phys; i++) {
 691                if (sas_node->phy[i].remote_identify.sas_address !=
 692                    mpt3sas_port->remote_identify.sas_address)
 693                        continue;
 694                list_add_tail(&sas_node->phy[i].port_siblings,
 695                    &mpt3sas_port->phy_list);
 696                mpt3sas_port->num_phys++;
 697        }
 698
 699        if (!mpt3sas_port->num_phys) {
 700                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
 701                    ioc->name, __FILE__, __LINE__, __func__);
 702                goto out_fail;
 703        }
 704
 705        if (!sas_node->parent_dev) {
 706                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
 707                    ioc->name, __FILE__, __LINE__, __func__);
 708                goto out_fail;
 709        }
 710        port = sas_port_alloc_num(sas_node->parent_dev);
 711        if ((sas_port_add(port))) {
 712                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
 713                    ioc->name, __FILE__, __LINE__, __func__);
 714                goto out_fail;
 715        }
 716
 717        list_for_each_entry(mpt3sas_phy, &mpt3sas_port->phy_list,
 718            port_siblings) {
 719                if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
 720                        dev_printk(KERN_INFO, &port->dev,
 721                                "add: handle(0x%04x), sas_addr(0x%016llx), phy(%d)\n",
 722                                handle, (unsigned long long)
 723                            mpt3sas_port->remote_identify.sas_address,
 724                            mpt3sas_phy->phy_id);
 725                sas_port_add_phy(port, mpt3sas_phy->phy);
 726                mpt3sas_phy->phy_belongs_to_port = 1;
 727        }
 728
 729        mpt3sas_port->port = port;
 730        if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE)
 731                rphy = sas_end_device_alloc(port);
 732        else
 733                rphy = sas_expander_alloc(port,
 734                    mpt3sas_port->remote_identify.device_type);
 735
 736        rphy->identify = mpt3sas_port->remote_identify;
 737
 738        if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) {
 739                sas_device = mpt3sas_get_sdev_by_addr(ioc,
 740                                    mpt3sas_port->remote_identify.sas_address);
 741                if (!sas_device) {
 742                        dfailprintk(ioc, printk(MPT3SAS_FMT
 743                                "failure at %s:%d/%s()!\n",
 744                                ioc->name, __FILE__, __LINE__, __func__));
 745                        goto out_fail;
 746                }
 747                sas_device->pend_sas_rphy_add = 1;
 748        }
 749
 750        if ((sas_rphy_add(rphy))) {
 751                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
 752                    ioc->name, __FILE__, __LINE__, __func__);
 753        }
 754
 755        if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) {
 756                sas_device->pend_sas_rphy_add = 0;
 757                sas_device_put(sas_device);
 758        }
 759
 760        if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
 761                dev_printk(KERN_INFO, &rphy->dev,
 762                        "add: handle(0x%04x), sas_addr(0x%016llx)\n",
 763                        handle, (unsigned long long)
 764                    mpt3sas_port->remote_identify.sas_address);
 765        mpt3sas_port->rphy = rphy;
 766        spin_lock_irqsave(&ioc->sas_node_lock, flags);
 767        list_add_tail(&mpt3sas_port->port_list, &sas_node->sas_port_list);
 768        spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 769
 770        /* fill in report manufacture */
 771        if (mpt3sas_port->remote_identify.device_type ==
 772            MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER ||
 773            mpt3sas_port->remote_identify.device_type ==
 774            MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER)
 775                _transport_expander_report_manufacture(ioc,
 776                    mpt3sas_port->remote_identify.sas_address,
 777                    rphy_to_expander_device(rphy));
 778        return mpt3sas_port;
 779
 780 out_fail:
 781        list_for_each_entry_safe(mpt3sas_phy, next, &mpt3sas_port->phy_list,
 782            port_siblings)
 783                list_del(&mpt3sas_phy->port_siblings);
 784        kfree(mpt3sas_port);
 785        return NULL;
 786}
 787
 788/**
 789 * mpt3sas_transport_port_remove - remove port from the list
 790 * @ioc: per adapter object
 791 * @sas_address: sas address of attached device
 792 * @sas_address_parent: sas address of parent expander or sas host
 793 * Context: This function will acquire ioc->sas_node_lock.
 794 *
 795 * Removing object and freeing associated memory from the
 796 * ioc->sas_port_list.
 797 *
 798 * Return nothing.
 799 */
 800void
 801mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
 802        u64 sas_address_parent)
 803{
 804        int i;
 805        unsigned long flags;
 806        struct _sas_port *mpt3sas_port, *next;
 807        struct _sas_node *sas_node;
 808        u8 found = 0;
 809        struct _sas_phy *mpt3sas_phy, *next_phy;
 810
 811        spin_lock_irqsave(&ioc->sas_node_lock, flags);
 812        sas_node = _transport_sas_node_find_by_sas_address(ioc,
 813            sas_address_parent);
 814        if (!sas_node) {
 815                spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 816                return;
 817        }
 818        list_for_each_entry_safe(mpt3sas_port, next, &sas_node->sas_port_list,
 819            port_list) {
 820                if (mpt3sas_port->remote_identify.sas_address != sas_address)
 821                        continue;
 822                found = 1;
 823                list_del(&mpt3sas_port->port_list);
 824                goto out;
 825        }
 826 out:
 827        if (!found) {
 828                spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 829                return;
 830        }
 831
 832        for (i = 0; i < sas_node->num_phys; i++) {
 833                if (sas_node->phy[i].remote_identify.sas_address == sas_address)
 834                        memset(&sas_node->phy[i].remote_identify, 0 ,
 835                            sizeof(struct sas_identify));
 836        }
 837
 838        spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 839
 840        list_for_each_entry_safe(mpt3sas_phy, next_phy,
 841            &mpt3sas_port->phy_list, port_siblings) {
 842                if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
 843                        dev_printk(KERN_INFO, &mpt3sas_port->port->dev,
 844                            "remove: sas_addr(0x%016llx), phy(%d)\n",
 845                            (unsigned long long)
 846                            mpt3sas_port->remote_identify.sas_address,
 847                            mpt3sas_phy->phy_id);
 848                mpt3sas_phy->phy_belongs_to_port = 0;
 849                sas_port_delete_phy(mpt3sas_port->port, mpt3sas_phy->phy);
 850                list_del(&mpt3sas_phy->port_siblings);
 851        }
 852        sas_port_delete(mpt3sas_port->port);
 853        kfree(mpt3sas_port);
 854}
 855
 856/**
 857 * mpt3sas_transport_add_host_phy - report sas_host phy to transport
 858 * @ioc: per adapter object
 859 * @mpt3sas_phy: mpt3sas per phy object
 860 * @phy_pg0: sas phy page 0
 861 * @parent_dev: parent device class object
 862 *
 863 * Returns 0 for success, non-zero for failure.
 864 */
 865int
 866mpt3sas_transport_add_host_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_phy
 867        *mpt3sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev)
 868{
 869        struct sas_phy *phy;
 870        int phy_index = mpt3sas_phy->phy_id;
 871
 872
 873        INIT_LIST_HEAD(&mpt3sas_phy->port_siblings);
 874        phy = sas_phy_alloc(parent_dev, phy_index);
 875        if (!phy) {
 876                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
 877                    ioc->name, __FILE__, __LINE__, __func__);
 878                return -1;
 879        }
 880        if ((_transport_set_identify(ioc, mpt3sas_phy->handle,
 881            &mpt3sas_phy->identify))) {
 882                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
 883                    ioc->name, __FILE__, __LINE__, __func__);
 884                sas_phy_free(phy);
 885                return -1;
 886        }
 887        phy->identify = mpt3sas_phy->identify;
 888        mpt3sas_phy->attached_handle = le16_to_cpu(phy_pg0.AttachedDevHandle);
 889        if (mpt3sas_phy->attached_handle)
 890                _transport_set_identify(ioc, mpt3sas_phy->attached_handle,
 891                    &mpt3sas_phy->remote_identify);
 892        phy->identify.phy_identifier = mpt3sas_phy->phy_id;
 893        phy->negotiated_linkrate = _transport_convert_phy_link_rate(
 894            phy_pg0.NegotiatedLinkRate & MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
 895        phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
 896            phy_pg0.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
 897        phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
 898            phy_pg0.HwLinkRate >> 4);
 899        phy->minimum_linkrate = _transport_convert_phy_link_rate(
 900            phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
 901        phy->maximum_linkrate = _transport_convert_phy_link_rate(
 902            phy_pg0.ProgrammedLinkRate >> 4);
 903
 904        if ((sas_phy_add(phy))) {
 905                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
 906                    ioc->name, __FILE__, __LINE__, __func__);
 907                sas_phy_free(phy);
 908                return -1;
 909        }
 910        if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
 911                dev_printk(KERN_INFO, &phy->dev,
 912                    "add: handle(0x%04x), sas_addr(0x%016llx)\n"
 913                    "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
 914                    mpt3sas_phy->handle, (unsigned long long)
 915                    mpt3sas_phy->identify.sas_address,
 916                    mpt3sas_phy->attached_handle,
 917                    (unsigned long long)
 918                    mpt3sas_phy->remote_identify.sas_address);
 919        mpt3sas_phy->phy = phy;
 920        return 0;
 921}
 922
 923
 924/**
 925 * mpt3sas_transport_add_expander_phy - report expander phy to transport
 926 * @ioc: per adapter object
 927 * @mpt3sas_phy: mpt3sas per phy object
 928 * @expander_pg1: expander page 1
 929 * @parent_dev: parent device class object
 930 *
 931 * Returns 0 for success, non-zero for failure.
 932 */
 933int
 934mpt3sas_transport_add_expander_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_phy
 935        *mpt3sas_phy, Mpi2ExpanderPage1_t expander_pg1,
 936        struct device *parent_dev)
 937{
 938        struct sas_phy *phy;
 939        int phy_index = mpt3sas_phy->phy_id;
 940
 941        INIT_LIST_HEAD(&mpt3sas_phy->port_siblings);
 942        phy = sas_phy_alloc(parent_dev, phy_index);
 943        if (!phy) {
 944                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
 945                    ioc->name, __FILE__, __LINE__, __func__);
 946                return -1;
 947        }
 948        if ((_transport_set_identify(ioc, mpt3sas_phy->handle,
 949            &mpt3sas_phy->identify))) {
 950                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
 951                    ioc->name, __FILE__, __LINE__, __func__);
 952                sas_phy_free(phy);
 953                return -1;
 954        }
 955        phy->identify = mpt3sas_phy->identify;
 956        mpt3sas_phy->attached_handle =
 957            le16_to_cpu(expander_pg1.AttachedDevHandle);
 958        if (mpt3sas_phy->attached_handle)
 959                _transport_set_identify(ioc, mpt3sas_phy->attached_handle,
 960                    &mpt3sas_phy->remote_identify);
 961        phy->identify.phy_identifier = mpt3sas_phy->phy_id;
 962        phy->negotiated_linkrate = _transport_convert_phy_link_rate(
 963            expander_pg1.NegotiatedLinkRate &
 964            MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
 965        phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
 966            expander_pg1.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
 967        phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
 968            expander_pg1.HwLinkRate >> 4);
 969        phy->minimum_linkrate = _transport_convert_phy_link_rate(
 970            expander_pg1.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
 971        phy->maximum_linkrate = _transport_convert_phy_link_rate(
 972            expander_pg1.ProgrammedLinkRate >> 4);
 973
 974        if ((sas_phy_add(phy))) {
 975                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
 976                    ioc->name, __FILE__, __LINE__, __func__);
 977                sas_phy_free(phy);
 978                return -1;
 979        }
 980        if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
 981                dev_printk(KERN_INFO, &phy->dev,
 982                    "add: handle(0x%04x), sas_addr(0x%016llx)\n"
 983                    "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
 984                    mpt3sas_phy->handle, (unsigned long long)
 985                    mpt3sas_phy->identify.sas_address,
 986                    mpt3sas_phy->attached_handle,
 987                    (unsigned long long)
 988                    mpt3sas_phy->remote_identify.sas_address);
 989        mpt3sas_phy->phy = phy;
 990        return 0;
 991}
 992
 993/**
 994 * mpt3sas_transport_update_links - refreshing phy link changes
 995 * @ioc: per adapter object
 996 * @sas_address: sas address of parent expander or sas host
 997 * @handle: attached device handle
 998 * @phy_numberv: phy number
 999 * @link_rate: new link rate
1000 *
1001 * Returns nothing.
1002 */
1003void
1004mpt3sas_transport_update_links(struct MPT3SAS_ADAPTER *ioc,
1005        u64 sas_address, u16 handle, u8 phy_number, u8 link_rate)
1006{
1007        unsigned long flags;
1008        struct _sas_node *sas_node;
1009        struct _sas_phy *mpt3sas_phy;
1010
1011        if (ioc->shost_recovery || ioc->pci_error_recovery)
1012                return;
1013
1014        spin_lock_irqsave(&ioc->sas_node_lock, flags);
1015        sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
1016        if (!sas_node) {
1017                spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1018                return;
1019        }
1020
1021        mpt3sas_phy = &sas_node->phy[phy_number];
1022        mpt3sas_phy->attached_handle = handle;
1023        spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1024        if (handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5)) {
1025                _transport_set_identify(ioc, handle,
1026                    &mpt3sas_phy->remote_identify);
1027                _transport_add_phy_to_an_existing_port(ioc, sas_node,
1028                    mpt3sas_phy, mpt3sas_phy->remote_identify.sas_address);
1029        } else
1030                memset(&mpt3sas_phy->remote_identify, 0 , sizeof(struct
1031                    sas_identify));
1032
1033        if (mpt3sas_phy->phy)
1034                mpt3sas_phy->phy->negotiated_linkrate =
1035                    _transport_convert_phy_link_rate(link_rate);
1036
1037        if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
1038                dev_printk(KERN_INFO, &mpt3sas_phy->phy->dev,
1039                    "refresh: parent sas_addr(0x%016llx),\n"
1040                    "\tlink_rate(0x%02x), phy(%d)\n"
1041                    "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
1042                    (unsigned long long)sas_address,
1043                    link_rate, phy_number, handle, (unsigned long long)
1044                    mpt3sas_phy->remote_identify.sas_address);
1045}
1046
1047static inline void *
1048phy_to_ioc(struct sas_phy *phy)
1049{
1050        struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
1051        return shost_priv(shost);
1052}
1053
1054static inline void *
1055rphy_to_ioc(struct sas_rphy *rphy)
1056{
1057        struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
1058        return shost_priv(shost);
1059}
1060
1061/* report phy error log structure */
1062struct phy_error_log_request {
1063        u8 smp_frame_type; /* 0x40 */
1064        u8 function; /* 0x11 */
1065        u8 allocated_response_length;
1066        u8 request_length; /* 02 */
1067        u8 reserved_1[5];
1068        u8 phy_identifier;
1069        u8 reserved_2[2];
1070};
1071
1072/* report phy error log reply structure */
1073struct phy_error_log_reply {
1074        u8 smp_frame_type; /* 0x41 */
1075        u8 function; /* 0x11 */
1076        u8 function_result;
1077        u8 response_length;
1078        __be16 expander_change_count;
1079        u8 reserved_1[3];
1080        u8 phy_identifier;
1081        u8 reserved_2[2];
1082        __be32 invalid_dword;
1083        __be32 running_disparity_error;
1084        __be32 loss_of_dword_sync;
1085        __be32 phy_reset_problem;
1086};
1087
1088/**
1089 * _transport_get_expander_phy_error_log - return expander counters
1090 * @ioc: per adapter object
1091 * @phy: The sas phy object
1092 *
1093 * Returns 0 for success, non-zero for failure.
1094 *
1095 */
1096static int
1097_transport_get_expander_phy_error_log(struct MPT3SAS_ADAPTER *ioc,
1098        struct sas_phy *phy)
1099{
1100        Mpi2SmpPassthroughRequest_t *mpi_request;
1101        Mpi2SmpPassthroughReply_t *mpi_reply;
1102        struct phy_error_log_request *phy_error_log_request;
1103        struct phy_error_log_reply *phy_error_log_reply;
1104        int rc;
1105        u16 smid;
1106        u32 ioc_state;
1107        void *psge;
1108        u8 issue_reset = 0;
1109        void *data_out = NULL;
1110        dma_addr_t data_out_dma;
1111        u32 sz;
1112        u16 wait_state_count;
1113
1114        if (ioc->shost_recovery || ioc->pci_error_recovery) {
1115                pr_info(MPT3SAS_FMT "%s: host reset in progress!\n",
1116                    __func__, ioc->name);
1117                return -EFAULT;
1118        }
1119
1120        mutex_lock(&ioc->transport_cmds.mutex);
1121
1122        if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) {
1123                pr_err(MPT3SAS_FMT "%s: transport_cmds in use\n",
1124                    ioc->name, __func__);
1125                rc = -EAGAIN;
1126                goto out;
1127        }
1128        ioc->transport_cmds.status = MPT3_CMD_PENDING;
1129
1130        wait_state_count = 0;
1131        ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
1132        while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1133                if (wait_state_count++ == 10) {
1134                        pr_err(MPT3SAS_FMT
1135                            "%s: failed due to ioc not operational\n",
1136                            ioc->name, __func__);
1137                        rc = -EFAULT;
1138                        goto out;
1139                }
1140                ssleep(1);
1141                ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
1142                pr_info(MPT3SAS_FMT
1143                        "%s: waiting for operational state(count=%d)\n",
1144                        ioc->name, __func__, wait_state_count);
1145        }
1146        if (wait_state_count)
1147                pr_info(MPT3SAS_FMT "%s: ioc is operational\n",
1148                    ioc->name, __func__);
1149
1150        smid = mpt3sas_base_get_smid(ioc, ioc->transport_cb_idx);
1151        if (!smid) {
1152                pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
1153                    ioc->name, __func__);
1154                rc = -EAGAIN;
1155                goto out;
1156        }
1157
1158        mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
1159        ioc->transport_cmds.smid = smid;
1160
1161        sz = sizeof(struct phy_error_log_request) +
1162            sizeof(struct phy_error_log_reply);
1163        data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
1164        if (!data_out) {
1165                pr_err("failure at %s:%d/%s()!\n", __FILE__,
1166                    __LINE__, __func__);
1167                rc = -ENOMEM;
1168                mpt3sas_base_free_smid(ioc, smid);
1169                goto out;
1170        }
1171
1172        rc = -EINVAL;
1173        memset(data_out, 0, sz);
1174        phy_error_log_request = data_out;
1175        phy_error_log_request->smp_frame_type = 0x40;
1176        phy_error_log_request->function = 0x11;
1177        phy_error_log_request->request_length = 2;
1178        phy_error_log_request->allocated_response_length = 0;
1179        phy_error_log_request->phy_identifier = phy->number;
1180
1181        memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
1182        mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
1183        mpi_request->PhysicalPort = 0xFF;
1184        mpi_request->VF_ID = 0; /* TODO */
1185        mpi_request->VP_ID = 0;
1186        mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
1187        mpi_request->RequestDataLength =
1188            cpu_to_le16(sizeof(struct phy_error_log_request));
1189        psge = &mpi_request->SGL;
1190
1191        ioc->build_sg(ioc, psge, data_out_dma,
1192                sizeof(struct phy_error_log_request),
1193            data_out_dma + sizeof(struct phy_error_log_request),
1194            sizeof(struct phy_error_log_reply));
1195
1196        dtransportprintk(ioc, pr_info(MPT3SAS_FMT
1197                "phy_error_log - send to sas_addr(0x%016llx), phy(%d)\n",
1198                ioc->name, (unsigned long long)phy->identify.sas_address,
1199                phy->number));
1200        init_completion(&ioc->transport_cmds.done);
1201        ioc->put_smid_default(ioc, smid);
1202        wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ);
1203
1204        if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) {
1205                pr_err(MPT3SAS_FMT "%s: timeout\n",
1206                    ioc->name, __func__);
1207                _debug_dump_mf(mpi_request,
1208                    sizeof(Mpi2SmpPassthroughRequest_t)/4);
1209                if (!(ioc->transport_cmds.status & MPT3_CMD_RESET))
1210                        issue_reset = 1;
1211                goto issue_host_reset;
1212        }
1213
1214        dtransportprintk(ioc, pr_info(MPT3SAS_FMT
1215                "phy_error_log - complete\n", ioc->name));
1216
1217        if (ioc->transport_cmds.status & MPT3_CMD_REPLY_VALID) {
1218
1219                mpi_reply = ioc->transport_cmds.reply;
1220
1221                dtransportprintk(ioc, pr_info(MPT3SAS_FMT
1222                    "phy_error_log - reply data transfer size(%d)\n",
1223                    ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
1224
1225                if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
1226                    sizeof(struct phy_error_log_reply))
1227                        goto out;
1228
1229                phy_error_log_reply = data_out +
1230                    sizeof(struct phy_error_log_request);
1231
1232                dtransportprintk(ioc, pr_info(MPT3SAS_FMT
1233                    "phy_error_log - function_result(%d)\n",
1234                    ioc->name, phy_error_log_reply->function_result));
1235
1236                phy->invalid_dword_count =
1237                    be32_to_cpu(phy_error_log_reply->invalid_dword);
1238                phy->running_disparity_error_count =
1239                    be32_to_cpu(phy_error_log_reply->running_disparity_error);
1240                phy->loss_of_dword_sync_count =
1241                    be32_to_cpu(phy_error_log_reply->loss_of_dword_sync);
1242                phy->phy_reset_problem_count =
1243                    be32_to_cpu(phy_error_log_reply->phy_reset_problem);
1244                rc = 0;
1245        } else
1246                dtransportprintk(ioc, pr_info(MPT3SAS_FMT
1247                    "phy_error_log - no reply\n", ioc->name));
1248
1249 issue_host_reset:
1250        if (issue_reset)
1251                mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
1252 out:
1253        ioc->transport_cmds.status = MPT3_CMD_NOT_USED;
1254        if (data_out)
1255                pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
1256
1257        mutex_unlock(&ioc->transport_cmds.mutex);
1258        return rc;
1259}
1260
1261/**
1262 * _transport_get_linkerrors - return phy counters for both hba and expanders
1263 * @phy: The sas phy object
1264 *
1265 * Returns 0 for success, non-zero for failure.
1266 *
1267 */
1268static int
1269_transport_get_linkerrors(struct sas_phy *phy)
1270{
1271        struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy);
1272        unsigned long flags;
1273        Mpi2ConfigReply_t mpi_reply;
1274        Mpi2SasPhyPage1_t phy_pg1;
1275
1276        spin_lock_irqsave(&ioc->sas_node_lock, flags);
1277        if (_transport_sas_node_find_by_sas_address(ioc,
1278            phy->identify.sas_address) == NULL) {
1279                spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1280                return -EINVAL;
1281        }
1282        spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1283
1284        if (phy->identify.sas_address != ioc->sas_hba.sas_address)
1285                return _transport_get_expander_phy_error_log(ioc, phy);
1286
1287        /* get hba phy error logs */
1288        if ((mpt3sas_config_get_phy_pg1(ioc, &mpi_reply, &phy_pg1,
1289                    phy->number))) {
1290                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1291                    ioc->name, __FILE__, __LINE__, __func__);
1292                return -ENXIO;
1293        }
1294
1295        if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
1296                pr_info(MPT3SAS_FMT
1297                        "phy(%d), ioc_status (0x%04x), loginfo(0x%08x)\n",
1298                        ioc->name, phy->number,
1299                        le16_to_cpu(mpi_reply.IOCStatus),
1300                    le32_to_cpu(mpi_reply.IOCLogInfo));
1301
1302        phy->invalid_dword_count = le32_to_cpu(phy_pg1.InvalidDwordCount);
1303        phy->running_disparity_error_count =
1304            le32_to_cpu(phy_pg1.RunningDisparityErrorCount);
1305        phy->loss_of_dword_sync_count =
1306            le32_to_cpu(phy_pg1.LossDwordSynchCount);
1307        phy->phy_reset_problem_count =
1308            le32_to_cpu(phy_pg1.PhyResetProblemCount);
1309        return 0;
1310}
1311
1312/**
1313 * _transport_get_enclosure_identifier -
1314 * @phy: The sas phy object
1315 *
1316 * Obtain the enclosure logical id for an expander.
1317 * Returns 0 for success, non-zero for failure.
1318 */
1319static int
1320_transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
1321{
1322        struct MPT3SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
1323        struct _sas_device *sas_device;
1324        unsigned long flags;
1325        int rc;
1326
1327        spin_lock_irqsave(&ioc->sas_device_lock, flags);
1328        sas_device = __mpt3sas_get_sdev_by_addr(ioc,
1329            rphy->identify.sas_address);
1330        if (sas_device) {
1331                *identifier = sas_device->enclosure_logical_id;
1332                rc = 0;
1333                sas_device_put(sas_device);
1334        } else {
1335                *identifier = 0;
1336                rc = -ENXIO;
1337        }
1338
1339        spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1340        return rc;
1341}
1342
1343/**
1344 * _transport_get_bay_identifier -
1345 * @phy: The sas phy object
1346 *
1347 * Returns the slot id for a device that resides inside an enclosure.
1348 */
1349static int
1350_transport_get_bay_identifier(struct sas_rphy *rphy)
1351{
1352        struct MPT3SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
1353        struct _sas_device *sas_device;
1354        unsigned long flags;
1355        int rc;
1356
1357        spin_lock_irqsave(&ioc->sas_device_lock, flags);
1358        sas_device = __mpt3sas_get_sdev_by_addr(ioc,
1359            rphy->identify.sas_address);
1360        if (sas_device) {
1361                rc = sas_device->slot;
1362                sas_device_put(sas_device);
1363        } else {
1364                rc = -ENXIO;
1365        }
1366        spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1367        return rc;
1368}
1369
1370/* phy control request structure */
1371struct phy_control_request {
1372        u8 smp_frame_type; /* 0x40 */
1373        u8 function; /* 0x91 */
1374        u8 allocated_response_length;
1375        u8 request_length; /* 0x09 */
1376        u16 expander_change_count;
1377        u8 reserved_1[3];
1378        u8 phy_identifier;
1379        u8 phy_operation;
1380        u8 reserved_2[13];
1381        u64 attached_device_name;
1382        u8 programmed_min_physical_link_rate;
1383        u8 programmed_max_physical_link_rate;
1384        u8 reserved_3[6];
1385};
1386
1387/* phy control reply structure */
1388struct phy_control_reply {
1389        u8 smp_frame_type; /* 0x41 */
1390        u8 function; /* 0x11 */
1391        u8 function_result;
1392        u8 response_length;
1393};
1394
1395#define SMP_PHY_CONTROL_LINK_RESET      (0x01)
1396#define SMP_PHY_CONTROL_HARD_RESET      (0x02)
1397#define SMP_PHY_CONTROL_DISABLE         (0x03)
1398
1399/**
1400 * _transport_expander_phy_control - expander phy control
1401 * @ioc: per adapter object
1402 * @phy: The sas phy object
1403 *
1404 * Returns 0 for success, non-zero for failure.
1405 *
1406 */
1407static int
1408_transport_expander_phy_control(struct MPT3SAS_ADAPTER *ioc,
1409        struct sas_phy *phy, u8 phy_operation)
1410{
1411        Mpi2SmpPassthroughRequest_t *mpi_request;
1412        Mpi2SmpPassthroughReply_t *mpi_reply;
1413        struct phy_control_request *phy_control_request;
1414        struct phy_control_reply *phy_control_reply;
1415        int rc;
1416        u16 smid;
1417        u32 ioc_state;
1418        void *psge;
1419        u8 issue_reset = 0;
1420        void *data_out = NULL;
1421        dma_addr_t data_out_dma;
1422        u32 sz;
1423        u16 wait_state_count;
1424
1425        if (ioc->shost_recovery || ioc->pci_error_recovery) {
1426                pr_info(MPT3SAS_FMT "%s: host reset in progress!\n",
1427                    __func__, ioc->name);
1428                return -EFAULT;
1429        }
1430
1431        mutex_lock(&ioc->transport_cmds.mutex);
1432
1433        if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) {
1434                pr_err(MPT3SAS_FMT "%s: transport_cmds in use\n",
1435                    ioc->name, __func__);
1436                rc = -EAGAIN;
1437                goto out;
1438        }
1439        ioc->transport_cmds.status = MPT3_CMD_PENDING;
1440
1441        wait_state_count = 0;
1442        ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
1443        while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1444                if (wait_state_count++ == 10) {
1445                        pr_err(MPT3SAS_FMT
1446                            "%s: failed due to ioc not operational\n",
1447                            ioc->name, __func__);
1448                        rc = -EFAULT;
1449                        goto out;
1450                }
1451                ssleep(1);
1452                ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
1453                pr_info(MPT3SAS_FMT
1454                        "%s: waiting for operational state(count=%d)\n",
1455                        ioc->name, __func__, wait_state_count);
1456        }
1457        if (wait_state_count)
1458                pr_info(MPT3SAS_FMT "%s: ioc is operational\n",
1459                    ioc->name, __func__);
1460
1461        smid = mpt3sas_base_get_smid(ioc, ioc->transport_cb_idx);
1462        if (!smid) {
1463                pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
1464                    ioc->name, __func__);
1465                rc = -EAGAIN;
1466                goto out;
1467        }
1468
1469        mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
1470        ioc->transport_cmds.smid = smid;
1471
1472        sz = sizeof(struct phy_control_request) +
1473            sizeof(struct phy_control_reply);
1474        data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
1475        if (!data_out) {
1476                pr_err("failure at %s:%d/%s()!\n", __FILE__,
1477                    __LINE__, __func__);
1478                rc = -ENOMEM;
1479                mpt3sas_base_free_smid(ioc, smid);
1480                goto out;
1481        }
1482
1483        rc = -EINVAL;
1484        memset(data_out, 0, sz);
1485        phy_control_request = data_out;
1486        phy_control_request->smp_frame_type = 0x40;
1487        phy_control_request->function = 0x91;
1488        phy_control_request->request_length = 9;
1489        phy_control_request->allocated_response_length = 0;
1490        phy_control_request->phy_identifier = phy->number;
1491        phy_control_request->phy_operation = phy_operation;
1492        phy_control_request->programmed_min_physical_link_rate =
1493            phy->minimum_linkrate << 4;
1494        phy_control_request->programmed_max_physical_link_rate =
1495            phy->maximum_linkrate << 4;
1496
1497        memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
1498        mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
1499        mpi_request->PhysicalPort = 0xFF;
1500        mpi_request->VF_ID = 0; /* TODO */
1501        mpi_request->VP_ID = 0;
1502        mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
1503        mpi_request->RequestDataLength =
1504            cpu_to_le16(sizeof(struct phy_error_log_request));
1505        psge = &mpi_request->SGL;
1506
1507        ioc->build_sg(ioc, psge, data_out_dma,
1508                            sizeof(struct phy_control_request),
1509            data_out_dma + sizeof(struct phy_control_request),
1510            sizeof(struct phy_control_reply));
1511
1512        dtransportprintk(ioc, pr_info(MPT3SAS_FMT
1513                "phy_control - send to sas_addr(0x%016llx), phy(%d), opcode(%d)\n",
1514                ioc->name, (unsigned long long)phy->identify.sas_address,
1515                phy->number, phy_operation));
1516        init_completion(&ioc->transport_cmds.done);
1517        ioc->put_smid_default(ioc, smid);
1518        wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ);
1519
1520        if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) {
1521                pr_err(MPT3SAS_FMT "%s: timeout\n",
1522                    ioc->name, __func__);
1523                _debug_dump_mf(mpi_request,
1524                    sizeof(Mpi2SmpPassthroughRequest_t)/4);
1525                if (!(ioc->transport_cmds.status & MPT3_CMD_RESET))
1526                        issue_reset = 1;
1527                goto issue_host_reset;
1528        }
1529
1530        dtransportprintk(ioc, pr_info(MPT3SAS_FMT
1531                "phy_control - complete\n", ioc->name));
1532
1533        if (ioc->transport_cmds.status & MPT3_CMD_REPLY_VALID) {
1534
1535                mpi_reply = ioc->transport_cmds.reply;
1536
1537                dtransportprintk(ioc, pr_info(MPT3SAS_FMT
1538                    "phy_control - reply data transfer size(%d)\n",
1539                    ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
1540
1541                if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
1542                    sizeof(struct phy_control_reply))
1543                        goto out;
1544
1545                phy_control_reply = data_out +
1546                    sizeof(struct phy_control_request);
1547
1548                dtransportprintk(ioc, pr_info(MPT3SAS_FMT
1549                    "phy_control - function_result(%d)\n",
1550                    ioc->name, phy_control_reply->function_result));
1551
1552                rc = 0;
1553        } else
1554                dtransportprintk(ioc, pr_info(MPT3SAS_FMT
1555                    "phy_control - no reply\n", ioc->name));
1556
1557 issue_host_reset:
1558        if (issue_reset)
1559                mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
1560 out:
1561        ioc->transport_cmds.status = MPT3_CMD_NOT_USED;
1562        if (data_out)
1563                pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
1564
1565        mutex_unlock(&ioc->transport_cmds.mutex);
1566        return rc;
1567}
1568
1569/**
1570 * _transport_phy_reset -
1571 * @phy: The sas phy object
1572 * @hard_reset:
1573 *
1574 * Returns 0 for success, non-zero for failure.
1575 */
1576static int
1577_transport_phy_reset(struct sas_phy *phy, int hard_reset)
1578{
1579        struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy);
1580        Mpi2SasIoUnitControlReply_t mpi_reply;
1581        Mpi2SasIoUnitControlRequest_t mpi_request;
1582        unsigned long flags;
1583
1584        spin_lock_irqsave(&ioc->sas_node_lock, flags);
1585        if (_transport_sas_node_find_by_sas_address(ioc,
1586            phy->identify.sas_address) == NULL) {
1587                spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1588                return -EINVAL;
1589        }
1590        spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1591
1592        /* handle expander phys */
1593        if (phy->identify.sas_address != ioc->sas_hba.sas_address)
1594                return _transport_expander_phy_control(ioc, phy,
1595                    (hard_reset == 1) ? SMP_PHY_CONTROL_HARD_RESET :
1596                    SMP_PHY_CONTROL_LINK_RESET);
1597
1598        /* handle hba phys */
1599        memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlRequest_t));
1600        mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
1601        mpi_request.Operation = hard_reset ?
1602            MPI2_SAS_OP_PHY_HARD_RESET : MPI2_SAS_OP_PHY_LINK_RESET;
1603        mpi_request.PhyNum = phy->number;
1604
1605        if ((mpt3sas_base_sas_iounit_control(ioc, &mpi_reply, &mpi_request))) {
1606                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1607                    ioc->name, __FILE__, __LINE__, __func__);
1608                return -ENXIO;
1609        }
1610
1611        if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
1612                pr_info(MPT3SAS_FMT
1613                "phy(%d), ioc_status(0x%04x), loginfo(0x%08x)\n",
1614                ioc->name, phy->number, le16_to_cpu(mpi_reply.IOCStatus),
1615                    le32_to_cpu(mpi_reply.IOCLogInfo));
1616
1617        return 0;
1618}
1619
1620/**
1621 * _transport_phy_enable - enable/disable phys
1622 * @phy: The sas phy object
1623 * @enable: enable phy when true
1624 *
1625 * Only support sas_host direct attached phys.
1626 * Returns 0 for success, non-zero for failure.
1627 */
1628static int
1629_transport_phy_enable(struct sas_phy *phy, int enable)
1630{
1631        struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy);
1632        Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
1633        Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
1634        Mpi2ConfigReply_t mpi_reply;
1635        u16 ioc_status;
1636        u16 sz;
1637        int rc = 0;
1638        unsigned long flags;
1639        int i, discovery_active;
1640
1641        spin_lock_irqsave(&ioc->sas_node_lock, flags);
1642        if (_transport_sas_node_find_by_sas_address(ioc,
1643            phy->identify.sas_address) == NULL) {
1644                spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1645                return -EINVAL;
1646        }
1647        spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1648
1649        /* handle expander phys */
1650        if (phy->identify.sas_address != ioc->sas_hba.sas_address)
1651                return _transport_expander_phy_control(ioc, phy,
1652                    (enable == 1) ? SMP_PHY_CONTROL_LINK_RESET :
1653                    SMP_PHY_CONTROL_DISABLE);
1654
1655        /* handle hba phys */
1656
1657        /* read sas_iounit page 0 */
1658        sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys *
1659            sizeof(Mpi2SasIOUnit0PhyData_t));
1660        sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
1661        if (!sas_iounit_pg0) {
1662                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1663                    ioc->name, __FILE__, __LINE__, __func__);
1664                rc = -ENOMEM;
1665                goto out;
1666        }
1667        if ((mpt3sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
1668            sas_iounit_pg0, sz))) {
1669                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1670                    ioc->name, __FILE__, __LINE__, __func__);
1671                rc = -ENXIO;
1672                goto out;
1673        }
1674        ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1675            MPI2_IOCSTATUS_MASK;
1676        if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1677                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1678                    ioc->name, __FILE__, __LINE__, __func__);
1679                rc = -EIO;
1680                goto out;
1681        }
1682
1683        /* unable to enable/disable phys when when discovery is active */
1684        for (i = 0, discovery_active = 0; i < ioc->sas_hba.num_phys ; i++) {
1685                if (sas_iounit_pg0->PhyData[i].PortFlags &
1686                    MPI2_SASIOUNIT0_PORTFLAGS_DISCOVERY_IN_PROGRESS) {
1687                        pr_err(MPT3SAS_FMT "discovery is active on " \
1688                            "port = %d, phy = %d: unable to enable/disable "
1689                            "phys, try again later!\n", ioc->name,
1690                            sas_iounit_pg0->PhyData[i].Port, i);
1691                        discovery_active = 1;
1692                }
1693        }
1694
1695        if (discovery_active) {
1696                rc = -EAGAIN;
1697                goto out;
1698        }
1699
1700        /* read sas_iounit page 1 */
1701        sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
1702            sizeof(Mpi2SasIOUnit1PhyData_t));
1703        sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
1704        if (!sas_iounit_pg1) {
1705                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1706                    ioc->name, __FILE__, __LINE__, __func__);
1707                rc = -ENOMEM;
1708                goto out;
1709        }
1710        if ((mpt3sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
1711            sas_iounit_pg1, sz))) {
1712                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1713                    ioc->name, __FILE__, __LINE__, __func__);
1714                rc = -ENXIO;
1715                goto out;
1716        }
1717        ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1718            MPI2_IOCSTATUS_MASK;
1719        if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1720                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1721                    ioc->name, __FILE__, __LINE__, __func__);
1722                rc = -EIO;
1723                goto out;
1724        }
1725
1726        /* copy Port/PortFlags/PhyFlags from page 0 */
1727        for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
1728                sas_iounit_pg1->PhyData[i].Port =
1729                    sas_iounit_pg0->PhyData[i].Port;
1730                sas_iounit_pg1->PhyData[i].PortFlags =
1731                    (sas_iounit_pg0->PhyData[i].PortFlags &
1732                    MPI2_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG);
1733                sas_iounit_pg1->PhyData[i].PhyFlags =
1734                    (sas_iounit_pg0->PhyData[i].PhyFlags &
1735                    (MPI2_SASIOUNIT0_PHYFLAGS_ZONING_ENABLED +
1736                    MPI2_SASIOUNIT0_PHYFLAGS_PHY_DISABLED));
1737        }
1738
1739        if (enable)
1740                sas_iounit_pg1->PhyData[phy->number].PhyFlags
1741                    &= ~MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
1742        else
1743                sas_iounit_pg1->PhyData[phy->number].PhyFlags
1744                    |= MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
1745
1746        mpt3sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1, sz);
1747
1748        /* link reset */
1749        if (enable)
1750                _transport_phy_reset(phy, 0);
1751
1752 out:
1753        kfree(sas_iounit_pg1);
1754        kfree(sas_iounit_pg0);
1755        return rc;
1756}
1757
1758/**
1759 * _transport_phy_speed - set phy min/max link rates
1760 * @phy: The sas phy object
1761 * @rates: rates defined in sas_phy_linkrates
1762 *
1763 * Only support sas_host direct attached phys.
1764 * Returns 0 for success, non-zero for failure.
1765 */
1766static int
1767_transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
1768{
1769        struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy);
1770        Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
1771        Mpi2SasPhyPage0_t phy_pg0;
1772        Mpi2ConfigReply_t mpi_reply;
1773        u16 ioc_status;
1774        u16 sz;
1775        int i;
1776        int rc = 0;
1777        unsigned long flags;
1778
1779        spin_lock_irqsave(&ioc->sas_node_lock, flags);
1780        if (_transport_sas_node_find_by_sas_address(ioc,
1781            phy->identify.sas_address) == NULL) {
1782                spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1783                return -EINVAL;
1784        }
1785        spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1786
1787        if (!rates->minimum_linkrate)
1788                rates->minimum_linkrate = phy->minimum_linkrate;
1789        else if (rates->minimum_linkrate < phy->minimum_linkrate_hw)
1790                rates->minimum_linkrate = phy->minimum_linkrate_hw;
1791
1792        if (!rates->maximum_linkrate)
1793                rates->maximum_linkrate = phy->maximum_linkrate;
1794        else if (rates->maximum_linkrate > phy->maximum_linkrate_hw)
1795                rates->maximum_linkrate = phy->maximum_linkrate_hw;
1796
1797        /* handle expander phys */
1798        if (phy->identify.sas_address != ioc->sas_hba.sas_address) {
1799                phy->minimum_linkrate = rates->minimum_linkrate;
1800                phy->maximum_linkrate = rates->maximum_linkrate;
1801                return _transport_expander_phy_control(ioc, phy,
1802                    SMP_PHY_CONTROL_LINK_RESET);
1803        }
1804
1805        /* handle hba phys */
1806
1807        /* sas_iounit page 1 */
1808        sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
1809            sizeof(Mpi2SasIOUnit1PhyData_t));
1810        sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
1811        if (!sas_iounit_pg1) {
1812                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1813                    ioc->name, __FILE__, __LINE__, __func__);
1814                rc = -ENOMEM;
1815                goto out;
1816        }
1817        if ((mpt3sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
1818            sas_iounit_pg1, sz))) {
1819                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1820                    ioc->name, __FILE__, __LINE__, __func__);
1821                rc = -ENXIO;
1822                goto out;
1823        }
1824        ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1825            MPI2_IOCSTATUS_MASK;
1826        if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1827                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1828                    ioc->name, __FILE__, __LINE__, __func__);
1829                rc = -EIO;
1830                goto out;
1831        }
1832
1833        for (i = 0; i < ioc->sas_hba.num_phys; i++) {
1834                if (phy->number != i) {
1835                        sas_iounit_pg1->PhyData[i].MaxMinLinkRate =
1836                            (ioc->sas_hba.phy[i].phy->minimum_linkrate +
1837                            (ioc->sas_hba.phy[i].phy->maximum_linkrate << 4));
1838                } else {
1839                        sas_iounit_pg1->PhyData[i].MaxMinLinkRate =
1840                            (rates->minimum_linkrate +
1841                            (rates->maximum_linkrate << 4));
1842                }
1843        }
1844
1845        if (mpt3sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1,
1846            sz)) {
1847                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1848                    ioc->name, __FILE__, __LINE__, __func__);
1849                rc = -ENXIO;
1850                goto out;
1851        }
1852
1853        /* link reset */
1854        _transport_phy_reset(phy, 0);
1855
1856        /* read phy page 0, then update the rates in the sas transport phy */
1857        if (!mpt3sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0,
1858            phy->number)) {
1859                phy->minimum_linkrate = _transport_convert_phy_link_rate(
1860                    phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
1861                phy->maximum_linkrate = _transport_convert_phy_link_rate(
1862                    phy_pg0.ProgrammedLinkRate >> 4);
1863                phy->negotiated_linkrate = _transport_convert_phy_link_rate(
1864                    phy_pg0.NegotiatedLinkRate &
1865                    MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
1866        }
1867
1868 out:
1869        kfree(sas_iounit_pg1);
1870        return rc;
1871}
1872
1873static int
1874_transport_map_smp_buffer(struct device *dev, struct bsg_buffer *buf,
1875                dma_addr_t *dma_addr, size_t *dma_len, void **p)
1876{
1877        /* Check if the request is split across multiple segments */
1878        if (buf->sg_cnt > 1) {
1879                *p = dma_alloc_coherent(dev, buf->payload_len, dma_addr,
1880                                GFP_KERNEL);
1881                if (!*p)
1882                        return -ENOMEM;
1883                *dma_len = buf->payload_len;
1884        } else {
1885                if (!dma_map_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL))
1886                        return -ENOMEM;
1887                *dma_addr = sg_dma_address(buf->sg_list);
1888                *dma_len = sg_dma_len(buf->sg_list);
1889                *p = NULL;
1890        }
1891
1892        return 0;
1893}
1894
1895static void
1896_transport_unmap_smp_buffer(struct device *dev, struct bsg_buffer *buf,
1897                dma_addr_t dma_addr, void *p)
1898{
1899        if (p)
1900                dma_free_coherent(dev, buf->payload_len, p, dma_addr);
1901        else
1902                dma_unmap_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL);
1903}
1904
1905/**
1906 * _transport_smp_handler - transport portal for smp passthru
1907 * @shost: shost object
1908 * @rphy: sas transport rphy object
1909 * @req:
1910 *
1911 * This used primarily for smp_utils.
1912 * Example:
1913 *           smp_rep_general /sys/class/bsg/expander-5:0
1914 */
1915static void
1916_transport_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
1917                struct sas_rphy *rphy)
1918{
1919        struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
1920        Mpi2SmpPassthroughRequest_t *mpi_request;
1921        Mpi2SmpPassthroughReply_t *mpi_reply;
1922        int rc;
1923        u16 smid;
1924        u32 ioc_state;
1925        void *psge;
1926        dma_addr_t dma_addr_in;
1927        dma_addr_t dma_addr_out;
1928        void *addr_in = NULL;
1929        void *addr_out = NULL;
1930        size_t dma_len_in;
1931        size_t dma_len_out;
1932        u16 wait_state_count;
1933        unsigned int reslen = 0;
1934
1935        if (ioc->shost_recovery || ioc->pci_error_recovery) {
1936                pr_info(MPT3SAS_FMT "%s: host reset in progress!\n",
1937                    __func__, ioc->name);
1938                rc = -EFAULT;
1939                goto out;
1940        }
1941
1942        rc = mutex_lock_interruptible(&ioc->transport_cmds.mutex);
1943        if (rc)
1944                goto out;
1945
1946        if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) {
1947                pr_err(MPT3SAS_FMT "%s: transport_cmds in use\n", ioc->name,
1948                    __func__);
1949                rc = -EAGAIN;
1950                goto out;
1951        }
1952        ioc->transport_cmds.status = MPT3_CMD_PENDING;
1953
1954        rc = _transport_map_smp_buffer(&ioc->pdev->dev, &job->request_payload,
1955                        &dma_addr_out, &dma_len_out, &addr_out);
1956        if (rc)
1957                goto out;
1958        if (addr_out) {
1959                sg_copy_to_buffer(job->request_payload.sg_list,
1960                                job->request_payload.sg_cnt, addr_out,
1961                                job->request_payload.payload_len);
1962        }
1963
1964        rc = _transport_map_smp_buffer(&ioc->pdev->dev, &job->reply_payload,
1965                        &dma_addr_in, &dma_len_in, &addr_in);
1966        if (rc)
1967                goto unmap_out;
1968
1969        wait_state_count = 0;
1970        ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
1971        while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1972                if (wait_state_count++ == 10) {
1973                        pr_err(MPT3SAS_FMT
1974                            "%s: failed due to ioc not operational\n",
1975                            ioc->name, __func__);
1976                        rc = -EFAULT;
1977                        goto unmap_in;
1978                }
1979                ssleep(1);
1980                ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
1981                pr_info(MPT3SAS_FMT
1982                        "%s: waiting for operational state(count=%d)\n",
1983                        ioc->name, __func__, wait_state_count);
1984        }
1985        if (wait_state_count)
1986                pr_info(MPT3SAS_FMT "%s: ioc is operational\n",
1987                    ioc->name, __func__);
1988
1989        smid = mpt3sas_base_get_smid(ioc, ioc->transport_cb_idx);
1990        if (!smid) {
1991                pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
1992                    ioc->name, __func__);
1993                rc = -EAGAIN;
1994                goto unmap_in;
1995        }
1996
1997        rc = 0;
1998        mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
1999        ioc->transport_cmds.smid = smid;
2000
2001        memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
2002        mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
2003        mpi_request->PhysicalPort = 0xFF;
2004        mpi_request->SASAddress = (rphy) ?
2005            cpu_to_le64(rphy->identify.sas_address) :
2006            cpu_to_le64(ioc->sas_hba.sas_address);
2007        mpi_request->RequestDataLength = cpu_to_le16(dma_len_out - 4);
2008        psge = &mpi_request->SGL;
2009
2010        ioc->build_sg(ioc, psge, dma_addr_out, dma_len_out - 4, dma_addr_in,
2011                        dma_len_in - 4);
2012
2013        dtransportprintk(ioc, pr_info(MPT3SAS_FMT
2014                "%s - sending smp request\n", ioc->name, __func__));
2015
2016        init_completion(&ioc->transport_cmds.done);
2017        ioc->put_smid_default(ioc, smid);
2018        wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ);
2019
2020        if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) {
2021                pr_err(MPT3SAS_FMT "%s : timeout\n",
2022                    __func__, ioc->name);
2023                _debug_dump_mf(mpi_request,
2024                    sizeof(Mpi2SmpPassthroughRequest_t)/4);
2025                if (!(ioc->transport_cmds.status & MPT3_CMD_RESET)) {
2026                        mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
2027                        rc = -ETIMEDOUT;
2028                        goto unmap_in;
2029                }
2030        }
2031
2032        dtransportprintk(ioc, pr_info(MPT3SAS_FMT
2033                "%s - complete\n", ioc->name, __func__));
2034
2035        if (!(ioc->transport_cmds.status & MPT3_CMD_REPLY_VALID)) {
2036                dtransportprintk(ioc, pr_info(MPT3SAS_FMT
2037                    "%s - no reply\n", ioc->name, __func__));
2038                rc = -ENXIO;
2039                goto unmap_in;
2040        }
2041
2042        mpi_reply = ioc->transport_cmds.reply;
2043
2044        dtransportprintk(ioc,
2045                pr_info(MPT3SAS_FMT "%s - reply data transfer size(%d)\n",
2046                        ioc->name, __func__,
2047                        le16_to_cpu(mpi_reply->ResponseDataLength)));
2048
2049        memcpy(job->reply, mpi_reply, sizeof(*mpi_reply));
2050        job->reply_len = sizeof(*mpi_reply);
2051        reslen = le16_to_cpu(mpi_reply->ResponseDataLength);
2052
2053        if (addr_in) {
2054                sg_copy_to_buffer(job->reply_payload.sg_list,
2055                                job->reply_payload.sg_cnt, addr_in,
2056                                job->reply_payload.payload_len);
2057        }
2058
2059        rc = 0;
2060 unmap_in:
2061        _transport_unmap_smp_buffer(&ioc->pdev->dev, &job->reply_payload,
2062                        dma_addr_in, addr_in);
2063 unmap_out:
2064        _transport_unmap_smp_buffer(&ioc->pdev->dev, &job->request_payload,
2065                        dma_addr_out, addr_out);
2066 out:
2067        ioc->transport_cmds.status = MPT3_CMD_NOT_USED;
2068        mutex_unlock(&ioc->transport_cmds.mutex);
2069        bsg_job_done(job, rc, reslen);
2070}
2071
2072struct sas_function_template mpt3sas_transport_functions = {
2073        .get_linkerrors         = _transport_get_linkerrors,
2074        .get_enclosure_identifier = _transport_get_enclosure_identifier,
2075        .get_bay_identifier     = _transport_get_bay_identifier,
2076        .phy_reset              = _transport_phy_reset,
2077        .phy_enable             = _transport_phy_enable,
2078        .set_phy_speed          = _transport_phy_speed,
2079        .smp_handler            = _transport_smp_handler,
2080};
2081
2082struct scsi_transport_template *mpt3sas_transport_template;
2083