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