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