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