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