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        if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
 723                dev_printk(KERN_INFO, &rphy->dev,
 724                        "add: handle(0x%04x), sas_addr(0x%016llx)\n",
 725                        handle, (unsigned long long)
 726                    mpt3sas_port->remote_identify.sas_address);
 727        mpt3sas_port->rphy = rphy;
 728        spin_lock_irqsave(&ioc->sas_node_lock, flags);
 729        list_add_tail(&mpt3sas_port->port_list, &sas_node->sas_port_list);
 730        spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 731
 732        /* fill in report manufacture */
 733        if (mpt3sas_port->remote_identify.device_type ==
 734            MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER ||
 735            mpt3sas_port->remote_identify.device_type ==
 736            MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER)
 737                _transport_expander_report_manufacture(ioc,
 738                    mpt3sas_port->remote_identify.sas_address,
 739                    rphy_to_expander_device(rphy));
 740        return mpt3sas_port;
 741
 742 out_fail:
 743        list_for_each_entry_safe(mpt3sas_phy, next, &mpt3sas_port->phy_list,
 744            port_siblings)
 745                list_del(&mpt3sas_phy->port_siblings);
 746        kfree(mpt3sas_port);
 747        return NULL;
 748}
 749
 750/**
 751 * mpt3sas_transport_port_remove - remove port from the list
 752 * @ioc: per adapter object
 753 * @sas_address: sas address of attached device
 754 * @sas_address_parent: sas address of parent expander or sas host
 755 * Context: This function will acquire ioc->sas_node_lock.
 756 *
 757 * Removing object and freeing associated memory from the
 758 * ioc->sas_port_list.
 759 */
 760void
 761mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
 762        u64 sas_address_parent)
 763{
 764        int i;
 765        unsigned long flags;
 766        struct _sas_port *mpt3sas_port, *next;
 767        struct _sas_node *sas_node;
 768        u8 found = 0;
 769        struct _sas_phy *mpt3sas_phy, *next_phy;
 770
 771        spin_lock_irqsave(&ioc->sas_node_lock, flags);
 772        sas_node = _transport_sas_node_find_by_sas_address(ioc,
 773            sas_address_parent);
 774        if (!sas_node) {
 775                spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 776                return;
 777        }
 778        list_for_each_entry_safe(mpt3sas_port, next, &sas_node->sas_port_list,
 779            port_list) {
 780                if (mpt3sas_port->remote_identify.sas_address != sas_address)
 781                        continue;
 782                found = 1;
 783                list_del(&mpt3sas_port->port_list);
 784                goto out;
 785        }
 786 out:
 787        if (!found) {
 788                spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 789                return;
 790        }
 791
 792        for (i = 0; i < sas_node->num_phys; i++) {
 793                if (sas_node->phy[i].remote_identify.sas_address == sas_address)
 794                        memset(&sas_node->phy[i].remote_identify, 0 ,
 795                            sizeof(struct sas_identify));
 796        }
 797
 798        spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 799
 800        list_for_each_entry_safe(mpt3sas_phy, next_phy,
 801            &mpt3sas_port->phy_list, port_siblings) {
 802                if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
 803                        dev_printk(KERN_INFO, &mpt3sas_port->port->dev,
 804                            "remove: sas_addr(0x%016llx), phy(%d)\n",
 805                            (unsigned long long)
 806                            mpt3sas_port->remote_identify.sas_address,
 807                            mpt3sas_phy->phy_id);
 808                mpt3sas_phy->phy_belongs_to_port = 0;
 809                if (!ioc->remove_host)
 810                        sas_port_delete_phy(mpt3sas_port->port,
 811                                                mpt3sas_phy->phy);
 812                list_del(&mpt3sas_phy->port_siblings);
 813        }
 814        if (!ioc->remove_host)
 815                sas_port_delete(mpt3sas_port->port);
 816        kfree(mpt3sas_port);
 817}
 818
 819/**
 820 * mpt3sas_transport_add_host_phy - report sas_host phy to transport
 821 * @ioc: per adapter object
 822 * @mpt3sas_phy: mpt3sas per phy object
 823 * @phy_pg0: sas phy page 0
 824 * @parent_dev: parent device class object
 825 *
 826 * Return: 0 for success, non-zero for failure.
 827 */
 828int
 829mpt3sas_transport_add_host_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_phy
 830        *mpt3sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev)
 831{
 832        struct sas_phy *phy;
 833        int phy_index = mpt3sas_phy->phy_id;
 834
 835
 836        INIT_LIST_HEAD(&mpt3sas_phy->port_siblings);
 837        phy = sas_phy_alloc(parent_dev, phy_index);
 838        if (!phy) {
 839                ioc_err(ioc, "failure at %s:%d/%s()!\n",
 840                        __FILE__, __LINE__, __func__);
 841                return -1;
 842        }
 843        if ((_transport_set_identify(ioc, mpt3sas_phy->handle,
 844            &mpt3sas_phy->identify))) {
 845                ioc_err(ioc, "failure at %s:%d/%s()!\n",
 846                        __FILE__, __LINE__, __func__);
 847                sas_phy_free(phy);
 848                return -1;
 849        }
 850        phy->identify = mpt3sas_phy->identify;
 851        mpt3sas_phy->attached_handle = le16_to_cpu(phy_pg0.AttachedDevHandle);
 852        if (mpt3sas_phy->attached_handle)
 853                _transport_set_identify(ioc, mpt3sas_phy->attached_handle,
 854                    &mpt3sas_phy->remote_identify);
 855        phy->identify.phy_identifier = mpt3sas_phy->phy_id;
 856        phy->negotiated_linkrate = _transport_convert_phy_link_rate(
 857            phy_pg0.NegotiatedLinkRate & MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
 858        phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
 859            phy_pg0.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
 860        phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
 861            phy_pg0.HwLinkRate >> 4);
 862        phy->minimum_linkrate = _transport_convert_phy_link_rate(
 863            phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
 864        phy->maximum_linkrate = _transport_convert_phy_link_rate(
 865            phy_pg0.ProgrammedLinkRate >> 4);
 866
 867        if ((sas_phy_add(phy))) {
 868                ioc_err(ioc, "failure at %s:%d/%s()!\n",
 869                        __FILE__, __LINE__, __func__);
 870                sas_phy_free(phy);
 871                return -1;
 872        }
 873        if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
 874                dev_printk(KERN_INFO, &phy->dev,
 875                    "add: handle(0x%04x), sas_addr(0x%016llx)\n"
 876                    "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
 877                    mpt3sas_phy->handle, (unsigned long long)
 878                    mpt3sas_phy->identify.sas_address,
 879                    mpt3sas_phy->attached_handle,
 880                    (unsigned long long)
 881                    mpt3sas_phy->remote_identify.sas_address);
 882        mpt3sas_phy->phy = phy;
 883        return 0;
 884}
 885
 886
 887/**
 888 * mpt3sas_transport_add_expander_phy - report expander phy to transport
 889 * @ioc: per adapter object
 890 * @mpt3sas_phy: mpt3sas per phy object
 891 * @expander_pg1: expander page 1
 892 * @parent_dev: parent device class object
 893 *
 894 * Return: 0 for success, non-zero for failure.
 895 */
 896int
 897mpt3sas_transport_add_expander_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_phy
 898        *mpt3sas_phy, Mpi2ExpanderPage1_t expander_pg1,
 899        struct device *parent_dev)
 900{
 901        struct sas_phy *phy;
 902        int phy_index = mpt3sas_phy->phy_id;
 903
 904        INIT_LIST_HEAD(&mpt3sas_phy->port_siblings);
 905        phy = sas_phy_alloc(parent_dev, phy_index);
 906        if (!phy) {
 907                ioc_err(ioc, "failure at %s:%d/%s()!\n",
 908                        __FILE__, __LINE__, __func__);
 909                return -1;
 910        }
 911        if ((_transport_set_identify(ioc, mpt3sas_phy->handle,
 912            &mpt3sas_phy->identify))) {
 913                ioc_err(ioc, "failure at %s:%d/%s()!\n",
 914                        __FILE__, __LINE__, __func__);
 915                sas_phy_free(phy);
 916                return -1;
 917        }
 918        phy->identify = mpt3sas_phy->identify;
 919        mpt3sas_phy->attached_handle =
 920            le16_to_cpu(expander_pg1.AttachedDevHandle);
 921        if (mpt3sas_phy->attached_handle)
 922                _transport_set_identify(ioc, mpt3sas_phy->attached_handle,
 923                    &mpt3sas_phy->remote_identify);
 924        phy->identify.phy_identifier = mpt3sas_phy->phy_id;
 925        phy->negotiated_linkrate = _transport_convert_phy_link_rate(
 926            expander_pg1.NegotiatedLinkRate &
 927            MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
 928        phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
 929            expander_pg1.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
 930        phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
 931            expander_pg1.HwLinkRate >> 4);
 932        phy->minimum_linkrate = _transport_convert_phy_link_rate(
 933            expander_pg1.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
 934        phy->maximum_linkrate = _transport_convert_phy_link_rate(
 935            expander_pg1.ProgrammedLinkRate >> 4);
 936
 937        if ((sas_phy_add(phy))) {
 938                ioc_err(ioc, "failure at %s:%d/%s()!\n",
 939                        __FILE__, __LINE__, __func__);
 940                sas_phy_free(phy);
 941                return -1;
 942        }
 943        if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
 944                dev_printk(KERN_INFO, &phy->dev,
 945                    "add: handle(0x%04x), sas_addr(0x%016llx)\n"
 946                    "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
 947                    mpt3sas_phy->handle, (unsigned long long)
 948                    mpt3sas_phy->identify.sas_address,
 949                    mpt3sas_phy->attached_handle,
 950                    (unsigned long long)
 951                    mpt3sas_phy->remote_identify.sas_address);
 952        mpt3sas_phy->phy = phy;
 953        return 0;
 954}
 955
 956/**
 957 * mpt3sas_transport_update_links - refreshing phy link changes
 958 * @ioc: per adapter object
 959 * @sas_address: sas address of parent expander or sas host
 960 * @handle: attached device handle
 961 * @phy_number: phy number
 962 * @link_rate: new link rate
 963 */
 964void
 965mpt3sas_transport_update_links(struct MPT3SAS_ADAPTER *ioc,
 966        u64 sas_address, u16 handle, u8 phy_number, u8 link_rate)
 967{
 968        unsigned long flags;
 969        struct _sas_node *sas_node;
 970        struct _sas_phy *mpt3sas_phy;
 971
 972        if (ioc->shost_recovery || ioc->pci_error_recovery)
 973                return;
 974
 975        spin_lock_irqsave(&ioc->sas_node_lock, flags);
 976        sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
 977        if (!sas_node) {
 978                spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 979                return;
 980        }
 981
 982        mpt3sas_phy = &sas_node->phy[phy_number];
 983        mpt3sas_phy->attached_handle = handle;
 984        spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 985        if (handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5)) {
 986                _transport_set_identify(ioc, handle,
 987                    &mpt3sas_phy->remote_identify);
 988                _transport_add_phy_to_an_existing_port(ioc, sas_node,
 989                    mpt3sas_phy, mpt3sas_phy->remote_identify.sas_address);
 990        } else
 991                memset(&mpt3sas_phy->remote_identify, 0 , sizeof(struct
 992                    sas_identify));
 993
 994        if (mpt3sas_phy->phy)
 995                mpt3sas_phy->phy->negotiated_linkrate =
 996                    _transport_convert_phy_link_rate(link_rate);
 997
 998        if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
 999                dev_printk(KERN_INFO, &mpt3sas_phy->phy->dev,
1000                    "refresh: parent sas_addr(0x%016llx),\n"
1001                    "\tlink_rate(0x%02x), phy(%d)\n"
1002                    "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
1003                    (unsigned long long)sas_address,
1004                    link_rate, phy_number, handle, (unsigned long long)
1005                    mpt3sas_phy->remote_identify.sas_address);
1006}
1007
1008static inline void *
1009phy_to_ioc(struct sas_phy *phy)
1010{
1011        struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
1012        return shost_priv(shost);
1013}
1014
1015static inline void *
1016rphy_to_ioc(struct sas_rphy *rphy)
1017{
1018        struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
1019        return shost_priv(shost);
1020}
1021
1022/* report phy error log structure */
1023struct phy_error_log_request {
1024        u8 smp_frame_type; /* 0x40 */
1025        u8 function; /* 0x11 */
1026        u8 allocated_response_length;
1027        u8 request_length; /* 02 */
1028        u8 reserved_1[5];
1029        u8 phy_identifier;
1030        u8 reserved_2[2];
1031};
1032
1033/* report phy error log reply structure */
1034struct phy_error_log_reply {
1035        u8 smp_frame_type; /* 0x41 */
1036        u8 function; /* 0x11 */
1037        u8 function_result;
1038        u8 response_length;
1039        __be16 expander_change_count;
1040        u8 reserved_1[3];
1041        u8 phy_identifier;
1042        u8 reserved_2[2];
1043        __be32 invalid_dword;
1044        __be32 running_disparity_error;
1045        __be32 loss_of_dword_sync;
1046        __be32 phy_reset_problem;
1047};
1048
1049/**
1050 * _transport_get_expander_phy_error_log - return expander counters
1051 * @ioc: per adapter object
1052 * @phy: The sas phy object
1053 *
1054 * Return: 0 for success, non-zero for failure.
1055 *
1056 */
1057static int
1058_transport_get_expander_phy_error_log(struct MPT3SAS_ADAPTER *ioc,
1059        struct sas_phy *phy)
1060{
1061        Mpi2SmpPassthroughRequest_t *mpi_request;
1062        Mpi2SmpPassthroughReply_t *mpi_reply;
1063        struct phy_error_log_request *phy_error_log_request;
1064        struct phy_error_log_reply *phy_error_log_reply;
1065        int rc;
1066        u16 smid;
1067        void *psge;
1068        u8 issue_reset = 0;
1069        void *data_out = NULL;
1070        dma_addr_t data_out_dma;
1071        u32 sz;
1072
1073        if (ioc->shost_recovery || ioc->pci_error_recovery) {
1074                ioc_info(ioc, "%s: host reset in progress!\n", __func__);
1075                return -EFAULT;
1076        }
1077
1078        mutex_lock(&ioc->transport_cmds.mutex);
1079
1080        if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) {
1081                ioc_err(ioc, "%s: transport_cmds in use\n", __func__);
1082                rc = -EAGAIN;
1083                goto out;
1084        }
1085        ioc->transport_cmds.status = MPT3_CMD_PENDING;
1086
1087        rc = mpt3sas_wait_for_ioc(ioc, IOC_OPERATIONAL_WAIT_COUNT);
1088        if (rc)
1089                goto out;
1090
1091        smid = mpt3sas_base_get_smid(ioc, ioc->transport_cb_idx);
1092        if (!smid) {
1093                ioc_err(ioc, "%s: failed obtaining a smid\n", __func__);
1094                rc = -EAGAIN;
1095                goto out;
1096        }
1097
1098        mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
1099        ioc->transport_cmds.smid = smid;
1100
1101        sz = sizeof(struct phy_error_log_request) +
1102            sizeof(struct phy_error_log_reply);
1103        data_out = dma_alloc_coherent(&ioc->pdev->dev, sz, &data_out_dma,
1104                        GFP_KERNEL);
1105        if (!data_out) {
1106                pr_err("failure at %s:%d/%s()!\n", __FILE__,
1107                    __LINE__, __func__);
1108                rc = -ENOMEM;
1109                mpt3sas_base_free_smid(ioc, smid);
1110                goto out;
1111        }
1112
1113        rc = -EINVAL;
1114        memset(data_out, 0, sz);
1115        phy_error_log_request = data_out;
1116        phy_error_log_request->smp_frame_type = 0x40;
1117        phy_error_log_request->function = 0x11;
1118        phy_error_log_request->request_length = 2;
1119        phy_error_log_request->allocated_response_length = 0;
1120        phy_error_log_request->phy_identifier = phy->number;
1121
1122        memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
1123        mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
1124        mpi_request->PhysicalPort = 0xFF;
1125        mpi_request->VF_ID = 0; /* TODO */
1126        mpi_request->VP_ID = 0;
1127        mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
1128        mpi_request->RequestDataLength =
1129            cpu_to_le16(sizeof(struct phy_error_log_request));
1130        psge = &mpi_request->SGL;
1131
1132        ioc->build_sg(ioc, psge, data_out_dma,
1133                sizeof(struct phy_error_log_request),
1134            data_out_dma + sizeof(struct phy_error_log_request),
1135            sizeof(struct phy_error_log_reply));
1136
1137        dtransportprintk(ioc,
1138                         ioc_info(ioc, "phy_error_log - send to sas_addr(0x%016llx), phy(%d)\n",
1139                                  (u64)phy->identify.sas_address,
1140                                  phy->number));
1141        init_completion(&ioc->transport_cmds.done);
1142        ioc->put_smid_default(ioc, smid);
1143        wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ);
1144
1145        if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) {
1146                ioc_err(ioc, "%s: timeout\n", __func__);
1147                _debug_dump_mf(mpi_request,
1148                    sizeof(Mpi2SmpPassthroughRequest_t)/4);
1149                if (!(ioc->transport_cmds.status & MPT3_CMD_RESET))
1150                        issue_reset = 1;
1151                goto issue_host_reset;
1152        }
1153
1154        dtransportprintk(ioc, ioc_info(ioc, "phy_error_log - complete\n"));
1155
1156        if (ioc->transport_cmds.status & MPT3_CMD_REPLY_VALID) {
1157
1158                mpi_reply = ioc->transport_cmds.reply;
1159
1160                dtransportprintk(ioc,
1161                                 ioc_info(ioc, "phy_error_log - reply data transfer size(%d)\n",
1162                                          le16_to_cpu(mpi_reply->ResponseDataLength)));
1163
1164                if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
1165                    sizeof(struct phy_error_log_reply))
1166                        goto out;
1167
1168                phy_error_log_reply = data_out +
1169                    sizeof(struct phy_error_log_request);
1170
1171                dtransportprintk(ioc,
1172                                 ioc_info(ioc, "phy_error_log - function_result(%d)\n",
1173                                          phy_error_log_reply->function_result));
1174
1175                phy->invalid_dword_count =
1176                    be32_to_cpu(phy_error_log_reply->invalid_dword);
1177                phy->running_disparity_error_count =
1178                    be32_to_cpu(phy_error_log_reply->running_disparity_error);
1179                phy->loss_of_dword_sync_count =
1180                    be32_to_cpu(phy_error_log_reply->loss_of_dword_sync);
1181                phy->phy_reset_problem_count =
1182                    be32_to_cpu(phy_error_log_reply->phy_reset_problem);
1183                rc = 0;
1184        } else
1185                dtransportprintk(ioc,
1186                                 ioc_info(ioc, "phy_error_log - no reply\n"));
1187
1188 issue_host_reset:
1189        if (issue_reset)
1190                mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
1191 out:
1192        ioc->transport_cmds.status = MPT3_CMD_NOT_USED;
1193        if (data_out)
1194                dma_free_coherent(&ioc->pdev->dev, sz, data_out, data_out_dma);
1195
1196        mutex_unlock(&ioc->transport_cmds.mutex);
1197        return rc;
1198}
1199
1200/**
1201 * _transport_get_linkerrors - return phy counters for both hba and expanders
1202 * @phy: The sas phy object
1203 *
1204 * Return: 0 for success, non-zero for failure.
1205 *
1206 */
1207static int
1208_transport_get_linkerrors(struct sas_phy *phy)
1209{
1210        struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy);
1211        unsigned long flags;
1212        Mpi2ConfigReply_t mpi_reply;
1213        Mpi2SasPhyPage1_t phy_pg1;
1214
1215        spin_lock_irqsave(&ioc->sas_node_lock, flags);
1216        if (_transport_sas_node_find_by_sas_address(ioc,
1217            phy->identify.sas_address) == NULL) {
1218                spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1219                return -EINVAL;
1220        }
1221        spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1222
1223        if (phy->identify.sas_address != ioc->sas_hba.sas_address)
1224                return _transport_get_expander_phy_error_log(ioc, phy);
1225
1226        /* get hba phy error logs */
1227        if ((mpt3sas_config_get_phy_pg1(ioc, &mpi_reply, &phy_pg1,
1228                    phy->number))) {
1229                ioc_err(ioc, "failure at %s:%d/%s()!\n",
1230                        __FILE__, __LINE__, __func__);
1231                return -ENXIO;
1232        }
1233
1234        if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
1235                ioc_info(ioc, "phy(%d), ioc_status (0x%04x), loginfo(0x%08x)\n",
1236                         phy->number,
1237                         le16_to_cpu(mpi_reply.IOCStatus),
1238                         le32_to_cpu(mpi_reply.IOCLogInfo));
1239
1240        phy->invalid_dword_count = le32_to_cpu(phy_pg1.InvalidDwordCount);
1241        phy->running_disparity_error_count =
1242            le32_to_cpu(phy_pg1.RunningDisparityErrorCount);
1243        phy->loss_of_dword_sync_count =
1244            le32_to_cpu(phy_pg1.LossDwordSynchCount);
1245        phy->phy_reset_problem_count =
1246            le32_to_cpu(phy_pg1.PhyResetProblemCount);
1247        return 0;
1248}
1249
1250/**
1251 * _transport_get_enclosure_identifier -
1252 * @rphy: The sas phy object
1253 * @identifier: ?
1254 *
1255 * Obtain the enclosure logical id for an expander.
1256 * Return: 0 for success, non-zero for failure.
1257 */
1258static int
1259_transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
1260{
1261        struct MPT3SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
1262        struct _sas_device *sas_device;
1263        unsigned long flags;
1264        int rc;
1265
1266        spin_lock_irqsave(&ioc->sas_device_lock, flags);
1267        sas_device = __mpt3sas_get_sdev_by_addr(ioc,
1268            rphy->identify.sas_address);
1269        if (sas_device) {
1270                *identifier = sas_device->enclosure_logical_id;
1271                rc = 0;
1272                sas_device_put(sas_device);
1273        } else {
1274                *identifier = 0;
1275                rc = -ENXIO;
1276        }
1277
1278        spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1279        return rc;
1280}
1281
1282/**
1283 * _transport_get_bay_identifier -
1284 * @rphy: The sas phy object
1285 *
1286 * Return: the slot id for a device that resides inside an enclosure.
1287 */
1288static int
1289_transport_get_bay_identifier(struct sas_rphy *rphy)
1290{
1291        struct MPT3SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
1292        struct _sas_device *sas_device;
1293        unsigned long flags;
1294        int rc;
1295
1296        spin_lock_irqsave(&ioc->sas_device_lock, flags);
1297        sas_device = __mpt3sas_get_sdev_by_addr(ioc,
1298            rphy->identify.sas_address);
1299        if (sas_device) {
1300                rc = sas_device->slot;
1301                sas_device_put(sas_device);
1302        } else {
1303                rc = -ENXIO;
1304        }
1305        spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1306        return rc;
1307}
1308
1309/* phy control request structure */
1310struct phy_control_request {
1311        u8 smp_frame_type; /* 0x40 */
1312        u8 function; /* 0x91 */
1313        u8 allocated_response_length;
1314        u8 request_length; /* 0x09 */
1315        u16 expander_change_count;
1316        u8 reserved_1[3];
1317        u8 phy_identifier;
1318        u8 phy_operation;
1319        u8 reserved_2[13];
1320        u64 attached_device_name;
1321        u8 programmed_min_physical_link_rate;
1322        u8 programmed_max_physical_link_rate;
1323        u8 reserved_3[6];
1324};
1325
1326/* phy control reply structure */
1327struct phy_control_reply {
1328        u8 smp_frame_type; /* 0x41 */
1329        u8 function; /* 0x11 */
1330        u8 function_result;
1331        u8 response_length;
1332};
1333
1334#define SMP_PHY_CONTROL_LINK_RESET      (0x01)
1335#define SMP_PHY_CONTROL_HARD_RESET      (0x02)
1336#define SMP_PHY_CONTROL_DISABLE         (0x03)
1337
1338/**
1339 * _transport_expander_phy_control - expander phy control
1340 * @ioc: per adapter object
1341 * @phy: The sas phy object
1342 * @phy_operation: ?
1343 *
1344 * Return: 0 for success, non-zero for failure.
1345 *
1346 */
1347static int
1348_transport_expander_phy_control(struct MPT3SAS_ADAPTER *ioc,
1349        struct sas_phy *phy, u8 phy_operation)
1350{
1351        Mpi2SmpPassthroughRequest_t *mpi_request;
1352        Mpi2SmpPassthroughReply_t *mpi_reply;
1353        struct phy_control_request *phy_control_request;
1354        struct phy_control_reply *phy_control_reply;
1355        int rc;
1356        u16 smid;
1357        void *psge;
1358        u8 issue_reset = 0;
1359        void *data_out = NULL;
1360        dma_addr_t data_out_dma;
1361        u32 sz;
1362
1363        if (ioc->shost_recovery || ioc->pci_error_recovery) {
1364                ioc_info(ioc, "%s: host reset in progress!\n", __func__);
1365                return -EFAULT;
1366        }
1367
1368        mutex_lock(&ioc->transport_cmds.mutex);
1369
1370        if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) {
1371                ioc_err(ioc, "%s: transport_cmds in use\n", __func__);
1372                rc = -EAGAIN;
1373                goto out;
1374        }
1375        ioc->transport_cmds.status = MPT3_CMD_PENDING;
1376
1377        rc = mpt3sas_wait_for_ioc(ioc, IOC_OPERATIONAL_WAIT_COUNT);
1378        if (rc)
1379                goto out;
1380
1381        smid = mpt3sas_base_get_smid(ioc, ioc->transport_cb_idx);
1382        if (!smid) {
1383                ioc_err(ioc, "%s: failed obtaining a smid\n", __func__);
1384                rc = -EAGAIN;
1385                goto out;
1386        }
1387
1388        mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
1389        ioc->transport_cmds.smid = smid;
1390
1391        sz = sizeof(struct phy_control_request) +
1392            sizeof(struct phy_control_reply);
1393        data_out = dma_alloc_coherent(&ioc->pdev->dev, sz, &data_out_dma,
1394                        GFP_KERNEL);
1395        if (!data_out) {
1396                pr_err("failure at %s:%d/%s()!\n", __FILE__,
1397                    __LINE__, __func__);
1398                rc = -ENOMEM;
1399                mpt3sas_base_free_smid(ioc, smid);
1400                goto out;
1401        }
1402
1403        rc = -EINVAL;
1404        memset(data_out, 0, sz);
1405        phy_control_request = data_out;
1406        phy_control_request->smp_frame_type = 0x40;
1407        phy_control_request->function = 0x91;
1408        phy_control_request->request_length = 9;
1409        phy_control_request->allocated_response_length = 0;
1410        phy_control_request->phy_identifier = phy->number;
1411        phy_control_request->phy_operation = phy_operation;
1412        phy_control_request->programmed_min_physical_link_rate =
1413            phy->minimum_linkrate << 4;
1414        phy_control_request->programmed_max_physical_link_rate =
1415            phy->maximum_linkrate << 4;
1416
1417        memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
1418        mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
1419        mpi_request->PhysicalPort = 0xFF;
1420        mpi_request->VF_ID = 0; /* TODO */
1421        mpi_request->VP_ID = 0;
1422        mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
1423        mpi_request->RequestDataLength =
1424            cpu_to_le16(sizeof(struct phy_error_log_request));
1425        psge = &mpi_request->SGL;
1426
1427        ioc->build_sg(ioc, psge, data_out_dma,
1428                            sizeof(struct phy_control_request),
1429            data_out_dma + sizeof(struct phy_control_request),
1430            sizeof(struct phy_control_reply));
1431
1432        dtransportprintk(ioc,
1433                         ioc_info(ioc, "phy_control - send to sas_addr(0x%016llx), phy(%d), opcode(%d)\n",
1434                                  (u64)phy->identify.sas_address,
1435                                  phy->number, phy_operation));
1436        init_completion(&ioc->transport_cmds.done);
1437        ioc->put_smid_default(ioc, smid);
1438        wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ);
1439
1440        if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) {
1441                ioc_err(ioc, "%s: timeout\n", __func__);
1442                _debug_dump_mf(mpi_request,
1443                    sizeof(Mpi2SmpPassthroughRequest_t)/4);
1444                if (!(ioc->transport_cmds.status & MPT3_CMD_RESET))
1445                        issue_reset = 1;
1446                goto issue_host_reset;
1447        }
1448
1449        dtransportprintk(ioc, ioc_info(ioc, "phy_control - complete\n"));
1450
1451        if (ioc->transport_cmds.status & MPT3_CMD_REPLY_VALID) {
1452
1453                mpi_reply = ioc->transport_cmds.reply;
1454
1455                dtransportprintk(ioc,
1456                                 ioc_info(ioc, "phy_control - reply data transfer size(%d)\n",
1457                                          le16_to_cpu(mpi_reply->ResponseDataLength)));
1458
1459                if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
1460                    sizeof(struct phy_control_reply))
1461                        goto out;
1462
1463                phy_control_reply = data_out +
1464                    sizeof(struct phy_control_request);
1465
1466                dtransportprintk(ioc,
1467                                 ioc_info(ioc, "phy_control - function_result(%d)\n",
1468                                          phy_control_reply->function_result));
1469
1470                rc = 0;
1471        } else
1472                dtransportprintk(ioc,
1473                                 ioc_info(ioc, "phy_control - no reply\n"));
1474
1475 issue_host_reset:
1476        if (issue_reset)
1477                mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
1478 out:
1479        ioc->transport_cmds.status = MPT3_CMD_NOT_USED;
1480        if (data_out)
1481                dma_free_coherent(&ioc->pdev->dev, sz, data_out,
1482                                data_out_dma);
1483
1484        mutex_unlock(&ioc->transport_cmds.mutex);
1485        return rc;
1486}
1487
1488/**
1489 * _transport_phy_reset -
1490 * @phy: The sas phy object
1491 * @hard_reset:
1492 *
1493 * Return: 0 for success, non-zero for failure.
1494 */
1495static int
1496_transport_phy_reset(struct sas_phy *phy, int hard_reset)
1497{
1498        struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy);
1499        Mpi2SasIoUnitControlReply_t mpi_reply;
1500        Mpi2SasIoUnitControlRequest_t mpi_request;
1501        unsigned long flags;
1502
1503        spin_lock_irqsave(&ioc->sas_node_lock, flags);
1504        if (_transport_sas_node_find_by_sas_address(ioc,
1505            phy->identify.sas_address) == NULL) {
1506                spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1507                return -EINVAL;
1508        }
1509        spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1510
1511        /* handle expander phys */
1512        if (phy->identify.sas_address != ioc->sas_hba.sas_address)
1513                return _transport_expander_phy_control(ioc, phy,
1514                    (hard_reset == 1) ? SMP_PHY_CONTROL_HARD_RESET :
1515                    SMP_PHY_CONTROL_LINK_RESET);
1516
1517        /* handle hba phys */
1518        memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlRequest_t));
1519        mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
1520        mpi_request.Operation = hard_reset ?
1521            MPI2_SAS_OP_PHY_HARD_RESET : MPI2_SAS_OP_PHY_LINK_RESET;
1522        mpi_request.PhyNum = phy->number;
1523
1524        if ((mpt3sas_base_sas_iounit_control(ioc, &mpi_reply, &mpi_request))) {
1525                ioc_err(ioc, "failure at %s:%d/%s()!\n",
1526                        __FILE__, __LINE__, __func__);
1527                return -ENXIO;
1528        }
1529
1530        if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
1531                ioc_info(ioc, "phy(%d), ioc_status(0x%04x), loginfo(0x%08x)\n",
1532                         phy->number, le16_to_cpu(mpi_reply.IOCStatus),
1533                         le32_to_cpu(mpi_reply.IOCLogInfo));
1534
1535        return 0;
1536}
1537
1538/**
1539 * _transport_phy_enable - enable/disable phys
1540 * @phy: The sas phy object
1541 * @enable: enable phy when true
1542 *
1543 * Only support sas_host direct attached phys.
1544 * Return: 0 for success, non-zero for failure.
1545 */
1546static int
1547_transport_phy_enable(struct sas_phy *phy, int enable)
1548{
1549        struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy);
1550        Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
1551        Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
1552        Mpi2ConfigReply_t mpi_reply;
1553        u16 ioc_status;
1554        u16 sz;
1555        int rc = 0;
1556        unsigned long flags;
1557        int i, discovery_active;
1558
1559        spin_lock_irqsave(&ioc->sas_node_lock, flags);
1560        if (_transport_sas_node_find_by_sas_address(ioc,
1561            phy->identify.sas_address) == NULL) {
1562                spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1563                return -EINVAL;
1564        }
1565        spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1566
1567        /* handle expander phys */
1568        if (phy->identify.sas_address != ioc->sas_hba.sas_address)
1569                return _transport_expander_phy_control(ioc, phy,
1570                    (enable == 1) ? SMP_PHY_CONTROL_LINK_RESET :
1571                    SMP_PHY_CONTROL_DISABLE);
1572
1573        /* handle hba phys */
1574
1575        /* read sas_iounit page 0 */
1576        sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys *
1577            sizeof(Mpi2SasIOUnit0PhyData_t));
1578        sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
1579        if (!sas_iounit_pg0) {
1580                ioc_err(ioc, "failure at %s:%d/%s()!\n",
1581                        __FILE__, __LINE__, __func__);
1582                rc = -ENOMEM;
1583                goto out;
1584        }
1585        if ((mpt3sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
1586            sas_iounit_pg0, sz))) {
1587                ioc_err(ioc, "failure at %s:%d/%s()!\n",
1588                        __FILE__, __LINE__, __func__);
1589                rc = -ENXIO;
1590                goto out;
1591        }
1592        ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1593            MPI2_IOCSTATUS_MASK;
1594        if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1595                ioc_err(ioc, "failure at %s:%d/%s()!\n",
1596                        __FILE__, __LINE__, __func__);
1597                rc = -EIO;
1598                goto out;
1599        }
1600
1601        /* unable to enable/disable phys when when discovery is active */
1602        for (i = 0, discovery_active = 0; i < ioc->sas_hba.num_phys ; i++) {
1603                if (sas_iounit_pg0->PhyData[i].PortFlags &
1604                    MPI2_SASIOUNIT0_PORTFLAGS_DISCOVERY_IN_PROGRESS) {
1605                        ioc_err(ioc, "discovery is active on port = %d, phy = %d: unable to enable/disable phys, try again later!\n",
1606                                sas_iounit_pg0->PhyData[i].Port, i);
1607                        discovery_active = 1;
1608                }
1609        }
1610
1611        if (discovery_active) {
1612                rc = -EAGAIN;
1613                goto out;
1614        }
1615
1616        /* read sas_iounit page 1 */
1617        sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
1618            sizeof(Mpi2SasIOUnit1PhyData_t));
1619        sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
1620        if (!sas_iounit_pg1) {
1621                ioc_err(ioc, "failure at %s:%d/%s()!\n",
1622                        __FILE__, __LINE__, __func__);
1623                rc = -ENOMEM;
1624                goto out;
1625        }
1626        if ((mpt3sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
1627            sas_iounit_pg1, sz))) {
1628                ioc_err(ioc, "failure at %s:%d/%s()!\n",
1629                        __FILE__, __LINE__, __func__);
1630                rc = -ENXIO;
1631                goto out;
1632        }
1633        ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1634            MPI2_IOCSTATUS_MASK;
1635        if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1636                ioc_err(ioc, "failure at %s:%d/%s()!\n",
1637                        __FILE__, __LINE__, __func__);
1638                rc = -EIO;
1639                goto out;
1640        }
1641
1642        /* copy Port/PortFlags/PhyFlags from page 0 */
1643        for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
1644                sas_iounit_pg1->PhyData[i].Port =
1645                    sas_iounit_pg0->PhyData[i].Port;
1646                sas_iounit_pg1->PhyData[i].PortFlags =
1647                    (sas_iounit_pg0->PhyData[i].PortFlags &
1648                    MPI2_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG);
1649                sas_iounit_pg1->PhyData[i].PhyFlags =
1650                    (sas_iounit_pg0->PhyData[i].PhyFlags &
1651                    (MPI2_SASIOUNIT0_PHYFLAGS_ZONING_ENABLED +
1652                    MPI2_SASIOUNIT0_PHYFLAGS_PHY_DISABLED));
1653        }
1654
1655        if (enable)
1656                sas_iounit_pg1->PhyData[phy->number].PhyFlags
1657                    &= ~MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
1658        else
1659                sas_iounit_pg1->PhyData[phy->number].PhyFlags
1660                    |= MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
1661
1662        mpt3sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1, sz);
1663
1664        /* link reset */
1665        if (enable)
1666                _transport_phy_reset(phy, 0);
1667
1668 out:
1669        kfree(sas_iounit_pg1);
1670        kfree(sas_iounit_pg0);
1671        return rc;
1672}
1673
1674/**
1675 * _transport_phy_speed - set phy min/max link rates
1676 * @phy: The sas phy object
1677 * @rates: rates defined in sas_phy_linkrates
1678 *
1679 * Only support sas_host direct attached phys.
1680 *
1681 * Return: 0 for success, non-zero for failure.
1682 */
1683static int
1684_transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
1685{
1686        struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy);
1687        Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
1688        Mpi2SasPhyPage0_t phy_pg0;
1689        Mpi2ConfigReply_t mpi_reply;
1690        u16 ioc_status;
1691        u16 sz;
1692        int i;
1693        int rc = 0;
1694        unsigned long flags;
1695
1696        spin_lock_irqsave(&ioc->sas_node_lock, flags);
1697        if (_transport_sas_node_find_by_sas_address(ioc,
1698            phy->identify.sas_address) == NULL) {
1699                spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1700                return -EINVAL;
1701        }
1702        spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1703
1704        if (!rates->minimum_linkrate)
1705                rates->minimum_linkrate = phy->minimum_linkrate;
1706        else if (rates->minimum_linkrate < phy->minimum_linkrate_hw)
1707                rates->minimum_linkrate = phy->minimum_linkrate_hw;
1708
1709        if (!rates->maximum_linkrate)
1710                rates->maximum_linkrate = phy->maximum_linkrate;
1711        else if (rates->maximum_linkrate > phy->maximum_linkrate_hw)
1712                rates->maximum_linkrate = phy->maximum_linkrate_hw;
1713
1714        /* handle expander phys */
1715        if (phy->identify.sas_address != ioc->sas_hba.sas_address) {
1716                phy->minimum_linkrate = rates->minimum_linkrate;
1717                phy->maximum_linkrate = rates->maximum_linkrate;
1718                return _transport_expander_phy_control(ioc, phy,
1719                    SMP_PHY_CONTROL_LINK_RESET);
1720        }
1721
1722        /* handle hba phys */
1723
1724        /* sas_iounit page 1 */
1725        sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
1726            sizeof(Mpi2SasIOUnit1PhyData_t));
1727        sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
1728        if (!sas_iounit_pg1) {
1729                ioc_err(ioc, "failure at %s:%d/%s()!\n",
1730                        __FILE__, __LINE__, __func__);
1731                rc = -ENOMEM;
1732                goto out;
1733        }
1734        if ((mpt3sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
1735            sas_iounit_pg1, sz))) {
1736                ioc_err(ioc, "failure at %s:%d/%s()!\n",
1737                        __FILE__, __LINE__, __func__);
1738                rc = -ENXIO;
1739                goto out;
1740        }
1741        ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1742            MPI2_IOCSTATUS_MASK;
1743        if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1744                ioc_err(ioc, "failure at %s:%d/%s()!\n",
1745                        __FILE__, __LINE__, __func__);
1746                rc = -EIO;
1747                goto out;
1748        }
1749
1750        for (i = 0; i < ioc->sas_hba.num_phys; i++) {
1751                if (phy->number != i) {
1752                        sas_iounit_pg1->PhyData[i].MaxMinLinkRate =
1753                            (ioc->sas_hba.phy[i].phy->minimum_linkrate +
1754                            (ioc->sas_hba.phy[i].phy->maximum_linkrate << 4));
1755                } else {
1756                        sas_iounit_pg1->PhyData[i].MaxMinLinkRate =
1757                            (rates->minimum_linkrate +
1758                            (rates->maximum_linkrate << 4));
1759                }
1760        }
1761
1762        if (mpt3sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1,
1763            sz)) {
1764                ioc_err(ioc, "failure at %s:%d/%s()!\n",
1765                        __FILE__, __LINE__, __func__);
1766                rc = -ENXIO;
1767                goto out;
1768        }
1769
1770        /* link reset */
1771        _transport_phy_reset(phy, 0);
1772
1773        /* read phy page 0, then update the rates in the sas transport phy */
1774        if (!mpt3sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0,
1775            phy->number)) {
1776                phy->minimum_linkrate = _transport_convert_phy_link_rate(
1777                    phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
1778                phy->maximum_linkrate = _transport_convert_phy_link_rate(
1779                    phy_pg0.ProgrammedLinkRate >> 4);
1780                phy->negotiated_linkrate = _transport_convert_phy_link_rate(
1781                    phy_pg0.NegotiatedLinkRate &
1782                    MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
1783        }
1784
1785 out:
1786        kfree(sas_iounit_pg1);
1787        return rc;
1788}
1789
1790static int
1791_transport_map_smp_buffer(struct device *dev, struct bsg_buffer *buf,
1792                dma_addr_t *dma_addr, size_t *dma_len, void **p)
1793{
1794        /* Check if the request is split across multiple segments */
1795        if (buf->sg_cnt > 1) {
1796                *p = dma_alloc_coherent(dev, buf->payload_len, dma_addr,
1797                                GFP_KERNEL);
1798                if (!*p)
1799                        return -ENOMEM;
1800                *dma_len = buf->payload_len;
1801        } else {
1802                if (!dma_map_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL))
1803                        return -ENOMEM;
1804                *dma_addr = sg_dma_address(buf->sg_list);
1805                *dma_len = sg_dma_len(buf->sg_list);
1806                *p = NULL;
1807        }
1808
1809        return 0;
1810}
1811
1812static void
1813_transport_unmap_smp_buffer(struct device *dev, struct bsg_buffer *buf,
1814                dma_addr_t dma_addr, void *p)
1815{
1816        if (p)
1817                dma_free_coherent(dev, buf->payload_len, p, dma_addr);
1818        else
1819                dma_unmap_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL);
1820}
1821
1822/**
1823 * _transport_smp_handler - transport portal for smp passthru
1824 * @job: ?
1825 * @shost: shost object
1826 * @rphy: sas transport rphy object
1827 *
1828 * This used primarily for smp_utils.
1829 * Example:
1830 *           smp_rep_general /sys/class/bsg/expander-5:0
1831 */
1832static void
1833_transport_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
1834                struct sas_rphy *rphy)
1835{
1836        struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
1837        Mpi2SmpPassthroughRequest_t *mpi_request;
1838        Mpi2SmpPassthroughReply_t *mpi_reply;
1839        int rc;
1840        u16 smid;
1841        void *psge;
1842        dma_addr_t dma_addr_in;
1843        dma_addr_t dma_addr_out;
1844        void *addr_in = NULL;
1845        void *addr_out = NULL;
1846        size_t dma_len_in;
1847        size_t dma_len_out;
1848        unsigned int reslen = 0;
1849
1850        if (ioc->shost_recovery || ioc->pci_error_recovery) {
1851                ioc_info(ioc, "%s: host reset in progress!\n", __func__);
1852                rc = -EFAULT;
1853                goto job_done;
1854        }
1855
1856        rc = mutex_lock_interruptible(&ioc->transport_cmds.mutex);
1857        if (rc)
1858                goto job_done;
1859
1860        if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) {
1861                ioc_err(ioc, "%s: transport_cmds in use\n",
1862                        __func__);
1863                rc = -EAGAIN;
1864                goto out;
1865        }
1866        ioc->transport_cmds.status = MPT3_CMD_PENDING;
1867
1868        rc = _transport_map_smp_buffer(&ioc->pdev->dev, &job->request_payload,
1869                        &dma_addr_out, &dma_len_out, &addr_out);
1870        if (rc)
1871                goto out;
1872        if (addr_out) {
1873                sg_copy_to_buffer(job->request_payload.sg_list,
1874                                job->request_payload.sg_cnt, addr_out,
1875                                job->request_payload.payload_len);
1876        }
1877
1878        rc = _transport_map_smp_buffer(&ioc->pdev->dev, &job->reply_payload,
1879                        &dma_addr_in, &dma_len_in, &addr_in);
1880        if (rc)
1881                goto unmap_out;
1882
1883        rc = mpt3sas_wait_for_ioc(ioc, IOC_OPERATIONAL_WAIT_COUNT);
1884        if (rc)
1885                goto unmap_in;
1886
1887        smid = mpt3sas_base_get_smid(ioc, ioc->transport_cb_idx);
1888        if (!smid) {
1889                ioc_err(ioc, "%s: failed obtaining a smid\n", __func__);
1890                rc = -EAGAIN;
1891                goto unmap_in;
1892        }
1893
1894        rc = 0;
1895        mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
1896        ioc->transport_cmds.smid = smid;
1897
1898        memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
1899        mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
1900        mpi_request->PhysicalPort = 0xFF;
1901        mpi_request->SASAddress = (rphy) ?
1902            cpu_to_le64(rphy->identify.sas_address) :
1903            cpu_to_le64(ioc->sas_hba.sas_address);
1904        mpi_request->RequestDataLength = cpu_to_le16(dma_len_out - 4);
1905        psge = &mpi_request->SGL;
1906
1907        ioc->build_sg(ioc, psge, dma_addr_out, dma_len_out - 4, dma_addr_in,
1908                        dma_len_in - 4);
1909
1910        dtransportprintk(ioc,
1911                         ioc_info(ioc, "%s: sending smp request\n", __func__));
1912
1913        init_completion(&ioc->transport_cmds.done);
1914        ioc->put_smid_default(ioc, smid);
1915        wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ);
1916
1917        if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) {
1918                ioc_err(ioc, "%s: timeout\n", __func__);
1919                _debug_dump_mf(mpi_request,
1920                    sizeof(Mpi2SmpPassthroughRequest_t)/4);
1921                if (!(ioc->transport_cmds.status & MPT3_CMD_RESET)) {
1922                        mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
1923                        rc = -ETIMEDOUT;
1924                        goto unmap_in;
1925                }
1926        }
1927
1928        dtransportprintk(ioc, ioc_info(ioc, "%s - complete\n", __func__));
1929
1930        if (!(ioc->transport_cmds.status & MPT3_CMD_REPLY_VALID)) {
1931                dtransportprintk(ioc,
1932                                 ioc_info(ioc, "%s: no reply\n", __func__));
1933                rc = -ENXIO;
1934                goto unmap_in;
1935        }
1936
1937        mpi_reply = ioc->transport_cmds.reply;
1938
1939        dtransportprintk(ioc,
1940                         ioc_info(ioc, "%s: reply data transfer size(%d)\n",
1941                                  __func__,
1942                                  le16_to_cpu(mpi_reply->ResponseDataLength)));
1943
1944        memcpy(job->reply, mpi_reply, sizeof(*mpi_reply));
1945        job->reply_len = sizeof(*mpi_reply);
1946        reslen = le16_to_cpu(mpi_reply->ResponseDataLength);
1947
1948        if (addr_in) {
1949                sg_copy_to_buffer(job->reply_payload.sg_list,
1950                                job->reply_payload.sg_cnt, addr_in,
1951                                job->reply_payload.payload_len);
1952        }
1953
1954        rc = 0;
1955 unmap_in:
1956        _transport_unmap_smp_buffer(&ioc->pdev->dev, &job->reply_payload,
1957                        dma_addr_in, addr_in);
1958 unmap_out:
1959        _transport_unmap_smp_buffer(&ioc->pdev->dev, &job->request_payload,
1960                        dma_addr_out, addr_out);
1961 out:
1962        ioc->transport_cmds.status = MPT3_CMD_NOT_USED;
1963        mutex_unlock(&ioc->transport_cmds.mutex);
1964job_done:
1965        bsg_job_done(job, rc, reslen);
1966}
1967
1968struct sas_function_template mpt3sas_transport_functions = {
1969        .get_linkerrors         = _transport_get_linkerrors,
1970        .get_enclosure_identifier = _transport_get_enclosure_identifier,
1971        .get_bay_identifier     = _transport_get_bay_identifier,
1972        .phy_reset              = _transport_phy_reset,
1973        .phy_enable             = _transport_phy_enable,
1974        .set_phy_speed          = _transport_phy_speed,
1975        .smp_handler            = _transport_smp_handler,
1976};
1977
1978struct scsi_transport_template *mpt3sas_transport_template;
1979