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