linux/drivers/message/fusion/mptsas.c
<<
>>
Prefs
   1/*
   2 *  linux/drivers/message/fusion/mptsas.c
   3 *      For use with LSI PCI chip/adapter(s)
   4 *      running LSI Fusion MPT (Message Passing Technology) firmware.
   5 *
   6 *  Copyright (c) 1999-2008 LSI Corporation
   7 *  (mailto:DL-MPTFusionLinux@lsi.com)
   8 */
   9/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  10/*
  11    This program is free software; you can redistribute it and/or modify
  12    it under the terms of the GNU General Public License as published by
  13    the Free Software Foundation; version 2 of the License.
  14
  15    This program is distributed in the hope that it will be useful,
  16    but WITHOUT ANY WARRANTY; without even the implied warranty of
  17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18    GNU General Public License for more details.
  19
  20    NO WARRANTY
  21    THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
  22    CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
  23    LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
  24    MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
  25    solely responsible for determining the appropriateness of using and
  26    distributing the Program and assumes all risks associated with its
  27    exercise of rights under this Agreement, including but not limited to
  28    the risks and costs of program errors, damage to or loss of data,
  29    programs or equipment, and unavailability or interruption of operations.
  30
  31    DISCLAIMER OF LIABILITY
  32    NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
  33    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  34    DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
  35    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
  36    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  37    USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
  38    HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
  39
  40    You should have received a copy of the GNU General Public License
  41    along with this program; if not, write to the Free Software
  42    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  43*/
  44/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  45
  46#include <linux/module.h>
  47#include <linux/kernel.h>
  48#include <linux/slab.h>
  49#include <linux/init.h>
  50#include <linux/errno.h>
  51#include <linux/jiffies.h>
  52#include <linux/workqueue.h>
  53#include <linux/delay.h>        /* for mdelay */
  54
  55#include <scsi/scsi.h>
  56#include <scsi/scsi_cmnd.h>
  57#include <scsi/scsi_device.h>
  58#include <scsi/scsi_host.h>
  59#include <scsi/scsi_transport_sas.h>
  60#include <scsi/scsi_transport.h>
  61#include <scsi/scsi_dbg.h>
  62
  63#include "mptbase.h"
  64#include "mptscsih.h"
  65#include "mptsas.h"
  66
  67
  68#define my_NAME         "Fusion MPT SAS Host driver"
  69#define my_VERSION      MPT_LINUX_VERSION_COMMON
  70#define MYNAM           "mptsas"
  71
  72/*
  73 * Reserved channel for integrated raid
  74 */
  75#define MPTSAS_RAID_CHANNEL     1
  76
  77#define SAS_CONFIG_PAGE_TIMEOUT         30
  78MODULE_AUTHOR(MODULEAUTHOR);
  79MODULE_DESCRIPTION(my_NAME);
  80MODULE_LICENSE("GPL");
  81MODULE_VERSION(my_VERSION);
  82
  83static int mpt_pt_clear;
  84module_param(mpt_pt_clear, int, 0);
  85MODULE_PARM_DESC(mpt_pt_clear,
  86                " Clear persistency table: enable=1  "
  87                "(default=MPTSCSIH_PT_CLEAR=0)");
  88
  89/* scsi-mid layer global parameter is max_report_luns, which is 511 */
  90#define MPTSAS_MAX_LUN (16895)
  91static int max_lun = MPTSAS_MAX_LUN;
  92module_param(max_lun, int, 0);
  93MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
  94
  95static int mpt_loadtime_max_sectors = 8192;
  96module_param(mpt_loadtime_max_sectors, int, 0);
  97MODULE_PARM_DESC(mpt_loadtime_max_sectors,
  98                " Maximum sector define for Host Bus Adaptor.Range 64 to 8192 default=8192");
  99
 100static u8       mptsasDoneCtx = MPT_MAX_PROTOCOL_DRIVERS;
 101static u8       mptsasTaskCtx = MPT_MAX_PROTOCOL_DRIVERS;
 102static u8       mptsasInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; /* Used only for internal commands */
 103static u8       mptsasMgmtCtx = MPT_MAX_PROTOCOL_DRIVERS;
 104static u8       mptsasDeviceResetCtx = MPT_MAX_PROTOCOL_DRIVERS;
 105
 106static void mptsas_firmware_event_work(struct work_struct *work);
 107static void mptsas_send_sas_event(struct fw_event_work *fw_event);
 108static void mptsas_send_raid_event(struct fw_event_work *fw_event);
 109static void mptsas_send_ir2_event(struct fw_event_work *fw_event);
 110static void mptsas_parse_device_info(struct sas_identify *identify,
 111                struct mptsas_devinfo *device_info);
 112static inline void mptsas_set_rphy(MPT_ADAPTER *ioc,
 113                struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy);
 114static struct mptsas_phyinfo    *mptsas_find_phyinfo_by_sas_address
 115                (MPT_ADAPTER *ioc, u64 sas_address);
 116static int mptsas_sas_device_pg0(MPT_ADAPTER *ioc,
 117        struct mptsas_devinfo *device_info, u32 form, u32 form_specific);
 118static int mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc,
 119        struct mptsas_enclosure *enclosure, u32 form, u32 form_specific);
 120static int mptsas_add_end_device(MPT_ADAPTER *ioc,
 121        struct mptsas_phyinfo *phy_info);
 122static void mptsas_del_end_device(MPT_ADAPTER *ioc,
 123        struct mptsas_phyinfo *phy_info);
 124static void mptsas_send_link_status_event(struct fw_event_work *fw_event);
 125static struct mptsas_portinfo   *mptsas_find_portinfo_by_sas_address
 126                (MPT_ADAPTER *ioc, u64 sas_address);
 127static void mptsas_expander_delete(MPT_ADAPTER *ioc,
 128                struct mptsas_portinfo *port_info, u8 force);
 129static void mptsas_send_expander_event(struct fw_event_work *fw_event);
 130static void mptsas_not_responding_devices(MPT_ADAPTER *ioc);
 131static void mptsas_scan_sas_topology(MPT_ADAPTER *ioc);
 132static void mptsas_broadcast_primitive_work(struct fw_event_work *fw_event);
 133static void mptsas_handle_queue_full_event(struct fw_event_work *fw_event);
 134static void mptsas_volume_delete(MPT_ADAPTER *ioc, u8 id);
 135void    mptsas_schedule_target_reset(void *ioc);
 136
 137static void mptsas_print_phy_data(MPT_ADAPTER *ioc,
 138                                        MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
 139{
 140        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 141            "---- IO UNIT PAGE 0 ------------\n", ioc->name));
 142        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handle=0x%X\n",
 143            ioc->name, le16_to_cpu(phy_data->AttachedDeviceHandle)));
 144        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Controller Handle=0x%X\n",
 145            ioc->name, le16_to_cpu(phy_data->ControllerDevHandle)));
 146        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Port=0x%X\n",
 147            ioc->name, phy_data->Port));
 148        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Port Flags=0x%X\n",
 149            ioc->name, phy_data->PortFlags));
 150        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Flags=0x%X\n",
 151            ioc->name, phy_data->PhyFlags));
 152        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Negotiated Link Rate=0x%X\n",
 153            ioc->name, phy_data->NegotiatedLinkRate));
 154        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 155            "Controller PHY Device Info=0x%X\n", ioc->name,
 156            le32_to_cpu(phy_data->ControllerPhyDeviceInfo)));
 157        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DiscoveryStatus=0x%X\n\n",
 158            ioc->name, le32_to_cpu(phy_data->DiscoveryStatus)));
 159}
 160
 161static void mptsas_print_phy_pg0(MPT_ADAPTER *ioc, SasPhyPage0_t *pg0)
 162{
 163        __le64 sas_address;
 164
 165        memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
 166
 167        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 168            "---- SAS PHY PAGE 0 ------------\n", ioc->name));
 169        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 170            "Attached Device Handle=0x%X\n", ioc->name,
 171            le16_to_cpu(pg0->AttachedDevHandle)));
 172        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SAS Address=0x%llX\n",
 173            ioc->name, (unsigned long long)le64_to_cpu(sas_address)));
 174        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 175            "Attached PHY Identifier=0x%X\n", ioc->name,
 176            pg0->AttachedPhyIdentifier));
 177        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Attached Device Info=0x%X\n",
 178            ioc->name, le32_to_cpu(pg0->AttachedDeviceInfo)));
 179        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Programmed Link Rate=0x%X\n",
 180            ioc->name,  pg0->ProgrammedLinkRate));
 181        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Change Count=0x%X\n",
 182            ioc->name, pg0->ChangeCount));
 183        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Info=0x%X\n\n",
 184            ioc->name, le32_to_cpu(pg0->PhyInfo)));
 185}
 186
 187static void mptsas_print_phy_pg1(MPT_ADAPTER *ioc, SasPhyPage1_t *pg1)
 188{
 189        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 190            "---- SAS PHY PAGE 1 ------------\n", ioc->name));
 191        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Invalid Dword Count=0x%x\n",
 192            ioc->name,  pg1->InvalidDwordCount));
 193        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 194            "Running Disparity Error Count=0x%x\n", ioc->name,
 195            pg1->RunningDisparityErrorCount));
 196        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 197            "Loss Dword Synch Count=0x%x\n", ioc->name,
 198            pg1->LossDwordSynchCount));
 199        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 200            "PHY Reset Problem Count=0x%x\n\n", ioc->name,
 201            pg1->PhyResetProblemCount));
 202}
 203
 204static void mptsas_print_device_pg0(MPT_ADAPTER *ioc, SasDevicePage0_t *pg0)
 205{
 206        __le64 sas_address;
 207
 208        memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
 209
 210        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 211            "---- SAS DEVICE PAGE 0 ---------\n", ioc->name));
 212        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handle=0x%X\n",
 213            ioc->name, le16_to_cpu(pg0->DevHandle)));
 214        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Parent Handle=0x%X\n",
 215            ioc->name, le16_to_cpu(pg0->ParentDevHandle)));
 216        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Enclosure Handle=0x%X\n",
 217            ioc->name, le16_to_cpu(pg0->EnclosureHandle)));
 218        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Slot=0x%X\n",
 219            ioc->name, le16_to_cpu(pg0->Slot)));
 220        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SAS Address=0x%llX\n",
 221            ioc->name, (unsigned long long)le64_to_cpu(sas_address)));
 222        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Target ID=0x%X\n",
 223            ioc->name, pg0->TargetID));
 224        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Bus=0x%X\n",
 225            ioc->name, pg0->Bus));
 226        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Parent Phy Num=0x%X\n",
 227            ioc->name, pg0->PhyNum));
 228        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Access Status=0x%X\n",
 229            ioc->name, le16_to_cpu(pg0->AccessStatus)));
 230        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Device Info=0x%X\n",
 231            ioc->name, le32_to_cpu(pg0->DeviceInfo)));
 232        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Flags=0x%X\n",
 233            ioc->name, le16_to_cpu(pg0->Flags)));
 234        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Physical Port=0x%X\n\n",
 235            ioc->name, pg0->PhysicalPort));
 236}
 237
 238static void mptsas_print_expander_pg1(MPT_ADAPTER *ioc, SasExpanderPage1_t *pg1)
 239{
 240        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 241            "---- SAS EXPANDER PAGE 1 ------------\n", ioc->name));
 242        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Physical Port=0x%X\n",
 243            ioc->name, pg1->PhysicalPort));
 244        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Identifier=0x%X\n",
 245            ioc->name, pg1->PhyIdentifier));
 246        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Negotiated Link Rate=0x%X\n",
 247            ioc->name, pg1->NegotiatedLinkRate));
 248        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Programmed Link Rate=0x%X\n",
 249            ioc->name, pg1->ProgrammedLinkRate));
 250        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Hardware Link Rate=0x%X\n",
 251            ioc->name, pg1->HwLinkRate));
 252        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Owner Device Handle=0x%X\n",
 253            ioc->name, le16_to_cpu(pg1->OwnerDevHandle)));
 254        dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 255            "Attached Device Handle=0x%X\n\n", ioc->name,
 256            le16_to_cpu(pg1->AttachedDevHandle)));
 257}
 258
 259/* inhibit sas firmware event handling */
 260static void
 261mptsas_fw_event_off(MPT_ADAPTER *ioc)
 262{
 263        unsigned long flags;
 264
 265        spin_lock_irqsave(&ioc->fw_event_lock, flags);
 266        ioc->fw_events_off = 1;
 267        ioc->sas_discovery_quiesce_io = 0;
 268        spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
 269
 270}
 271
 272/* enable sas firmware event handling */
 273static void
 274mptsas_fw_event_on(MPT_ADAPTER *ioc)
 275{
 276        unsigned long flags;
 277
 278        spin_lock_irqsave(&ioc->fw_event_lock, flags);
 279        ioc->fw_events_off = 0;
 280        spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
 281}
 282
 283/* queue a sas firmware event */
 284static void
 285mptsas_add_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
 286    unsigned long delay)
 287{
 288        unsigned long flags;
 289
 290        spin_lock_irqsave(&ioc->fw_event_lock, flags);
 291        list_add_tail(&fw_event->list, &ioc->fw_event_list);
 292        fw_event->users = 1;
 293        INIT_DELAYED_WORK(&fw_event->work, mptsas_firmware_event_work);
 294        devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: add (fw_event=0x%p)"
 295                "on cpuid %d\n", ioc->name, __func__,
 296                fw_event, smp_processor_id()));
 297        queue_delayed_work_on(smp_processor_id(), ioc->fw_event_q,
 298            &fw_event->work, delay);
 299        spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
 300}
 301
 302/* requeue a sas firmware event */
 303static void
 304mptsas_requeue_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
 305    unsigned long delay)
 306{
 307        unsigned long flags;
 308        spin_lock_irqsave(&ioc->fw_event_lock, flags);
 309        devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: reschedule task "
 310            "(fw_event=0x%p)on cpuid %d\n", ioc->name, __func__,
 311                fw_event, smp_processor_id()));
 312        fw_event->retries++;
 313        queue_delayed_work_on(smp_processor_id(), ioc->fw_event_q,
 314            &fw_event->work, msecs_to_jiffies(delay));
 315        spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
 316}
 317
 318static void __mptsas_free_fw_event(MPT_ADAPTER *ioc,
 319                                   struct fw_event_work *fw_event)
 320{
 321        devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: kfree (fw_event=0x%p)\n",
 322            ioc->name, __func__, fw_event));
 323        list_del(&fw_event->list);
 324        kfree(fw_event);
 325}
 326
 327/* free memory associated to a sas firmware event */
 328static void
 329mptsas_free_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event)
 330{
 331        unsigned long flags;
 332
 333        spin_lock_irqsave(&ioc->fw_event_lock, flags);
 334        fw_event->users--;
 335        if (!fw_event->users)
 336                __mptsas_free_fw_event(ioc, fw_event);
 337        spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
 338}
 339
 340/* walk the firmware event queue, and either stop or wait for
 341 * outstanding events to complete */
 342static void
 343mptsas_cleanup_fw_event_q(MPT_ADAPTER *ioc)
 344{
 345        struct fw_event_work *fw_event;
 346        struct mptsas_target_reset_event *target_reset_list, *n;
 347        MPT_SCSI_HOST   *hd = shost_priv(ioc->sh);
 348        unsigned long flags;
 349
 350        /* flush the target_reset_list */
 351        if (!list_empty(&hd->target_reset_list)) {
 352                list_for_each_entry_safe(target_reset_list, n,
 353                    &hd->target_reset_list, list) {
 354                        dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 355                            "%s: removing target reset for id=%d\n",
 356                            ioc->name, __func__,
 357                           target_reset_list->sas_event_data.TargetID));
 358                        list_del(&target_reset_list->list);
 359                        kfree(target_reset_list);
 360                }
 361        }
 362
 363        if (list_empty(&ioc->fw_event_list) || !ioc->fw_event_q)
 364                return;
 365
 366        spin_lock_irqsave(&ioc->fw_event_lock, flags);
 367
 368        while (!list_empty(&ioc->fw_event_list)) {
 369                bool canceled = false;
 370
 371                fw_event = list_first_entry(&ioc->fw_event_list,
 372                                            struct fw_event_work, list);
 373                fw_event->users++;
 374                spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
 375                if (cancel_delayed_work_sync(&fw_event->work))
 376                        canceled = true;
 377
 378                spin_lock_irqsave(&ioc->fw_event_lock, flags);
 379                if (canceled)
 380                        fw_event->users--;
 381                fw_event->users--;
 382                WARN_ON_ONCE(fw_event->users);
 383                __mptsas_free_fw_event(ioc, fw_event);
 384        }
 385        spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
 386}
 387
 388
 389static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
 390{
 391        struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
 392        return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
 393}
 394
 395static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
 396{
 397        struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
 398        return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
 399}
 400
 401/*
 402 * mptsas_find_portinfo_by_handle
 403 *
 404 * This function should be called with the sas_topology_mutex already held
 405 */
 406static struct mptsas_portinfo *
 407mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
 408{
 409        struct mptsas_portinfo *port_info, *rc=NULL;
 410        int i;
 411
 412        list_for_each_entry(port_info, &ioc->sas_topology, list)
 413                for (i = 0; i < port_info->num_phys; i++)
 414                        if (port_info->phy_info[i].identify.handle == handle) {
 415                                rc = port_info;
 416                                goto out;
 417                        }
 418 out:
 419        return rc;
 420}
 421
 422/**
 423 *      mptsas_find_portinfo_by_sas_address - find and return portinfo for
 424 *              this sas_address
 425 *      @ioc: Pointer to MPT_ADAPTER structure
 426 *      @sas_address: expander sas address
 427 *
 428 *      This function should be called with the sas_topology_mutex already held.
 429 *
 430 *      Return: %NULL if not found.
 431 **/
 432static struct mptsas_portinfo *
 433mptsas_find_portinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
 434{
 435        struct mptsas_portinfo *port_info, *rc = NULL;
 436        int i;
 437
 438        if (sas_address >= ioc->hba_port_sas_addr &&
 439            sas_address < (ioc->hba_port_sas_addr +
 440            ioc->hba_port_num_phy))
 441                return ioc->hba_port_info;
 442
 443        mutex_lock(&ioc->sas_topology_mutex);
 444        list_for_each_entry(port_info, &ioc->sas_topology, list)
 445                for (i = 0; i < port_info->num_phys; i++)
 446                        if (port_info->phy_info[i].identify.sas_address ==
 447                            sas_address) {
 448                                rc = port_info;
 449                                goto out;
 450                        }
 451 out:
 452        mutex_unlock(&ioc->sas_topology_mutex);
 453        return rc;
 454}
 455
 456/*
 457 * Returns true if there is a scsi end device
 458 */
 459static inline int
 460mptsas_is_end_device(struct mptsas_devinfo * attached)
 461{
 462        if ((attached->sas_address) &&
 463            (attached->device_info &
 464            MPI_SAS_DEVICE_INFO_END_DEVICE) &&
 465            ((attached->device_info &
 466            MPI_SAS_DEVICE_INFO_SSP_TARGET) |
 467            (attached->device_info &
 468            MPI_SAS_DEVICE_INFO_STP_TARGET) |
 469            (attached->device_info &
 470            MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
 471                return 1;
 472        else
 473                return 0;
 474}
 475
 476/* no mutex */
 477static void
 478mptsas_port_delete(MPT_ADAPTER *ioc, struct mptsas_portinfo_details * port_details)
 479{
 480        struct mptsas_portinfo *port_info;
 481        struct mptsas_phyinfo *phy_info;
 482        u8      i;
 483
 484        if (!port_details)
 485                return;
 486
 487        port_info = port_details->port_info;
 488        phy_info = port_info->phy_info;
 489
 490        dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: [%p]: num_phys=%02d "
 491            "bitmask=0x%016llX\n", ioc->name, __func__, port_details,
 492            port_details->num_phys, (unsigned long long)
 493            port_details->phy_bitmask));
 494
 495        for (i = 0; i < port_info->num_phys; i++, phy_info++) {
 496                if(phy_info->port_details != port_details)
 497                        continue;
 498                memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
 499                mptsas_set_rphy(ioc, phy_info, NULL);
 500                phy_info->port_details = NULL;
 501        }
 502        kfree(port_details);
 503}
 504
 505static inline struct sas_rphy *
 506mptsas_get_rphy(struct mptsas_phyinfo *phy_info)
 507{
 508        if (phy_info->port_details)
 509                return phy_info->port_details->rphy;
 510        else
 511                return NULL;
 512}
 513
 514static inline void
 515mptsas_set_rphy(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy)
 516{
 517        if (phy_info->port_details) {
 518                phy_info->port_details->rphy = rphy;
 519                dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sas_rphy_add: rphy=%p\n",
 520                    ioc->name, rphy));
 521        }
 522
 523        if (rphy) {
 524                dsaswideprintk(ioc, dev_printk(KERN_DEBUG,
 525                    &rphy->dev, MYIOC_s_FMT "add:", ioc->name));
 526                dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "rphy=%p release=%p\n",
 527                    ioc->name, rphy, rphy->dev.release));
 528        }
 529}
 530
 531static inline struct sas_port *
 532mptsas_get_port(struct mptsas_phyinfo *phy_info)
 533{
 534        if (phy_info->port_details)
 535                return phy_info->port_details->port;
 536        else
 537                return NULL;
 538}
 539
 540static inline void
 541mptsas_set_port(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_port *port)
 542{
 543        if (phy_info->port_details)
 544                phy_info->port_details->port = port;
 545
 546        if (port) {
 547                dsaswideprintk(ioc, dev_printk(KERN_DEBUG,
 548                    &port->dev, MYIOC_s_FMT "add:", ioc->name));
 549                dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "port=%p release=%p\n",
 550                    ioc->name, port, port->dev.release));
 551        }
 552}
 553
 554static inline struct scsi_target *
 555mptsas_get_starget(struct mptsas_phyinfo *phy_info)
 556{
 557        if (phy_info->port_details)
 558                return phy_info->port_details->starget;
 559        else
 560                return NULL;
 561}
 562
 563static inline void
 564mptsas_set_starget(struct mptsas_phyinfo *phy_info, struct scsi_target *
 565starget)
 566{
 567        if (phy_info->port_details)
 568                phy_info->port_details->starget = starget;
 569}
 570
 571/**
 572 *      mptsas_add_device_component - adds a new device component to our lists
 573 *      @ioc: Pointer to MPT_ADAPTER structure
 574 *      @channel: channel number
 575 *      @id: Logical Target ID for reset (if appropriate)
 576 *      @sas_address: expander sas address
 577 *      @device_info: specific bits (flags) for devices
 578 *      @slot: enclosure slot ID
 579 *      @enclosure_logical_id: enclosure WWN
 580 *
 581 **/
 582static void
 583mptsas_add_device_component(MPT_ADAPTER *ioc, u8 channel, u8 id,
 584        u64 sas_address, u32 device_info, u16 slot, u64 enclosure_logical_id)
 585{
 586        struct mptsas_device_info       *sas_info, *next;
 587        struct scsi_device      *sdev;
 588        struct scsi_target      *starget;
 589        struct sas_rphy *rphy;
 590
 591        /*
 592         * Delete all matching devices out of the list
 593         */
 594        mutex_lock(&ioc->sas_device_info_mutex);
 595        list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
 596            list) {
 597                if (!sas_info->is_logical_volume &&
 598                    (sas_info->sas_address == sas_address ||
 599                    (sas_info->fw.channel == channel &&
 600                     sas_info->fw.id == id))) {
 601                        list_del(&sas_info->list);
 602                        kfree(sas_info);
 603                }
 604        }
 605
 606        sas_info = kzalloc(sizeof(struct mptsas_device_info), GFP_KERNEL);
 607        if (!sas_info)
 608                goto out;
 609
 610        /*
 611         * Set Firmware mapping
 612         */
 613        sas_info->fw.id = id;
 614        sas_info->fw.channel = channel;
 615
 616        sas_info->sas_address = sas_address;
 617        sas_info->device_info = device_info;
 618        sas_info->slot = slot;
 619        sas_info->enclosure_logical_id = enclosure_logical_id;
 620        INIT_LIST_HEAD(&sas_info->list);
 621        list_add_tail(&sas_info->list, &ioc->sas_device_info_list);
 622
 623        /*
 624         * Set OS mapping
 625         */
 626        shost_for_each_device(sdev, ioc->sh) {
 627                starget = scsi_target(sdev);
 628                rphy = dev_to_rphy(starget->dev.parent);
 629                if (rphy->identify.sas_address == sas_address) {
 630                        sas_info->os.id = starget->id;
 631                        sas_info->os.channel = starget->channel;
 632                }
 633        }
 634
 635 out:
 636        mutex_unlock(&ioc->sas_device_info_mutex);
 637        return;
 638}
 639
 640/**
 641 *      mptsas_add_device_component_by_fw - adds a new device component by FW ID
 642 *      @ioc: Pointer to MPT_ADAPTER structure
 643 *      @channel: channel number
 644 *      @id: Logical Target ID
 645 *
 646 **/
 647static void
 648mptsas_add_device_component_by_fw(MPT_ADAPTER *ioc, u8 channel, u8 id)
 649{
 650        struct mptsas_devinfo sas_device;
 651        struct mptsas_enclosure enclosure_info;
 652        int rc;
 653
 654        rc = mptsas_sas_device_pg0(ioc, &sas_device,
 655            (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
 656             MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
 657            (channel << 8) + id);
 658        if (rc)
 659                return;
 660
 661        memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
 662        mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
 663            (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
 664             MPI_SAS_ENCLOS_PGAD_FORM_SHIFT),
 665             sas_device.handle_enclosure);
 666
 667        mptsas_add_device_component(ioc, sas_device.channel,
 668            sas_device.id, sas_device.sas_address, sas_device.device_info,
 669            sas_device.slot, enclosure_info.enclosure_logical_id);
 670}
 671
 672/**
 673 *      mptsas_add_device_component_starget_ir - Handle Integrated RAID, adding each individual device to list
 674 *      @ioc: Pointer to MPT_ADAPTER structure
 675 *      @starget: SCSI target for this SCSI device
 676 *
 677 **/
 678static void
 679mptsas_add_device_component_starget_ir(MPT_ADAPTER *ioc,
 680                struct scsi_target *starget)
 681{
 682        CONFIGPARMS                     cfg;
 683        ConfigPageHeader_t              hdr;
 684        dma_addr_t                      dma_handle;
 685        pRaidVolumePage0_t              buffer = NULL;
 686        int                             i;
 687        RaidPhysDiskPage0_t             phys_disk;
 688        struct mptsas_device_info       *sas_info, *next;
 689
 690        memset(&cfg, 0 , sizeof(CONFIGPARMS));
 691        memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
 692        hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
 693        /* assumption that all volumes on channel = 0 */
 694        cfg.pageAddr = starget->id;
 695        cfg.cfghdr.hdr = &hdr;
 696        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
 697        cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
 698
 699        if (mpt_config(ioc, &cfg) != 0)
 700                goto out;
 701
 702        if (!hdr.PageLength)
 703                goto out;
 704
 705        buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
 706            &dma_handle);
 707
 708        if (!buffer)
 709                goto out;
 710
 711        cfg.physAddr = dma_handle;
 712        cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
 713
 714        if (mpt_config(ioc, &cfg) != 0)
 715                goto out;
 716
 717        if (!buffer->NumPhysDisks)
 718                goto out;
 719
 720        /*
 721         * Adding entry for hidden components
 722         */
 723        for (i = 0; i < buffer->NumPhysDisks; i++) {
 724
 725                if (mpt_raid_phys_disk_pg0(ioc,
 726                    buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
 727                        continue;
 728
 729                mptsas_add_device_component_by_fw(ioc, phys_disk.PhysDiskBus,
 730                    phys_disk.PhysDiskID);
 731
 732                mutex_lock(&ioc->sas_device_info_mutex);
 733                list_for_each_entry(sas_info, &ioc->sas_device_info_list,
 734                    list) {
 735                        if (!sas_info->is_logical_volume &&
 736                            (sas_info->fw.channel == phys_disk.PhysDiskBus &&
 737                            sas_info->fw.id == phys_disk.PhysDiskID)) {
 738                                sas_info->is_hidden_raid_component = 1;
 739                                sas_info->volume_id = starget->id;
 740                        }
 741                }
 742                mutex_unlock(&ioc->sas_device_info_mutex);
 743
 744        }
 745
 746        /*
 747         * Delete all matching devices out of the list
 748         */
 749        mutex_lock(&ioc->sas_device_info_mutex);
 750        list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
 751            list) {
 752                if (sas_info->is_logical_volume && sas_info->fw.id ==
 753                    starget->id) {
 754                        list_del(&sas_info->list);
 755                        kfree(sas_info);
 756                }
 757        }
 758
 759        sas_info = kzalloc(sizeof(struct mptsas_device_info), GFP_KERNEL);
 760        if (sas_info) {
 761                sas_info->fw.id = starget->id;
 762                sas_info->os.id = starget->id;
 763                sas_info->os.channel = starget->channel;
 764                sas_info->is_logical_volume = 1;
 765                INIT_LIST_HEAD(&sas_info->list);
 766                list_add_tail(&sas_info->list, &ioc->sas_device_info_list);
 767        }
 768        mutex_unlock(&ioc->sas_device_info_mutex);
 769
 770 out:
 771        if (buffer)
 772                pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
 773                    dma_handle);
 774}
 775
 776/**
 777 *      mptsas_add_device_component_starget - adds a SCSI target device component
 778 *      @ioc: Pointer to MPT_ADAPTER structure
 779 *      @starget: SCSI target for this SCSI device
 780 *
 781 **/
 782static void
 783mptsas_add_device_component_starget(MPT_ADAPTER *ioc,
 784        struct scsi_target *starget)
 785{
 786        struct sas_rphy *rphy;
 787        struct mptsas_phyinfo   *phy_info = NULL;
 788        struct mptsas_enclosure enclosure_info;
 789
 790        rphy = dev_to_rphy(starget->dev.parent);
 791        phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
 792                        rphy->identify.sas_address);
 793        if (!phy_info)
 794                return;
 795
 796        memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
 797        mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
 798                (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
 799                MPI_SAS_ENCLOS_PGAD_FORM_SHIFT),
 800                phy_info->attached.handle_enclosure);
 801
 802        mptsas_add_device_component(ioc, phy_info->attached.channel,
 803                phy_info->attached.id, phy_info->attached.sas_address,
 804                phy_info->attached.device_info,
 805                phy_info->attached.slot, enclosure_info.enclosure_logical_id);
 806}
 807
 808/**
 809 *      mptsas_del_device_component_by_os - Once a device has been removed, we mark the entry in the list as being cached
 810 *      @ioc: Pointer to MPT_ADAPTER structure
 811 *      @channel: os mapped id's
 812 *      @id: Logical Target ID
 813 *
 814 **/
 815static void
 816mptsas_del_device_component_by_os(MPT_ADAPTER *ioc, u8 channel, u8 id)
 817{
 818        struct mptsas_device_info       *sas_info, *next;
 819
 820        /*
 821         * Set is_cached flag
 822         */
 823        list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
 824                list) {
 825                if (sas_info->os.channel == channel && sas_info->os.id == id)
 826                        sas_info->is_cached = 1;
 827        }
 828}
 829
 830/**
 831 *      mptsas_del_device_components - Cleaning the list
 832 *      @ioc: Pointer to MPT_ADAPTER structure
 833 *
 834 **/
 835static void
 836mptsas_del_device_components(MPT_ADAPTER *ioc)
 837{
 838        struct mptsas_device_info       *sas_info, *next;
 839
 840        mutex_lock(&ioc->sas_device_info_mutex);
 841        list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
 842                list) {
 843                list_del(&sas_info->list);
 844                kfree(sas_info);
 845        }
 846        mutex_unlock(&ioc->sas_device_info_mutex);
 847}
 848
 849
 850/*
 851 * mptsas_setup_wide_ports
 852 *
 853 * Updates for new and existing narrow/wide port configuration
 854 * in the sas_topology
 855 */
 856static void
 857mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
 858{
 859        struct mptsas_portinfo_details * port_details;
 860        struct mptsas_phyinfo *phy_info, *phy_info_cmp;
 861        u64     sas_address;
 862        int     i, j;
 863
 864        mutex_lock(&ioc->sas_topology_mutex);
 865
 866        phy_info = port_info->phy_info;
 867        for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
 868                if (phy_info->attached.handle)
 869                        continue;
 870                port_details = phy_info->port_details;
 871                if (!port_details)
 872                        continue;
 873                if (port_details->num_phys < 2)
 874                        continue;
 875                /*
 876                 * Removing a phy from a port, letting the last
 877                 * phy be removed by firmware events.
 878                 */
 879                dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 880                    "%s: [%p]: deleting phy = %d\n",
 881                    ioc->name, __func__, port_details, i));
 882                port_details->num_phys--;
 883                port_details->phy_bitmask &= ~ (1 << phy_info->phy_id);
 884                memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
 885                if (phy_info->phy) {
 886                        devtprintk(ioc, dev_printk(KERN_DEBUG,
 887                                &phy_info->phy->dev, MYIOC_s_FMT
 888                                "delete phy %d, phy-obj (0x%p)\n", ioc->name,
 889                                phy_info->phy_id, phy_info->phy));
 890                        sas_port_delete_phy(port_details->port, phy_info->phy);
 891                }
 892                phy_info->port_details = NULL;
 893        }
 894
 895        /*
 896         * Populate and refresh the tree
 897         */
 898        phy_info = port_info->phy_info;
 899        for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
 900                sas_address = phy_info->attached.sas_address;
 901                dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "phy_id=%d sas_address=0x%018llX\n",
 902                    ioc->name, i, (unsigned long long)sas_address));
 903                if (!sas_address)
 904                        continue;
 905                port_details = phy_info->port_details;
 906                /*
 907                 * Forming a port
 908                 */
 909                if (!port_details) {
 910                        port_details = kzalloc(sizeof(struct
 911                                mptsas_portinfo_details), GFP_KERNEL);
 912                        if (!port_details)
 913                                goto out;
 914                        port_details->num_phys = 1;
 915                        port_details->port_info = port_info;
 916                        if (phy_info->phy_id < 64 )
 917                                port_details->phy_bitmask |=
 918                                    (1 << phy_info->phy_id);
 919                        phy_info->sas_port_add_phy=1;
 920                        dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tForming port\n\t\t"
 921                            "phy_id=%d sas_address=0x%018llX\n",
 922                            ioc->name, i, (unsigned long long)sas_address));
 923                        phy_info->port_details = port_details;
 924                }
 925
 926                if (i == port_info->num_phys - 1)
 927                        continue;
 928                phy_info_cmp = &port_info->phy_info[i + 1];
 929                for (j = i + 1 ; j < port_info->num_phys ; j++,
 930                    phy_info_cmp++) {
 931                        if (!phy_info_cmp->attached.sas_address)
 932                                continue;
 933                        if (sas_address != phy_info_cmp->attached.sas_address)
 934                                continue;
 935                        if (phy_info_cmp->port_details == port_details )
 936                                continue;
 937                        dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 938                            "\t\tphy_id=%d sas_address=0x%018llX\n",
 939                            ioc->name, j, (unsigned long long)
 940                            phy_info_cmp->attached.sas_address));
 941                        if (phy_info_cmp->port_details) {
 942                                port_details->rphy =
 943                                    mptsas_get_rphy(phy_info_cmp);
 944                                port_details->port =
 945                                    mptsas_get_port(phy_info_cmp);
 946                                port_details->starget =
 947                                    mptsas_get_starget(phy_info_cmp);
 948                                port_details->num_phys =
 949                                        phy_info_cmp->port_details->num_phys;
 950                                if (!phy_info_cmp->port_details->num_phys)
 951                                        kfree(phy_info_cmp->port_details);
 952                        } else
 953                                phy_info_cmp->sas_port_add_phy=1;
 954                        /*
 955                         * Adding a phy to a port
 956                         */
 957                        phy_info_cmp->port_details = port_details;
 958                        if (phy_info_cmp->phy_id < 64 )
 959                                port_details->phy_bitmask |=
 960                                (1 << phy_info_cmp->phy_id);
 961                        port_details->num_phys++;
 962                }
 963        }
 964
 965 out:
 966
 967        for (i = 0; i < port_info->num_phys; i++) {
 968                port_details = port_info->phy_info[i].port_details;
 969                if (!port_details)
 970                        continue;
 971                dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 972                    "%s: [%p]: phy_id=%02d num_phys=%02d "
 973                    "bitmask=0x%016llX\n", ioc->name, __func__,
 974                    port_details, i, port_details->num_phys,
 975                    (unsigned long long)port_details->phy_bitmask));
 976                dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tport = %p rphy=%p\n",
 977                    ioc->name, port_details->port, port_details->rphy));
 978        }
 979        dsaswideprintk(ioc, printk("\n"));
 980        mutex_unlock(&ioc->sas_topology_mutex);
 981}
 982
 983/**
 984 * mptsas_find_vtarget - find a virtual target device (FC LUN device or
 985 *                              SCSI target device)
 986 *
 987 * @ioc: Pointer to MPT_ADAPTER structure
 988 * @channel: channel number
 989 * @id: Logical Target ID
 990 *
 991 **/
 992static VirtTarget *
 993mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id)
 994{
 995        struct scsi_device              *sdev;
 996        VirtDevice                      *vdevice;
 997        VirtTarget                      *vtarget = NULL;
 998
 999        shost_for_each_device(sdev, ioc->sh) {
1000                vdevice = sdev->hostdata;
1001                if ((vdevice == NULL) ||
1002                        (vdevice->vtarget == NULL))
1003                        continue;
1004                if ((vdevice->vtarget->tflags &
1005                    MPT_TARGET_FLAGS_RAID_COMPONENT ||
1006                    vdevice->vtarget->raidVolume))
1007                        continue;
1008                if (vdevice->vtarget->id == id &&
1009                        vdevice->vtarget->channel == channel)
1010                        vtarget = vdevice->vtarget;
1011        }
1012        return vtarget;
1013}
1014
1015static void
1016mptsas_queue_device_delete(MPT_ADAPTER *ioc,
1017        MpiEventDataSasDeviceStatusChange_t *sas_event_data)
1018{
1019        struct fw_event_work *fw_event;
1020
1021        fw_event = kzalloc(sizeof(*fw_event) +
1022                           sizeof(MpiEventDataSasDeviceStatusChange_t),
1023                           GFP_ATOMIC);
1024        if (!fw_event) {
1025                printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n",
1026                    ioc->name, __func__, __LINE__);
1027                return;
1028        }
1029        memcpy(fw_event->event_data, sas_event_data,
1030            sizeof(MpiEventDataSasDeviceStatusChange_t));
1031        fw_event->event = MPI_EVENT_SAS_DEVICE_STATUS_CHANGE;
1032        fw_event->ioc = ioc;
1033        mptsas_add_fw_event(ioc, fw_event, msecs_to_jiffies(1));
1034}
1035
1036static void
1037mptsas_queue_rescan(MPT_ADAPTER *ioc)
1038{
1039        struct fw_event_work *fw_event;
1040
1041        fw_event = kzalloc(sizeof(*fw_event), GFP_ATOMIC);
1042        if (!fw_event) {
1043                printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n",
1044                    ioc->name, __func__, __LINE__);
1045                return;
1046        }
1047        fw_event->event = -1;
1048        fw_event->ioc = ioc;
1049        mptsas_add_fw_event(ioc, fw_event, msecs_to_jiffies(1));
1050}
1051
1052
1053/**
1054 * mptsas_target_reset - Issues TARGET_RESET to end device using
1055 *                       handshaking method
1056 *
1057 * @ioc: Pointer to MPT_ADAPTER structure
1058 * @channel: channel number
1059 * @id: Logical Target ID for reset
1060 *
1061 * Return: (1) success
1062 *         (0) failure
1063 *
1064 **/
1065static int
1066mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id)
1067{
1068        MPT_FRAME_HDR   *mf;
1069        SCSITaskMgmt_t  *pScsiTm;
1070        if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0)
1071                return 0;
1072
1073
1074        mf = mpt_get_msg_frame(mptsasDeviceResetCtx, ioc);
1075        if (mf == NULL) {
1076                dfailprintk(ioc, printk(MYIOC_s_WARN_FMT
1077                        "%s, no msg frames @%d!!\n", ioc->name,
1078                        __func__, __LINE__));
1079                goto out_fail;
1080        }
1081
1082        dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n",
1083                ioc->name, mf));
1084
1085        /* Format the Request
1086         */
1087        pScsiTm = (SCSITaskMgmt_t *) mf;
1088        memset (pScsiTm, 0, sizeof(SCSITaskMgmt_t));
1089        pScsiTm->TargetID = id;
1090        pScsiTm->Bus = channel;
1091        pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
1092        pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
1093        pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION;
1094
1095        DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf);
1096
1097        dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1098           "TaskMgmt type=%d (sas device delete) fw_channel = %d fw_id = %d)\n",
1099           ioc->name, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, channel, id));
1100
1101        mpt_put_msg_frame_hi_pri(mptsasDeviceResetCtx, ioc, mf);
1102
1103        return 1;
1104
1105 out_fail:
1106
1107        mpt_clear_taskmgmt_in_progress_flag(ioc);
1108        return 0;
1109}
1110
1111static void
1112mptsas_block_io_sdev(struct scsi_device *sdev, void *data)
1113{
1114        scsi_device_set_state(sdev, SDEV_BLOCK);
1115}
1116
1117static void
1118mptsas_block_io_starget(struct scsi_target *starget)
1119{
1120        if (starget)
1121                starget_for_each_device(starget, NULL, mptsas_block_io_sdev);
1122}
1123
1124/**
1125 * mptsas_target_reset_queue - queue a target reset
1126 *
1127 * @ioc: Pointer to MPT_ADAPTER structure
1128 * @sas_event_data: SAS Device Status Change Event data
1129 *
1130 * Receive request for TARGET_RESET after receiving a firmware
1131 * event NOT_RESPONDING_EVENT, then put command in link list
1132 * and queue if task_queue already in use.
1133 *
1134 **/
1135static void
1136mptsas_target_reset_queue(MPT_ADAPTER *ioc,
1137    EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
1138{
1139        MPT_SCSI_HOST   *hd = shost_priv(ioc->sh);
1140        VirtTarget *vtarget = NULL;
1141        struct mptsas_target_reset_event *target_reset_list;
1142        u8              id, channel;
1143
1144        id = sas_event_data->TargetID;
1145        channel = sas_event_data->Bus;
1146
1147        vtarget = mptsas_find_vtarget(ioc, channel, id);
1148        if (vtarget) {
1149                mptsas_block_io_starget(vtarget->starget);
1150                vtarget->deleted = 1; /* block IO */
1151        }
1152
1153        target_reset_list = kzalloc(sizeof(struct mptsas_target_reset_event),
1154            GFP_ATOMIC);
1155        if (!target_reset_list) {
1156                dfailprintk(ioc, printk(MYIOC_s_WARN_FMT
1157                        "%s, failed to allocate mem @%d..!!\n",
1158                        ioc->name, __func__, __LINE__));
1159                return;
1160        }
1161
1162        memcpy(&target_reset_list->sas_event_data, sas_event_data,
1163                sizeof(*sas_event_data));
1164        list_add_tail(&target_reset_list->list, &hd->target_reset_list);
1165
1166        target_reset_list->time_count = jiffies;
1167
1168        if (mptsas_target_reset(ioc, channel, id)) {
1169                target_reset_list->target_reset_issued = 1;
1170        }
1171}
1172
1173/**
1174 * mptsas_schedule_target_reset- send pending target reset
1175 * @iocp: per adapter object
1176 *
1177 * This function will delete scheduled target reset from the list and
1178 * try to send next target reset. This will be called from completion
1179 * context of any Task management command.
1180 */
1181
1182void
1183mptsas_schedule_target_reset(void *iocp)
1184{
1185        MPT_ADAPTER *ioc = (MPT_ADAPTER *)(iocp);
1186        MPT_SCSI_HOST   *hd = shost_priv(ioc->sh);
1187        struct list_head *head = &hd->target_reset_list;
1188        struct mptsas_target_reset_event        *target_reset_list;
1189        u8              id, channel;
1190        /*
1191         * issue target reset to next device in the queue
1192         */
1193
1194        if (list_empty(head))
1195                return;
1196
1197        target_reset_list = list_entry(head->next,
1198                struct mptsas_target_reset_event, list);
1199
1200        id = target_reset_list->sas_event_data.TargetID;
1201        channel = target_reset_list->sas_event_data.Bus;
1202        target_reset_list->time_count = jiffies;
1203
1204        if (mptsas_target_reset(ioc, channel, id))
1205                target_reset_list->target_reset_issued = 1;
1206        return;
1207}
1208
1209
1210/**
1211 *      mptsas_taskmgmt_complete - complete SAS task management function
1212 *      @ioc: Pointer to MPT_ADAPTER structure
1213 *      @mf: MPT message frame
1214 *      @mr: SCSI Task Management Reply structure ptr (may be %NULL)
1215 *
1216 *      Completion for TARGET_RESET after NOT_RESPONDING_EVENT, enable work
1217 *      queue to finish off removing device from upper layers, then send next
1218 *      TARGET_RESET in the queue.
1219 **/
1220static int
1221mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
1222{
1223        MPT_SCSI_HOST   *hd = shost_priv(ioc->sh);
1224        struct list_head *head = &hd->target_reset_list;
1225        u8              id, channel;
1226        struct mptsas_target_reset_event        *target_reset_list;
1227        SCSITaskMgmtReply_t *pScsiTmReply;
1228
1229        dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt completed: "
1230            "(mf = %p, mr = %p)\n", ioc->name, mf, mr));
1231
1232        pScsiTmReply = (SCSITaskMgmtReply_t *)mr;
1233        if (!pScsiTmReply)
1234                return 0;
1235
1236        dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1237            "\tTaskMgmt completed: fw_channel = %d, fw_id = %d,\n"
1238            "\ttask_type = 0x%02X, iocstatus = 0x%04X "
1239            "loginfo = 0x%08X,\n\tresponse_code = 0x%02X, "
1240            "term_cmnds = %d\n", ioc->name,
1241            pScsiTmReply->Bus, pScsiTmReply->TargetID,
1242            pScsiTmReply->TaskType,
1243            le16_to_cpu(pScsiTmReply->IOCStatus),
1244            le32_to_cpu(pScsiTmReply->IOCLogInfo),
1245            pScsiTmReply->ResponseCode,
1246            le32_to_cpu(pScsiTmReply->TerminationCount)));
1247
1248        if (pScsiTmReply->ResponseCode)
1249                mptscsih_taskmgmt_response_code(ioc,
1250                pScsiTmReply->ResponseCode);
1251
1252        if (pScsiTmReply->TaskType ==
1253            MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK || pScsiTmReply->TaskType ==
1254             MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET) {
1255                ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
1256                ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
1257                memcpy(ioc->taskmgmt_cmds.reply, mr,
1258                    min(MPT_DEFAULT_FRAME_SIZE, 4 * mr->u.reply.MsgLength));
1259                if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_PENDING) {
1260                        ioc->taskmgmt_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
1261                        complete(&ioc->taskmgmt_cmds.done);
1262                        return 1;
1263                }
1264                return 0;
1265        }
1266
1267        mpt_clear_taskmgmt_in_progress_flag(ioc);
1268
1269        if (list_empty(head))
1270                return 1;
1271
1272        target_reset_list = list_entry(head->next,
1273            struct mptsas_target_reset_event, list);
1274
1275        dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1276            "TaskMgmt: completed (%d seconds)\n",
1277            ioc->name, jiffies_to_msecs(jiffies -
1278            target_reset_list->time_count)/1000));
1279
1280        id = pScsiTmReply->TargetID;
1281        channel = pScsiTmReply->Bus;
1282        target_reset_list->time_count = jiffies;
1283
1284        /*
1285         * retry target reset
1286         */
1287        if (!target_reset_list->target_reset_issued) {
1288                if (mptsas_target_reset(ioc, channel, id))
1289                        target_reset_list->target_reset_issued = 1;
1290                return 1;
1291        }
1292
1293        /*
1294         * enable work queue to remove device from upper layers
1295         */
1296        list_del(&target_reset_list->list);
1297        if (!ioc->fw_events_off)
1298                mptsas_queue_device_delete(ioc,
1299                        &target_reset_list->sas_event_data);
1300
1301
1302        ioc->schedule_target_reset(ioc);
1303
1304        return 1;
1305}
1306
1307/**
1308 * mptsas_ioc_reset - issue an IOC reset for this reset phase
1309 *
1310 * @ioc: Pointer to MPT_ADAPTER structure
1311 * @reset_phase: id of phase of reset
1312 *
1313 **/
1314static int
1315mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
1316{
1317        MPT_SCSI_HOST   *hd;
1318        int rc;
1319
1320        rc = mptscsih_ioc_reset(ioc, reset_phase);
1321        if ((ioc->bus_type != SAS) || (!rc))
1322                return rc;
1323
1324        hd = shost_priv(ioc->sh);
1325        if (!hd->ioc)
1326                goto out;
1327
1328        switch (reset_phase) {
1329        case MPT_IOC_SETUP_RESET:
1330                dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1331                    "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __func__));
1332                mptsas_fw_event_off(ioc);
1333                break;
1334        case MPT_IOC_PRE_RESET:
1335                dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1336                    "%s: MPT_IOC_PRE_RESET\n", ioc->name, __func__));
1337                break;
1338        case MPT_IOC_POST_RESET:
1339                dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1340                    "%s: MPT_IOC_POST_RESET\n", ioc->name, __func__));
1341                if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_PENDING) {
1342                        ioc->sas_mgmt.status |= MPT_MGMT_STATUS_DID_IOCRESET;
1343                        complete(&ioc->sas_mgmt.done);
1344                }
1345                mptsas_cleanup_fw_event_q(ioc);
1346                mptsas_queue_rescan(ioc);
1347                break;
1348        default:
1349                break;
1350        }
1351
1352 out:
1353        return rc;
1354}
1355
1356
1357/**
1358 * enum device_state - TUR device state
1359 * @DEVICE_RETRY: need to retry the TUR
1360 * @DEVICE_ERROR: TUR return error, don't add device
1361 * @DEVICE_READY: device can be added
1362 *
1363 */
1364enum device_state{
1365        DEVICE_RETRY,
1366        DEVICE_ERROR,
1367        DEVICE_READY,
1368};
1369
1370static int
1371mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
1372                u32 form, u32 form_specific)
1373{
1374        ConfigExtendedPageHeader_t hdr;
1375        CONFIGPARMS cfg;
1376        SasEnclosurePage0_t *buffer;
1377        dma_addr_t dma_handle;
1378        int error;
1379        __le64 le_identifier;
1380
1381        memset(&hdr, 0, sizeof(hdr));
1382        hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
1383        hdr.PageNumber = 0;
1384        hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1385        hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
1386
1387        cfg.cfghdr.ehdr = &hdr;
1388        cfg.physAddr = -1;
1389        cfg.pageAddr = form + form_specific;
1390        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1391        cfg.dir = 0;    /* read */
1392        cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
1393
1394        error = mpt_config(ioc, &cfg);
1395        if (error)
1396                goto out;
1397        if (!hdr.ExtPageLength) {
1398                error = -ENXIO;
1399                goto out;
1400        }
1401
1402        buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1403                        &dma_handle);
1404        if (!buffer) {
1405                error = -ENOMEM;
1406                goto out;
1407        }
1408
1409        cfg.physAddr = dma_handle;
1410        cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1411
1412        error = mpt_config(ioc, &cfg);
1413        if (error)
1414                goto out_free_consistent;
1415
1416        /* save config data */
1417        memcpy(&le_identifier, &buffer->EnclosureLogicalID, sizeof(__le64));
1418        enclosure->enclosure_logical_id = le64_to_cpu(le_identifier);
1419        enclosure->enclosure_handle = le16_to_cpu(buffer->EnclosureHandle);
1420        enclosure->flags = le16_to_cpu(buffer->Flags);
1421        enclosure->num_slot = le16_to_cpu(buffer->NumSlots);
1422        enclosure->start_slot = le16_to_cpu(buffer->StartSlot);
1423        enclosure->start_id = buffer->StartTargetID;
1424        enclosure->start_channel = buffer->StartBus;
1425        enclosure->sep_id = buffer->SEPTargetID;
1426        enclosure->sep_channel = buffer->SEPBus;
1427
1428 out_free_consistent:
1429        pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1430                            buffer, dma_handle);
1431 out:
1432        return error;
1433}
1434
1435/**
1436 *      mptsas_add_end_device - report a new end device to sas transport layer
1437 *      @ioc: Pointer to MPT_ADAPTER structure
1438 *      @phy_info: describes attached device
1439 *
1440 *      return (0) success (1) failure
1441 *
1442 **/
1443static int
1444mptsas_add_end_device(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info)
1445{
1446        struct sas_rphy *rphy;
1447        struct sas_port *port;
1448        struct sas_identify identify;
1449        char *ds = NULL;
1450        u8 fw_id;
1451
1452        if (!phy_info) {
1453                dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1454                        "%s: exit at line=%d\n", ioc->name,
1455                         __func__, __LINE__));
1456                return 1;
1457        }
1458
1459        fw_id = phy_info->attached.id;
1460
1461        if (mptsas_get_rphy(phy_info)) {
1462                dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1463                        "%s: fw_id=%d exit at line=%d\n", ioc->name,
1464                         __func__, fw_id, __LINE__));
1465                return 2;
1466        }
1467
1468        port = mptsas_get_port(phy_info);
1469        if (!port) {
1470                dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1471                        "%s: fw_id=%d exit at line=%d\n", ioc->name,
1472                         __func__, fw_id, __LINE__));
1473                return 3;
1474        }
1475
1476        if (phy_info->attached.device_info &
1477            MPI_SAS_DEVICE_INFO_SSP_TARGET)
1478                ds = "ssp";
1479        if (phy_info->attached.device_info &
1480            MPI_SAS_DEVICE_INFO_STP_TARGET)
1481                ds = "stp";
1482        if (phy_info->attached.device_info &
1483            MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1484                ds = "sata";
1485
1486        printk(MYIOC_s_INFO_FMT "attaching %s device: fw_channel %d, fw_id %d,"
1487            " phy %d, sas_addr 0x%llx\n", ioc->name, ds,
1488            phy_info->attached.channel, phy_info->attached.id,
1489            phy_info->attached.phy_id, (unsigned long long)
1490            phy_info->attached.sas_address);
1491
1492        mptsas_parse_device_info(&identify, &phy_info->attached);
1493        rphy = sas_end_device_alloc(port);
1494        if (!rphy) {
1495                dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1496                        "%s: fw_id=%d exit at line=%d\n", ioc->name,
1497                         __func__, fw_id, __LINE__));
1498                return 5; /* non-fatal: an rphy can be added later */
1499        }
1500
1501        rphy->identify = identify;
1502        if (sas_rphy_add(rphy)) {
1503                dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1504                        "%s: fw_id=%d exit at line=%d\n", ioc->name,
1505                         __func__, fw_id, __LINE__));
1506                sas_rphy_free(rphy);
1507                return 6;
1508        }
1509        mptsas_set_rphy(ioc, phy_info, rphy);
1510        return 0;
1511}
1512
1513/**
1514 *      mptsas_del_end_device - report a deleted end device to sas transport layer
1515 *      @ioc: Pointer to MPT_ADAPTER structure
1516 *      @phy_info: describes attached device
1517 *
1518 **/
1519static void
1520mptsas_del_end_device(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info)
1521{
1522        struct sas_rphy *rphy;
1523        struct sas_port *port;
1524        struct mptsas_portinfo *port_info;
1525        struct mptsas_phyinfo *phy_info_parent;
1526        int i;
1527        char *ds = NULL;
1528        u8 fw_id;
1529        u64 sas_address;
1530
1531        if (!phy_info)
1532                return;
1533
1534        fw_id = phy_info->attached.id;
1535        sas_address = phy_info->attached.sas_address;
1536
1537        if (!phy_info->port_details) {
1538                dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1539                        "%s: fw_id=%d exit at line=%d\n", ioc->name,
1540                         __func__, fw_id, __LINE__));
1541                return;
1542        }
1543        rphy = mptsas_get_rphy(phy_info);
1544        if (!rphy) {
1545                dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1546                        "%s: fw_id=%d exit at line=%d\n", ioc->name,
1547                         __func__, fw_id, __LINE__));
1548                return;
1549        }
1550
1551        if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_INITIATOR
1552                || phy_info->attached.device_info
1553                        & MPI_SAS_DEVICE_INFO_SMP_INITIATOR
1554                || phy_info->attached.device_info
1555                        & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
1556                ds = "initiator";
1557        if (phy_info->attached.device_info &
1558            MPI_SAS_DEVICE_INFO_SSP_TARGET)
1559                ds = "ssp";
1560        if (phy_info->attached.device_info &
1561            MPI_SAS_DEVICE_INFO_STP_TARGET)
1562                ds = "stp";
1563        if (phy_info->attached.device_info &
1564            MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1565                ds = "sata";
1566
1567        dev_printk(KERN_DEBUG, &rphy->dev, MYIOC_s_FMT
1568            "removing %s device: fw_channel %d, fw_id %d, phy %d,"
1569            "sas_addr 0x%llx\n", ioc->name, ds, phy_info->attached.channel,
1570            phy_info->attached.id, phy_info->attached.phy_id,
1571            (unsigned long long) sas_address);
1572
1573        port = mptsas_get_port(phy_info);
1574        if (!port) {
1575                dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1576                        "%s: fw_id=%d exit at line=%d\n", ioc->name,
1577                         __func__, fw_id, __LINE__));
1578                return;
1579        }
1580        port_info = phy_info->portinfo;
1581        phy_info_parent = port_info->phy_info;
1582        for (i = 0; i < port_info->num_phys; i++, phy_info_parent++) {
1583                if (!phy_info_parent->phy)
1584                        continue;
1585                if (phy_info_parent->attached.sas_address !=
1586                    sas_address)
1587                        continue;
1588                dev_printk(KERN_DEBUG, &phy_info_parent->phy->dev,
1589                    MYIOC_s_FMT "delete phy %d, phy-obj (0x%p)\n",
1590                    ioc->name, phy_info_parent->phy_id,
1591                    phy_info_parent->phy);
1592                sas_port_delete_phy(port, phy_info_parent->phy);
1593        }
1594
1595        dev_printk(KERN_DEBUG, &port->dev, MYIOC_s_FMT
1596            "delete port %d, sas_addr (0x%llx)\n", ioc->name,
1597             port->port_identifier, (unsigned long long)sas_address);
1598        sas_port_delete(port);
1599        mptsas_set_port(ioc, phy_info, NULL);
1600        mptsas_port_delete(ioc, phy_info->port_details);
1601}
1602
1603static struct mptsas_phyinfo *
1604mptsas_refreshing_device_handles(MPT_ADAPTER *ioc,
1605        struct mptsas_devinfo *sas_device)
1606{
1607        struct mptsas_phyinfo *phy_info;
1608        struct mptsas_portinfo *port_info;
1609        int i;
1610
1611        phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
1612            sas_device->sas_address);
1613        if (!phy_info)
1614                goto out;
1615        port_info = phy_info->portinfo;
1616        if (!port_info)
1617                goto out;
1618        mutex_lock(&ioc->sas_topology_mutex);
1619        for (i = 0; i < port_info->num_phys; i++) {
1620                if (port_info->phy_info[i].attached.sas_address !=
1621                        sas_device->sas_address)
1622                        continue;
1623                port_info->phy_info[i].attached.channel = sas_device->channel;
1624                port_info->phy_info[i].attached.id = sas_device->id;
1625                port_info->phy_info[i].attached.sas_address =
1626                    sas_device->sas_address;
1627                port_info->phy_info[i].attached.handle = sas_device->handle;
1628                port_info->phy_info[i].attached.handle_parent =
1629                    sas_device->handle_parent;
1630                port_info->phy_info[i].attached.handle_enclosure =
1631                    sas_device->handle_enclosure;
1632        }
1633        mutex_unlock(&ioc->sas_topology_mutex);
1634 out:
1635        return phy_info;
1636}
1637
1638/**
1639 * mptsas_firmware_event_work - work thread for processing fw events
1640 * @work: work queue payload containing info describing the event
1641 * Context: user
1642 *
1643 */
1644static void
1645mptsas_firmware_event_work(struct work_struct *work)
1646{
1647        struct fw_event_work *fw_event =
1648                container_of(work, struct fw_event_work, work.work);
1649        MPT_ADAPTER *ioc = fw_event->ioc;
1650
1651        /* special rescan topology handling */
1652        if (fw_event->event == -1) {
1653                if (ioc->in_rescan) {
1654                        devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1655                                "%s: rescan ignored as it is in progress\n",
1656                                ioc->name, __func__));
1657                        return;
1658                }
1659                devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: rescan after "
1660                    "reset\n", ioc->name, __func__));
1661                ioc->in_rescan = 1;
1662                mptsas_not_responding_devices(ioc);
1663                mptsas_scan_sas_topology(ioc);
1664                ioc->in_rescan = 0;
1665                mptsas_free_fw_event(ioc, fw_event);
1666                mptsas_fw_event_on(ioc);
1667                return;
1668        }
1669
1670        /* events handling turned off during host reset */
1671        if (ioc->fw_events_off) {
1672                mptsas_free_fw_event(ioc, fw_event);
1673                return;
1674        }
1675
1676        devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: fw_event=(0x%p), "
1677            "event = (0x%02x)\n", ioc->name, __func__, fw_event,
1678            (fw_event->event & 0xFF)));
1679
1680        switch (fw_event->event) {
1681        case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
1682                mptsas_send_sas_event(fw_event);
1683                break;
1684        case MPI_EVENT_INTEGRATED_RAID:
1685                mptsas_send_raid_event(fw_event);
1686                break;
1687        case MPI_EVENT_IR2:
1688                mptsas_send_ir2_event(fw_event);
1689                break;
1690        case MPI_EVENT_PERSISTENT_TABLE_FULL:
1691                mptbase_sas_persist_operation(ioc,
1692                    MPI_SAS_OP_CLEAR_NOT_PRESENT);
1693                mptsas_free_fw_event(ioc, fw_event);
1694                break;
1695        case MPI_EVENT_SAS_BROADCAST_PRIMITIVE:
1696                mptsas_broadcast_primitive_work(fw_event);
1697                break;
1698        case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE:
1699                mptsas_send_expander_event(fw_event);
1700                break;
1701        case MPI_EVENT_SAS_PHY_LINK_STATUS:
1702                mptsas_send_link_status_event(fw_event);
1703                break;
1704        case MPI_EVENT_QUEUE_FULL:
1705                mptsas_handle_queue_full_event(fw_event);
1706                break;
1707        }
1708}
1709
1710
1711
1712static int
1713mptsas_slave_configure(struct scsi_device *sdev)
1714{
1715        struct Scsi_Host        *host = sdev->host;
1716        MPT_SCSI_HOST   *hd = shost_priv(host);
1717        MPT_ADAPTER     *ioc = hd->ioc;
1718        VirtDevice      *vdevice = sdev->hostdata;
1719
1720        if (vdevice->vtarget->deleted) {
1721                sdev_printk(KERN_INFO, sdev, "clearing deleted flag\n");
1722                vdevice->vtarget->deleted = 0;
1723        }
1724
1725        /*
1726         * RAID volumes placed beyond the last expected port.
1727         * Ignore sending sas mode pages in that case..
1728         */
1729        if (sdev->channel == MPTSAS_RAID_CHANNEL) {
1730                mptsas_add_device_component_starget_ir(ioc, scsi_target(sdev));
1731                goto out;
1732        }
1733
1734        sas_read_port_mode_page(sdev);
1735
1736        mptsas_add_device_component_starget(ioc, scsi_target(sdev));
1737
1738 out:
1739        return mptscsih_slave_configure(sdev);
1740}
1741
1742static int
1743mptsas_target_alloc(struct scsi_target *starget)
1744{
1745        struct Scsi_Host *host = dev_to_shost(&starget->dev);
1746        MPT_SCSI_HOST           *hd = shost_priv(host);
1747        VirtTarget              *vtarget;
1748        u8                      id, channel;
1749        struct sas_rphy         *rphy;
1750        struct mptsas_portinfo  *p;
1751        int                      i;
1752        MPT_ADAPTER             *ioc = hd->ioc;
1753
1754        vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
1755        if (!vtarget)
1756                return -ENOMEM;
1757
1758        vtarget->starget = starget;
1759        vtarget->ioc_id = ioc->id;
1760        vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
1761        id = starget->id;
1762        channel = 0;
1763
1764        /*
1765         * RAID volumes placed beyond the last expected port.
1766         */
1767        if (starget->channel == MPTSAS_RAID_CHANNEL) {
1768                if (!ioc->raid_data.pIocPg2) {
1769                        kfree(vtarget);
1770                        return -ENXIO;
1771                }
1772                for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
1773                        if (id == ioc->raid_data.pIocPg2->
1774                                        RaidVolume[i].VolumeID) {
1775                                channel = ioc->raid_data.pIocPg2->
1776                                        RaidVolume[i].VolumeBus;
1777                        }
1778                }
1779                vtarget->raidVolume = 1;
1780                goto out;
1781        }
1782
1783        rphy = dev_to_rphy(starget->dev.parent);
1784        mutex_lock(&ioc->sas_topology_mutex);
1785        list_for_each_entry(p, &ioc->sas_topology, list) {
1786                for (i = 0; i < p->num_phys; i++) {
1787                        if (p->phy_info[i].attached.sas_address !=
1788                                        rphy->identify.sas_address)
1789                                continue;
1790                        id = p->phy_info[i].attached.id;
1791                        channel = p->phy_info[i].attached.channel;
1792                        mptsas_set_starget(&p->phy_info[i], starget);
1793
1794                        /*
1795                         * Exposing hidden raid components
1796                         */
1797                        if (mptscsih_is_phys_disk(ioc, channel, id)) {
1798                                id = mptscsih_raid_id_to_num(ioc,
1799                                                channel, id);
1800                                vtarget->tflags |=
1801                                    MPT_TARGET_FLAGS_RAID_COMPONENT;
1802                                p->phy_info[i].attached.phys_disk_num = id;
1803                        }
1804                        mutex_unlock(&ioc->sas_topology_mutex);
1805                        goto out;
1806                }
1807        }
1808        mutex_unlock(&ioc->sas_topology_mutex);
1809
1810        kfree(vtarget);
1811        return -ENXIO;
1812
1813 out:
1814        vtarget->id = id;
1815        vtarget->channel = channel;
1816        starget->hostdata = vtarget;
1817        return 0;
1818}
1819
1820static void
1821mptsas_target_destroy(struct scsi_target *starget)
1822{
1823        struct Scsi_Host *host = dev_to_shost(&starget->dev);
1824        MPT_SCSI_HOST           *hd = shost_priv(host);
1825        struct sas_rphy         *rphy;
1826        struct mptsas_portinfo  *p;
1827        int                      i;
1828        MPT_ADAPTER     *ioc = hd->ioc;
1829        VirtTarget      *vtarget;
1830
1831        if (!starget->hostdata)
1832                return;
1833
1834        vtarget = starget->hostdata;
1835
1836        mptsas_del_device_component_by_os(ioc, starget->channel,
1837            starget->id);
1838
1839
1840        if (starget->channel == MPTSAS_RAID_CHANNEL)
1841                goto out;
1842
1843        rphy = dev_to_rphy(starget->dev.parent);
1844        list_for_each_entry(p, &ioc->sas_topology, list) {
1845                for (i = 0; i < p->num_phys; i++) {
1846                        if (p->phy_info[i].attached.sas_address !=
1847                                        rphy->identify.sas_address)
1848                                continue;
1849
1850                        starget_printk(KERN_INFO, starget, MYIOC_s_FMT
1851                        "delete device: fw_channel %d, fw_id %d, phy %d, "
1852                        "sas_addr 0x%llx\n", ioc->name,
1853                        p->phy_info[i].attached.channel,
1854                        p->phy_info[i].attached.id,
1855                        p->phy_info[i].attached.phy_id, (unsigned long long)
1856                        p->phy_info[i].attached.sas_address);
1857
1858                        mptsas_set_starget(&p->phy_info[i], NULL);
1859                }
1860        }
1861
1862 out:
1863        vtarget->starget = NULL;
1864        kfree(starget->hostdata);
1865        starget->hostdata = NULL;
1866}
1867
1868
1869static int
1870mptsas_slave_alloc(struct scsi_device *sdev)
1871{
1872        struct Scsi_Host        *host = sdev->host;
1873        MPT_SCSI_HOST           *hd = shost_priv(host);
1874        struct sas_rphy         *rphy;
1875        struct mptsas_portinfo  *p;
1876        VirtDevice              *vdevice;
1877        struct scsi_target      *starget;
1878        int                     i;
1879        MPT_ADAPTER *ioc = hd->ioc;
1880
1881        vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
1882        if (!vdevice) {
1883                printk(MYIOC_s_ERR_FMT "slave_alloc kzalloc(%zd) FAILED!\n",
1884                                ioc->name, sizeof(VirtDevice));
1885                return -ENOMEM;
1886        }
1887        starget = scsi_target(sdev);
1888        vdevice->vtarget = starget->hostdata;
1889
1890        if (sdev->channel == MPTSAS_RAID_CHANNEL)
1891                goto out;
1892
1893        rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
1894        mutex_lock(&ioc->sas_topology_mutex);
1895        list_for_each_entry(p, &ioc->sas_topology, list) {
1896                for (i = 0; i < p->num_phys; i++) {
1897                        if (p->phy_info[i].attached.sas_address !=
1898                                        rphy->identify.sas_address)
1899                                continue;
1900                        vdevice->lun = sdev->lun;
1901                        /*
1902                         * Exposing hidden raid components
1903                         */
1904                        if (mptscsih_is_phys_disk(ioc,
1905                            p->phy_info[i].attached.channel,
1906                            p->phy_info[i].attached.id))
1907                                sdev->no_uld_attach = 1;
1908                        mutex_unlock(&ioc->sas_topology_mutex);
1909                        goto out;
1910                }
1911        }
1912        mutex_unlock(&ioc->sas_topology_mutex);
1913
1914        kfree(vdevice);
1915        return -ENXIO;
1916
1917 out:
1918        vdevice->vtarget->num_luns++;
1919        sdev->hostdata = vdevice;
1920        return 0;
1921}
1922
1923static int
1924mptsas_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *SCpnt)
1925{
1926        MPT_SCSI_HOST   *hd;
1927        MPT_ADAPTER     *ioc;
1928        VirtDevice      *vdevice = SCpnt->device->hostdata;
1929
1930        if (!vdevice || !vdevice->vtarget || vdevice->vtarget->deleted) {
1931                SCpnt->result = DID_NO_CONNECT << 16;
1932                SCpnt->scsi_done(SCpnt);
1933                return 0;
1934        }
1935
1936        hd = shost_priv(shost);
1937        ioc = hd->ioc;
1938
1939        if (ioc->sas_discovery_quiesce_io)
1940                return SCSI_MLQUEUE_HOST_BUSY;
1941
1942        if (ioc->debug_level & MPT_DEBUG_SCSI)
1943                scsi_print_command(SCpnt);
1944
1945        return mptscsih_qcmd(SCpnt);
1946}
1947
1948/**
1949 *      mptsas_eh_timed_out - resets the scsi_cmnd timeout
1950 *              if the device under question is currently in the
1951 *              device removal delay.
1952 *      @sc: scsi command that the midlayer is about to time out
1953 *
1954 **/
1955static enum blk_eh_timer_return mptsas_eh_timed_out(struct scsi_cmnd *sc)
1956{
1957        MPT_SCSI_HOST *hd;
1958        MPT_ADAPTER   *ioc;
1959        VirtDevice    *vdevice;
1960        enum blk_eh_timer_return rc = BLK_EH_DONE;
1961
1962        hd = shost_priv(sc->device->host);
1963        if (hd == NULL) {
1964                printk(KERN_ERR MYNAM ": %s: Can't locate host! (sc=%p)\n",
1965                    __func__, sc);
1966                goto done;
1967        }
1968
1969        ioc = hd->ioc;
1970        if (ioc->bus_type != SAS) {
1971                printk(KERN_ERR MYNAM ": %s: Wrong bus type (sc=%p)\n",
1972                    __func__, sc);
1973                goto done;
1974        }
1975
1976        /* In case if IOC is in reset from internal context.
1977        *  Do not execute EEH for the same IOC. SML should to reset timer.
1978        */
1979        if (ioc->ioc_reset_in_progress) {
1980                dtmprintk(ioc, printk(MYIOC_s_WARN_FMT ": %s: ioc is in reset,"
1981                    "SML need to reset the timer (sc=%p)\n",
1982                    ioc->name, __func__, sc));
1983                rc = BLK_EH_RESET_TIMER;
1984        }
1985        vdevice = sc->device->hostdata;
1986        if (vdevice && vdevice->vtarget && (vdevice->vtarget->inDMD
1987                || vdevice->vtarget->deleted)) {
1988                dtmprintk(ioc, printk(MYIOC_s_WARN_FMT ": %s: target removed "
1989                    "or in device removal delay (sc=%p)\n",
1990                    ioc->name, __func__, sc));
1991                rc = BLK_EH_RESET_TIMER;
1992                goto done;
1993        }
1994
1995done:
1996        return rc;
1997}
1998
1999
2000static struct scsi_host_template mptsas_driver_template = {
2001        .module                         = THIS_MODULE,
2002        .proc_name                      = "mptsas",
2003        .show_info                      = mptscsih_show_info,
2004        .name                           = "MPT SAS Host",
2005        .info                           = mptscsih_info,
2006        .queuecommand                   = mptsas_qcmd,
2007        .target_alloc                   = mptsas_target_alloc,
2008        .slave_alloc                    = mptsas_slave_alloc,
2009        .slave_configure                = mptsas_slave_configure,
2010        .target_destroy                 = mptsas_target_destroy,
2011        .slave_destroy                  = mptscsih_slave_destroy,
2012        .change_queue_depth             = mptscsih_change_queue_depth,
2013        .eh_timed_out                   = mptsas_eh_timed_out,
2014        .eh_abort_handler               = mptscsih_abort,
2015        .eh_device_reset_handler        = mptscsih_dev_reset,
2016        .eh_host_reset_handler          = mptscsih_host_reset,
2017        .bios_param                     = mptscsih_bios_param,
2018        .can_queue                      = MPT_SAS_CAN_QUEUE,
2019        .this_id                        = -1,
2020        .sg_tablesize                   = MPT_SCSI_SG_DEPTH,
2021        .max_sectors                    = 8192,
2022        .cmd_per_lun                    = 7,
2023        .shost_attrs                    = mptscsih_host_attrs,
2024        .no_write_same                  = 1,
2025};
2026
2027static int mptsas_get_linkerrors(struct sas_phy *phy)
2028{
2029        MPT_ADAPTER *ioc = phy_to_ioc(phy);
2030        ConfigExtendedPageHeader_t hdr;
2031        CONFIGPARMS cfg;
2032        SasPhyPage1_t *buffer;
2033        dma_addr_t dma_handle;
2034        int error;
2035
2036        /* FIXME: only have link errors on local phys */
2037        if (!scsi_is_sas_phy_local(phy))
2038                return -EINVAL;
2039
2040        hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
2041        hdr.ExtPageLength = 0;
2042        hdr.PageNumber = 1 /* page number 1*/;
2043        hdr.Reserved1 = 0;
2044        hdr.Reserved2 = 0;
2045        hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2046        hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
2047
2048        cfg.cfghdr.ehdr = &hdr;
2049        cfg.physAddr = -1;
2050        cfg.pageAddr = phy->identify.phy_identifier;
2051        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2052        cfg.dir = 0;    /* read */
2053        cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
2054
2055        error = mpt_config(ioc, &cfg);
2056        if (error)
2057                return error;
2058        if (!hdr.ExtPageLength)
2059                return -ENXIO;
2060
2061        buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2062                                      &dma_handle);
2063        if (!buffer)
2064                return -ENOMEM;
2065
2066        cfg.physAddr = dma_handle;
2067        cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2068
2069        error = mpt_config(ioc, &cfg);
2070        if (error)
2071                goto out_free_consistent;
2072
2073        mptsas_print_phy_pg1(ioc, buffer);
2074
2075        phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);
2076        phy->running_disparity_error_count =
2077                le32_to_cpu(buffer->RunningDisparityErrorCount);
2078        phy->loss_of_dword_sync_count =
2079                le32_to_cpu(buffer->LossDwordSynchCount);
2080        phy->phy_reset_problem_count =
2081                le32_to_cpu(buffer->PhyResetProblemCount);
2082
2083 out_free_consistent:
2084        pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2085                            buffer, dma_handle);
2086        return error;
2087}
2088
2089static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
2090                MPT_FRAME_HDR *reply)
2091{
2092        ioc->sas_mgmt.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
2093        if (reply != NULL) {
2094                ioc->sas_mgmt.status |= MPT_MGMT_STATUS_RF_VALID;
2095                memcpy(ioc->sas_mgmt.reply, reply,
2096                    min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
2097        }
2098
2099        if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_PENDING) {
2100                ioc->sas_mgmt.status &= ~MPT_MGMT_STATUS_PENDING;
2101                complete(&ioc->sas_mgmt.done);
2102                return 1;
2103        }
2104        return 0;
2105}
2106
2107static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
2108{
2109        MPT_ADAPTER *ioc = phy_to_ioc(phy);
2110        SasIoUnitControlRequest_t *req;
2111        SasIoUnitControlReply_t *reply;
2112        MPT_FRAME_HDR *mf;
2113        MPIHeader_t *hdr;
2114        unsigned long timeleft;
2115        int error = -ERESTARTSYS;
2116
2117        /* FIXME: fusion doesn't allow non-local phy reset */
2118        if (!scsi_is_sas_phy_local(phy))
2119                return -EINVAL;
2120
2121        /* not implemented for expanders */
2122        if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
2123                return -ENXIO;
2124
2125        if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
2126                goto out;
2127
2128        mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
2129        if (!mf) {
2130                error = -ENOMEM;
2131                goto out_unlock;
2132        }
2133
2134        hdr = (MPIHeader_t *) mf;
2135        req = (SasIoUnitControlRequest_t *)mf;
2136        memset(req, 0, sizeof(SasIoUnitControlRequest_t));
2137        req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
2138        req->MsgContext = hdr->MsgContext;
2139        req->Operation = hard_reset ?
2140                MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
2141        req->PhyNum = phy->identify.phy_identifier;
2142
2143        INITIALIZE_MGMT_STATUS(ioc->sas_mgmt.status)
2144        mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
2145
2146        timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
2147                        10 * HZ);
2148        if (!(ioc->sas_mgmt.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
2149                error = -ETIME;
2150                mpt_free_msg_frame(ioc, mf);
2151                if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_DID_IOCRESET)
2152                        goto out_unlock;
2153                if (!timeleft)
2154                        mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);
2155                goto out_unlock;
2156        }
2157
2158        /* a reply frame is expected */
2159        if ((ioc->sas_mgmt.status &
2160            MPT_MGMT_STATUS_RF_VALID) == 0) {
2161                error = -ENXIO;
2162                goto out_unlock;
2163        }
2164
2165        /* process the completed Reply Message Frame */
2166        reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
2167        if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
2168                printk(MYIOC_s_INFO_FMT "%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
2169                    ioc->name, __func__, reply->IOCStatus, reply->IOCLogInfo);
2170                error = -ENXIO;
2171                goto out_unlock;
2172        }
2173
2174        error = 0;
2175
2176 out_unlock:
2177        CLEAR_MGMT_STATUS(ioc->sas_mgmt.status)
2178        mutex_unlock(&ioc->sas_mgmt.mutex);
2179 out:
2180        return error;
2181}
2182
2183static int
2184mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
2185{
2186        MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
2187        int i, error;
2188        struct mptsas_portinfo *p;
2189        struct mptsas_enclosure enclosure_info;
2190        u64 enclosure_handle;
2191
2192        mutex_lock(&ioc->sas_topology_mutex);
2193        list_for_each_entry(p, &ioc->sas_topology, list) {
2194                for (i = 0; i < p->num_phys; i++) {
2195                        if (p->phy_info[i].attached.sas_address ==
2196                            rphy->identify.sas_address) {
2197                                enclosure_handle = p->phy_info[i].
2198                                        attached.handle_enclosure;
2199                                goto found_info;
2200                        }
2201                }
2202        }
2203        mutex_unlock(&ioc->sas_topology_mutex);
2204        return -ENXIO;
2205
2206 found_info:
2207        mutex_unlock(&ioc->sas_topology_mutex);
2208        memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
2209        error = mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
2210                        (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
2211                         MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle);
2212        if (!error)
2213                *identifier = enclosure_info.enclosure_logical_id;
2214        return error;
2215}
2216
2217static int
2218mptsas_get_bay_identifier(struct sas_rphy *rphy)
2219{
2220        MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
2221        struct mptsas_portinfo *p;
2222        int i, rc;
2223
2224        mutex_lock(&ioc->sas_topology_mutex);
2225        list_for_each_entry(p, &ioc->sas_topology, list) {
2226                for (i = 0; i < p->num_phys; i++) {
2227                        if (p->phy_info[i].attached.sas_address ==
2228                            rphy->identify.sas_address) {
2229                                rc = p->phy_info[i].attached.slot;
2230                                goto out;
2231                        }
2232                }
2233        }
2234        rc = -ENXIO;
2235 out:
2236        mutex_unlock(&ioc->sas_topology_mutex);
2237        return rc;
2238}
2239
2240static void mptsas_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
2241                struct sas_rphy *rphy)
2242{
2243        MPT_ADAPTER *ioc = ((MPT_SCSI_HOST *) shost->hostdata)->ioc;
2244        MPT_FRAME_HDR *mf;
2245        SmpPassthroughRequest_t *smpreq;
2246        int flagsLength;
2247        unsigned long timeleft;
2248        char *psge;
2249        u64 sas_address = 0;
2250        unsigned int reslen = 0;
2251        int ret = -EINVAL;
2252
2253        /* do we need to support multiple segments? */
2254        if (job->request_payload.sg_cnt > 1 ||
2255            job->reply_payload.sg_cnt > 1) {
2256                printk(MYIOC_s_ERR_FMT "%s: multiple segments req %u, rsp %u\n",
2257                    ioc->name, __func__, job->request_payload.payload_len,
2258                    job->reply_payload.payload_len);
2259                goto out;
2260        }
2261
2262        ret = mutex_lock_interruptible(&ioc->sas_mgmt.mutex);
2263        if (ret)
2264                goto out;
2265
2266        mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
2267        if (!mf) {
2268                ret = -ENOMEM;
2269                goto out_unlock;
2270        }
2271
2272        smpreq = (SmpPassthroughRequest_t *)mf;
2273        memset(smpreq, 0, sizeof(*smpreq));
2274
2275        smpreq->RequestDataLength =
2276                cpu_to_le16(job->request_payload.payload_len - 4);
2277        smpreq->Function = MPI_FUNCTION_SMP_PASSTHROUGH;
2278
2279        if (rphy)
2280                sas_address = rphy->identify.sas_address;
2281        else {
2282                struct mptsas_portinfo *port_info;
2283
2284                mutex_lock(&ioc->sas_topology_mutex);
2285                port_info = ioc->hba_port_info;
2286                if (port_info && port_info->phy_info)
2287                        sas_address =
2288                                port_info->phy_info[0].phy->identify.sas_address;
2289                mutex_unlock(&ioc->sas_topology_mutex);
2290        }
2291
2292        *((u64 *)&smpreq->SASAddress) = cpu_to_le64(sas_address);
2293
2294        psge = (char *)
2295                (((int *) mf) + (offsetof(SmpPassthroughRequest_t, SGL) / 4));
2296
2297        /* request */
2298        flagsLength = (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
2299                       MPI_SGE_FLAGS_END_OF_BUFFER |
2300                       MPI_SGE_FLAGS_DIRECTION)
2301                       << MPI_SGE_FLAGS_SHIFT;
2302
2303        if (!dma_map_sg(&ioc->pcidev->dev, job->request_payload.sg_list,
2304                        1, PCI_DMA_BIDIRECTIONAL))
2305                goto put_mf;
2306
2307        flagsLength |= (sg_dma_len(job->request_payload.sg_list) - 4);
2308        ioc->add_sge(psge, flagsLength,
2309                        sg_dma_address(job->request_payload.sg_list));
2310        psge += ioc->SGE_size;
2311
2312        /* response */
2313        flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
2314                MPI_SGE_FLAGS_SYSTEM_ADDRESS |
2315                MPI_SGE_FLAGS_IOC_TO_HOST |
2316                MPI_SGE_FLAGS_END_OF_BUFFER;
2317
2318        flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
2319
2320        if (!dma_map_sg(&ioc->pcidev->dev, job->reply_payload.sg_list,
2321                        1, PCI_DMA_BIDIRECTIONAL))
2322                goto unmap_out;
2323        flagsLength |= sg_dma_len(job->reply_payload.sg_list) + 4;
2324        ioc->add_sge(psge, flagsLength,
2325                        sg_dma_address(job->reply_payload.sg_list));
2326
2327        INITIALIZE_MGMT_STATUS(ioc->sas_mgmt.status)
2328        mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
2329
2330        timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ);
2331        if (!(ioc->sas_mgmt.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
2332                ret = -ETIME;
2333                mpt_free_msg_frame(ioc, mf);
2334                mf = NULL;
2335                if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_DID_IOCRESET)
2336                        goto unmap_in;
2337                if (!timeleft)
2338                        mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);
2339                goto unmap_in;
2340        }
2341        mf = NULL;
2342
2343        if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_RF_VALID) {
2344                SmpPassthroughReply_t *smprep;
2345
2346                smprep = (SmpPassthroughReply_t *)ioc->sas_mgmt.reply;
2347                memcpy(job->reply, smprep, sizeof(*smprep));
2348                job->reply_len = sizeof(*smprep);
2349                reslen = smprep->ResponseDataLength;
2350        } else {
2351                printk(MYIOC_s_ERR_FMT
2352                    "%s: smp passthru reply failed to be returned\n",
2353                    ioc->name, __func__);
2354                ret = -ENXIO;
2355        }
2356
2357unmap_in:
2358        dma_unmap_sg(&ioc->pcidev->dev, job->reply_payload.sg_list, 1,
2359                        PCI_DMA_BIDIRECTIONAL);
2360unmap_out:
2361        dma_unmap_sg(&ioc->pcidev->dev, job->request_payload.sg_list, 1,
2362                        PCI_DMA_BIDIRECTIONAL);
2363put_mf:
2364        if (mf)
2365                mpt_free_msg_frame(ioc, mf);
2366out_unlock:
2367        CLEAR_MGMT_STATUS(ioc->sas_mgmt.status)
2368        mutex_unlock(&ioc->sas_mgmt.mutex);
2369out:
2370        bsg_job_done(job, ret, reslen);
2371}
2372
2373static struct sas_function_template mptsas_transport_functions = {
2374        .get_linkerrors         = mptsas_get_linkerrors,
2375        .get_enclosure_identifier = mptsas_get_enclosure_identifier,
2376        .get_bay_identifier     = mptsas_get_bay_identifier,
2377        .phy_reset              = mptsas_phy_reset,
2378        .smp_handler            = mptsas_smp_handler,
2379};
2380
2381static struct scsi_transport_template *mptsas_transport_template;
2382
2383static int
2384mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
2385{
2386        ConfigExtendedPageHeader_t hdr;
2387        CONFIGPARMS cfg;
2388        SasIOUnitPage0_t *buffer;
2389        dma_addr_t dma_handle;
2390        int error, i;
2391
2392        hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
2393        hdr.ExtPageLength = 0;
2394        hdr.PageNumber = 0;
2395        hdr.Reserved1 = 0;
2396        hdr.Reserved2 = 0;
2397        hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2398        hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
2399
2400        cfg.cfghdr.ehdr = &hdr;
2401        cfg.physAddr = -1;
2402        cfg.pageAddr = 0;
2403        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2404        cfg.dir = 0;    /* read */
2405        cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
2406
2407        error = mpt_config(ioc, &cfg);
2408        if (error)
2409                goto out;
2410        if (!hdr.ExtPageLength) {
2411                error = -ENXIO;
2412                goto out;
2413        }
2414
2415        buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2416                                            &dma_handle);
2417        if (!buffer) {
2418                error = -ENOMEM;
2419                goto out;
2420        }
2421
2422        cfg.physAddr = dma_handle;
2423        cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2424
2425        error = mpt_config(ioc, &cfg);
2426        if (error)
2427                goto out_free_consistent;
2428
2429        port_info->num_phys = buffer->NumPhys;
2430        port_info->phy_info = kcalloc(port_info->num_phys,
2431                sizeof(struct mptsas_phyinfo), GFP_KERNEL);
2432        if (!port_info->phy_info) {
2433                error = -ENOMEM;
2434                goto out_free_consistent;
2435        }
2436
2437        ioc->nvdata_version_persistent =
2438            le16_to_cpu(buffer->NvdataVersionPersistent);
2439        ioc->nvdata_version_default =
2440            le16_to_cpu(buffer->NvdataVersionDefault);
2441
2442        for (i = 0; i < port_info->num_phys; i++) {
2443                mptsas_print_phy_data(ioc, &buffer->PhyData[i]);
2444                port_info->phy_info[i].phy_id = i;
2445                port_info->phy_info[i].port_id =
2446                    buffer->PhyData[i].Port;
2447                port_info->phy_info[i].negotiated_link_rate =
2448                    buffer->PhyData[i].NegotiatedLinkRate;
2449                port_info->phy_info[i].portinfo = port_info;
2450                port_info->phy_info[i].handle =
2451                    le16_to_cpu(buffer->PhyData[i].ControllerDevHandle);
2452        }
2453
2454 out_free_consistent:
2455        pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2456                            buffer, dma_handle);
2457 out:
2458        return error;
2459}
2460
2461static int
2462mptsas_sas_io_unit_pg1(MPT_ADAPTER *ioc)
2463{
2464        ConfigExtendedPageHeader_t hdr;
2465        CONFIGPARMS cfg;
2466        SasIOUnitPage1_t *buffer;
2467        dma_addr_t dma_handle;
2468        int error;
2469        u8 device_missing_delay;
2470
2471        memset(&hdr, 0, sizeof(ConfigExtendedPageHeader_t));
2472        memset(&cfg, 0, sizeof(CONFIGPARMS));
2473
2474        cfg.cfghdr.ehdr = &hdr;
2475        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2476        cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
2477        cfg.cfghdr.ehdr->PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2478        cfg.cfghdr.ehdr->ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
2479        cfg.cfghdr.ehdr->PageVersion = MPI_SASIOUNITPAGE1_PAGEVERSION;
2480        cfg.cfghdr.ehdr->PageNumber = 1;
2481
2482        error = mpt_config(ioc, &cfg);
2483        if (error)
2484                goto out;
2485        if (!hdr.ExtPageLength) {
2486                error = -ENXIO;
2487                goto out;
2488        }
2489
2490        buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2491                                            &dma_handle);
2492        if (!buffer) {
2493                error = -ENOMEM;
2494                goto out;
2495        }
2496
2497        cfg.physAddr = dma_handle;
2498        cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2499
2500        error = mpt_config(ioc, &cfg);
2501        if (error)
2502                goto out_free_consistent;
2503
2504        ioc->io_missing_delay  =
2505            le16_to_cpu(buffer->IODeviceMissingDelay);
2506        device_missing_delay = buffer->ReportDeviceMissingDelay;
2507        ioc->device_missing_delay = (device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_UNIT_16) ?
2508            (device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16 :
2509            device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
2510
2511 out_free_consistent:
2512        pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2513                            buffer, dma_handle);
2514 out:
2515        return error;
2516}
2517
2518static int
2519mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
2520                u32 form, u32 form_specific)
2521{
2522        ConfigExtendedPageHeader_t hdr;
2523        CONFIGPARMS cfg;
2524        SasPhyPage0_t *buffer;
2525        dma_addr_t dma_handle;
2526        int error;
2527
2528        hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
2529        hdr.ExtPageLength = 0;
2530        hdr.PageNumber = 0;
2531        hdr.Reserved1 = 0;
2532        hdr.Reserved2 = 0;
2533        hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2534        hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
2535
2536        cfg.cfghdr.ehdr = &hdr;
2537        cfg.dir = 0;    /* read */
2538        cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
2539
2540        /* Get Phy Pg 0 for each Phy. */
2541        cfg.physAddr = -1;
2542        cfg.pageAddr = form + form_specific;
2543        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2544
2545        error = mpt_config(ioc, &cfg);
2546        if (error)
2547                goto out;
2548
2549        if (!hdr.ExtPageLength) {
2550                error = -ENXIO;
2551                goto out;
2552        }
2553
2554        buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2555                                      &dma_handle);
2556        if (!buffer) {
2557                error = -ENOMEM;
2558                goto out;
2559        }
2560
2561        cfg.physAddr = dma_handle;
2562        cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2563
2564        error = mpt_config(ioc, &cfg);
2565        if (error)
2566                goto out_free_consistent;
2567
2568        mptsas_print_phy_pg0(ioc, buffer);
2569
2570        phy_info->hw_link_rate = buffer->HwLinkRate;
2571        phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
2572        phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
2573        phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
2574
2575 out_free_consistent:
2576        pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2577                            buffer, dma_handle);
2578 out:
2579        return error;
2580}
2581
2582static int
2583mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
2584                u32 form, u32 form_specific)
2585{
2586        ConfigExtendedPageHeader_t hdr;
2587        CONFIGPARMS cfg;
2588        SasDevicePage0_t *buffer;
2589        dma_addr_t dma_handle;
2590        __le64 sas_address;
2591        int error=0;
2592
2593        hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
2594        hdr.ExtPageLength = 0;
2595        hdr.PageNumber = 0;
2596        hdr.Reserved1 = 0;
2597        hdr.Reserved2 = 0;
2598        hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2599        hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
2600
2601        cfg.cfghdr.ehdr = &hdr;
2602        cfg.pageAddr = form + form_specific;
2603        cfg.physAddr = -1;
2604        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2605        cfg.dir = 0;    /* read */
2606        cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
2607
2608        memset(device_info, 0, sizeof(struct mptsas_devinfo));
2609        error = mpt_config(ioc, &cfg);
2610        if (error)
2611                goto out;
2612        if (!hdr.ExtPageLength) {
2613                error = -ENXIO;
2614                goto out;
2615        }
2616
2617        buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2618                                      &dma_handle);
2619        if (!buffer) {
2620                error = -ENOMEM;
2621                goto out;
2622        }
2623
2624        cfg.physAddr = dma_handle;
2625        cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2626
2627        error = mpt_config(ioc, &cfg);
2628
2629        if (error == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
2630                error = -ENODEV;
2631                goto out_free_consistent;
2632        }
2633
2634        if (error)
2635                goto out_free_consistent;
2636
2637        mptsas_print_device_pg0(ioc, buffer);
2638
2639        memset(device_info, 0, sizeof(struct mptsas_devinfo));
2640        device_info->handle = le16_to_cpu(buffer->DevHandle);
2641        device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
2642        device_info->handle_enclosure =
2643            le16_to_cpu(buffer->EnclosureHandle);
2644        device_info->slot = le16_to_cpu(buffer->Slot);
2645        device_info->phy_id = buffer->PhyNum;
2646        device_info->port_id = buffer->PhysicalPort;
2647        device_info->id = buffer->TargetID;
2648        device_info->phys_disk_num = ~0;
2649        device_info->channel = buffer->Bus;
2650        memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
2651        device_info->sas_address = le64_to_cpu(sas_address);
2652        device_info->device_info =
2653            le32_to_cpu(buffer->DeviceInfo);
2654        device_info->flags = le16_to_cpu(buffer->Flags);
2655
2656 out_free_consistent:
2657        pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2658                            buffer, dma_handle);
2659 out:
2660        return error;
2661}
2662
2663static int
2664mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
2665                u32 form, u32 form_specific)
2666{
2667        ConfigExtendedPageHeader_t hdr;
2668        CONFIGPARMS cfg;
2669        SasExpanderPage0_t *buffer;
2670        dma_addr_t dma_handle;
2671        int i, error;
2672        __le64 sas_address;
2673
2674        memset(port_info, 0, sizeof(struct mptsas_portinfo));
2675        hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
2676        hdr.ExtPageLength = 0;
2677        hdr.PageNumber = 0;
2678        hdr.Reserved1 = 0;
2679        hdr.Reserved2 = 0;
2680        hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2681        hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
2682
2683        cfg.cfghdr.ehdr = &hdr;
2684        cfg.physAddr = -1;
2685        cfg.pageAddr = form + form_specific;
2686        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2687        cfg.dir = 0;    /* read */
2688        cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
2689
2690        memset(port_info, 0, sizeof(struct mptsas_portinfo));
2691        error = mpt_config(ioc, &cfg);
2692        if (error)
2693                goto out;
2694
2695        if (!hdr.ExtPageLength) {
2696                error = -ENXIO;
2697                goto out;
2698        }
2699
2700        buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2701                                      &dma_handle);
2702        if (!buffer) {
2703                error = -ENOMEM;
2704                goto out;
2705        }
2706
2707        cfg.physAddr = dma_handle;
2708        cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2709
2710        error = mpt_config(ioc, &cfg);
2711        if (error == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
2712                error = -ENODEV;
2713                goto out_free_consistent;
2714        }
2715
2716        if (error)
2717                goto out_free_consistent;
2718
2719        /* save config data */
2720        port_info->num_phys = (buffer->NumPhys) ? buffer->NumPhys : 1;
2721        port_info->phy_info = kcalloc(port_info->num_phys,
2722                sizeof(struct mptsas_phyinfo), GFP_KERNEL);
2723        if (!port_info->phy_info) {
2724                error = -ENOMEM;
2725                goto out_free_consistent;
2726        }
2727
2728        memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
2729        for (i = 0; i < port_info->num_phys; i++) {
2730                port_info->phy_info[i].portinfo = port_info;
2731                port_info->phy_info[i].handle =
2732                    le16_to_cpu(buffer->DevHandle);
2733                port_info->phy_info[i].identify.sas_address =
2734                    le64_to_cpu(sas_address);
2735                port_info->phy_info[i].identify.handle_parent =
2736                    le16_to_cpu(buffer->ParentDevHandle);
2737        }
2738
2739 out_free_consistent:
2740        pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2741                            buffer, dma_handle);
2742 out:
2743        return error;
2744}
2745
2746static int
2747mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
2748                u32 form, u32 form_specific)
2749{
2750        ConfigExtendedPageHeader_t hdr;
2751        CONFIGPARMS cfg;
2752        SasExpanderPage1_t *buffer;
2753        dma_addr_t dma_handle;
2754        int error=0;
2755
2756        hdr.PageVersion = MPI_SASEXPANDER1_PAGEVERSION;
2757        hdr.ExtPageLength = 0;
2758        hdr.PageNumber = 1;
2759        hdr.Reserved1 = 0;
2760        hdr.Reserved2 = 0;
2761        hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2762        hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
2763
2764        cfg.cfghdr.ehdr = &hdr;
2765        cfg.physAddr = -1;
2766        cfg.pageAddr = form + form_specific;
2767        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2768        cfg.dir = 0;    /* read */
2769        cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
2770
2771        error = mpt_config(ioc, &cfg);
2772        if (error)
2773                goto out;
2774
2775        if (!hdr.ExtPageLength) {
2776                error = -ENXIO;
2777                goto out;
2778        }
2779
2780        buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2781                                      &dma_handle);
2782        if (!buffer) {
2783                error = -ENOMEM;
2784                goto out;
2785        }
2786
2787        cfg.physAddr = dma_handle;
2788        cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2789
2790        error = mpt_config(ioc, &cfg);
2791
2792        if (error == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
2793                error = -ENODEV;
2794                goto out_free_consistent;
2795        }
2796
2797        if (error)
2798                goto out_free_consistent;
2799
2800
2801        mptsas_print_expander_pg1(ioc, buffer);
2802
2803        /* save config data */
2804        phy_info->phy_id = buffer->PhyIdentifier;
2805        phy_info->port_id = buffer->PhysicalPort;
2806        phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
2807        phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
2808        phy_info->hw_link_rate = buffer->HwLinkRate;
2809        phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
2810        phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
2811
2812 out_free_consistent:
2813        pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2814                            buffer, dma_handle);
2815 out:
2816        return error;
2817}
2818
2819struct rep_manu_request{
2820        u8 smp_frame_type;
2821        u8 function;
2822        u8 reserved;
2823        u8 request_length;
2824};
2825
2826struct rep_manu_reply{
2827        u8 smp_frame_type; /* 0x41 */
2828        u8 function; /* 0x01 */
2829        u8 function_result;
2830        u8 response_length;
2831        u16 expander_change_count;
2832        u8 reserved0[2];
2833        u8 sas_format:1;
2834        u8 reserved1:7;
2835        u8 reserved2[3];
2836        u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN];
2837        u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN];
2838        u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN];
2839        u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN];
2840        u16 component_id;
2841        u8 component_revision_id;
2842        u8 reserved3;
2843        u8 vendor_specific[8];
2844};
2845
2846/**
2847  * mptsas_exp_repmanufacture_info - sets expander manufacturer info
2848  * @ioc: per adapter object
2849  * @sas_address: expander sas address
2850  * @edev: the sas_expander_device object
2851  *
2852  * For an edge expander or a fanout expander:
2853  * fills in the sas_expander_device object when SMP port is created.
2854  *
2855  * Return: 0 for success, non-zero for failure.
2856  */
2857static int
2858mptsas_exp_repmanufacture_info(MPT_ADAPTER *ioc,
2859        u64 sas_address, struct sas_expander_device *edev)
2860{
2861        MPT_FRAME_HDR *mf;
2862        SmpPassthroughRequest_t *smpreq;
2863        SmpPassthroughReply_t *smprep;
2864        struct rep_manu_reply *manufacture_reply;
2865        struct rep_manu_request *manufacture_request;
2866        int ret;
2867        int flagsLength;
2868        unsigned long timeleft;
2869        char *psge;
2870        unsigned long flags;
2871        void *data_out = NULL;
2872        dma_addr_t data_out_dma = 0;
2873        u32 sz;
2874
2875        spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
2876        if (ioc->ioc_reset_in_progress) {
2877                spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
2878                printk(MYIOC_s_INFO_FMT "%s: host reset in progress!\n",
2879                        __func__, ioc->name);
2880                return -EFAULT;
2881        }
2882        spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
2883
2884        ret = mutex_lock_interruptible(&ioc->sas_mgmt.mutex);
2885        if (ret)
2886                goto out;
2887
2888        mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
2889        if (!mf) {
2890                ret = -ENOMEM;
2891                goto out_unlock;
2892        }
2893
2894        smpreq = (SmpPassthroughRequest_t *)mf;
2895        memset(smpreq, 0, sizeof(*smpreq));
2896
2897        sz = sizeof(struct rep_manu_request) + sizeof(struct rep_manu_reply);
2898
2899        data_out = pci_alloc_consistent(ioc->pcidev, sz, &data_out_dma);
2900        if (!data_out) {
2901                printk(KERN_ERR "Memory allocation failure at %s:%d/%s()!\n",
2902                        __FILE__, __LINE__, __func__);
2903                ret = -ENOMEM;
2904                goto put_mf;
2905        }
2906
2907        manufacture_request = data_out;
2908        manufacture_request->smp_frame_type = 0x40;
2909        manufacture_request->function = 1;
2910        manufacture_request->reserved = 0;
2911        manufacture_request->request_length = 0;
2912
2913        smpreq->Function = MPI_FUNCTION_SMP_PASSTHROUGH;
2914        smpreq->PhysicalPort = 0xFF;
2915        *((u64 *)&smpreq->SASAddress) = cpu_to_le64(sas_address);
2916        smpreq->RequestDataLength = sizeof(struct rep_manu_request);
2917
2918        psge = (char *)
2919                (((int *) mf) + (offsetof(SmpPassthroughRequest_t, SGL) / 4));
2920
2921        flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
2922                MPI_SGE_FLAGS_SYSTEM_ADDRESS |
2923                MPI_SGE_FLAGS_HOST_TO_IOC |
2924                MPI_SGE_FLAGS_END_OF_BUFFER;
2925        flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
2926        flagsLength |= sizeof(struct rep_manu_request);
2927
2928        ioc->add_sge(psge, flagsLength, data_out_dma);
2929        psge += ioc->SGE_size;
2930
2931        flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
2932                MPI_SGE_FLAGS_SYSTEM_ADDRESS |
2933                MPI_SGE_FLAGS_IOC_TO_HOST |
2934                MPI_SGE_FLAGS_END_OF_BUFFER;
2935        flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
2936        flagsLength |= sizeof(struct rep_manu_reply);
2937        ioc->add_sge(psge, flagsLength, data_out_dma +
2938        sizeof(struct rep_manu_request));
2939
2940        INITIALIZE_MGMT_STATUS(ioc->sas_mgmt.status)
2941        mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
2942
2943        timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ);
2944        if (!(ioc->sas_mgmt.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
2945                ret = -ETIME;
2946                mpt_free_msg_frame(ioc, mf);
2947                mf = NULL;
2948                if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_DID_IOCRESET)
2949                        goto out_free;
2950                if (!timeleft)
2951                        mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);
2952                goto out_free;
2953        }
2954
2955        mf = NULL;
2956
2957        if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_RF_VALID) {
2958                u8 *tmp;
2959
2960                smprep = (SmpPassthroughReply_t *)ioc->sas_mgmt.reply;
2961                if (le16_to_cpu(smprep->ResponseDataLength) !=
2962                    sizeof(struct rep_manu_reply))
2963                        goto out_free;
2964
2965                manufacture_reply = data_out + sizeof(struct rep_manu_request);
2966                strncpy(edev->vendor_id, manufacture_reply->vendor_id,
2967                        SAS_EXPANDER_VENDOR_ID_LEN);
2968                strncpy(edev->product_id, manufacture_reply->product_id,
2969                        SAS_EXPANDER_PRODUCT_ID_LEN);
2970                strncpy(edev->product_rev, manufacture_reply->product_rev,
2971                        SAS_EXPANDER_PRODUCT_REV_LEN);
2972                edev->level = manufacture_reply->sas_format;
2973                if (manufacture_reply->sas_format) {
2974                        strncpy(edev->component_vendor_id,
2975                                manufacture_reply->component_vendor_id,
2976                                SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN);
2977                        tmp = (u8 *)&manufacture_reply->component_id;
2978                        edev->component_id = tmp[0] << 8 | tmp[1];
2979                        edev->component_revision_id =
2980                                manufacture_reply->component_revision_id;
2981                }
2982        } else {
2983                printk(MYIOC_s_ERR_FMT
2984                        "%s: smp passthru reply failed to be returned\n",
2985                        ioc->name, __func__);
2986                ret = -ENXIO;
2987        }
2988out_free:
2989        if (data_out_dma)
2990                pci_free_consistent(ioc->pcidev, sz, data_out, data_out_dma);
2991put_mf:
2992        if (mf)
2993                mpt_free_msg_frame(ioc, mf);
2994out_unlock:
2995        CLEAR_MGMT_STATUS(ioc->sas_mgmt.status)
2996        mutex_unlock(&ioc->sas_mgmt.mutex);
2997out:
2998        return ret;
2999}
3000
3001static void
3002mptsas_parse_device_info(struct sas_identify *identify,
3003                struct mptsas_devinfo *device_info)
3004{
3005        u16 protocols;
3006
3007        identify->sas_address = device_info->sas_address;
3008        identify->phy_identifier = device_info->phy_id;
3009
3010        /*
3011         * Fill in Phy Initiator Port Protocol.
3012         * Bits 6:3, more than one bit can be set, fall through cases.
3013         */
3014        protocols = device_info->device_info & 0x78;
3015        identify->initiator_port_protocols = 0;
3016        if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
3017                identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
3018        if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
3019                identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
3020        if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
3021                identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
3022        if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
3023                identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
3024
3025        /*
3026         * Fill in Phy Target Port Protocol.
3027         * Bits 10:7, more than one bit can be set, fall through cases.
3028         */
3029        protocols = device_info->device_info & 0x780;
3030        identify->target_port_protocols = 0;
3031        if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
3032                identify->target_port_protocols |= SAS_PROTOCOL_SSP;
3033        if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
3034                identify->target_port_protocols |= SAS_PROTOCOL_STP;
3035        if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
3036                identify->target_port_protocols |= SAS_PROTOCOL_SMP;
3037        if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
3038                identify->target_port_protocols |= SAS_PROTOCOL_SATA;
3039
3040        /*
3041         * Fill in Attached device type.
3042         */
3043        switch (device_info->device_info &
3044                        MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
3045        case MPI_SAS_DEVICE_INFO_NO_DEVICE:
3046                identify->device_type = SAS_PHY_UNUSED;
3047                break;
3048        case MPI_SAS_DEVICE_INFO_END_DEVICE:
3049                identify->device_type = SAS_END_DEVICE;
3050                break;
3051        case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
3052                identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
3053                break;
3054        case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
3055                identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
3056                break;
3057        }
3058}
3059
3060static int mptsas_probe_one_phy(struct device *dev,
3061                struct mptsas_phyinfo *phy_info, int index, int local)
3062{
3063        MPT_ADAPTER *ioc;
3064        struct sas_phy *phy;
3065        struct sas_port *port;
3066        int error = 0;
3067        VirtTarget *vtarget;
3068
3069        if (!dev) {
3070                error = -ENODEV;
3071                goto out;
3072        }
3073
3074        if (!phy_info->phy) {
3075                phy = sas_phy_alloc(dev, index);
3076                if (!phy) {
3077                        error = -ENOMEM;
3078                        goto out;
3079                }
3080        } else
3081                phy = phy_info->phy;
3082
3083        mptsas_parse_device_info(&phy->identify, &phy_info->identify);
3084
3085        /*
3086         * Set Negotiated link rate.
3087         */
3088        switch (phy_info->negotiated_link_rate) {
3089        case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
3090                phy->negotiated_linkrate = SAS_PHY_DISABLED;
3091                break;
3092        case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
3093                phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
3094                break;
3095        case MPI_SAS_IOUNIT0_RATE_1_5:
3096                phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
3097                break;
3098        case MPI_SAS_IOUNIT0_RATE_3_0:
3099                phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
3100                break;
3101        case MPI_SAS_IOUNIT0_RATE_6_0:
3102                phy->negotiated_linkrate = SAS_LINK_RATE_6_0_GBPS;
3103                break;
3104        case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
3105        case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
3106        default:
3107                phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
3108                break;
3109        }
3110
3111        /*
3112         * Set Max hardware link rate.
3113         */
3114        switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
3115        case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
3116                phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
3117                break;
3118        case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
3119                phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
3120                break;
3121        default:
3122                break;
3123        }
3124
3125        /*
3126         * Set Max programmed link rate.
3127         */
3128        switch (phy_info->programmed_link_rate &
3129                        MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
3130        case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
3131                phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
3132                break;
3133        case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
3134                phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
3135                break;
3136        default:
3137                break;
3138        }
3139
3140        /*
3141         * Set Min hardware link rate.
3142         */
3143        switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
3144        case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
3145                phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
3146                break;
3147        case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
3148                phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
3149                break;
3150        default:
3151                break;
3152        }
3153
3154        /*
3155         * Set Min programmed link rate.
3156         */
3157        switch (phy_info->programmed_link_rate &
3158                        MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
3159        case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
3160                phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
3161                break;
3162        case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
3163                phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
3164                break;
3165        default:
3166                break;
3167        }
3168
3169        if (!phy_info->phy) {
3170
3171                error = sas_phy_add(phy);
3172                if (error) {
3173                        sas_phy_free(phy);
3174                        goto out;
3175                }
3176                phy_info->phy = phy;
3177        }
3178
3179        if (!phy_info->attached.handle ||
3180                        !phy_info->port_details)
3181                goto out;
3182
3183        port = mptsas_get_port(phy_info);
3184        ioc = phy_to_ioc(phy_info->phy);
3185
3186        if (phy_info->sas_port_add_phy) {
3187
3188                if (!port) {
3189                        port = sas_port_alloc_num(dev);
3190                        if (!port) {
3191                                error = -ENOMEM;
3192                                goto out;
3193                        }
3194                        error = sas_port_add(port);
3195                        if (error) {
3196                                dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3197                                        "%s: exit at line=%d\n", ioc->name,
3198                                        __func__, __LINE__));
3199                                goto out;
3200                        }
3201                        mptsas_set_port(ioc, phy_info, port);
3202                        devtprintk(ioc, dev_printk(KERN_DEBUG, &port->dev,
3203                            MYIOC_s_FMT "add port %d, sas_addr (0x%llx)\n",
3204                            ioc->name, port->port_identifier,
3205                            (unsigned long long)phy_info->
3206                            attached.sas_address));
3207                }
3208                dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3209                        "sas_port_add_phy: phy_id=%d\n",
3210                        ioc->name, phy_info->phy_id));
3211                sas_port_add_phy(port, phy_info->phy);
3212                phy_info->sas_port_add_phy = 0;
3213                devtprintk(ioc, dev_printk(KERN_DEBUG, &phy_info->phy->dev,
3214                    MYIOC_s_FMT "add phy %d, phy-obj (0x%p)\n", ioc->name,
3215                     phy_info->phy_id, phy_info->phy));
3216        }
3217        if (!mptsas_get_rphy(phy_info) && port && !port->rphy) {
3218
3219                struct sas_rphy *rphy;
3220                struct device *parent;
3221                struct sas_identify identify;
3222
3223                parent = dev->parent->parent;
3224                /*
3225                 * Let the hotplug_work thread handle processing
3226                 * the adding/removing of devices that occur
3227                 * after start of day.
3228                 */
3229                if (mptsas_is_end_device(&phy_info->attached) &&
3230                    phy_info->attached.handle_parent) {
3231                        goto out;
3232                }
3233
3234                mptsas_parse_device_info(&identify, &phy_info->attached);
3235                if (scsi_is_host_device(parent)) {
3236                        struct mptsas_portinfo *port_info;
3237                        int i;
3238
3239                        port_info = ioc->hba_port_info;
3240
3241                        for (i = 0; i < port_info->num_phys; i++)
3242                                if (port_info->phy_info[i].identify.sas_address ==
3243                                    identify.sas_address) {
3244                                        sas_port_mark_backlink(port);
3245                                        goto out;
3246                                }
3247
3248                } else if (scsi_is_sas_rphy(parent)) {
3249                        struct sas_rphy *parent_rphy = dev_to_rphy(parent);
3250                        if (identify.sas_address ==
3251                            parent_rphy->identify.sas_address) {
3252                                sas_port_mark_backlink(port);
3253                                goto out;
3254                        }
3255                }
3256
3257                switch (identify.device_type) {
3258                case SAS_END_DEVICE:
3259                        rphy = sas_end_device_alloc(port);
3260                        break;
3261                case SAS_EDGE_EXPANDER_DEVICE:
3262                case SAS_FANOUT_EXPANDER_DEVICE:
3263                        rphy = sas_expander_alloc(port, identify.device_type);
3264                        break;
3265                default:
3266                        rphy = NULL;
3267                        break;
3268                }
3269                if (!rphy) {
3270                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3271                                "%s: exit at line=%d\n", ioc->name,
3272                                __func__, __LINE__));
3273                        goto out;
3274                }
3275
3276                rphy->identify = identify;
3277                error = sas_rphy_add(rphy);
3278                if (error) {
3279                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3280                                "%s: exit at line=%d\n", ioc->name,
3281                                __func__, __LINE__));
3282                        sas_rphy_free(rphy);
3283                        goto out;
3284                }
3285                mptsas_set_rphy(ioc, phy_info, rphy);
3286                if (identify.device_type == SAS_EDGE_EXPANDER_DEVICE ||
3287                        identify.device_type == SAS_FANOUT_EXPANDER_DEVICE)
3288                                mptsas_exp_repmanufacture_info(ioc,
3289                                        identify.sas_address,
3290                                        rphy_to_expander_device(rphy));
3291        }
3292
3293        /* If the device exists, verify it wasn't previously flagged
3294        as a missing device.  If so, clear it */
3295        vtarget = mptsas_find_vtarget(ioc,
3296            phy_info->attached.channel,
3297            phy_info->attached.id);
3298        if (vtarget && vtarget->inDMD) {
3299                printk(KERN_INFO "Device returned, unsetting inDMD\n");
3300                vtarget->inDMD = 0;
3301        }
3302
3303 out:
3304        return error;
3305}
3306
3307static int
3308mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
3309{
3310        struct mptsas_portinfo *port_info, *hba;
3311        int error = -ENOMEM, i;
3312
3313        hba = kzalloc(sizeof(struct mptsas_portinfo), GFP_KERNEL);
3314        if (! hba)
3315                goto out;
3316
3317        error = mptsas_sas_io_unit_pg0(ioc, hba);
3318        if (error)
3319                goto out_free_port_info;
3320
3321        mptsas_sas_io_unit_pg1(ioc);
3322        mutex_lock(&ioc->sas_topology_mutex);
3323        port_info = ioc->hba_port_info;
3324        if (!port_info) {
3325                ioc->hba_port_info = port_info = hba;
3326                ioc->hba_port_num_phy = port_info->num_phys;
3327                list_add_tail(&port_info->list, &ioc->sas_topology);
3328        } else {
3329                for (i = 0; i < hba->num_phys; i++) {
3330                        port_info->phy_info[i].negotiated_link_rate =
3331                                hba->phy_info[i].negotiated_link_rate;
3332                        port_info->phy_info[i].handle =
3333                                hba->phy_info[i].handle;
3334                        port_info->phy_info[i].port_id =
3335                                hba->phy_info[i].port_id;
3336                }
3337                kfree(hba->phy_info);
3338                kfree(hba);
3339                hba = NULL;
3340        }
3341        mutex_unlock(&ioc->sas_topology_mutex);
3342#if defined(CPQ_CIM)
3343        ioc->num_ports = port_info->num_phys;
3344#endif
3345        for (i = 0; i < port_info->num_phys; i++) {
3346                mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
3347                        (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
3348                         MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
3349                port_info->phy_info[i].identify.handle =
3350                    port_info->phy_info[i].handle;
3351                mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
3352                        (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
3353                         MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3354                         port_info->phy_info[i].identify.handle);
3355                if (!ioc->hba_port_sas_addr)
3356                        ioc->hba_port_sas_addr =
3357                            port_info->phy_info[i].identify.sas_address;
3358                port_info->phy_info[i].identify.phy_id =
3359                    port_info->phy_info[i].phy_id = i;
3360                if (port_info->phy_info[i].attached.handle)
3361                        mptsas_sas_device_pg0(ioc,
3362                                &port_info->phy_info[i].attached,
3363                                (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
3364                                 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3365                                port_info->phy_info[i].attached.handle);
3366        }
3367
3368        mptsas_setup_wide_ports(ioc, port_info);
3369
3370        for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
3371                mptsas_probe_one_phy(&ioc->sh->shost_gendev,
3372                    &port_info->phy_info[i], ioc->sas_index, 1);
3373
3374        return 0;
3375
3376 out_free_port_info:
3377        kfree(hba);
3378 out:
3379        return error;
3380}
3381
3382static void
3383mptsas_expander_refresh(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
3384{
3385        struct mptsas_portinfo *parent;
3386        struct device *parent_dev;
3387        struct sas_rphy *rphy;
3388        int             i;
3389        u64             sas_address; /* expander sas address */
3390        u32             handle;
3391
3392        handle = port_info->phy_info[0].handle;
3393        sas_address = port_info->phy_info[0].identify.sas_address;
3394        for (i = 0; i < port_info->num_phys; i++) {
3395                mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
3396                    (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
3397                    MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + handle);
3398
3399                mptsas_sas_device_pg0(ioc,
3400                    &port_info->phy_info[i].identify,
3401                    (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
3402                    MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3403                    port_info->phy_info[i].identify.handle);
3404                port_info->phy_info[i].identify.phy_id =
3405                    port_info->phy_info[i].phy_id;
3406
3407                if (port_info->phy_info[i].attached.handle) {
3408                        mptsas_sas_device_pg0(ioc,
3409                            &port_info->phy_info[i].attached,
3410                            (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
3411                             MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3412                            port_info->phy_info[i].attached.handle);
3413                        port_info->phy_info[i].attached.phy_id =
3414                            port_info->phy_info[i].phy_id;
3415                }
3416        }
3417
3418        mutex_lock(&ioc->sas_topology_mutex);
3419        parent = mptsas_find_portinfo_by_handle(ioc,
3420            port_info->phy_info[0].identify.handle_parent);
3421        if (!parent) {
3422                mutex_unlock(&ioc->sas_topology_mutex);
3423                return;
3424        }
3425        for (i = 0, parent_dev = NULL; i < parent->num_phys && !parent_dev;
3426            i++) {
3427                if (parent->phy_info[i].attached.sas_address == sas_address) {
3428                        rphy = mptsas_get_rphy(&parent->phy_info[i]);
3429                        parent_dev = &rphy->dev;
3430                }
3431        }
3432        mutex_unlock(&ioc->sas_topology_mutex);
3433
3434        mptsas_setup_wide_ports(ioc, port_info);
3435        for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
3436                mptsas_probe_one_phy(parent_dev, &port_info->phy_info[i],
3437                    ioc->sas_index, 0);
3438}
3439
3440static void
3441mptsas_expander_event_add(MPT_ADAPTER *ioc,
3442    MpiEventDataSasExpanderStatusChange_t *expander_data)
3443{
3444        struct mptsas_portinfo *port_info;
3445        int i;
3446        __le64 sas_address;
3447
3448        port_info = kzalloc(sizeof(struct mptsas_portinfo), GFP_KERNEL);
3449        BUG_ON(!port_info);
3450        port_info->num_phys = (expander_data->NumPhys) ?
3451            expander_data->NumPhys : 1;
3452        port_info->phy_info = kcalloc(port_info->num_phys,
3453            sizeof(struct mptsas_phyinfo), GFP_KERNEL);
3454        BUG_ON(!port_info->phy_info);
3455        memcpy(&sas_address, &expander_data->SASAddress, sizeof(__le64));
3456        for (i = 0; i < port_info->num_phys; i++) {
3457                port_info->phy_info[i].portinfo = port_info;
3458                port_info->phy_info[i].handle =
3459                    le16_to_cpu(expander_data->DevHandle);
3460                port_info->phy_info[i].identify.sas_address =
3461                    le64_to_cpu(sas_address);
3462                port_info->phy_info[i].identify.handle_parent =
3463                    le16_to_cpu(expander_data->ParentDevHandle);
3464        }
3465
3466        mutex_lock(&ioc->sas_topology_mutex);
3467        list_add_tail(&port_info->list, &ioc->sas_topology);
3468        mutex_unlock(&ioc->sas_topology_mutex);
3469
3470        printk(MYIOC_s_INFO_FMT "add expander: num_phys %d, "
3471            "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
3472            (unsigned long long)sas_address);
3473
3474        mptsas_expander_refresh(ioc, port_info);
3475}
3476
3477/**
3478 * mptsas_delete_expander_siblings - remove siblings attached to expander
3479 * @ioc: Pointer to MPT_ADAPTER structure
3480 * @parent: the parent port_info object
3481 * @expander: the expander port_info object
3482 **/
3483static void
3484mptsas_delete_expander_siblings(MPT_ADAPTER *ioc, struct mptsas_portinfo
3485    *parent, struct mptsas_portinfo *expander)
3486{
3487        struct mptsas_phyinfo *phy_info;
3488        struct mptsas_portinfo *port_info;
3489        struct sas_rphy *rphy;
3490        int i;
3491
3492        phy_info = expander->phy_info;
3493        for (i = 0; i < expander->num_phys; i++, phy_info++) {
3494                rphy = mptsas_get_rphy(phy_info);
3495                if (!rphy)
3496                        continue;
3497                if (rphy->identify.device_type == SAS_END_DEVICE)
3498                        mptsas_del_end_device(ioc, phy_info);
3499        }
3500
3501        phy_info = expander->phy_info;
3502        for (i = 0; i < expander->num_phys; i++, phy_info++) {
3503                rphy = mptsas_get_rphy(phy_info);
3504                if (!rphy)
3505                        continue;
3506                if (rphy->identify.device_type ==
3507                    MPI_SAS_DEVICE_INFO_EDGE_EXPANDER ||
3508                    rphy->identify.device_type ==
3509                    MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER) {
3510                        port_info = mptsas_find_portinfo_by_sas_address(ioc,
3511                            rphy->identify.sas_address);
3512                        if (!port_info)
3513                                continue;
3514                        if (port_info == parent) /* backlink rphy */
3515                                continue;
3516                        /*
3517                        Delete this expander even if the expdevpage is exists
3518                        because the parent expander is already deleted
3519                        */
3520                        mptsas_expander_delete(ioc, port_info, 1);
3521                }
3522        }
3523}
3524
3525
3526/**
3527 *      mptsas_expander_delete - remove this expander
3528 *      @ioc: Pointer to MPT_ADAPTER structure
3529 *      @port_info: expander port_info struct
3530 *      @force: Flag to forcefully delete the expander
3531 *
3532 **/
3533
3534static void mptsas_expander_delete(MPT_ADAPTER *ioc,
3535                struct mptsas_portinfo *port_info, u8 force)
3536{
3537
3538        struct mptsas_portinfo *parent;
3539        int             i;
3540        u64             expander_sas_address;
3541        struct mptsas_phyinfo *phy_info;
3542        struct mptsas_portinfo buffer;
3543        struct mptsas_portinfo_details *port_details;
3544        struct sas_port *port;
3545
3546        if (!port_info)
3547                return;
3548
3549        /* see if expander is still there before deleting */
3550        mptsas_sas_expander_pg0(ioc, &buffer,
3551            (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
3552            MPI_SAS_EXPAND_PGAD_FORM_SHIFT),
3553            port_info->phy_info[0].identify.handle);
3554
3555        if (buffer.num_phys) {
3556                kfree(buffer.phy_info);
3557                if (!force)
3558                        return;
3559        }
3560
3561
3562        /*
3563         * Obtain the port_info instance to the parent port
3564         */
3565        port_details = NULL;
3566        expander_sas_address =
3567            port_info->phy_info[0].identify.sas_address;
3568        parent = mptsas_find_portinfo_by_handle(ioc,
3569            port_info->phy_info[0].identify.handle_parent);
3570        mptsas_delete_expander_siblings(ioc, parent, port_info);
3571        if (!parent)
3572                goto out;
3573
3574        /*
3575         * Delete rphys in the parent that point
3576         * to this expander.
3577         */
3578        phy_info = parent->phy_info;
3579        port = NULL;
3580        for (i = 0; i < parent->num_phys; i++, phy_info++) {
3581                if (!phy_info->phy)
3582                        continue;
3583                if (phy_info->attached.sas_address !=
3584                    expander_sas_address)
3585                        continue;
3586                if (!port) {
3587                        port = mptsas_get_port(phy_info);
3588                        port_details = phy_info->port_details;
3589                }
3590                dev_printk(KERN_DEBUG, &phy_info->phy->dev,
3591                    MYIOC_s_FMT "delete phy %d, phy-obj (0x%p)\n", ioc->name,
3592                    phy_info->phy_id, phy_info->phy);
3593                sas_port_delete_phy(port, phy_info->phy);
3594        }
3595        if (port) {
3596                dev_printk(KERN_DEBUG, &port->dev,
3597                    MYIOC_s_FMT "delete port %d, sas_addr (0x%llx)\n",
3598                    ioc->name, port->port_identifier,
3599                    (unsigned long long)expander_sas_address);
3600                sas_port_delete(port);
3601                mptsas_port_delete(ioc, port_details);
3602        }
3603 out:
3604
3605        printk(MYIOC_s_INFO_FMT "delete expander: num_phys %d, "
3606            "sas_addr (0x%llx)\n",  ioc->name, port_info->num_phys,
3607            (unsigned long long)expander_sas_address);
3608
3609        /*
3610         * free link
3611         */
3612        list_del(&port_info->list);
3613        kfree(port_info->phy_info);
3614        kfree(port_info);
3615}
3616
3617
3618/**
3619 * mptsas_send_expander_event - expanders events
3620 * @fw_event: event data
3621 *
3622 *
3623 * This function handles adding, removing, and refreshing
3624 * device handles within the expander objects.
3625 */
3626static void
3627mptsas_send_expander_event(struct fw_event_work *fw_event)
3628{
3629        MPT_ADAPTER *ioc;
3630        MpiEventDataSasExpanderStatusChange_t *expander_data;
3631        struct mptsas_portinfo *port_info;
3632        __le64 sas_address;
3633        int i;
3634
3635        ioc = fw_event->ioc;
3636        expander_data = (MpiEventDataSasExpanderStatusChange_t *)
3637            fw_event->event_data;
3638        memcpy(&sas_address, &expander_data->SASAddress, sizeof(__le64));
3639        sas_address = le64_to_cpu(sas_address);
3640        port_info = mptsas_find_portinfo_by_sas_address(ioc, sas_address);
3641
3642        if (expander_data->ReasonCode == MPI_EVENT_SAS_EXP_RC_ADDED) {
3643                if (port_info) {
3644                        for (i = 0; i < port_info->num_phys; i++) {
3645                                port_info->phy_info[i].portinfo = port_info;
3646                                port_info->phy_info[i].handle =
3647                                    le16_to_cpu(expander_data->DevHandle);
3648                                port_info->phy_info[i].identify.sas_address =
3649                                    le64_to_cpu(sas_address);
3650                                port_info->phy_info[i].identify.handle_parent =
3651                                    le16_to_cpu(expander_data->ParentDevHandle);
3652                        }
3653                        mptsas_expander_refresh(ioc, port_info);
3654                } else if (!port_info && expander_data->NumPhys)
3655                        mptsas_expander_event_add(ioc, expander_data);
3656        } else if (expander_data->ReasonCode ==
3657            MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING)
3658                mptsas_expander_delete(ioc, port_info, 0);
3659
3660        mptsas_free_fw_event(ioc, fw_event);
3661}
3662
3663
3664/**
3665 * mptsas_expander_add - adds a newly discovered expander
3666 * @ioc: Pointer to MPT_ADAPTER structure
3667 * @handle: device handle
3668 *
3669 */
3670static struct mptsas_portinfo *
3671mptsas_expander_add(MPT_ADAPTER *ioc, u16 handle)
3672{
3673        struct mptsas_portinfo buffer, *port_info;
3674        int i;
3675
3676        if ((mptsas_sas_expander_pg0(ioc, &buffer,
3677            (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
3678            MPI_SAS_EXPAND_PGAD_FORM_SHIFT), handle)))
3679                return NULL;
3680
3681        port_info = kzalloc(sizeof(struct mptsas_portinfo), GFP_ATOMIC);
3682        if (!port_info) {
3683                dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3684                "%s: exit at line=%d\n", ioc->name,
3685                __func__, __LINE__));
3686                return NULL;
3687        }
3688        port_info->num_phys = buffer.num_phys;
3689        port_info->phy_info = buffer.phy_info;
3690        for (i = 0; i < port_info->num_phys; i++)
3691                port_info->phy_info[i].portinfo = port_info;
3692        mutex_lock(&ioc->sas_topology_mutex);
3693        list_add_tail(&port_info->list, &ioc->sas_topology);
3694        mutex_unlock(&ioc->sas_topology_mutex);
3695        printk(MYIOC_s_INFO_FMT "add expander: num_phys %d, "
3696            "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
3697            (unsigned long long)buffer.phy_info[0].identify.sas_address);
3698        mptsas_expander_refresh(ioc, port_info);
3699        return port_info;
3700}
3701
3702static void
3703mptsas_send_link_status_event(struct fw_event_work *fw_event)
3704{
3705        MPT_ADAPTER *ioc;
3706        MpiEventDataSasPhyLinkStatus_t *link_data;
3707        struct mptsas_portinfo *port_info;
3708        struct mptsas_phyinfo *phy_info = NULL;
3709        __le64 sas_address;
3710        u8 phy_num;
3711        u8 link_rate;
3712
3713        ioc = fw_event->ioc;
3714        link_data = (MpiEventDataSasPhyLinkStatus_t *)fw_event->event_data;
3715
3716        memcpy(&sas_address, &link_data->SASAddress, sizeof(__le64));
3717        sas_address = le64_to_cpu(sas_address);
3718        link_rate = link_data->LinkRates >> 4;
3719        phy_num = link_data->PhyNum;
3720
3721        port_info = mptsas_find_portinfo_by_sas_address(ioc, sas_address);
3722        if (port_info) {
3723                phy_info = &port_info->phy_info[phy_num];
3724                if (phy_info)
3725                        phy_info->negotiated_link_rate = link_rate;
3726        }
3727
3728        if (link_rate == MPI_SAS_IOUNIT0_RATE_1_5 ||
3729            link_rate == MPI_SAS_IOUNIT0_RATE_3_0 ||
3730            link_rate == MPI_SAS_IOUNIT0_RATE_6_0) {
3731
3732                if (!port_info) {
3733                        if (ioc->old_sas_discovery_protocal) {
3734                                port_info = mptsas_expander_add(ioc,
3735                                        le16_to_cpu(link_data->DevHandle));
3736                                if (port_info)
3737                                        goto out;
3738                        }
3739                        goto out;
3740                }
3741
3742                if (port_info == ioc->hba_port_info)
3743                        mptsas_probe_hba_phys(ioc);
3744                else
3745                        mptsas_expander_refresh(ioc, port_info);
3746        } else if (phy_info && phy_info->phy) {
3747                if (link_rate ==  MPI_SAS_IOUNIT0_RATE_PHY_DISABLED)
3748                        phy_info->phy->negotiated_linkrate =
3749                            SAS_PHY_DISABLED;
3750                else if (link_rate ==
3751                    MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION)
3752                        phy_info->phy->negotiated_linkrate =
3753                            SAS_LINK_RATE_FAILED;
3754                else {
3755                        phy_info->phy->negotiated_linkrate =
3756                            SAS_LINK_RATE_UNKNOWN;
3757                        if (ioc->device_missing_delay &&
3758                            mptsas_is_end_device(&phy_info->attached)) {
3759                                struct scsi_device              *sdev;
3760                                VirtDevice                      *vdevice;
3761                                u8      channel, id;
3762                                id = phy_info->attached.id;
3763                                channel = phy_info->attached.channel;
3764                                devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3765                                "Link down for fw_id %d:fw_channel %d\n",
3766                                    ioc->name, phy_info->attached.id,
3767                                    phy_info->attached.channel));
3768
3769                                shost_for_each_device(sdev, ioc->sh) {
3770                                        vdevice = sdev->hostdata;
3771                                        if ((vdevice == NULL) ||
3772                                                (vdevice->vtarget == NULL))
3773                                                continue;
3774                                        if ((vdevice->vtarget->tflags &
3775                                            MPT_TARGET_FLAGS_RAID_COMPONENT ||
3776                                            vdevice->vtarget->raidVolume))
3777                                                continue;
3778                                        if (vdevice->vtarget->id == id &&
3779                                                vdevice->vtarget->channel ==
3780                                                channel)
3781                                                devtprintk(ioc,
3782                                                printk(MYIOC_s_DEBUG_FMT
3783                                                "SDEV OUTSTANDING CMDS"
3784                                                "%d\n", ioc->name,
3785                                                scsi_device_busy(sdev)));
3786                                }
3787
3788                        }
3789                }
3790        }
3791 out:
3792        mptsas_free_fw_event(ioc, fw_event);
3793}
3794
3795static void
3796mptsas_not_responding_devices(MPT_ADAPTER *ioc)
3797{
3798        struct mptsas_portinfo buffer, *port_info;
3799        struct mptsas_device_info       *sas_info;
3800        struct mptsas_devinfo sas_device;
3801        u32     handle;
3802        VirtTarget *vtarget = NULL;
3803        struct mptsas_phyinfo *phy_info;
3804        u8 found_expander;
3805        int retval, retry_count;
3806        unsigned long flags;
3807
3808        mpt_findImVolumes(ioc);
3809
3810        spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
3811        if (ioc->ioc_reset_in_progress) {
3812                dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3813                   "%s: exiting due to a parallel reset \n", ioc->name,
3814                    __func__));
3815                spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
3816                return;
3817        }
3818        spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
3819
3820        /* devices, logical volumes */
3821        mutex_lock(&ioc->sas_device_info_mutex);
3822 redo_device_scan:
3823        list_for_each_entry(sas_info, &ioc->sas_device_info_list, list) {
3824                if (sas_info->is_cached)
3825                        continue;
3826                if (!sas_info->is_logical_volume) {
3827                        sas_device.handle = 0;
3828                        retry_count = 0;
3829retry_page:
3830                        retval = mptsas_sas_device_pg0(ioc, &sas_device,
3831                                (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID
3832                                << MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3833                                (sas_info->fw.channel << 8) +
3834                                sas_info->fw.id);
3835
3836                        if (sas_device.handle)
3837                                continue;
3838                        if (retval == -EBUSY) {
3839                                spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
3840                                if (ioc->ioc_reset_in_progress) {
3841                                        dfailprintk(ioc,
3842                                        printk(MYIOC_s_DEBUG_FMT
3843                                        "%s: exiting due to reset\n",
3844                                        ioc->name, __func__));
3845                                        spin_unlock_irqrestore
3846                                        (&ioc->taskmgmt_lock, flags);
3847                                        mutex_unlock(&ioc->
3848                                        sas_device_info_mutex);
3849                                        return;
3850                                }
3851                                spin_unlock_irqrestore(&ioc->taskmgmt_lock,
3852                                flags);
3853                        }
3854
3855                        if (retval && (retval != -ENODEV)) {
3856                                if (retry_count < 10) {
3857                                        retry_count++;
3858                                        goto retry_page;
3859                                } else {
3860                                        devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3861                                        "%s: Config page retry exceeded retry "
3862                                        "count deleting device 0x%llx\n",
3863                                        ioc->name, __func__,
3864                                        sas_info->sas_address));
3865                                }
3866                        }
3867
3868                        /* delete device */
3869                        vtarget = mptsas_find_vtarget(ioc,
3870                                sas_info->fw.channel, sas_info->fw.id);
3871
3872                        if (vtarget)
3873                                vtarget->deleted = 1;
3874
3875                        phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
3876                                        sas_info->sas_address);
3877
3878                        mptsas_del_end_device(ioc, phy_info);
3879                        goto redo_device_scan;
3880                } else
3881                        mptsas_volume_delete(ioc, sas_info->fw.id);
3882        }
3883        mutex_unlock(&ioc->sas_device_info_mutex);
3884
3885        /* expanders */
3886        mutex_lock(&ioc->sas_topology_mutex);
3887 redo_expander_scan:
3888        list_for_each_entry(port_info, &ioc->sas_topology, list) {
3889
3890                if (!(port_info->phy_info[0].identify.device_info &
3891                    MPI_SAS_DEVICE_INFO_SMP_TARGET))
3892                        continue;
3893                found_expander = 0;
3894                handle = 0xFFFF;
3895                while (!mptsas_sas_expander_pg0(ioc, &buffer,
3896                    (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
3897                     MPI_SAS_EXPAND_PGAD_FORM_SHIFT), handle) &&
3898                    !found_expander) {
3899
3900                        handle = buffer.phy_info[0].handle;
3901                        if (buffer.phy_info[0].identify.sas_address ==
3902                            port_info->phy_info[0].identify.sas_address) {
3903                                found_expander = 1;
3904                        }
3905                        kfree(buffer.phy_info);
3906                }
3907
3908                if (!found_expander) {
3909                        mptsas_expander_delete(ioc, port_info, 0);
3910                        goto redo_expander_scan;
3911                }
3912        }
3913        mutex_unlock(&ioc->sas_topology_mutex);
3914}
3915
3916/**
3917 *      mptsas_probe_expanders - adding expanders
3918 *      @ioc: Pointer to MPT_ADAPTER structure
3919 *
3920 **/
3921static void
3922mptsas_probe_expanders(MPT_ADAPTER *ioc)
3923{
3924        struct mptsas_portinfo buffer, *port_info;
3925        u32                     handle;
3926        int i;
3927
3928        handle = 0xFFFF;
3929        while (!mptsas_sas_expander_pg0(ioc, &buffer,
3930            (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
3931             MPI_SAS_EXPAND_PGAD_FORM_SHIFT), handle)) {
3932
3933                handle = buffer.phy_info[0].handle;
3934                port_info = mptsas_find_portinfo_by_sas_address(ioc,
3935                    buffer.phy_info[0].identify.sas_address);
3936
3937                if (port_info) {
3938                        /* refreshing handles */
3939                        for (i = 0; i < buffer.num_phys; i++) {
3940                                port_info->phy_info[i].handle = handle;
3941                                port_info->phy_info[i].identify.handle_parent =
3942                                    buffer.phy_info[0].identify.handle_parent;
3943                        }
3944                        mptsas_expander_refresh(ioc, port_info);
3945                        kfree(buffer.phy_info);
3946                        continue;
3947                }
3948
3949                port_info = kzalloc(sizeof(struct mptsas_portinfo), GFP_KERNEL);
3950                if (!port_info) {
3951                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3952                        "%s: exit at line=%d\n", ioc->name,
3953                        __func__, __LINE__));
3954                        return;
3955                }
3956                port_info->num_phys = buffer.num_phys;
3957                port_info->phy_info = buffer.phy_info;
3958                for (i = 0; i < port_info->num_phys; i++)
3959                        port_info->phy_info[i].portinfo = port_info;
3960                mutex_lock(&ioc->sas_topology_mutex);
3961                list_add_tail(&port_info->list, &ioc->sas_topology);
3962                mutex_unlock(&ioc->sas_topology_mutex);
3963                printk(MYIOC_s_INFO_FMT "add expander: num_phys %d, "
3964                    "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
3965            (unsigned long long)buffer.phy_info[0].identify.sas_address);
3966                mptsas_expander_refresh(ioc, port_info);
3967        }
3968}
3969
3970static void
3971mptsas_probe_devices(MPT_ADAPTER *ioc)
3972{
3973        u16 handle;
3974        struct mptsas_devinfo sas_device;
3975        struct mptsas_phyinfo *phy_info;
3976
3977        handle = 0xFFFF;
3978        while (!(mptsas_sas_device_pg0(ioc, &sas_device,
3979            MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
3980
3981                handle = sas_device.handle;
3982
3983                if ((sas_device.device_info &
3984                     (MPI_SAS_DEVICE_INFO_SSP_TARGET |
3985                      MPI_SAS_DEVICE_INFO_STP_TARGET |
3986                      MPI_SAS_DEVICE_INFO_SATA_DEVICE)) == 0)
3987                        continue;
3988
3989                /* If there is no FW B_T mapping for this device then continue
3990                 * */
3991                if (!(sas_device.flags & MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)
3992                        || !(sas_device.flags &
3993                        MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED))
3994                        continue;
3995
3996                phy_info = mptsas_refreshing_device_handles(ioc, &sas_device);
3997                if (!phy_info)
3998                        continue;
3999
4000                if (mptsas_get_rphy(phy_info))
4001                        continue;
4002
4003                mptsas_add_end_device(ioc, phy_info);
4004        }
4005}
4006
4007/**
4008 *      mptsas_scan_sas_topology - scans new SAS topology
4009 *        (part of probe or rescan)
4010 *      @ioc: Pointer to MPT_ADAPTER structure
4011 *
4012 **/
4013static void
4014mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
4015{
4016        struct scsi_device *sdev;
4017        int i;
4018
4019        mptsas_probe_hba_phys(ioc);
4020        mptsas_probe_expanders(ioc);
4021        mptsas_probe_devices(ioc);
4022
4023        /*
4024          Reporting RAID volumes.
4025        */
4026        if (!ioc->ir_firmware || !ioc->raid_data.pIocPg2 ||
4027            !ioc->raid_data.pIocPg2->NumActiveVolumes)
4028                return;
4029        for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
4030                sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
4031                    ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
4032                if (sdev) {
4033                        scsi_device_put(sdev);
4034                        continue;
4035                }
4036                printk(MYIOC_s_INFO_FMT "attaching raid volume, channel %d, "
4037                    "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL,
4038                    ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID);
4039                scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
4040                    ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
4041        }
4042}
4043
4044
4045static void
4046mptsas_handle_queue_full_event(struct fw_event_work *fw_event)
4047{
4048        MPT_ADAPTER *ioc;
4049        EventDataQueueFull_t *qfull_data;
4050        struct mptsas_device_info *sas_info;
4051        struct scsi_device      *sdev;
4052        int depth;
4053        int id = -1;
4054        int channel = -1;
4055        int fw_id, fw_channel;
4056        u16 current_depth;
4057
4058
4059        ioc = fw_event->ioc;
4060        qfull_data = (EventDataQueueFull_t *)fw_event->event_data;
4061        fw_id = qfull_data->TargetID;
4062        fw_channel = qfull_data->Bus;
4063        current_depth = le16_to_cpu(qfull_data->CurrentDepth);
4064
4065        /* if hidden raid component, look for the volume id */
4066        mutex_lock(&ioc->sas_device_info_mutex);
4067        if (mptscsih_is_phys_disk(ioc, fw_channel, fw_id)) {
4068                list_for_each_entry(sas_info, &ioc->sas_device_info_list,
4069                    list) {
4070                        if (sas_info->is_cached ||
4071                            sas_info->is_logical_volume)
4072                                continue;
4073                        if (sas_info->is_hidden_raid_component &&
4074                            (sas_info->fw.channel == fw_channel &&
4075                            sas_info->fw.id == fw_id)) {
4076                                id = sas_info->volume_id;
4077                                channel = MPTSAS_RAID_CHANNEL;
4078                                goto out;
4079                        }
4080                }
4081        } else {
4082                list_for_each_entry(sas_info, &ioc->sas_device_info_list,
4083                    list) {
4084                        if (sas_info->is_cached ||
4085                            sas_info->is_hidden_raid_component ||
4086                            sas_info->is_logical_volume)
4087                                continue;
4088                        if (sas_info->fw.channel == fw_channel &&
4089                            sas_info->fw.id == fw_id) {
4090                                id = sas_info->os.id;
4091                                channel = sas_info->os.channel;
4092                                goto out;
4093                        }
4094                }
4095
4096        }
4097
4098 out:
4099        mutex_unlock(&ioc->sas_device_info_mutex);
4100
4101        if (id != -1) {
4102                shost_for_each_device(sdev, ioc->sh) {
4103                        if (sdev->id == id && sdev->channel == channel) {
4104                                if (current_depth > sdev->queue_depth) {
4105                                        sdev_printk(KERN_INFO, sdev,
4106                                            "strange observation, the queue "
4107                                            "depth is (%d) meanwhile fw queue "
4108                                            "depth (%d)\n", sdev->queue_depth,
4109                                            current_depth);
4110                                        continue;
4111                                }
4112                                depth = scsi_track_queue_full(sdev,
4113                                        sdev->queue_depth - 1);
4114                                if (depth > 0)
4115                                        sdev_printk(KERN_INFO, sdev,
4116                                        "Queue depth reduced to (%d)\n",
4117                                           depth);
4118                                else if (depth < 0)
4119                                        sdev_printk(KERN_INFO, sdev,
4120                                        "Tagged Command Queueing is being "
4121                                        "disabled\n");
4122                                else if (depth == 0)
4123                                        sdev_printk(KERN_DEBUG, sdev,
4124                                        "Queue depth not changed yet\n");
4125                        }
4126                }
4127        }
4128
4129        mptsas_free_fw_event(ioc, fw_event);
4130}
4131
4132
4133static struct mptsas_phyinfo *
4134mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
4135{
4136        struct mptsas_portinfo *port_info;
4137        struct mptsas_phyinfo *phy_info = NULL;
4138        int i;
4139
4140        mutex_lock(&ioc->sas_topology_mutex);
4141        list_for_each_entry(port_info, &ioc->sas_topology, list) {
4142                for (i = 0; i < port_info->num_phys; i++) {
4143                        if (!mptsas_is_end_device(
4144                                &port_info->phy_info[i].attached))
4145                                continue;
4146                        if (port_info->phy_info[i].attached.sas_address
4147                            != sas_address)
4148                                continue;
4149                        phy_info = &port_info->phy_info[i];
4150                        break;
4151                }
4152        }
4153        mutex_unlock(&ioc->sas_topology_mutex);
4154        return phy_info;
4155}
4156
4157/**
4158 *      mptsas_find_phyinfo_by_phys_disk_num - find phyinfo for the
4159 *        specified @phys_disk_num
4160 *      @ioc: Pointer to MPT_ADAPTER structure
4161 *      @phys_disk_num: (hot plug) physical disk number (for RAID support)
4162 *      @channel: channel number
4163 *      @id: Logical Target ID
4164 *
4165 **/
4166static struct mptsas_phyinfo *
4167mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 phys_disk_num,
4168        u8 channel, u8 id)
4169{
4170        struct mptsas_phyinfo *phy_info = NULL;
4171        struct mptsas_portinfo *port_info;
4172        RaidPhysDiskPage1_t *phys_disk = NULL;
4173        int num_paths;
4174        u64 sas_address = 0;
4175        int i;
4176
4177        phy_info = NULL;
4178        if (!ioc->raid_data.pIocPg3)
4179                return NULL;
4180        /* dual port support */
4181        num_paths = mpt_raid_phys_disk_get_num_paths(ioc, phys_disk_num);
4182        if (!num_paths)
4183                goto out;
4184        phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) +
4185           (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL);
4186        if (!phys_disk)
4187                goto out;
4188        mpt_raid_phys_disk_pg1(ioc, phys_disk_num, phys_disk);
4189        for (i = 0; i < num_paths; i++) {
4190                if ((phys_disk->Path[i].Flags & 1) != 0)
4191                        /* entry no longer valid */
4192                        continue;
4193                if ((id == phys_disk->Path[i].PhysDiskID) &&
4194                    (channel == phys_disk->Path[i].PhysDiskBus)) {
4195                        memcpy(&sas_address, &phys_disk->Path[i].WWID,
4196                                sizeof(u64));
4197                        phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
4198                                        sas_address);
4199                        goto out;
4200                }
4201        }
4202
4203 out:
4204        kfree(phys_disk);
4205        if (phy_info)
4206                return phy_info;
4207
4208        /*
4209         * Extra code to handle RAID0 case, where the sas_address is not updated
4210         * in phys_disk_page_1 when hotswapped
4211         */
4212        mutex_lock(&ioc->sas_topology_mutex);
4213        list_for_each_entry(port_info, &ioc->sas_topology, list) {
4214                for (i = 0; i < port_info->num_phys && !phy_info; i++) {
4215                        if (!mptsas_is_end_device(
4216                                &port_info->phy_info[i].attached))
4217                                continue;
4218                        if (port_info->phy_info[i].attached.phys_disk_num == ~0)
4219                                continue;
4220                        if ((port_info->phy_info[i].attached.phys_disk_num ==
4221                            phys_disk_num) &&
4222                            (port_info->phy_info[i].attached.id == id) &&
4223                            (port_info->phy_info[i].attached.channel ==
4224                             channel))
4225                                phy_info = &port_info->phy_info[i];
4226                }
4227        }
4228        mutex_unlock(&ioc->sas_topology_mutex);
4229        return phy_info;
4230}
4231
4232static void
4233mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
4234{
4235        int rc;
4236
4237        sdev->no_uld_attach = data ? 1 : 0;
4238        rc = scsi_device_reprobe(sdev);
4239}
4240
4241static void
4242mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
4243{
4244        starget_for_each_device(starget, uld_attach ? (void *)1 : NULL,
4245                        mptsas_reprobe_lun);
4246}
4247
4248static void
4249mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id)
4250{
4251        CONFIGPARMS                     cfg;
4252        ConfigPageHeader_t              hdr;
4253        dma_addr_t                      dma_handle;
4254        pRaidVolumePage0_t              buffer = NULL;
4255        RaidPhysDiskPage0_t             phys_disk;
4256        int                             i;
4257        struct mptsas_phyinfo   *phy_info;
4258        struct mptsas_devinfo           sas_device;
4259
4260        memset(&cfg, 0 , sizeof(CONFIGPARMS));
4261        memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
4262        hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
4263        cfg.pageAddr = (channel << 8) + id;
4264        cfg.cfghdr.hdr = &hdr;
4265        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4266        cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
4267
4268        if (mpt_config(ioc, &cfg) != 0)
4269                goto out;
4270
4271        if (!hdr.PageLength)
4272                goto out;
4273
4274        buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
4275            &dma_handle);
4276
4277        if (!buffer)
4278                goto out;
4279
4280        cfg.physAddr = dma_handle;
4281        cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4282
4283        if (mpt_config(ioc, &cfg) != 0)
4284                goto out;
4285
4286        if (!(buffer->VolumeStatus.Flags &
4287            MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE))
4288                goto out;
4289
4290        if (!buffer->NumPhysDisks)
4291                goto out;
4292
4293        for (i = 0; i < buffer->NumPhysDisks; i++) {
4294
4295                if (mpt_raid_phys_disk_pg0(ioc,
4296                    buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
4297                        continue;
4298
4299                if (mptsas_sas_device_pg0(ioc, &sas_device,
4300                    (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
4301                     MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
4302                        (phys_disk.PhysDiskBus << 8) +
4303                        phys_disk.PhysDiskID))
4304                        continue;
4305
4306                /* If there is no FW B_T mapping for this device then continue
4307                 * */
4308                if (!(sas_device.flags & MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)
4309                        || !(sas_device.flags &
4310                        MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED))
4311                        continue;
4312
4313
4314                phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
4315                    sas_device.sas_address);
4316                mptsas_add_end_device(ioc, phy_info);
4317        }
4318
4319 out:
4320        if (buffer)
4321                pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
4322                    dma_handle);
4323}
4324/*
4325 * Work queue thread to handle SAS hotplug events
4326 */
4327static void
4328mptsas_hotplug_work(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
4329    struct mptsas_hotplug_event *hot_plug_info)
4330{
4331        struct mptsas_phyinfo *phy_info;
4332        struct scsi_target * starget;
4333        struct mptsas_devinfo sas_device;
4334        VirtTarget *vtarget;
4335        int i;
4336        struct mptsas_portinfo *port_info;
4337
4338        switch (hot_plug_info->event_type) {
4339
4340        case MPTSAS_ADD_PHYSDISK:
4341
4342                if (!ioc->raid_data.pIocPg2)
4343                        break;
4344
4345                for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
4346                        if (ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID ==
4347                            hot_plug_info->id) {
4348                                printk(MYIOC_s_WARN_FMT "firmware bug: unable "
4349                                    "to add hidden disk - target_id matches "
4350                                    "volume_id\n", ioc->name);
4351                                mptsas_free_fw_event(ioc, fw_event);
4352                                return;
4353                        }
4354                }
4355                mpt_findImVolumes(ioc);
4356                fallthrough;
4357
4358        case MPTSAS_ADD_DEVICE:
4359                memset(&sas_device, 0, sizeof(struct mptsas_devinfo));
4360                mptsas_sas_device_pg0(ioc, &sas_device,
4361                    (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
4362                    MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
4363                    (hot_plug_info->channel << 8) +
4364                    hot_plug_info->id);
4365
4366                /* If there is no FW B_T mapping for this device then break
4367                 * */
4368                if (!(sas_device.flags & MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)
4369                        || !(sas_device.flags &
4370                        MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED))
4371                        break;
4372
4373                if (!sas_device.handle)
4374                        return;
4375
4376                phy_info = mptsas_refreshing_device_handles(ioc, &sas_device);
4377                /* Device hot plug */
4378                if (!phy_info) {
4379                        devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4380                                "%s %d HOT PLUG: "
4381                                "parent handle of device %x\n", ioc->name,
4382                                __func__, __LINE__, sas_device.handle_parent));
4383                        port_info = mptsas_find_portinfo_by_handle(ioc,
4384                                sas_device.handle_parent);
4385
4386                        if (port_info == ioc->hba_port_info)
4387                                mptsas_probe_hba_phys(ioc);
4388                        else if (port_info)
4389                                mptsas_expander_refresh(ioc, port_info);
4390                        else {
4391                                dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4392                                        "%s %d port info is NULL\n",
4393                                        ioc->name, __func__, __LINE__));
4394                                break;
4395                        }
4396                        phy_info = mptsas_refreshing_device_handles
4397                                (ioc, &sas_device);
4398                }
4399
4400                if (!phy_info) {
4401                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4402                                "%s %d phy info is NULL\n",
4403                                ioc->name, __func__, __LINE__));
4404                        break;
4405                }
4406
4407                if (mptsas_get_rphy(phy_info))
4408                        break;
4409
4410                mptsas_add_end_device(ioc, phy_info);
4411                break;
4412
4413        case MPTSAS_DEL_DEVICE:
4414                phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
4415                    hot_plug_info->sas_address);
4416                mptsas_del_end_device(ioc, phy_info);
4417                break;
4418
4419        case MPTSAS_DEL_PHYSDISK:
4420
4421                mpt_findImVolumes(ioc);
4422
4423                phy_info = mptsas_find_phyinfo_by_phys_disk_num(
4424                                ioc, hot_plug_info->phys_disk_num,
4425                                hot_plug_info->channel,
4426                                hot_plug_info->id);
4427                mptsas_del_end_device(ioc, phy_info);
4428                break;
4429
4430        case MPTSAS_ADD_PHYSDISK_REPROBE:
4431
4432                if (mptsas_sas_device_pg0(ioc, &sas_device,
4433                    (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
4434                     MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
4435                    (hot_plug_info->channel << 8) + hot_plug_info->id)) {
4436                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4437                        "%s: fw_id=%d exit at line=%d\n", ioc->name,
4438                                 __func__, hot_plug_info->id, __LINE__));
4439                        break;
4440                }
4441
4442                /* If there is no FW B_T mapping for this device then break
4443                 * */
4444                if (!(sas_device.flags & MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)
4445                        || !(sas_device.flags &
4446                        MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED))
4447                        break;
4448
4449                phy_info = mptsas_find_phyinfo_by_sas_address(
4450                    ioc, sas_device.sas_address);
4451
4452                if (!phy_info) {
4453                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4454                                "%s: fw_id=%d exit at line=%d\n", ioc->name,
4455                                 __func__, hot_plug_info->id, __LINE__));
4456                        break;
4457                }
4458
4459                starget = mptsas_get_starget(phy_info);
4460                if (!starget) {
4461                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4462                                "%s: fw_id=%d exit at line=%d\n", ioc->name,
4463                                 __func__, hot_plug_info->id, __LINE__));
4464                        break;
4465                }
4466
4467                vtarget = starget->hostdata;
4468                if (!vtarget) {
4469                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4470                                "%s: fw_id=%d exit at line=%d\n", ioc->name,
4471                                 __func__, hot_plug_info->id, __LINE__));
4472                        break;
4473                }
4474
4475                mpt_findImVolumes(ioc);
4476
4477                starget_printk(KERN_INFO, starget, MYIOC_s_FMT "RAID Hidding: "
4478                    "fw_channel=%d, fw_id=%d, physdsk %d, sas_addr 0x%llx\n",
4479                    ioc->name, hot_plug_info->channel, hot_plug_info->id,
4480                    hot_plug_info->phys_disk_num, (unsigned long long)
4481                    sas_device.sas_address);
4482
4483                vtarget->id = hot_plug_info->phys_disk_num;
4484                vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
4485                phy_info->attached.phys_disk_num = hot_plug_info->phys_disk_num;
4486                mptsas_reprobe_target(starget, 1);
4487                break;
4488
4489        case MPTSAS_DEL_PHYSDISK_REPROBE:
4490
4491                if (mptsas_sas_device_pg0(ioc, &sas_device,
4492                    (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
4493                     MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
4494                        (hot_plug_info->channel << 8) + hot_plug_info->id)) {
4495                                dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4496                                    "%s: fw_id=%d exit at line=%d\n",
4497                                    ioc->name, __func__,
4498                                    hot_plug_info->id, __LINE__));
4499                        break;
4500                }
4501
4502                /* If there is no FW B_T mapping for this device then break
4503                 * */
4504                if (!(sas_device.flags & MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)
4505                        || !(sas_device.flags &
4506                        MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED))
4507                        break;
4508
4509                phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
4510                                sas_device.sas_address);
4511                if (!phy_info) {
4512                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4513                            "%s: fw_id=%d exit at line=%d\n", ioc->name,
4514                         __func__, hot_plug_info->id, __LINE__));
4515                        break;
4516                }
4517
4518                starget = mptsas_get_starget(phy_info);
4519                if (!starget) {
4520                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4521                            "%s: fw_id=%d exit at line=%d\n", ioc->name,
4522                         __func__, hot_plug_info->id, __LINE__));
4523                        break;
4524                }
4525
4526                vtarget = starget->hostdata;
4527                if (!vtarget) {
4528                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4529                            "%s: fw_id=%d exit at line=%d\n", ioc->name,
4530                         __func__, hot_plug_info->id, __LINE__));
4531                        break;
4532                }
4533
4534                if (!(vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)) {
4535                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4536                            "%s: fw_id=%d exit at line=%d\n", ioc->name,
4537                         __func__, hot_plug_info->id, __LINE__));
4538                        break;
4539                }
4540
4541                mpt_findImVolumes(ioc);
4542
4543                starget_printk(KERN_INFO, starget, MYIOC_s_FMT "RAID Exposing:"
4544                    " fw_channel=%d, fw_id=%d, physdsk %d, sas_addr 0x%llx\n",
4545                    ioc->name, hot_plug_info->channel, hot_plug_info->id,
4546                    hot_plug_info->phys_disk_num, (unsigned long long)
4547                    sas_device.sas_address);
4548
4549                vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
4550                vtarget->id = hot_plug_info->id;
4551                phy_info->attached.phys_disk_num = ~0;
4552                mptsas_reprobe_target(starget, 0);
4553                mptsas_add_device_component_by_fw(ioc,
4554                    hot_plug_info->channel, hot_plug_info->id);
4555                break;
4556
4557        case MPTSAS_ADD_RAID:
4558
4559                mpt_findImVolumes(ioc);
4560                printk(MYIOC_s_INFO_FMT "attaching raid volume, channel %d, "
4561                    "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL,
4562                    hot_plug_info->id);
4563                scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
4564                    hot_plug_info->id, 0);
4565                break;
4566
4567        case MPTSAS_DEL_RAID:
4568
4569                mpt_findImVolumes(ioc);
4570                printk(MYIOC_s_INFO_FMT "removing raid volume, channel %d, "
4571                    "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL,
4572                    hot_plug_info->id);
4573                scsi_remove_device(hot_plug_info->sdev);
4574                scsi_device_put(hot_plug_info->sdev);
4575                break;
4576
4577        case MPTSAS_ADD_INACTIVE_VOLUME:
4578
4579                mpt_findImVolumes(ioc);
4580                mptsas_adding_inactive_raid_components(ioc,
4581                    hot_plug_info->channel, hot_plug_info->id);
4582                break;
4583
4584        default:
4585                break;
4586        }
4587
4588        mptsas_free_fw_event(ioc, fw_event);
4589}
4590
4591static void
4592mptsas_send_sas_event(struct fw_event_work *fw_event)
4593{
4594        MPT_ADAPTER *ioc;
4595        struct mptsas_hotplug_event hot_plug_info;
4596        EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data;
4597        u32 device_info;
4598        u64 sas_address;
4599
4600        ioc = fw_event->ioc;
4601        sas_event_data = (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)
4602            fw_event->event_data;
4603        device_info = le32_to_cpu(sas_event_data->DeviceInfo);
4604
4605        if ((device_info &
4606                (MPI_SAS_DEVICE_INFO_SSP_TARGET |
4607                MPI_SAS_DEVICE_INFO_STP_TARGET |
4608                MPI_SAS_DEVICE_INFO_SATA_DEVICE)) == 0) {
4609                mptsas_free_fw_event(ioc, fw_event);
4610                return;
4611        }
4612
4613        if (sas_event_data->ReasonCode ==
4614                MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED) {
4615                mptbase_sas_persist_operation(ioc,
4616                MPI_SAS_OP_CLEAR_NOT_PRESENT);
4617                mptsas_free_fw_event(ioc, fw_event);
4618                return;
4619        }
4620
4621        switch (sas_event_data->ReasonCode) {
4622        case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
4623        case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
4624                memset(&hot_plug_info, 0, sizeof(struct mptsas_hotplug_event));
4625                hot_plug_info.handle = le16_to_cpu(sas_event_data->DevHandle);
4626                hot_plug_info.channel = sas_event_data->Bus;
4627                hot_plug_info.id = sas_event_data->TargetID;
4628                hot_plug_info.phy_id = sas_event_data->PhyNum;
4629                memcpy(&sas_address, &sas_event_data->SASAddress,
4630                    sizeof(u64));
4631                hot_plug_info.sas_address = le64_to_cpu(sas_address);
4632                hot_plug_info.device_info = device_info;
4633                if (sas_event_data->ReasonCode &
4634                    MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
4635                        hot_plug_info.event_type = MPTSAS_ADD_DEVICE;
4636                else
4637                        hot_plug_info.event_type = MPTSAS_DEL_DEVICE;
4638                mptsas_hotplug_work(ioc, fw_event, &hot_plug_info);
4639                break;
4640
4641        case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
4642                mptbase_sas_persist_operation(ioc,
4643                    MPI_SAS_OP_CLEAR_NOT_PRESENT);
4644                mptsas_free_fw_event(ioc, fw_event);
4645                break;
4646
4647        case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
4648        /* TODO */
4649        case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
4650        /* TODO */
4651        default:
4652                mptsas_free_fw_event(ioc, fw_event);
4653                break;
4654        }
4655}
4656
4657static void
4658mptsas_send_raid_event(struct fw_event_work *fw_event)
4659{
4660        MPT_ADAPTER *ioc;
4661        EVENT_DATA_RAID *raid_event_data;
4662        struct mptsas_hotplug_event hot_plug_info;
4663        int status;
4664        int state;
4665        struct scsi_device *sdev = NULL;
4666        VirtDevice *vdevice = NULL;
4667        RaidPhysDiskPage0_t phys_disk;
4668
4669        ioc = fw_event->ioc;
4670        raid_event_data = (EVENT_DATA_RAID *)fw_event->event_data;
4671        status = le32_to_cpu(raid_event_data->SettingsStatus);
4672        state = (status >> 8) & 0xff;
4673
4674        memset(&hot_plug_info, 0, sizeof(struct mptsas_hotplug_event));
4675        hot_plug_info.id = raid_event_data->VolumeID;
4676        hot_plug_info.channel = raid_event_data->VolumeBus;
4677        hot_plug_info.phys_disk_num = raid_event_data->PhysDiskNum;
4678
4679        if (raid_event_data->ReasonCode == MPI_EVENT_RAID_RC_VOLUME_DELETED ||
4680            raid_event_data->ReasonCode == MPI_EVENT_RAID_RC_VOLUME_CREATED ||
4681            raid_event_data->ReasonCode ==
4682            MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED) {
4683                sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
4684                    hot_plug_info.id, 0);
4685                hot_plug_info.sdev = sdev;
4686                if (sdev)
4687                        vdevice = sdev->hostdata;
4688        }
4689
4690        devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Entering %s: "
4691            "ReasonCode=%02x\n", ioc->name, __func__,
4692            raid_event_data->ReasonCode));
4693
4694        switch (raid_event_data->ReasonCode) {
4695        case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
4696                hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK_REPROBE;
4697                break;
4698        case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
4699                hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK_REPROBE;
4700                break;
4701        case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
4702                switch (state) {
4703                case MPI_PD_STATE_ONLINE:
4704                case MPI_PD_STATE_NOT_COMPATIBLE:
4705                        mpt_raid_phys_disk_pg0(ioc,
4706                            raid_event_data->PhysDiskNum, &phys_disk);
4707                        hot_plug_info.id = phys_disk.PhysDiskID;
4708                        hot_plug_info.channel = phys_disk.PhysDiskBus;
4709                        hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK;
4710                        break;
4711                case MPI_PD_STATE_FAILED:
4712                case MPI_PD_STATE_MISSING:
4713                case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
4714                case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
4715                case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
4716                        hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK;
4717                        break;
4718                default:
4719                        break;
4720                }
4721                break;
4722        case MPI_EVENT_RAID_RC_VOLUME_DELETED:
4723                if (!sdev)
4724                        break;
4725                vdevice->vtarget->deleted = 1; /* block IO */
4726                hot_plug_info.event_type = MPTSAS_DEL_RAID;
4727                break;
4728        case MPI_EVENT_RAID_RC_VOLUME_CREATED:
4729                if (sdev) {
4730                        scsi_device_put(sdev);
4731                        break;
4732                }
4733                hot_plug_info.event_type = MPTSAS_ADD_RAID;
4734                break;
4735        case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
4736                if (!(status & MPI_RAIDVOL0_STATUS_FLAG_ENABLED)) {
4737                        if (!sdev)
4738                                break;
4739                        vdevice->vtarget->deleted = 1; /* block IO */
4740                        hot_plug_info.event_type = MPTSAS_DEL_RAID;
4741                        break;
4742                }
4743                switch (state) {
4744                case MPI_RAIDVOL0_STATUS_STATE_FAILED:
4745                case MPI_RAIDVOL0_STATUS_STATE_MISSING:
4746                        if (!sdev)
4747                                break;
4748                        vdevice->vtarget->deleted = 1; /* block IO */
4749                        hot_plug_info.event_type = MPTSAS_DEL_RAID;
4750                        break;
4751                case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
4752                case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
4753                        if (sdev) {
4754                                scsi_device_put(sdev);
4755                                break;
4756                        }
4757                        hot_plug_info.event_type = MPTSAS_ADD_RAID;
4758                        break;
4759                default:
4760                        break;
4761                }
4762                break;
4763        default:
4764                break;
4765        }
4766
4767        if (hot_plug_info.event_type != MPTSAS_IGNORE_EVENT)
4768                mptsas_hotplug_work(ioc, fw_event, &hot_plug_info);
4769        else
4770                mptsas_free_fw_event(ioc, fw_event);
4771}
4772
4773/**
4774 *      mptsas_issue_tm - send mptsas internal tm request
4775 *      @ioc: Pointer to MPT_ADAPTER structure
4776 *      @type: Task Management type
4777 *      @channel: channel number for task management
4778 *      @id: Logical Target ID for reset (if appropriate)
4779 *      @lun: Logical unit for reset (if appropriate)
4780 *      @task_context: Context for the task to be aborted
4781 *      @timeout: timeout for task management control
4782 *      @issue_reset: set to 1 on return if reset is needed, else 0
4783 *
4784 *      Return: 0 on success or -1 on failure.
4785 *
4786 */
4787static int
4788mptsas_issue_tm(MPT_ADAPTER *ioc, u8 type, u8 channel, u8 id, u64 lun,
4789        int task_context, ulong timeout, u8 *issue_reset)
4790{
4791        MPT_FRAME_HDR   *mf;
4792        SCSITaskMgmt_t  *pScsiTm;
4793        int              retval;
4794        unsigned long    timeleft;
4795
4796        *issue_reset = 0;
4797        mf = mpt_get_msg_frame(mptsasDeviceResetCtx, ioc);
4798        if (mf == NULL) {
4799                retval = -1; /* return failure */
4800                dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "TaskMgmt request: no "
4801                    "msg frames!!\n", ioc->name));
4802                goto out;
4803        }
4804
4805        dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request: mr = %p, "
4806            "task_type = 0x%02X,\n\t timeout = %ld, fw_channel = %d, "
4807            "fw_id = %d, lun = %lld,\n\t task_context = 0x%x\n", ioc->name, mf,
4808             type, timeout, channel, id, (unsigned long long)lun,
4809             task_context));
4810
4811        pScsiTm = (SCSITaskMgmt_t *) mf;
4812        memset(pScsiTm, 0, sizeof(SCSITaskMgmt_t));
4813        pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
4814        pScsiTm->TaskType = type;
4815        pScsiTm->MsgFlags = 0;
4816        pScsiTm->TargetID = id;
4817        pScsiTm->Bus = channel;
4818        pScsiTm->ChainOffset = 0;
4819        pScsiTm->Reserved = 0;
4820        pScsiTm->Reserved1 = 0;
4821        pScsiTm->TaskMsgContext = task_context;
4822        int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN);
4823
4824        INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status)
4825        CLEAR_MGMT_STATUS(ioc->internal_cmds.status)
4826        retval = 0;
4827        mpt_put_msg_frame_hi_pri(mptsasDeviceResetCtx, ioc, mf);
4828
4829        /* Now wait for the command to complete */
4830        timeleft = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done,
4831            timeout*HZ);
4832        if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
4833                retval = -1; /* return failure */
4834                dtmprintk(ioc, printk(MYIOC_s_ERR_FMT
4835                    "TaskMgmt request: TIMED OUT!(mr=%p)\n", ioc->name, mf));
4836                mpt_free_msg_frame(ioc, mf);
4837                if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
4838                        goto out;
4839                *issue_reset = 1;
4840                goto out;
4841        }
4842
4843        if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
4844                retval = -1; /* return failure */
4845                dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4846                    "TaskMgmt request: failed with no reply\n", ioc->name));
4847                goto out;
4848        }
4849
4850 out:
4851        CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status)
4852        return retval;
4853}
4854
4855/**
4856 *      mptsas_broadcast_primitive_work - Handle broadcast primitives
4857 *      @fw_event: work queue payload containing info describing the event
4858 *
4859 *      This will be handled in workqueue context.
4860 */
4861static void
4862mptsas_broadcast_primitive_work(struct fw_event_work *fw_event)
4863{
4864        MPT_ADAPTER *ioc = fw_event->ioc;
4865        MPT_FRAME_HDR   *mf;
4866        VirtDevice      *vdevice;
4867        int                     ii;
4868        struct scsi_cmnd        *sc;
4869        SCSITaskMgmtReply_t     *pScsiTmReply;
4870        u8                      issue_reset;
4871        int                     task_context;
4872        u8                      channel, id;
4873        int                      lun;
4874        u32                      termination_count;
4875        u32                      query_count;
4876
4877        dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4878            "%s - enter\n", ioc->name, __func__));
4879
4880        mutex_lock(&ioc->taskmgmt_cmds.mutex);
4881        if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) {
4882                mutex_unlock(&ioc->taskmgmt_cmds.mutex);
4883                mptsas_requeue_fw_event(ioc, fw_event, 1000);
4884                return;
4885        }
4886
4887        issue_reset = 0;
4888        termination_count = 0;
4889        query_count = 0;
4890        mpt_findImVolumes(ioc);
4891        pScsiTmReply = (SCSITaskMgmtReply_t *) ioc->taskmgmt_cmds.reply;
4892
4893        for (ii = 0; ii < ioc->req_depth; ii++) {
4894                if (ioc->fw_events_off)
4895                        goto out;
4896                sc = mptscsih_get_scsi_lookup(ioc, ii);
4897                if (!sc)
4898                        continue;
4899                mf = MPT_INDEX_2_MFPTR(ioc, ii);
4900                if (!mf)
4901                        continue;
4902                task_context = mf->u.frame.hwhdr.msgctxu.MsgContext;
4903                vdevice = sc->device->hostdata;
4904                if (!vdevice || !vdevice->vtarget)
4905                        continue;
4906                if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
4907                        continue; /* skip hidden raid components */
4908                if (vdevice->vtarget->raidVolume)
4909                        continue; /* skip hidden raid components */
4910                channel = vdevice->vtarget->channel;
4911                id = vdevice->vtarget->id;
4912                lun = vdevice->lun;
4913                if (mptsas_issue_tm(ioc, MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK,
4914                    channel, id, (u64)lun, task_context, 30, &issue_reset))
4915                        goto out;
4916                query_count++;
4917                termination_count +=
4918                    le32_to_cpu(pScsiTmReply->TerminationCount);
4919                if ((pScsiTmReply->IOCStatus == MPI_IOCSTATUS_SUCCESS) &&
4920                    (pScsiTmReply->ResponseCode ==
4921                    MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED ||
4922                    pScsiTmReply->ResponseCode ==
4923                    MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC))
4924                        continue;
4925                if (mptsas_issue_tm(ioc,
4926                    MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET,
4927                    channel, id, (u64)lun, 0, 30, &issue_reset))
4928                        goto out;
4929                termination_count +=
4930                    le32_to_cpu(pScsiTmReply->TerminationCount);
4931        }
4932
4933 out:
4934        dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4935            "%s - exit, query_count = %d termination_count = %d\n",
4936            ioc->name, __func__, query_count, termination_count));
4937
4938        ioc->broadcast_aen_busy = 0;
4939        mpt_clear_taskmgmt_in_progress_flag(ioc);
4940        mutex_unlock(&ioc->taskmgmt_cmds.mutex);
4941
4942        if (issue_reset) {
4943                printk(MYIOC_s_WARN_FMT
4944                       "Issuing Reset from %s!! doorbell=0x%08x\n",
4945                       ioc->name, __func__, mpt_GetIocState(ioc, 0));
4946                mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);
4947        }
4948        mptsas_free_fw_event(ioc, fw_event);
4949}
4950
4951/*
4952 * mptsas_send_ir2_event - handle exposing hidden disk when
4953 * an inactive raid volume is added
4954 *
4955 * @ioc: Pointer to MPT_ADAPTER structure
4956 * @ir2_data
4957 *
4958 */
4959static void
4960mptsas_send_ir2_event(struct fw_event_work *fw_event)
4961{
4962        MPT_ADAPTER     *ioc;
4963        struct mptsas_hotplug_event hot_plug_info;
4964        MPI_EVENT_DATA_IR2      *ir2_data;
4965        u8 reasonCode;
4966        RaidPhysDiskPage0_t phys_disk;
4967
4968        ioc = fw_event->ioc;
4969        ir2_data = (MPI_EVENT_DATA_IR2 *)fw_event->event_data;
4970        reasonCode = ir2_data->ReasonCode;
4971
4972        devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Entering %s: "
4973            "ReasonCode=%02x\n", ioc->name, __func__, reasonCode));
4974
4975        memset(&hot_plug_info, 0, sizeof(struct mptsas_hotplug_event));
4976        hot_plug_info.id = ir2_data->TargetID;
4977        hot_plug_info.channel = ir2_data->Bus;
4978        switch (reasonCode) {
4979        case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
4980                hot_plug_info.event_type = MPTSAS_ADD_INACTIVE_VOLUME;
4981                break;
4982        case MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED:
4983                hot_plug_info.phys_disk_num = ir2_data->PhysDiskNum;
4984                hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK;
4985                break;
4986        case MPI_EVENT_IR2_RC_DUAL_PORT_ADDED:
4987                hot_plug_info.phys_disk_num = ir2_data->PhysDiskNum;
4988                mpt_raid_phys_disk_pg0(ioc,
4989                    ir2_data->PhysDiskNum, &phys_disk);
4990                hot_plug_info.id = phys_disk.PhysDiskID;
4991                hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK;
4992                break;
4993        default:
4994                mptsas_free_fw_event(ioc, fw_event);
4995                return;
4996        }
4997        mptsas_hotplug_work(ioc, fw_event, &hot_plug_info);
4998}
4999
5000static int
5001mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
5002{
5003        u32 event = le32_to_cpu(reply->Event);
5004        int event_data_sz;
5005        struct fw_event_work *fw_event;
5006        unsigned long delay;
5007
5008        if (ioc->bus_type != SAS)
5009                return 0;
5010
5011        /* events turned off due to host reset or driver unloading */
5012        if (ioc->fw_events_off)
5013                return 0;
5014
5015        delay = msecs_to_jiffies(1);
5016        switch (event) {
5017        case MPI_EVENT_SAS_BROADCAST_PRIMITIVE:
5018        {
5019                EVENT_DATA_SAS_BROADCAST_PRIMITIVE *broadcast_event_data =
5020                    (EVENT_DATA_SAS_BROADCAST_PRIMITIVE *)reply->Data;
5021                if (broadcast_event_data->Primitive !=
5022                    MPI_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT)
5023                        return 0;
5024                if (ioc->broadcast_aen_busy)
5025                        return 0;
5026                ioc->broadcast_aen_busy = 1;
5027                break;
5028        }
5029        case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
5030        {
5031                EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data =
5032                    (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data;
5033                u16     ioc_stat;
5034                ioc_stat = le16_to_cpu(reply->IOCStatus);
5035
5036                if (sas_event_data->ReasonCode ==
5037                    MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING) {
5038                        mptsas_target_reset_queue(ioc, sas_event_data);
5039                        return 0;
5040                }
5041                if (sas_event_data->ReasonCode ==
5042                        MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET &&
5043                        ioc->device_missing_delay &&
5044                        (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)) {
5045                        VirtTarget *vtarget = NULL;
5046                        u8              id, channel;
5047
5048                        id = sas_event_data->TargetID;
5049                        channel = sas_event_data->Bus;
5050
5051                        vtarget = mptsas_find_vtarget(ioc, channel, id);
5052                        if (vtarget) {
5053                                devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5054                                    "LogInfo (0x%x) available for "
5055                                   "INTERNAL_DEVICE_RESET"
5056                                   "fw_id %d fw_channel %d\n", ioc->name,
5057                                   le32_to_cpu(reply->IOCLogInfo),
5058                                   id, channel));
5059                                if (vtarget->raidVolume) {
5060                                        devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5061                                        "Skipping Raid Volume for inDMD\n",
5062                                        ioc->name));
5063                                } else {
5064                                        devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5065                                        "Setting device flag inDMD\n",
5066                                        ioc->name));
5067                                        vtarget->inDMD = 1;
5068                                }
5069
5070                        }
5071
5072                }
5073
5074                break;
5075        }
5076        case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE:
5077        {
5078                MpiEventDataSasExpanderStatusChange_t *expander_data =
5079                    (MpiEventDataSasExpanderStatusChange_t *)reply->Data;
5080
5081                if (ioc->old_sas_discovery_protocal)
5082                        return 0;
5083
5084                if (expander_data->ReasonCode ==
5085                    MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING &&
5086                    ioc->device_missing_delay)
5087                        delay = HZ * ioc->device_missing_delay;
5088                break;
5089        }
5090        case MPI_EVENT_SAS_DISCOVERY:
5091        {
5092                u32 discovery_status;
5093                EventDataSasDiscovery_t *discovery_data =
5094                    (EventDataSasDiscovery_t *)reply->Data;
5095
5096                discovery_status = le32_to_cpu(discovery_data->DiscoveryStatus);
5097                ioc->sas_discovery_quiesce_io = discovery_status ? 1 : 0;
5098                if (ioc->old_sas_discovery_protocal && !discovery_status)
5099                        mptsas_queue_rescan(ioc);
5100                return 0;
5101        }
5102        case MPI_EVENT_INTEGRATED_RAID:
5103        case MPI_EVENT_PERSISTENT_TABLE_FULL:
5104        case MPI_EVENT_IR2:
5105        case MPI_EVENT_SAS_PHY_LINK_STATUS:
5106        case MPI_EVENT_QUEUE_FULL:
5107                break;
5108        default:
5109                return 0;
5110        }
5111
5112        event_data_sz = ((reply->MsgLength * 4) -
5113            offsetof(EventNotificationReply_t, Data));
5114        fw_event = kzalloc(sizeof(*fw_event) + event_data_sz, GFP_ATOMIC);
5115        if (!fw_event) {
5116                printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n", ioc->name,
5117                 __func__, __LINE__);
5118                return 0;
5119        }
5120        memcpy(fw_event->event_data, reply->Data, event_data_sz);
5121        fw_event->event = event;
5122        fw_event->ioc = ioc;
5123        mptsas_add_fw_event(ioc, fw_event, delay);
5124        return 0;
5125}
5126
5127/* Delete a volume when no longer listed in ioc pg2
5128 */
5129static void mptsas_volume_delete(MPT_ADAPTER *ioc, u8 id)
5130{
5131        struct scsi_device *sdev;
5132        int i;
5133
5134        sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL, id, 0);
5135        if (!sdev)
5136                return;
5137        if (!ioc->raid_data.pIocPg2)
5138                goto out;
5139        if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
5140                goto out;
5141        for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++)
5142                if (ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID == id)
5143                        goto release_sdev;
5144 out:
5145        printk(MYIOC_s_INFO_FMT "removing raid volume, channel %d, "
5146            "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL, id);
5147        scsi_remove_device(sdev);
5148 release_sdev:
5149        scsi_device_put(sdev);
5150}
5151
5152static int
5153mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
5154{
5155        struct Scsi_Host        *sh;
5156        MPT_SCSI_HOST           *hd;
5157        MPT_ADAPTER             *ioc;
5158        unsigned long            flags;
5159        int                      ii;
5160        int                      numSGE = 0;
5161        int                      scale;
5162        int                      ioc_cap;
5163        int                     error=0;
5164        int                     r;
5165
5166        r = mpt_attach(pdev,id);
5167        if (r)
5168                return r;
5169
5170        ioc = pci_get_drvdata(pdev);
5171        mptsas_fw_event_off(ioc);
5172        ioc->DoneCtx = mptsasDoneCtx;
5173        ioc->TaskCtx = mptsasTaskCtx;
5174        ioc->InternalCtx = mptsasInternalCtx;
5175        ioc->schedule_target_reset = &mptsas_schedule_target_reset;
5176        ioc->schedule_dead_ioc_flush_running_cmds =
5177                                &mptscsih_flush_running_cmds;
5178        /*  Added sanity check on readiness of the MPT adapter.
5179         */
5180        if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
5181                printk(MYIOC_s_WARN_FMT
5182                  "Skipping because it's not operational!\n",
5183                  ioc->name);
5184                error = -ENODEV;
5185                goto out_mptsas_probe;
5186        }
5187
5188        if (!ioc->active) {
5189                printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
5190                  ioc->name);
5191                error = -ENODEV;
5192                goto out_mptsas_probe;
5193        }
5194
5195        /*  Sanity check - ensure at least 1 port is INITIATOR capable
5196         */
5197        ioc_cap = 0;
5198        for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
5199                if (ioc->pfacts[ii].ProtocolFlags &
5200                                MPI_PORTFACTS_PROTOCOL_INITIATOR)
5201                        ioc_cap++;
5202        }
5203
5204        if (!ioc_cap) {
5205                printk(MYIOC_s_WARN_FMT
5206                        "Skipping ioc=%p because SCSI Initiator mode "
5207                        "is NOT enabled!\n", ioc->name, ioc);
5208                return 0;
5209        }
5210
5211        sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
5212        if (!sh) {
5213                printk(MYIOC_s_WARN_FMT
5214                        "Unable to register controller with SCSI subsystem\n",
5215                        ioc->name);
5216                error = -1;
5217                goto out_mptsas_probe;
5218        }
5219
5220        spin_lock_irqsave(&ioc->FreeQlock, flags);
5221
5222        /* Attach the SCSI Host to the IOC structure
5223         */
5224        ioc->sh = sh;
5225
5226        sh->io_port = 0;
5227        sh->n_io_port = 0;
5228        sh->irq = 0;
5229
5230        /* set 16 byte cdb's */
5231        sh->max_cmd_len = 16;
5232        sh->can_queue = min_t(int, ioc->req_depth - 10, sh->can_queue);
5233        sh->max_id = -1;
5234        sh->max_lun = max_lun;
5235        sh->transportt = mptsas_transport_template;
5236
5237        /* Required entry.
5238         */
5239        sh->unique_id = ioc->id;
5240
5241        INIT_LIST_HEAD(&ioc->sas_topology);
5242        mutex_init(&ioc->sas_topology_mutex);
5243        mutex_init(&ioc->sas_discovery_mutex);
5244        mutex_init(&ioc->sas_mgmt.mutex);
5245        init_completion(&ioc->sas_mgmt.done);
5246
5247        /* Verify that we won't exceed the maximum
5248         * number of chain buffers
5249         * We can optimize:  ZZ = req_sz/sizeof(SGE)
5250         * For 32bit SGE's:
5251         *  numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
5252         *               + (req_sz - 64)/sizeof(SGE)
5253         * A slightly different algorithm is required for
5254         * 64bit SGEs.
5255         */
5256        scale = ioc->req_sz/ioc->SGE_size;
5257        if (ioc->sg_addr_size == sizeof(u64)) {
5258                numSGE = (scale - 1) *
5259                  (ioc->facts.MaxChainDepth-1) + scale +
5260                  (ioc->req_sz - 60) / ioc->SGE_size;
5261        } else {
5262                numSGE = 1 + (scale - 1) *
5263                  (ioc->facts.MaxChainDepth-1) + scale +
5264                  (ioc->req_sz - 64) / ioc->SGE_size;
5265        }
5266
5267        if (numSGE < sh->sg_tablesize) {
5268                /* Reset this value */
5269                dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5270                  "Resetting sg_tablesize to %d from %d\n",
5271                  ioc->name, numSGE, sh->sg_tablesize));
5272                sh->sg_tablesize = numSGE;
5273        }
5274
5275        if (mpt_loadtime_max_sectors) {
5276                if (mpt_loadtime_max_sectors < 64 ||
5277                        mpt_loadtime_max_sectors > 8192) {
5278                        printk(MYIOC_s_INFO_FMT "Invalid value passed for"
5279                                "mpt_loadtime_max_sectors %d."
5280                                "Range from 64 to 8192\n", ioc->name,
5281                                mpt_loadtime_max_sectors);
5282                }
5283                mpt_loadtime_max_sectors &=  0xFFFFFFFE;
5284                dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5285                        "Resetting max sector to %d from %d\n",
5286                  ioc->name, mpt_loadtime_max_sectors, sh->max_sectors));
5287                sh->max_sectors = mpt_loadtime_max_sectors;
5288        }
5289
5290        hd = shost_priv(sh);
5291        hd->ioc = ioc;
5292
5293        /* SCSI needs scsi_cmnd lookup table!
5294         * (with size equal to req_depth*PtrSz!)
5295         */
5296        ioc->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
5297        if (!ioc->ScsiLookup) {
5298                error = -ENOMEM;
5299                spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5300                goto out_mptsas_probe;
5301        }
5302        spin_lock_init(&ioc->scsi_lookup_lock);
5303
5304        dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
5305                 ioc->name, ioc->ScsiLookup));
5306
5307        ioc->sas_data.ptClear = mpt_pt_clear;
5308
5309        hd->last_queue_full = 0;
5310        INIT_LIST_HEAD(&hd->target_reset_list);
5311        INIT_LIST_HEAD(&ioc->sas_device_info_list);
5312        mutex_init(&ioc->sas_device_info_mutex);
5313
5314        spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5315
5316        if (ioc->sas_data.ptClear==1) {
5317                mptbase_sas_persist_operation(
5318                    ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
5319        }
5320
5321        error = scsi_add_host(sh, &ioc->pcidev->dev);
5322        if (error) {
5323                dprintk(ioc, printk(MYIOC_s_ERR_FMT
5324                  "scsi_add_host failed\n", ioc->name));
5325                goto out_mptsas_probe;
5326        }
5327
5328        /* older firmware doesn't support expander events */
5329        if ((ioc->facts.HeaderVersion >> 8) < 0xE)
5330                ioc->old_sas_discovery_protocal = 1;
5331        mptsas_scan_sas_topology(ioc);
5332        mptsas_fw_event_on(ioc);
5333        return 0;
5334
5335 out_mptsas_probe:
5336
5337        mptscsih_remove(pdev);
5338        return error;
5339}
5340
5341static void
5342mptsas_shutdown(struct pci_dev *pdev)
5343{
5344        MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
5345
5346        mptsas_fw_event_off(ioc);
5347        mptsas_cleanup_fw_event_q(ioc);
5348}
5349
5350static void mptsas_remove(struct pci_dev *pdev)
5351{
5352        MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
5353        struct mptsas_portinfo *p, *n;
5354        int i;
5355
5356        if (!ioc->sh) {
5357                printk(MYIOC_s_INFO_FMT "IOC is in Target mode\n", ioc->name);
5358                mpt_detach(pdev);
5359                return;
5360        }
5361
5362        mptsas_shutdown(pdev);
5363
5364        mptsas_del_device_components(ioc);
5365
5366        ioc->sas_discovery_ignore_events = 1;
5367        sas_remove_host(ioc->sh);
5368
5369        mutex_lock(&ioc->sas_topology_mutex);
5370        list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
5371                list_del(&p->list);
5372                for (i = 0 ; i < p->num_phys ; i++)
5373                        mptsas_port_delete(ioc, p->phy_info[i].port_details);
5374
5375                kfree(p->phy_info);
5376                kfree(p);
5377        }
5378        mutex_unlock(&ioc->sas_topology_mutex);
5379        ioc->hba_port_info = NULL;
5380        mptscsih_remove(pdev);
5381}
5382
5383static struct pci_device_id mptsas_pci_table[] = {
5384        { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064,
5385                PCI_ANY_ID, PCI_ANY_ID },
5386        { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068,
5387                PCI_ANY_ID, PCI_ANY_ID },
5388        { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064E,
5389                PCI_ANY_ID, PCI_ANY_ID },
5390        { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068E,
5391                PCI_ANY_ID, PCI_ANY_ID },
5392        { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1078,
5393                PCI_ANY_ID, PCI_ANY_ID },
5394        { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068_820XELP,
5395                PCI_ANY_ID, PCI_ANY_ID },
5396        {0}     /* Terminating entry */
5397};
5398MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
5399
5400
5401static struct pci_driver mptsas_driver = {
5402        .name           = "mptsas",
5403        .id_table       = mptsas_pci_table,
5404        .probe          = mptsas_probe,
5405        .remove         = mptsas_remove,
5406        .shutdown       = mptsas_shutdown,
5407#ifdef CONFIG_PM
5408        .suspend        = mptscsih_suspend,
5409        .resume         = mptscsih_resume,
5410#endif
5411};
5412
5413static int __init
5414mptsas_init(void)
5415{
5416        int error;
5417
5418        show_mptmod_ver(my_NAME, my_VERSION);
5419
5420        mptsas_transport_template =
5421            sas_attach_transport(&mptsas_transport_functions);
5422        if (!mptsas_transport_template)
5423                return -ENODEV;
5424
5425        mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER,
5426            "mptscsih_io_done");
5427        mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER,
5428            "mptscsih_taskmgmt_complete");
5429        mptsasInternalCtx =
5430                mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER,
5431                    "mptscsih_scandv_complete");
5432        mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER,
5433            "mptsas_mgmt_done");
5434        mptsasDeviceResetCtx =
5435                mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER,
5436                    "mptsas_taskmgmt_complete");
5437
5438        mpt_event_register(mptsasDoneCtx, mptsas_event_process);
5439        mpt_reset_register(mptsasDoneCtx, mptsas_ioc_reset);
5440
5441        error = pci_register_driver(&mptsas_driver);
5442        if (error)
5443                sas_release_transport(mptsas_transport_template);
5444
5445        return error;
5446}
5447
5448static void __exit
5449mptsas_exit(void)
5450{
5451        pci_unregister_driver(&mptsas_driver);
5452        sas_release_transport(mptsas_transport_template);
5453
5454        mpt_reset_deregister(mptsasDoneCtx);
5455        mpt_event_deregister(mptsasDoneCtx);
5456
5457        mpt_deregister(mptsasMgmtCtx);
5458        mpt_deregister(mptsasInternalCtx);
5459        mpt_deregister(mptsasTaskCtx);
5460        mpt_deregister(mptsasDoneCtx);
5461        mpt_deregister(mptsasDeviceResetCtx);
5462}
5463
5464module_init(mptsas_init);
5465module_exit(mptsas_exit);
5466