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