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_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
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                done(SCpnt);
1908                return 0;
1909        }
1910
1911        hd = shost_priv(SCpnt->device->host);
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,done);
1921}
1922
1923static DEF_SCSI_QCMD(mptsas_qcmd)
1924
1925/**
1926 *      mptsas_mptsas_eh_timed_out - resets the scsi_cmnd timeout
1927 *              if the device under question is currently in the
1928 *              device removal delay.
1929 *      @sc: scsi command that the midlayer is about to time out
1930 *
1931 **/
1932static enum blk_eh_timer_return mptsas_eh_timed_out(struct scsi_cmnd *sc)
1933{
1934        MPT_SCSI_HOST *hd;
1935        MPT_ADAPTER   *ioc;
1936        VirtDevice    *vdevice;
1937        enum blk_eh_timer_return rc = BLK_EH_NOT_HANDLED;
1938
1939        hd = shost_priv(sc->device->host);
1940        if (hd == NULL) {
1941                printk(KERN_ERR MYNAM ": %s: Can't locate host! (sc=%p)\n",
1942                    __func__, sc);
1943                goto done;
1944        }
1945
1946        ioc = hd->ioc;
1947        if (ioc->bus_type != SAS) {
1948                printk(KERN_ERR MYNAM ": %s: Wrong bus type (sc=%p)\n",
1949                    __func__, sc);
1950                goto done;
1951        }
1952
1953        /* In case if IOC is in reset from internal context.
1954        *  Do not execute EEH for the same IOC. SML should to reset timer.
1955        */
1956        if (ioc->ioc_reset_in_progress) {
1957                dtmprintk(ioc, printk(MYIOC_s_WARN_FMT ": %s: ioc is in reset,"
1958                    "SML need to reset the timer (sc=%p)\n",
1959                    ioc->name, __func__, sc));
1960                rc = BLK_EH_RESET_TIMER;
1961        }
1962        vdevice = sc->device->hostdata;
1963        if (vdevice && vdevice->vtarget && (vdevice->vtarget->inDMD
1964                || vdevice->vtarget->deleted)) {
1965                dtmprintk(ioc, printk(MYIOC_s_WARN_FMT ": %s: target removed "
1966                    "or in device removal delay (sc=%p)\n",
1967                    ioc->name, __func__, sc));
1968                rc = BLK_EH_RESET_TIMER;
1969                goto done;
1970        }
1971
1972done:
1973        return rc;
1974}
1975
1976
1977static struct scsi_host_template mptsas_driver_template = {
1978        .module                         = THIS_MODULE,
1979        .proc_name                      = "mptsas",
1980        .proc_info                      = mptscsih_proc_info,
1981        .name                           = "MPT SAS Host",
1982        .info                           = mptscsih_info,
1983        .queuecommand                   = mptsas_qcmd,
1984        .target_alloc                   = mptsas_target_alloc,
1985        .slave_alloc                    = mptsas_slave_alloc,
1986        .slave_configure                = mptsas_slave_configure,
1987        .target_destroy                 = mptsas_target_destroy,
1988        .slave_destroy                  = mptscsih_slave_destroy,
1989        .change_queue_depth             = mptscsih_change_queue_depth,
1990        .eh_abort_handler               = mptscsih_abort,
1991        .eh_device_reset_handler        = mptscsih_dev_reset,
1992        .eh_host_reset_handler          = mptscsih_host_reset,
1993        .bios_param                     = mptscsih_bios_param,
1994        .can_queue                      = MPT_SAS_CAN_QUEUE,
1995        .this_id                        = -1,
1996        .sg_tablesize                   = MPT_SCSI_SG_DEPTH,
1997        .max_sectors                    = 8192,
1998        .cmd_per_lun                    = 7,
1999        .use_clustering                 = ENABLE_CLUSTERING,
2000        .shost_attrs                    = mptscsih_host_attrs,
2001};
2002
2003static int mptsas_get_linkerrors(struct sas_phy *phy)
2004{
2005        MPT_ADAPTER *ioc = phy_to_ioc(phy);
2006        ConfigExtendedPageHeader_t hdr;
2007        CONFIGPARMS cfg;
2008        SasPhyPage1_t *buffer;
2009        dma_addr_t dma_handle;
2010        int error;
2011
2012        /* FIXME: only have link errors on local phys */
2013        if (!scsi_is_sas_phy_local(phy))
2014                return -EINVAL;
2015
2016        hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
2017        hdr.ExtPageLength = 0;
2018        hdr.PageNumber = 1 /* page number 1*/;
2019        hdr.Reserved1 = 0;
2020        hdr.Reserved2 = 0;
2021        hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2022        hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
2023
2024        cfg.cfghdr.ehdr = &hdr;
2025        cfg.physAddr = -1;
2026        cfg.pageAddr = phy->identify.phy_identifier;
2027        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2028        cfg.dir = 0;    /* read */
2029        cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
2030
2031        error = mpt_config(ioc, &cfg);
2032        if (error)
2033                return error;
2034        if (!hdr.ExtPageLength)
2035                return -ENXIO;
2036
2037        buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2038                                      &dma_handle);
2039        if (!buffer)
2040                return -ENOMEM;
2041
2042        cfg.physAddr = dma_handle;
2043        cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2044
2045        error = mpt_config(ioc, &cfg);
2046        if (error)
2047                goto out_free_consistent;
2048
2049        mptsas_print_phy_pg1(ioc, buffer);
2050
2051        phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);
2052        phy->running_disparity_error_count =
2053                le32_to_cpu(buffer->RunningDisparityErrorCount);
2054        phy->loss_of_dword_sync_count =
2055                le32_to_cpu(buffer->LossDwordSynchCount);
2056        phy->phy_reset_problem_count =
2057                le32_to_cpu(buffer->PhyResetProblemCount);
2058
2059 out_free_consistent:
2060        pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2061                            buffer, dma_handle);
2062        return error;
2063}
2064
2065static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
2066                MPT_FRAME_HDR *reply)
2067{
2068        ioc->sas_mgmt.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
2069        if (reply != NULL) {
2070                ioc->sas_mgmt.status |= MPT_MGMT_STATUS_RF_VALID;
2071                memcpy(ioc->sas_mgmt.reply, reply,
2072                    min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
2073        }
2074
2075        if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_PENDING) {
2076                ioc->sas_mgmt.status &= ~MPT_MGMT_STATUS_PENDING;
2077                complete(&ioc->sas_mgmt.done);
2078                return 1;
2079        }
2080        return 0;
2081}
2082
2083static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
2084{
2085        MPT_ADAPTER *ioc = phy_to_ioc(phy);
2086        SasIoUnitControlRequest_t *req;
2087        SasIoUnitControlReply_t *reply;
2088        MPT_FRAME_HDR *mf;
2089        MPIHeader_t *hdr;
2090        unsigned long timeleft;
2091        int error = -ERESTARTSYS;
2092
2093        /* FIXME: fusion doesn't allow non-local phy reset */
2094        if (!scsi_is_sas_phy_local(phy))
2095                return -EINVAL;
2096
2097        /* not implemented for expanders */
2098        if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
2099                return -ENXIO;
2100
2101        if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
2102                goto out;
2103
2104        mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
2105        if (!mf) {
2106                error = -ENOMEM;
2107                goto out_unlock;
2108        }
2109
2110        hdr = (MPIHeader_t *) mf;
2111        req = (SasIoUnitControlRequest_t *)mf;
2112        memset(req, 0, sizeof(SasIoUnitControlRequest_t));
2113        req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
2114        req->MsgContext = hdr->MsgContext;
2115        req->Operation = hard_reset ?
2116                MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
2117        req->PhyNum = phy->identify.phy_identifier;
2118
2119        INITIALIZE_MGMT_STATUS(ioc->sas_mgmt.status)
2120        mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
2121
2122        timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
2123                        10 * HZ);
2124        if (!(ioc->sas_mgmt.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
2125                error = -ETIME;
2126                mpt_free_msg_frame(ioc, mf);
2127                if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_DID_IOCRESET)
2128                        goto out_unlock;
2129                if (!timeleft)
2130                        mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);
2131                goto out_unlock;
2132        }
2133
2134        /* a reply frame is expected */
2135        if ((ioc->sas_mgmt.status &
2136            MPT_MGMT_STATUS_RF_VALID) == 0) {
2137                error = -ENXIO;
2138                goto out_unlock;
2139        }
2140
2141        /* process the completed Reply Message Frame */
2142        reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
2143        if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
2144                printk(MYIOC_s_INFO_FMT "%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
2145                    ioc->name, __func__, reply->IOCStatus, reply->IOCLogInfo);
2146                error = -ENXIO;
2147                goto out_unlock;
2148        }
2149
2150        error = 0;
2151
2152 out_unlock:
2153        CLEAR_MGMT_STATUS(ioc->sas_mgmt.status)
2154        mutex_unlock(&ioc->sas_mgmt.mutex);
2155 out:
2156        return error;
2157}
2158
2159static int
2160mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
2161{
2162        MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
2163        int i, error;
2164        struct mptsas_portinfo *p;
2165        struct mptsas_enclosure enclosure_info;
2166        u64 enclosure_handle;
2167
2168        mutex_lock(&ioc->sas_topology_mutex);
2169        list_for_each_entry(p, &ioc->sas_topology, list) {
2170                for (i = 0; i < p->num_phys; i++) {
2171                        if (p->phy_info[i].attached.sas_address ==
2172                            rphy->identify.sas_address) {
2173                                enclosure_handle = p->phy_info[i].
2174                                        attached.handle_enclosure;
2175                                goto found_info;
2176                        }
2177                }
2178        }
2179        mutex_unlock(&ioc->sas_topology_mutex);
2180        return -ENXIO;
2181
2182 found_info:
2183        mutex_unlock(&ioc->sas_topology_mutex);
2184        memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
2185        error = mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
2186                        (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
2187                         MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle);
2188        if (!error)
2189                *identifier = enclosure_info.enclosure_logical_id;
2190        return error;
2191}
2192
2193static int
2194mptsas_get_bay_identifier(struct sas_rphy *rphy)
2195{
2196        MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
2197        struct mptsas_portinfo *p;
2198        int i, rc;
2199
2200        mutex_lock(&ioc->sas_topology_mutex);
2201        list_for_each_entry(p, &ioc->sas_topology, list) {
2202                for (i = 0; i < p->num_phys; i++) {
2203                        if (p->phy_info[i].attached.sas_address ==
2204                            rphy->identify.sas_address) {
2205                                rc = p->phy_info[i].attached.slot;
2206                                goto out;
2207                        }
2208                }
2209        }
2210        rc = -ENXIO;
2211 out:
2212        mutex_unlock(&ioc->sas_topology_mutex);
2213        return rc;
2214}
2215
2216static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
2217                              struct request *req)
2218{
2219        MPT_ADAPTER *ioc = ((MPT_SCSI_HOST *) shost->hostdata)->ioc;
2220        MPT_FRAME_HDR *mf;
2221        SmpPassthroughRequest_t *smpreq;
2222        struct request *rsp = req->next_rq;
2223        int ret;
2224        int flagsLength;
2225        unsigned long timeleft;
2226        char *psge;
2227        dma_addr_t dma_addr_in = 0;
2228        dma_addr_t dma_addr_out = 0;
2229        u64 sas_address = 0;
2230
2231        if (!rsp) {
2232                printk(MYIOC_s_ERR_FMT "%s: the smp response space is missing\n",
2233                    ioc->name, __func__);
2234                return -EINVAL;
2235        }
2236
2237        /* do we need to support multiple segments? */
2238        if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
2239                printk(MYIOC_s_ERR_FMT "%s: multiple segments req %u %u, rsp %u %u\n",
2240                    ioc->name, __func__, req->bio->bi_vcnt, blk_rq_bytes(req),
2241                    rsp->bio->bi_vcnt, blk_rq_bytes(rsp));
2242                return -EINVAL;
2243        }
2244
2245        ret = mutex_lock_interruptible(&ioc->sas_mgmt.mutex);
2246        if (ret)
2247                goto out;
2248
2249        mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
2250        if (!mf) {
2251                ret = -ENOMEM;
2252                goto out_unlock;
2253        }
2254
2255        smpreq = (SmpPassthroughRequest_t *)mf;
2256        memset(smpreq, 0, sizeof(*smpreq));
2257
2258        smpreq->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4);
2259        smpreq->Function = MPI_FUNCTION_SMP_PASSTHROUGH;
2260
2261        if (rphy)
2262                sas_address = rphy->identify.sas_address;
2263        else {
2264                struct mptsas_portinfo *port_info;
2265
2266                mutex_lock(&ioc->sas_topology_mutex);
2267                port_info = ioc->hba_port_info;
2268                if (port_info && port_info->phy_info)
2269                        sas_address =
2270                                port_info->phy_info[0].phy->identify.sas_address;
2271                mutex_unlock(&ioc->sas_topology_mutex);
2272        }
2273
2274        *((u64 *)&smpreq->SASAddress) = cpu_to_le64(sas_address);
2275
2276        psge = (char *)
2277                (((int *) mf) + (offsetof(SmpPassthroughRequest_t, SGL) / 4));
2278
2279        /* request */
2280        flagsLength = (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
2281                       MPI_SGE_FLAGS_END_OF_BUFFER |
2282                       MPI_SGE_FLAGS_DIRECTION)
2283                       << MPI_SGE_FLAGS_SHIFT;
2284        flagsLength |= (blk_rq_bytes(req) - 4);
2285
2286        dma_addr_out = pci_map_single(ioc->pcidev, bio_data(req->bio),
2287                                      blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL);
2288        if (!dma_addr_out)
2289                goto put_mf;
2290        ioc->add_sge(psge, flagsLength, dma_addr_out);
2291        psge += ioc->SGE_size;
2292
2293        /* response */
2294        flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
2295                MPI_SGE_FLAGS_SYSTEM_ADDRESS |
2296                MPI_SGE_FLAGS_IOC_TO_HOST |
2297                MPI_SGE_FLAGS_END_OF_BUFFER;
2298
2299        flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
2300        flagsLength |= blk_rq_bytes(rsp) + 4;
2301        dma_addr_in =  pci_map_single(ioc->pcidev, bio_data(rsp->bio),
2302                                      blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL);
2303        if (!dma_addr_in)
2304                goto unmap;
2305        ioc->add_sge(psge, flagsLength, dma_addr_in);
2306
2307        INITIALIZE_MGMT_STATUS(ioc->sas_mgmt.status)
2308        mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
2309
2310        timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ);
2311        if (!(ioc->sas_mgmt.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
2312                ret = -ETIME;
2313                mpt_free_msg_frame(ioc, mf);
2314                mf = NULL;
2315                if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_DID_IOCRESET)
2316                        goto unmap;
2317                if (!timeleft)
2318                        mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);
2319                goto unmap;
2320        }
2321        mf = NULL;
2322
2323        if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_RF_VALID) {
2324                SmpPassthroughReply_t *smprep;
2325
2326                smprep = (SmpPassthroughReply_t *)ioc->sas_mgmt.reply;
2327                memcpy(req->sense, smprep, sizeof(*smprep));
2328                req->sense_len = sizeof(*smprep);
2329                req->resid_len = 0;
2330                rsp->resid_len -= smprep->ResponseDataLength;
2331        } else {
2332                printk(MYIOC_s_ERR_FMT
2333                    "%s: smp passthru reply failed to be returned\n",
2334                    ioc->name, __func__);
2335                ret = -ENXIO;
2336        }
2337unmap:
2338        if (dma_addr_out)
2339                pci_unmap_single(ioc->pcidev, dma_addr_out, blk_rq_bytes(req),
2340                                 PCI_DMA_BIDIRECTIONAL);
2341        if (dma_addr_in)
2342                pci_unmap_single(ioc->pcidev, dma_addr_in, blk_rq_bytes(rsp),
2343                                 PCI_DMA_BIDIRECTIONAL);
2344put_mf:
2345        if (mf)
2346                mpt_free_msg_frame(ioc, mf);
2347out_unlock:
2348        CLEAR_MGMT_STATUS(ioc->sas_mgmt.status)
2349        mutex_unlock(&ioc->sas_mgmt.mutex);
2350out:
2351        return ret;
2352}
2353
2354static struct sas_function_template mptsas_transport_functions = {
2355        .get_linkerrors         = mptsas_get_linkerrors,
2356        .get_enclosure_identifier = mptsas_get_enclosure_identifier,
2357        .get_bay_identifier     = mptsas_get_bay_identifier,
2358        .phy_reset              = mptsas_phy_reset,
2359        .smp_handler            = mptsas_smp_handler,
2360};
2361
2362static struct scsi_transport_template *mptsas_transport_template;
2363
2364static int
2365mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
2366{
2367        ConfigExtendedPageHeader_t hdr;
2368        CONFIGPARMS cfg;
2369        SasIOUnitPage0_t *buffer;
2370        dma_addr_t dma_handle;
2371        int error, i;
2372
2373        hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
2374        hdr.ExtPageLength = 0;
2375        hdr.PageNumber = 0;
2376        hdr.Reserved1 = 0;
2377        hdr.Reserved2 = 0;
2378        hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2379        hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
2380
2381        cfg.cfghdr.ehdr = &hdr;
2382        cfg.physAddr = -1;
2383        cfg.pageAddr = 0;
2384        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2385        cfg.dir = 0;    /* read */
2386        cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
2387
2388        error = mpt_config(ioc, &cfg);
2389        if (error)
2390                goto out;
2391        if (!hdr.ExtPageLength) {
2392                error = -ENXIO;
2393                goto out;
2394        }
2395
2396        buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2397                                            &dma_handle);
2398        if (!buffer) {
2399                error = -ENOMEM;
2400                goto out;
2401        }
2402
2403        cfg.physAddr = dma_handle;
2404        cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2405
2406        error = mpt_config(ioc, &cfg);
2407        if (error)
2408                goto out_free_consistent;
2409
2410        port_info->num_phys = buffer->NumPhys;
2411        port_info->phy_info = kcalloc(port_info->num_phys,
2412                sizeof(struct mptsas_phyinfo), GFP_KERNEL);
2413        if (!port_info->phy_info) {
2414                error = -ENOMEM;
2415                goto out_free_consistent;
2416        }
2417
2418        ioc->nvdata_version_persistent =
2419            le16_to_cpu(buffer->NvdataVersionPersistent);
2420        ioc->nvdata_version_default =
2421            le16_to_cpu(buffer->NvdataVersionDefault);
2422
2423        for (i = 0; i < port_info->num_phys; i++) {
2424                mptsas_print_phy_data(ioc, &buffer->PhyData[i]);
2425                port_info->phy_info[i].phy_id = i;
2426                port_info->phy_info[i].port_id =
2427                    buffer->PhyData[i].Port;
2428                port_info->phy_info[i].negotiated_link_rate =
2429                    buffer->PhyData[i].NegotiatedLinkRate;
2430                port_info->phy_info[i].portinfo = port_info;
2431                port_info->phy_info[i].handle =
2432                    le16_to_cpu(buffer->PhyData[i].ControllerDevHandle);
2433        }
2434
2435 out_free_consistent:
2436        pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2437                            buffer, dma_handle);
2438 out:
2439        return error;
2440}
2441
2442static int
2443mptsas_sas_io_unit_pg1(MPT_ADAPTER *ioc)
2444{
2445        ConfigExtendedPageHeader_t hdr;
2446        CONFIGPARMS cfg;
2447        SasIOUnitPage1_t *buffer;
2448        dma_addr_t dma_handle;
2449        int error;
2450        u8 device_missing_delay;
2451
2452        memset(&hdr, 0, sizeof(ConfigExtendedPageHeader_t));
2453        memset(&cfg, 0, sizeof(CONFIGPARMS));
2454
2455        cfg.cfghdr.ehdr = &hdr;
2456        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2457        cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
2458        cfg.cfghdr.ehdr->PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2459        cfg.cfghdr.ehdr->ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
2460        cfg.cfghdr.ehdr->PageVersion = MPI_SASIOUNITPAGE1_PAGEVERSION;
2461        cfg.cfghdr.ehdr->PageNumber = 1;
2462
2463        error = mpt_config(ioc, &cfg);
2464        if (error)
2465                goto out;
2466        if (!hdr.ExtPageLength) {
2467                error = -ENXIO;
2468                goto out;
2469        }
2470
2471        buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2472                                            &dma_handle);
2473        if (!buffer) {
2474                error = -ENOMEM;
2475                goto out;
2476        }
2477
2478        cfg.physAddr = dma_handle;
2479        cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2480
2481        error = mpt_config(ioc, &cfg);
2482        if (error)
2483                goto out_free_consistent;
2484
2485        ioc->io_missing_delay  =
2486            le16_to_cpu(buffer->IODeviceMissingDelay);
2487        device_missing_delay = buffer->ReportDeviceMissingDelay;
2488        ioc->device_missing_delay = (device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_UNIT_16) ?
2489            (device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16 :
2490            device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
2491
2492 out_free_consistent:
2493        pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2494                            buffer, dma_handle);
2495 out:
2496        return error;
2497}
2498
2499static int
2500mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
2501                u32 form, u32 form_specific)
2502{
2503        ConfigExtendedPageHeader_t hdr;
2504        CONFIGPARMS cfg;
2505        SasPhyPage0_t *buffer;
2506        dma_addr_t dma_handle;
2507        int error;
2508
2509        hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
2510        hdr.ExtPageLength = 0;
2511        hdr.PageNumber = 0;
2512        hdr.Reserved1 = 0;
2513        hdr.Reserved2 = 0;
2514        hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2515        hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
2516
2517        cfg.cfghdr.ehdr = &hdr;
2518        cfg.dir = 0;    /* read */
2519        cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
2520
2521        /* Get Phy Pg 0 for each Phy. */
2522        cfg.physAddr = -1;
2523        cfg.pageAddr = form + form_specific;
2524        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2525
2526        error = mpt_config(ioc, &cfg);
2527        if (error)
2528                goto out;
2529
2530        if (!hdr.ExtPageLength) {
2531                error = -ENXIO;
2532                goto out;
2533        }
2534
2535        buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2536                                      &dma_handle);
2537        if (!buffer) {
2538                error = -ENOMEM;
2539                goto out;
2540        }
2541
2542        cfg.physAddr = dma_handle;
2543        cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2544
2545        error = mpt_config(ioc, &cfg);
2546        if (error)
2547                goto out_free_consistent;
2548
2549        mptsas_print_phy_pg0(ioc, buffer);
2550
2551        phy_info->hw_link_rate = buffer->HwLinkRate;
2552        phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
2553        phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
2554        phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
2555
2556 out_free_consistent:
2557        pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2558                            buffer, dma_handle);
2559 out:
2560        return error;
2561}
2562
2563static int
2564mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
2565                u32 form, u32 form_specific)
2566{
2567        ConfigExtendedPageHeader_t hdr;
2568        CONFIGPARMS cfg;
2569        SasDevicePage0_t *buffer;
2570        dma_addr_t dma_handle;
2571        __le64 sas_address;
2572        int error=0;
2573
2574        hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
2575        hdr.ExtPageLength = 0;
2576        hdr.PageNumber = 0;
2577        hdr.Reserved1 = 0;
2578        hdr.Reserved2 = 0;
2579        hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2580        hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
2581
2582        cfg.cfghdr.ehdr = &hdr;
2583        cfg.pageAddr = form + form_specific;
2584        cfg.physAddr = -1;
2585        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2586        cfg.dir = 0;    /* read */
2587        cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
2588
2589        memset(device_info, 0, sizeof(struct mptsas_devinfo));
2590        error = mpt_config(ioc, &cfg);
2591        if (error)
2592                goto out;
2593        if (!hdr.ExtPageLength) {
2594                error = -ENXIO;
2595                goto out;
2596        }
2597
2598        buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2599                                      &dma_handle);
2600        if (!buffer) {
2601                error = -ENOMEM;
2602                goto out;
2603        }
2604
2605        cfg.physAddr = dma_handle;
2606        cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2607
2608        error = mpt_config(ioc, &cfg);
2609
2610        if (error == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
2611                error = -ENODEV;
2612                goto out_free_consistent;
2613        }
2614
2615        if (error)
2616                goto out_free_consistent;
2617
2618        mptsas_print_device_pg0(ioc, buffer);
2619
2620        memset(device_info, 0, sizeof(struct mptsas_devinfo));
2621        device_info->handle = le16_to_cpu(buffer->DevHandle);
2622        device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
2623        device_info->handle_enclosure =
2624            le16_to_cpu(buffer->EnclosureHandle);
2625        device_info->slot = le16_to_cpu(buffer->Slot);
2626        device_info->phy_id = buffer->PhyNum;
2627        device_info->port_id = buffer->PhysicalPort;
2628        device_info->id = buffer->TargetID;
2629        device_info->phys_disk_num = ~0;
2630        device_info->channel = buffer->Bus;
2631        memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
2632        device_info->sas_address = le64_to_cpu(sas_address);
2633        device_info->device_info =
2634            le32_to_cpu(buffer->DeviceInfo);
2635        device_info->flags = le16_to_cpu(buffer->Flags);
2636
2637 out_free_consistent:
2638        pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2639                            buffer, dma_handle);
2640 out:
2641        return error;
2642}
2643
2644static int
2645mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
2646                u32 form, u32 form_specific)
2647{
2648        ConfigExtendedPageHeader_t hdr;
2649        CONFIGPARMS cfg;
2650        SasExpanderPage0_t *buffer;
2651        dma_addr_t dma_handle;
2652        int i, error;
2653        __le64 sas_address;
2654
2655        memset(port_info, 0, sizeof(struct mptsas_portinfo));
2656        hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
2657        hdr.ExtPageLength = 0;
2658        hdr.PageNumber = 0;
2659        hdr.Reserved1 = 0;
2660        hdr.Reserved2 = 0;
2661        hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2662        hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
2663
2664        cfg.cfghdr.ehdr = &hdr;
2665        cfg.physAddr = -1;
2666        cfg.pageAddr = form + form_specific;
2667        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2668        cfg.dir = 0;    /* read */
2669        cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
2670
2671        memset(port_info, 0, sizeof(struct mptsas_portinfo));
2672        error = mpt_config(ioc, &cfg);
2673        if (error)
2674                goto out;
2675
2676        if (!hdr.ExtPageLength) {
2677                error = -ENXIO;
2678                goto out;
2679        }
2680
2681        buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2682                                      &dma_handle);
2683        if (!buffer) {
2684                error = -ENOMEM;
2685                goto out;
2686        }
2687
2688        cfg.physAddr = dma_handle;
2689        cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2690
2691        error = mpt_config(ioc, &cfg);
2692        if (error == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
2693                error = -ENODEV;
2694                goto out_free_consistent;
2695        }
2696
2697        if (error)
2698                goto out_free_consistent;
2699
2700        /* save config data */
2701        port_info->num_phys = (buffer->NumPhys) ? buffer->NumPhys : 1;
2702        port_info->phy_info = kcalloc(port_info->num_phys,
2703                sizeof(struct mptsas_phyinfo), GFP_KERNEL);
2704        if (!port_info->phy_info) {
2705                error = -ENOMEM;
2706                goto out_free_consistent;
2707        }
2708
2709        memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
2710        for (i = 0; i < port_info->num_phys; i++) {
2711                port_info->phy_info[i].portinfo = port_info;
2712                port_info->phy_info[i].handle =
2713                    le16_to_cpu(buffer->DevHandle);
2714                port_info->phy_info[i].identify.sas_address =
2715                    le64_to_cpu(sas_address);
2716                port_info->phy_info[i].identify.handle_parent =
2717                    le16_to_cpu(buffer->ParentDevHandle);
2718        }
2719
2720 out_free_consistent:
2721        pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2722                            buffer, dma_handle);
2723 out:
2724        return error;
2725}
2726
2727static int
2728mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
2729                u32 form, u32 form_specific)
2730{
2731        ConfigExtendedPageHeader_t hdr;
2732        CONFIGPARMS cfg;
2733        SasExpanderPage1_t *buffer;
2734        dma_addr_t dma_handle;
2735        int error=0;
2736
2737        hdr.PageVersion = MPI_SASEXPANDER1_PAGEVERSION;
2738        hdr.ExtPageLength = 0;
2739        hdr.PageNumber = 1;
2740        hdr.Reserved1 = 0;
2741        hdr.Reserved2 = 0;
2742        hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2743        hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
2744
2745        cfg.cfghdr.ehdr = &hdr;
2746        cfg.physAddr = -1;
2747        cfg.pageAddr = form + form_specific;
2748        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2749        cfg.dir = 0;    /* read */
2750        cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
2751
2752        error = mpt_config(ioc, &cfg);
2753        if (error)
2754                goto out;
2755
2756        if (!hdr.ExtPageLength) {
2757                error = -ENXIO;
2758                goto out;
2759        }
2760
2761        buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2762                                      &dma_handle);
2763        if (!buffer) {
2764                error = -ENOMEM;
2765                goto out;
2766        }
2767
2768        cfg.physAddr = dma_handle;
2769        cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2770
2771        error = mpt_config(ioc, &cfg);
2772
2773        if (error == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
2774                error = -ENODEV;
2775                goto out_free_consistent;
2776        }
2777
2778        if (error)
2779                goto out_free_consistent;
2780
2781
2782        mptsas_print_expander_pg1(ioc, buffer);
2783
2784        /* save config data */
2785        phy_info->phy_id = buffer->PhyIdentifier;
2786        phy_info->port_id = buffer->PhysicalPort;
2787        phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
2788        phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
2789        phy_info->hw_link_rate = buffer->HwLinkRate;
2790        phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
2791        phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
2792
2793 out_free_consistent:
2794        pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2795                            buffer, dma_handle);
2796 out:
2797        return error;
2798}
2799
2800struct rep_manu_request{
2801        u8 smp_frame_type;
2802        u8 function;
2803        u8 reserved;
2804        u8 request_length;
2805};
2806
2807struct rep_manu_reply{
2808        u8 smp_frame_type; /* 0x41 */
2809        u8 function; /* 0x01 */
2810        u8 function_result;
2811        u8 response_length;
2812        u16 expander_change_count;
2813        u8 reserved0[2];
2814        u8 sas_format:1;
2815        u8 reserved1:7;
2816        u8 reserved2[3];
2817        u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN];
2818        u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN];
2819        u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN];
2820        u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN];
2821        u16 component_id;
2822        u8 component_revision_id;
2823        u8 reserved3;
2824        u8 vendor_specific[8];
2825};
2826
2827/**
2828  * mptsas_exp_repmanufacture_info -
2829  * @ioc: per adapter object
2830  * @sas_address: expander sas address
2831  * @edev: the sas_expander_device object
2832  *
2833  * Fills in the sas_expander_device object when SMP port is created.
2834  *
2835  * Returns 0 for success, non-zero for failure.
2836  */
2837static int
2838mptsas_exp_repmanufacture_info(MPT_ADAPTER *ioc,
2839        u64 sas_address, struct sas_expander_device *edev)
2840{
2841        MPT_FRAME_HDR *mf;
2842        SmpPassthroughRequest_t *smpreq;
2843        SmpPassthroughReply_t *smprep;
2844        struct rep_manu_reply *manufacture_reply;
2845        struct rep_manu_request *manufacture_request;
2846        int ret;
2847        int flagsLength;
2848        unsigned long timeleft;
2849        char *psge;
2850        unsigned long flags;
2851        void *data_out = NULL;
2852        dma_addr_t data_out_dma = 0;
2853        u32 sz;
2854
2855        spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
2856        if (ioc->ioc_reset_in_progress) {
2857                spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
2858                printk(MYIOC_s_INFO_FMT "%s: host reset in progress!\n",
2859                        __func__, ioc->name);
2860                return -EFAULT;
2861        }
2862        spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
2863
2864        ret = mutex_lock_interruptible(&ioc->sas_mgmt.mutex);
2865        if (ret)
2866                goto out;
2867
2868        mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
2869        if (!mf) {
2870                ret = -ENOMEM;
2871                goto out_unlock;
2872        }
2873
2874        smpreq = (SmpPassthroughRequest_t *)mf;
2875        memset(smpreq, 0, sizeof(*smpreq));
2876
2877        sz = sizeof(struct rep_manu_request) + sizeof(struct rep_manu_reply);
2878
2879        data_out = pci_alloc_consistent(ioc->pcidev, sz, &data_out_dma);
2880        if (!data_out) {
2881                printk(KERN_ERR "Memory allocation failure at %s:%d/%s()!\n",
2882                        __FILE__, __LINE__, __func__);
2883                ret = -ENOMEM;
2884                goto put_mf;
2885        }
2886
2887        manufacture_request = data_out;
2888        manufacture_request->smp_frame_type = 0x40;
2889        manufacture_request->function = 1;
2890        manufacture_request->reserved = 0;
2891        manufacture_request->request_length = 0;
2892
2893        smpreq->Function = MPI_FUNCTION_SMP_PASSTHROUGH;
2894        smpreq->PhysicalPort = 0xFF;
2895        *((u64 *)&smpreq->SASAddress) = cpu_to_le64(sas_address);
2896        smpreq->RequestDataLength = sizeof(struct rep_manu_request);
2897
2898        psge = (char *)
2899                (((int *) mf) + (offsetof(SmpPassthroughRequest_t, SGL) / 4));
2900
2901        flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
2902                MPI_SGE_FLAGS_SYSTEM_ADDRESS |
2903                MPI_SGE_FLAGS_HOST_TO_IOC |
2904                MPI_SGE_FLAGS_END_OF_BUFFER;
2905        flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
2906        flagsLength |= sizeof(struct rep_manu_request);
2907
2908        ioc->add_sge(psge, flagsLength, data_out_dma);
2909        psge += ioc->SGE_size;
2910
2911        flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
2912                MPI_SGE_FLAGS_SYSTEM_ADDRESS |
2913                MPI_SGE_FLAGS_IOC_TO_HOST |
2914                MPI_SGE_FLAGS_END_OF_BUFFER;
2915        flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
2916        flagsLength |= sizeof(struct rep_manu_reply);
2917        ioc->add_sge(psge, flagsLength, data_out_dma +
2918        sizeof(struct rep_manu_request));
2919
2920        INITIALIZE_MGMT_STATUS(ioc->sas_mgmt.status)
2921        mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
2922
2923        timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ);
2924        if (!(ioc->sas_mgmt.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
2925                ret = -ETIME;
2926                mpt_free_msg_frame(ioc, mf);
2927                mf = NULL;
2928                if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_DID_IOCRESET)
2929                        goto out_free;
2930                if (!timeleft)
2931                        mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);
2932                goto out_free;
2933        }
2934
2935        mf = NULL;
2936
2937        if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_RF_VALID) {
2938                u8 *tmp;
2939
2940        smprep = (SmpPassthroughReply_t *)ioc->sas_mgmt.reply;
2941        if (le16_to_cpu(smprep->ResponseDataLength) !=
2942                sizeof(struct rep_manu_reply))
2943                        goto out_free;
2944
2945        manufacture_reply = data_out + sizeof(struct rep_manu_request);
2946        strncpy(edev->vendor_id, manufacture_reply->vendor_id,
2947                SAS_EXPANDER_VENDOR_ID_LEN);
2948        strncpy(edev->product_id, manufacture_reply->product_id,
2949                SAS_EXPANDER_PRODUCT_ID_LEN);
2950        strncpy(edev->product_rev, manufacture_reply->product_rev,
2951                SAS_EXPANDER_PRODUCT_REV_LEN);
2952        edev->level = manufacture_reply->sas_format;
2953        if (manufacture_reply->sas_format) {
2954                strncpy(edev->component_vendor_id,
2955                        manufacture_reply->component_vendor_id,
2956                                SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN);
2957                tmp = (u8 *)&manufacture_reply->component_id;
2958                edev->component_id = tmp[0] << 8 | tmp[1];
2959                edev->component_revision_id =
2960                        manufacture_reply->component_revision_id;
2961                }
2962        } else {
2963                printk(MYIOC_s_ERR_FMT
2964                        "%s: smp passthru reply failed to be returned\n",
2965                        ioc->name, __func__);
2966                ret = -ENXIO;
2967        }
2968out_free:
2969        if (data_out_dma)
2970                pci_free_consistent(ioc->pcidev, sz, data_out, data_out_dma);
2971put_mf:
2972        if (mf)
2973                mpt_free_msg_frame(ioc, mf);
2974out_unlock:
2975        CLEAR_MGMT_STATUS(ioc->sas_mgmt.status)
2976        mutex_unlock(&ioc->sas_mgmt.mutex);
2977out:
2978        return ret;
2979 }
2980
2981static void
2982mptsas_parse_device_info(struct sas_identify *identify,
2983                struct mptsas_devinfo *device_info)
2984{
2985        u16 protocols;
2986
2987        identify->sas_address = device_info->sas_address;
2988        identify->phy_identifier = device_info->phy_id;
2989
2990        /*
2991         * Fill in Phy Initiator Port Protocol.
2992         * Bits 6:3, more than one bit can be set, fall through cases.
2993         */
2994        protocols = device_info->device_info & 0x78;
2995        identify->initiator_port_protocols = 0;
2996        if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
2997                identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
2998        if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
2999                identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
3000        if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
3001                identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
3002        if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
3003                identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
3004
3005        /*
3006         * Fill in Phy Target Port Protocol.
3007         * Bits 10:7, more than one bit can be set, fall through cases.
3008         */
3009        protocols = device_info->device_info & 0x780;
3010        identify->target_port_protocols = 0;
3011        if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
3012                identify->target_port_protocols |= SAS_PROTOCOL_SSP;
3013        if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
3014                identify->target_port_protocols |= SAS_PROTOCOL_STP;
3015        if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
3016                identify->target_port_protocols |= SAS_PROTOCOL_SMP;
3017        if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
3018                identify->target_port_protocols |= SAS_PROTOCOL_SATA;
3019
3020        /*
3021         * Fill in Attached device type.
3022         */
3023        switch (device_info->device_info &
3024                        MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
3025        case MPI_SAS_DEVICE_INFO_NO_DEVICE:
3026                identify->device_type = SAS_PHY_UNUSED;
3027                break;
3028        case MPI_SAS_DEVICE_INFO_END_DEVICE:
3029                identify->device_type = SAS_END_DEVICE;
3030                break;
3031        case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
3032                identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
3033                break;
3034        case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
3035                identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
3036                break;
3037        }
3038}
3039
3040static int mptsas_probe_one_phy(struct device *dev,
3041                struct mptsas_phyinfo *phy_info, int index, int local)
3042{
3043        MPT_ADAPTER *ioc;
3044        struct sas_phy *phy;
3045        struct sas_port *port;
3046        int error = 0;
3047        VirtTarget *vtarget;
3048
3049        if (!dev) {
3050                error = -ENODEV;
3051                goto out;
3052        }
3053
3054        if (!phy_info->phy) {
3055                phy = sas_phy_alloc(dev, index);
3056                if (!phy) {
3057                        error = -ENOMEM;
3058                        goto out;
3059                }
3060        } else
3061                phy = phy_info->phy;
3062
3063        mptsas_parse_device_info(&phy->identify, &phy_info->identify);
3064
3065        /*
3066         * Set Negotiated link rate.
3067         */
3068        switch (phy_info->negotiated_link_rate) {
3069        case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
3070                phy->negotiated_linkrate = SAS_PHY_DISABLED;
3071                break;
3072        case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
3073                phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
3074                break;
3075        case MPI_SAS_IOUNIT0_RATE_1_5:
3076                phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
3077                break;
3078        case MPI_SAS_IOUNIT0_RATE_3_0:
3079                phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
3080                break;
3081        case MPI_SAS_IOUNIT0_RATE_6_0:
3082                phy->negotiated_linkrate = SAS_LINK_RATE_6_0_GBPS;
3083                break;
3084        case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
3085        case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
3086        default:
3087                phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
3088                break;
3089        }
3090
3091        /*
3092         * Set Max hardware link rate.
3093         */
3094        switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
3095        case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
3096                phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
3097                break;
3098        case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
3099                phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
3100                break;
3101        default:
3102                break;
3103        }
3104
3105        /*
3106         * Set Max programmed link rate.
3107         */
3108        switch (phy_info->programmed_link_rate &
3109                        MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
3110        case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
3111                phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
3112                break;
3113        case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
3114                phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
3115                break;
3116        default:
3117                break;
3118        }
3119
3120        /*
3121         * Set Min hardware link rate.
3122         */
3123        switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
3124        case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
3125                phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
3126                break;
3127        case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
3128                phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
3129                break;
3130        default:
3131                break;
3132        }
3133
3134        /*
3135         * Set Min programmed link rate.
3136         */
3137        switch (phy_info->programmed_link_rate &
3138                        MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
3139        case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
3140                phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
3141                break;
3142        case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
3143                phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
3144                break;
3145        default:
3146                break;
3147        }
3148
3149        if (!phy_info->phy) {
3150
3151                error = sas_phy_add(phy);
3152                if (error) {
3153                        sas_phy_free(phy);
3154                        goto out;
3155                }
3156                phy_info->phy = phy;
3157        }
3158
3159        if (!phy_info->attached.handle ||
3160                        !phy_info->port_details)
3161                goto out;
3162
3163        port = mptsas_get_port(phy_info);
3164        ioc = phy_to_ioc(phy_info->phy);
3165
3166        if (phy_info->sas_port_add_phy) {
3167
3168                if (!port) {
3169                        port = sas_port_alloc_num(dev);
3170                        if (!port) {
3171                                error = -ENOMEM;
3172                                goto out;
3173                        }
3174                        error = sas_port_add(port);
3175                        if (error) {
3176                                dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3177                                        "%s: exit at line=%d\n", ioc->name,
3178                                        __func__, __LINE__));
3179                                goto out;
3180                        }
3181                        mptsas_set_port(ioc, phy_info, port);
3182                        devtprintk(ioc, dev_printk(KERN_DEBUG, &port->dev,
3183                            MYIOC_s_FMT "add port %d, sas_addr (0x%llx)\n",
3184                            ioc->name, port->port_identifier,
3185                            (unsigned long long)phy_info->
3186                            attached.sas_address));
3187                }
3188                dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3189                        "sas_port_add_phy: phy_id=%d\n",
3190                        ioc->name, phy_info->phy_id));
3191                sas_port_add_phy(port, phy_info->phy);
3192                phy_info->sas_port_add_phy = 0;
3193                devtprintk(ioc, dev_printk(KERN_DEBUG, &phy_info->phy->dev,
3194                    MYIOC_s_FMT "add phy %d, phy-obj (0x%p)\n", ioc->name,
3195                     phy_info->phy_id, phy_info->phy));
3196        }
3197        if (!mptsas_get_rphy(phy_info) && port && !port->rphy) {
3198
3199                struct sas_rphy *rphy;
3200                struct device *parent;
3201                struct sas_identify identify;
3202
3203                parent = dev->parent->parent;
3204                /*
3205                 * Let the hotplug_work thread handle processing
3206                 * the adding/removing of devices that occur
3207                 * after start of day.
3208                 */
3209                if (mptsas_is_end_device(&phy_info->attached) &&
3210                    phy_info->attached.handle_parent) {
3211                        goto out;
3212                }
3213
3214                mptsas_parse_device_info(&identify, &phy_info->attached);
3215                if (scsi_is_host_device(parent)) {
3216                        struct mptsas_portinfo *port_info;
3217                        int i;
3218
3219                        port_info = ioc->hba_port_info;
3220
3221                        for (i = 0; i < port_info->num_phys; i++)
3222                                if (port_info->phy_info[i].identify.sas_address ==
3223                                    identify.sas_address) {
3224                                        sas_port_mark_backlink(port);
3225                                        goto out;
3226                                }
3227
3228                } else if (scsi_is_sas_rphy(parent)) {
3229                        struct sas_rphy *parent_rphy = dev_to_rphy(parent);
3230                        if (identify.sas_address ==
3231                            parent_rphy->identify.sas_address) {
3232                                sas_port_mark_backlink(port);
3233                                goto out;
3234                        }
3235                }
3236
3237                switch (identify.device_type) {
3238                case SAS_END_DEVICE:
3239                        rphy = sas_end_device_alloc(port);
3240                        break;
3241                case SAS_EDGE_EXPANDER_DEVICE:
3242                case SAS_FANOUT_EXPANDER_DEVICE:
3243                        rphy = sas_expander_alloc(port, identify.device_type);
3244                        break;
3245                default:
3246                        rphy = NULL;
3247                        break;
3248                }
3249                if (!rphy) {
3250                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3251                                "%s: exit at line=%d\n", ioc->name,
3252                                __func__, __LINE__));
3253                        goto out;
3254                }
3255
3256                rphy->identify = identify;
3257                error = sas_rphy_add(rphy);
3258                if (error) {
3259                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3260                                "%s: exit at line=%d\n", ioc->name,
3261                                __func__, __LINE__));
3262                        sas_rphy_free(rphy);
3263                        goto out;
3264                }
3265                mptsas_set_rphy(ioc, phy_info, rphy);
3266                if (identify.device_type == SAS_EDGE_EXPANDER_DEVICE ||
3267                        identify.device_type == SAS_FANOUT_EXPANDER_DEVICE)
3268                                mptsas_exp_repmanufacture_info(ioc,
3269                                        identify.sas_address,
3270                                        rphy_to_expander_device(rphy));
3271        }
3272
3273        /* If the device exists,verify it wasn't previously flagged
3274        as a missing device.  If so, clear it */
3275        vtarget = mptsas_find_vtarget(ioc,
3276            phy_info->attached.channel,
3277            phy_info->attached.id);
3278        if (vtarget && vtarget->inDMD) {
3279                printk(KERN_INFO "Device returned, unsetting inDMD\n");
3280                vtarget->inDMD = 0;
3281        }
3282
3283 out:
3284        return error;
3285}
3286
3287static int
3288mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
3289{
3290        struct mptsas_portinfo *port_info, *hba;
3291        int error = -ENOMEM, i;
3292
3293        hba = kzalloc(sizeof(struct mptsas_portinfo), GFP_KERNEL);
3294        if (! hba)
3295                goto out;
3296
3297        error = mptsas_sas_io_unit_pg0(ioc, hba);
3298        if (error)
3299                goto out_free_port_info;
3300
3301        mptsas_sas_io_unit_pg1(ioc);
3302        mutex_lock(&ioc->sas_topology_mutex);
3303        port_info = ioc->hba_port_info;
3304        if (!port_info) {
3305                ioc->hba_port_info = port_info = hba;
3306                ioc->hba_port_num_phy = port_info->num_phys;
3307                list_add_tail(&port_info->list, &ioc->sas_topology);
3308        } else {
3309                for (i = 0; i < hba->num_phys; i++) {
3310                        port_info->phy_info[i].negotiated_link_rate =
3311                                hba->phy_info[i].negotiated_link_rate;
3312                        port_info->phy_info[i].handle =
3313                                hba->phy_info[i].handle;
3314                        port_info->phy_info[i].port_id =
3315                                hba->phy_info[i].port_id;
3316                }
3317                kfree(hba->phy_info);
3318                kfree(hba);
3319                hba = NULL;
3320        }
3321        mutex_unlock(&ioc->sas_topology_mutex);
3322#if defined(CPQ_CIM)
3323        ioc->num_ports = port_info->num_phys;
3324#endif
3325        for (i = 0; i < port_info->num_phys; i++) {
3326                mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
3327                        (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
3328                         MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
3329                port_info->phy_info[i].identify.handle =
3330                    port_info->phy_info[i].handle;
3331                mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
3332                        (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
3333                         MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3334                         port_info->phy_info[i].identify.handle);
3335                if (!ioc->hba_port_sas_addr)
3336                        ioc->hba_port_sas_addr =
3337                            port_info->phy_info[i].identify.sas_address;
3338                port_info->phy_info[i].identify.phy_id =
3339                    port_info->phy_info[i].phy_id = i;
3340                if (port_info->phy_info[i].attached.handle)
3341                        mptsas_sas_device_pg0(ioc,
3342                                &port_info->phy_info[i].attached,
3343                                (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
3344                                 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3345                                port_info->phy_info[i].attached.handle);
3346        }
3347
3348        mptsas_setup_wide_ports(ioc, port_info);
3349
3350        for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
3351                mptsas_probe_one_phy(&ioc->sh->shost_gendev,
3352                    &port_info->phy_info[i], ioc->sas_index, 1);
3353
3354        return 0;
3355
3356 out_free_port_info:
3357        kfree(hba);
3358 out:
3359        return error;
3360}
3361
3362static void
3363mptsas_expander_refresh(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
3364{
3365        struct mptsas_portinfo *parent;
3366        struct device *parent_dev;
3367        struct sas_rphy *rphy;
3368        int             i;
3369        u64             sas_address; /* expander sas address */
3370        u32             handle;
3371
3372        handle = port_info->phy_info[0].handle;
3373        sas_address = port_info->phy_info[0].identify.sas_address;
3374        for (i = 0; i < port_info->num_phys; i++) {
3375                mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
3376                    (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
3377                    MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + handle);
3378
3379                mptsas_sas_device_pg0(ioc,
3380                    &port_info->phy_info[i].identify,
3381                    (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
3382                    MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3383                    port_info->phy_info[i].identify.handle);
3384                port_info->phy_info[i].identify.phy_id =
3385                    port_info->phy_info[i].phy_id;
3386
3387                if (port_info->phy_info[i].attached.handle) {
3388                        mptsas_sas_device_pg0(ioc,
3389                            &port_info->phy_info[i].attached,
3390                            (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
3391                             MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3392                            port_info->phy_info[i].attached.handle);
3393                        port_info->phy_info[i].attached.phy_id =
3394                            port_info->phy_info[i].phy_id;
3395                }
3396        }
3397
3398        mutex_lock(&ioc->sas_topology_mutex);
3399        parent = mptsas_find_portinfo_by_handle(ioc,
3400            port_info->phy_info[0].identify.handle_parent);
3401        if (!parent) {
3402                mutex_unlock(&ioc->sas_topology_mutex);
3403                return;
3404        }
3405        for (i = 0, parent_dev = NULL; i < parent->num_phys && !parent_dev;
3406            i++) {
3407                if (parent->phy_info[i].attached.sas_address == sas_address) {
3408                        rphy = mptsas_get_rphy(&parent->phy_info[i]);
3409                        parent_dev = &rphy->dev;
3410                }
3411        }
3412        mutex_unlock(&ioc->sas_topology_mutex);
3413
3414        mptsas_setup_wide_ports(ioc, port_info);
3415        for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
3416                mptsas_probe_one_phy(parent_dev, &port_info->phy_info[i],
3417                    ioc->sas_index, 0);
3418}
3419
3420static void
3421mptsas_expander_event_add(MPT_ADAPTER *ioc,
3422    MpiEventDataSasExpanderStatusChange_t *expander_data)
3423{
3424        struct mptsas_portinfo *port_info;
3425        int i;
3426        __le64 sas_address;
3427
3428        port_info = kzalloc(sizeof(struct mptsas_portinfo), GFP_KERNEL);
3429        if (!port_info)
3430                BUG();
3431        port_info->num_phys = (expander_data->NumPhys) ?
3432            expander_data->NumPhys : 1;
3433        port_info->phy_info = kcalloc(port_info->num_phys,
3434            sizeof(struct mptsas_phyinfo), GFP_KERNEL);
3435        if (!port_info->phy_info)
3436                BUG();
3437        memcpy(&sas_address, &expander_data->SASAddress, sizeof(__le64));
3438        for (i = 0; i < port_info->num_phys; i++) {
3439                port_info->phy_info[i].portinfo = port_info;
3440                port_info->phy_info[i].handle =
3441                    le16_to_cpu(expander_data->DevHandle);
3442                port_info->phy_info[i].identify.sas_address =
3443                    le64_to_cpu(sas_address);
3444                port_info->phy_info[i].identify.handle_parent =
3445                    le16_to_cpu(expander_data->ParentDevHandle);
3446        }
3447
3448        mutex_lock(&ioc->sas_topology_mutex);
3449        list_add_tail(&port_info->list, &ioc->sas_topology);
3450        mutex_unlock(&ioc->sas_topology_mutex);
3451
3452        printk(MYIOC_s_INFO_FMT "add expander: num_phys %d, "
3453            "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
3454            (unsigned long long)sas_address);
3455
3456        mptsas_expander_refresh(ioc, port_info);
3457}
3458
3459/**
3460 * mptsas_delete_expander_siblings - remove siblings attached to expander
3461 * @ioc: Pointer to MPT_ADAPTER structure
3462 * @parent: the parent port_info object
3463 * @expander: the expander port_info object
3464 **/
3465static void
3466mptsas_delete_expander_siblings(MPT_ADAPTER *ioc, struct mptsas_portinfo
3467    *parent, struct mptsas_portinfo *expander)
3468{
3469        struct mptsas_phyinfo *phy_info;
3470        struct mptsas_portinfo *port_info;
3471        struct sas_rphy *rphy;
3472        int i;
3473
3474        phy_info = expander->phy_info;
3475        for (i = 0; i < expander->num_phys; i++, phy_info++) {
3476                rphy = mptsas_get_rphy(phy_info);
3477                if (!rphy)
3478                        continue;
3479                if (rphy->identify.device_type == SAS_END_DEVICE)
3480                        mptsas_del_end_device(ioc, phy_info);
3481        }
3482
3483        phy_info = expander->phy_info;
3484        for (i = 0; i < expander->num_phys; i++, phy_info++) {
3485                rphy = mptsas_get_rphy(phy_info);
3486                if (!rphy)
3487                        continue;
3488                if (rphy->identify.device_type ==
3489                    MPI_SAS_DEVICE_INFO_EDGE_EXPANDER ||
3490                    rphy->identify.device_type ==
3491                    MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER) {
3492                        port_info = mptsas_find_portinfo_by_sas_address(ioc,
3493                            rphy->identify.sas_address);
3494                        if (!port_info)
3495                                continue;
3496                        if (port_info == parent) /* backlink rphy */
3497                                continue;
3498                        /*
3499                        Delete this expander even if the expdevpage is exists
3500                        because the parent expander is already deleted
3501                        */
3502                        mptsas_expander_delete(ioc, port_info, 1);
3503                }
3504        }
3505}
3506
3507
3508/**
3509 *      mptsas_expander_delete - remove this expander
3510 *      @ioc: Pointer to MPT_ADAPTER structure
3511 *      @port_info: expander port_info struct
3512 *      @force: Flag to forcefully delete the expander
3513 *
3514 **/
3515
3516static void mptsas_expander_delete(MPT_ADAPTER *ioc,
3517                struct mptsas_portinfo *port_info, u8 force)
3518{
3519
3520        struct mptsas_portinfo *parent;
3521        int             i;
3522        u64             expander_sas_address;
3523        struct mptsas_phyinfo *phy_info;
3524        struct mptsas_portinfo buffer;
3525        struct mptsas_portinfo_details *port_details;
3526        struct sas_port *port;
3527
3528        if (!port_info)
3529                return;
3530
3531        /* see if expander is still there before deleting */
3532        mptsas_sas_expander_pg0(ioc, &buffer,
3533            (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
3534            MPI_SAS_EXPAND_PGAD_FORM_SHIFT),
3535            port_info->phy_info[0].identify.handle);
3536
3537        if (buffer.num_phys) {
3538                kfree(buffer.phy_info);
3539                if (!force)
3540                        return;
3541        }
3542
3543
3544        /*
3545         * Obtain the port_info instance to the parent port
3546         */
3547        port_details = NULL;
3548        expander_sas_address =
3549            port_info->phy_info[0].identify.sas_address;
3550        parent = mptsas_find_portinfo_by_handle(ioc,
3551            port_info->phy_info[0].identify.handle_parent);
3552        mptsas_delete_expander_siblings(ioc, parent, port_info);
3553        if (!parent)
3554                goto out;
3555
3556        /*
3557         * Delete rphys in the parent that point
3558         * to this expander.
3559         */
3560        phy_info = parent->phy_info;
3561        port = NULL;
3562        for (i = 0; i < parent->num_phys; i++, phy_info++) {
3563                if (!phy_info->phy)
3564                        continue;
3565                if (phy_info->attached.sas_address !=
3566                    expander_sas_address)
3567                        continue;
3568                if (!port) {
3569                        port = mptsas_get_port(phy_info);
3570                        port_details = phy_info->port_details;
3571                }
3572                dev_printk(KERN_DEBUG, &phy_info->phy->dev,
3573                    MYIOC_s_FMT "delete phy %d, phy-obj (0x%p)\n", ioc->name,
3574                    phy_info->phy_id, phy_info->phy);
3575                sas_port_delete_phy(port, phy_info->phy);
3576        }
3577        if (port) {
3578                dev_printk(KERN_DEBUG, &port->dev,
3579                    MYIOC_s_FMT "delete port %d, sas_addr (0x%llx)\n",
3580                    ioc->name, port->port_identifier,
3581                    (unsigned long long)expander_sas_address);
3582                sas_port_delete(port);
3583                mptsas_port_delete(ioc, port_details);
3584        }
3585 out:
3586
3587        printk(MYIOC_s_INFO_FMT "delete expander: num_phys %d, "
3588            "sas_addr (0x%llx)\n",  ioc->name, port_info->num_phys,
3589            (unsigned long long)expander_sas_address);
3590
3591        /*
3592         * free link
3593         */
3594        list_del(&port_info->list);
3595        kfree(port_info->phy_info);
3596        kfree(port_info);
3597}
3598
3599
3600/**
3601 * mptsas_send_expander_event - expanders events
3602 * @ioc: Pointer to MPT_ADAPTER structure
3603 * @expander_data: event data
3604 *
3605 *
3606 * This function handles adding, removing, and refreshing
3607 * device handles within the expander objects.
3608 */
3609static void
3610mptsas_send_expander_event(struct fw_event_work *fw_event)
3611{
3612        MPT_ADAPTER *ioc;
3613        MpiEventDataSasExpanderStatusChange_t *expander_data;
3614        struct mptsas_portinfo *port_info;
3615        __le64 sas_address;
3616        int i;
3617
3618        ioc = fw_event->ioc;
3619        expander_data = (MpiEventDataSasExpanderStatusChange_t *)
3620            fw_event->event_data;
3621        memcpy(&sas_address, &expander_data->SASAddress, sizeof(__le64));
3622        sas_address = le64_to_cpu(sas_address);
3623        port_info = mptsas_find_portinfo_by_sas_address(ioc, sas_address);
3624
3625        if (expander_data->ReasonCode == MPI_EVENT_SAS_EXP_RC_ADDED) {
3626                if (port_info) {
3627                        for (i = 0; i < port_info->num_phys; i++) {
3628                                port_info->phy_info[i].portinfo = port_info;
3629                                port_info->phy_info[i].handle =
3630                                    le16_to_cpu(expander_data->DevHandle);
3631                                port_info->phy_info[i].identify.sas_address =
3632                                    le64_to_cpu(sas_address);
3633                                port_info->phy_info[i].identify.handle_parent =
3634                                    le16_to_cpu(expander_data->ParentDevHandle);
3635                        }
3636                        mptsas_expander_refresh(ioc, port_info);
3637                } else if (!port_info && expander_data->NumPhys)
3638                        mptsas_expander_event_add(ioc, expander_data);
3639        } else if (expander_data->ReasonCode ==
3640            MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING)
3641                mptsas_expander_delete(ioc, port_info, 0);
3642
3643        mptsas_free_fw_event(ioc, fw_event);
3644}
3645
3646
3647/**
3648 * mptsas_expander_add -
3649 * @ioc: Pointer to MPT_ADAPTER structure
3650 * @handle:
3651 *
3652 */
3653struct mptsas_portinfo *
3654mptsas_expander_add(MPT_ADAPTER *ioc, u16 handle)
3655{
3656        struct mptsas_portinfo buffer, *port_info;
3657        int i;
3658
3659        if ((mptsas_sas_expander_pg0(ioc, &buffer,
3660            (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
3661            MPI_SAS_EXPAND_PGAD_FORM_SHIFT), handle)))
3662                return NULL;
3663
3664        port_info = kzalloc(sizeof(struct mptsas_portinfo), GFP_ATOMIC);
3665        if (!port_info) {
3666                dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3667                "%s: exit at line=%d\n", ioc->name,
3668                __func__, __LINE__));
3669                return NULL;
3670        }
3671        port_info->num_phys = buffer.num_phys;
3672        port_info->phy_info = buffer.phy_info;
3673        for (i = 0; i < port_info->num_phys; i++)
3674                port_info->phy_info[i].portinfo = port_info;
3675        mutex_lock(&ioc->sas_topology_mutex);
3676        list_add_tail(&port_info->list, &ioc->sas_topology);
3677        mutex_unlock(&ioc->sas_topology_mutex);
3678        printk(MYIOC_s_INFO_FMT "add expander: num_phys %d, "
3679            "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
3680            (unsigned long long)buffer.phy_info[0].identify.sas_address);
3681        mptsas_expander_refresh(ioc, port_info);
3682        return port_info;
3683}
3684
3685static void
3686mptsas_send_link_status_event(struct fw_event_work *fw_event)
3687{
3688        MPT_ADAPTER *ioc;
3689        MpiEventDataSasPhyLinkStatus_t *link_data;
3690        struct mptsas_portinfo *port_info;
3691        struct mptsas_phyinfo *phy_info = NULL;
3692        __le64 sas_address;
3693        u8 phy_num;
3694        u8 link_rate;
3695
3696        ioc = fw_event->ioc;
3697        link_data = (MpiEventDataSasPhyLinkStatus_t *)fw_event->event_data;
3698
3699        memcpy(&sas_address, &link_data->SASAddress, sizeof(__le64));
3700        sas_address = le64_to_cpu(sas_address);
3701        link_rate = link_data->LinkRates >> 4;
3702        phy_num = link_data->PhyNum;
3703
3704        port_info = mptsas_find_portinfo_by_sas_address(ioc, sas_address);
3705        if (port_info) {
3706                phy_info = &port_info->phy_info[phy_num];
3707                if (phy_info)
3708                        phy_info->negotiated_link_rate = link_rate;
3709        }
3710
3711        if (link_rate == MPI_SAS_IOUNIT0_RATE_1_5 ||
3712            link_rate == MPI_SAS_IOUNIT0_RATE_3_0 ||
3713            link_rate == MPI_SAS_IOUNIT0_RATE_6_0) {
3714
3715                if (!port_info) {
3716                        if (ioc->old_sas_discovery_protocal) {
3717                                port_info = mptsas_expander_add(ioc,
3718                                        le16_to_cpu(link_data->DevHandle));
3719                                if (port_info)
3720                                        goto out;
3721                        }
3722                        goto out;
3723                }
3724
3725                if (port_info == ioc->hba_port_info)
3726                        mptsas_probe_hba_phys(ioc);
3727                else
3728                        mptsas_expander_refresh(ioc, port_info);
3729        } else if (phy_info && phy_info->phy) {
3730                if (link_rate ==  MPI_SAS_IOUNIT0_RATE_PHY_DISABLED)
3731                        phy_info->phy->negotiated_linkrate =
3732                            SAS_PHY_DISABLED;
3733                else if (link_rate ==
3734                    MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION)
3735                        phy_info->phy->negotiated_linkrate =
3736                            SAS_LINK_RATE_FAILED;
3737                else {
3738                        phy_info->phy->negotiated_linkrate =
3739                            SAS_LINK_RATE_UNKNOWN;
3740                        if (ioc->device_missing_delay &&
3741                            mptsas_is_end_device(&phy_info->attached)) {
3742                                struct scsi_device              *sdev;
3743                                VirtDevice                      *vdevice;
3744                                u8      channel, id;
3745                                id = phy_info->attached.id;
3746                                channel = phy_info->attached.channel;
3747                                devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3748                                "Link down for fw_id %d:fw_channel %d\n",
3749                                    ioc->name, phy_info->attached.id,
3750                                    phy_info->attached.channel));
3751
3752                                shost_for_each_device(sdev, ioc->sh) {
3753                                        vdevice = sdev->hostdata;
3754                                        if ((vdevice == NULL) ||
3755                                                (vdevice->vtarget == NULL))
3756                                                continue;
3757                                        if ((vdevice->vtarget->tflags &
3758                                            MPT_TARGET_FLAGS_RAID_COMPONENT ||
3759                                            vdevice->vtarget->raidVolume))
3760                                                continue;
3761                                        if (vdevice->vtarget->id == id &&
3762                                                vdevice->vtarget->channel ==
3763                                                channel)
3764                                                devtprintk(ioc,
3765                                                printk(MYIOC_s_DEBUG_FMT
3766                                                "SDEV OUTSTANDING CMDS"
3767                                                "%d\n", ioc->name,
3768                                                sdev->device_busy));
3769                                }
3770
3771                        }
3772                }
3773        }
3774 out:
3775        mptsas_free_fw_event(ioc, fw_event);
3776}
3777
3778static void
3779mptsas_not_responding_devices(MPT_ADAPTER *ioc)
3780{
3781        struct mptsas_portinfo buffer, *port_info;
3782        struct mptsas_device_info       *sas_info;
3783        struct mptsas_devinfo sas_device;
3784        u32     handle;
3785        VirtTarget *vtarget = NULL;
3786        struct mptsas_phyinfo *phy_info;
3787        u8 found_expander;
3788        int retval, retry_count;
3789        unsigned long flags;
3790
3791        mpt_findImVolumes(ioc);
3792
3793        spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
3794        if (ioc->ioc_reset_in_progress) {
3795                dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3796                   "%s: exiting due to a parallel reset \n", ioc->name,
3797                    __func__));
3798                spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
3799                return;
3800        }
3801        spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
3802
3803        /* devices, logical volumes */
3804        mutex_lock(&ioc->sas_device_info_mutex);
3805 redo_device_scan:
3806        list_for_each_entry(sas_info, &ioc->sas_device_info_list, list) {
3807                if (sas_info->is_cached)
3808                        continue;
3809                if (!sas_info->is_logical_volume) {
3810                        sas_device.handle = 0;
3811                        retry_count = 0;
3812retry_page:
3813                        retval = mptsas_sas_device_pg0(ioc, &sas_device,
3814                                (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID
3815                                << MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3816                                (sas_info->fw.channel << 8) +
3817                                sas_info->fw.id);
3818
3819                        if (sas_device.handle)
3820                                continue;
3821                        if (retval == -EBUSY) {
3822                                spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
3823                                if (ioc->ioc_reset_in_progress) {
3824                                        dfailprintk(ioc,
3825                                        printk(MYIOC_s_DEBUG_FMT
3826                                        "%s: exiting due to reset\n",
3827                                        ioc->name, __func__));
3828                                        spin_unlock_irqrestore
3829                                        (&ioc->taskmgmt_lock, flags);
3830                                        mutex_unlock(&ioc->
3831                                        sas_device_info_mutex);
3832                                        return;
3833                                }
3834                                spin_unlock_irqrestore(&ioc->taskmgmt_lock,
3835                                flags);
3836                        }
3837
3838                        if (retval && (retval != -ENODEV)) {
3839                                if (retry_count < 10) {
3840                                        retry_count++;
3841                                        goto retry_page;
3842                                } else {
3843                                        devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3844                                        "%s: Config page retry exceeded retry "
3845                                        "count deleting device 0x%llx\n",
3846                                        ioc->name, __func__,
3847                                        sas_info->sas_address));
3848                                }
3849                        }
3850
3851                        /* delete device */
3852                        vtarget = mptsas_find_vtarget(ioc,
3853                                sas_info->fw.channel, sas_info->fw.id);
3854
3855                        if (vtarget)
3856                                vtarget->deleted = 1;
3857
3858                        phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
3859                                        sas_info->sas_address);
3860
3861                        if (phy_info) {
3862                                mptsas_del_end_device(ioc, phy_info);
3863                                goto redo_device_scan;
3864                        }
3865                } else
3866                        mptsas_volume_delete(ioc, sas_info->fw.id);
3867        }
3868        mutex_unlock(&ioc->sas_device_info_mutex);
3869
3870        /* expanders */
3871        mutex_lock(&ioc->sas_topology_mutex);
3872 redo_expander_scan:
3873        list_for_each_entry(port_info, &ioc->sas_topology, list) {
3874
3875                if (port_info->phy_info &&
3876                    (!(port_info->phy_info[0].identify.device_info &
3877                    MPI_SAS_DEVICE_INFO_SMP_TARGET)))
3878                        continue;
3879                found_expander = 0;
3880                handle = 0xFFFF;
3881                while (!mptsas_sas_expander_pg0(ioc, &buffer,
3882                    (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
3883                     MPI_SAS_EXPAND_PGAD_FORM_SHIFT), handle) &&
3884                    !found_expander) {
3885
3886                        handle = buffer.phy_info[0].handle;
3887                        if (buffer.phy_info[0].identify.sas_address ==
3888                            port_info->phy_info[0].identify.sas_address) {
3889                                found_expander = 1;
3890                        }
3891                        kfree(buffer.phy_info);
3892                }
3893
3894                if (!found_expander) {
3895                        mptsas_expander_delete(ioc, port_info, 0);
3896                        goto redo_expander_scan;
3897                }
3898        }
3899        mutex_unlock(&ioc->sas_topology_mutex);
3900}
3901
3902/**
3903 *      mptsas_probe_expanders - adding expanders
3904 *      @ioc: Pointer to MPT_ADAPTER structure
3905 *
3906 **/
3907static void
3908mptsas_probe_expanders(MPT_ADAPTER *ioc)
3909{
3910        struct mptsas_portinfo buffer, *port_info;
3911        u32                     handle;
3912        int i;
3913
3914        handle = 0xFFFF;
3915        while (!mptsas_sas_expander_pg0(ioc, &buffer,
3916            (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
3917             MPI_SAS_EXPAND_PGAD_FORM_SHIFT), handle)) {
3918
3919                handle = buffer.phy_info[0].handle;
3920                port_info = mptsas_find_portinfo_by_sas_address(ioc,
3921                    buffer.phy_info[0].identify.sas_address);
3922
3923                if (port_info) {
3924                        /* refreshing handles */
3925                        for (i = 0; i < buffer.num_phys; i++) {
3926                                port_info->phy_info[i].handle = handle;
3927                                port_info->phy_info[i].identify.handle_parent =
3928                                    buffer.phy_info[0].identify.handle_parent;
3929                        }
3930                        mptsas_expander_refresh(ioc, port_info);
3931                        kfree(buffer.phy_info);
3932                        continue;
3933                }
3934
3935                port_info = kzalloc(sizeof(struct mptsas_portinfo), GFP_KERNEL);
3936                if (!port_info) {
3937                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3938                        "%s: exit at line=%d\n", ioc->name,
3939                        __func__, __LINE__));
3940                        return;
3941                }
3942                port_info->num_phys = buffer.num_phys;
3943                port_info->phy_info = buffer.phy_info;
3944                for (i = 0; i < port_info->num_phys; i++)
3945                        port_info->phy_info[i].portinfo = port_info;
3946                mutex_lock(&ioc->sas_topology_mutex);
3947                list_add_tail(&port_info->list, &ioc->sas_topology);
3948                mutex_unlock(&ioc->sas_topology_mutex);
3949                printk(MYIOC_s_INFO_FMT "add expander: num_phys %d, "
3950                    "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
3951            (unsigned long long)buffer.phy_info[0].identify.sas_address);
3952                mptsas_expander_refresh(ioc, port_info);
3953        }
3954}
3955
3956static void
3957mptsas_probe_devices(MPT_ADAPTER *ioc)
3958{
3959        u16 handle;
3960        struct mptsas_devinfo sas_device;
3961        struct mptsas_phyinfo *phy_info;
3962
3963        handle = 0xFFFF;
3964        while (!(mptsas_sas_device_pg0(ioc, &sas_device,
3965            MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
3966
3967                handle = sas_device.handle;
3968
3969                if ((sas_device.device_info &
3970                     (MPI_SAS_DEVICE_INFO_SSP_TARGET |
3971                      MPI_SAS_DEVICE_INFO_STP_TARGET |
3972                      MPI_SAS_DEVICE_INFO_SATA_DEVICE)) == 0)
3973                        continue;
3974
3975                /* If there is no FW B_T mapping for this device then continue
3976                 * */
3977                if (!(sas_device.flags & MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)
3978                        || !(sas_device.flags &
3979                        MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED))
3980                        continue;
3981
3982                phy_info = mptsas_refreshing_device_handles(ioc, &sas_device);
3983                if (!phy_info)
3984                        continue;
3985
3986                if (mptsas_get_rphy(phy_info))
3987                        continue;
3988
3989                mptsas_add_end_device(ioc, phy_info);
3990        }
3991}
3992
3993/**
3994 *      mptsas_scan_sas_topology -
3995 *      @ioc: Pointer to MPT_ADAPTER structure
3996 *      @sas_address:
3997 *
3998 **/
3999static void
4000mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
4001{
4002        struct scsi_device *sdev;
4003        int i;
4004
4005        mptsas_probe_hba_phys(ioc);
4006        mptsas_probe_expanders(ioc);
4007        mptsas_probe_devices(ioc);
4008
4009        /*
4010          Reporting RAID volumes.
4011        */
4012        if (!ioc->ir_firmware || !ioc->raid_data.pIocPg2 ||
4013            !ioc->raid_data.pIocPg2->NumActiveVolumes)
4014                return;
4015        for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
4016                sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
4017                    ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
4018                if (sdev) {
4019                        scsi_device_put(sdev);
4020                        continue;
4021                }
4022                printk(MYIOC_s_INFO_FMT "attaching raid volume, channel %d, "
4023                    "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL,
4024                    ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID);
4025                scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
4026                    ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
4027        }
4028}
4029
4030
4031static void
4032mptsas_handle_queue_full_event(struct fw_event_work *fw_event)
4033{
4034        MPT_ADAPTER *ioc;
4035        EventDataQueueFull_t *qfull_data;
4036        struct mptsas_device_info *sas_info;
4037        struct scsi_device      *sdev;
4038        int depth;
4039        int id = -1;
4040        int channel = -1;
4041        int fw_id, fw_channel;
4042        u16 current_depth;
4043
4044
4045        ioc = fw_event->ioc;
4046        qfull_data = (EventDataQueueFull_t *)fw_event->event_data;
4047        fw_id = qfull_data->TargetID;
4048        fw_channel = qfull_data->Bus;
4049        current_depth = le16_to_cpu(qfull_data->CurrentDepth);
4050
4051        /* if hidden raid component, look for the volume id */
4052        mutex_lock(&ioc->sas_device_info_mutex);
4053        if (mptscsih_is_phys_disk(ioc, fw_channel, fw_id)) {
4054                list_for_each_entry(sas_info, &ioc->sas_device_info_list,
4055                    list) {
4056                        if (sas_info->is_cached ||
4057                            sas_info->is_logical_volume)
4058                                continue;
4059                        if (sas_info->is_hidden_raid_component &&
4060                            (sas_info->fw.channel == fw_channel &&
4061                            sas_info->fw.id == fw_id)) {
4062                                id = sas_info->volume_id;
4063                                channel = MPTSAS_RAID_CHANNEL;
4064                                goto out;
4065                        }
4066                }
4067        } else {
4068                list_for_each_entry(sas_info, &ioc->sas_device_info_list,
4069                    list) {
4070                        if (sas_info->is_cached ||
4071                            sas_info->is_hidden_raid_component ||
4072                            sas_info->is_logical_volume)
4073                                continue;
4074                        if (sas_info->fw.channel == fw_channel &&
4075                            sas_info->fw.id == fw_id) {
4076                                id = sas_info->os.id;
4077                                channel = sas_info->os.channel;
4078                                goto out;
4079                        }
4080                }
4081
4082        }
4083
4084 out:
4085        mutex_unlock(&ioc->sas_device_info_mutex);
4086
4087        if (id != -1) {
4088                shost_for_each_device(sdev, ioc->sh) {
4089                        if (sdev->id == id && sdev->channel == channel) {
4090                                if (current_depth > sdev->queue_depth) {
4091                                        sdev_printk(KERN_INFO, sdev,
4092                                            "strange observation, the queue "
4093                                            "depth is (%d) meanwhile fw queue "
4094                                            "depth (%d)\n", sdev->queue_depth,
4095                                            current_depth);
4096                                        continue;
4097                                }
4098                                depth = scsi_track_queue_full(sdev,
4099                                    current_depth - 1);
4100                                if (depth > 0)
4101                                        sdev_printk(KERN_INFO, sdev,
4102                                        "Queue depth reduced to (%d)\n",
4103                                           depth);
4104                                else if (depth < 0)
4105                                        sdev_printk(KERN_INFO, sdev,
4106                                        "Tagged Command Queueing is being "
4107                                        "disabled\n");
4108                                else if (depth == 0)
4109                                        sdev_printk(KERN_INFO, sdev,
4110                                        "Queue depth not changed yet\n");
4111                        }
4112                }
4113        }
4114
4115        mptsas_free_fw_event(ioc, fw_event);
4116}
4117
4118
4119static struct mptsas_phyinfo *
4120mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
4121{
4122        struct mptsas_portinfo *port_info;
4123        struct mptsas_phyinfo *phy_info = NULL;
4124        int i;
4125
4126        mutex_lock(&ioc->sas_topology_mutex);
4127        list_for_each_entry(port_info, &ioc->sas_topology, list) {
4128                for (i = 0; i < port_info->num_phys; i++) {
4129                        if (!mptsas_is_end_device(
4130                                &port_info->phy_info[i].attached))
4131                                continue;
4132                        if (port_info->phy_info[i].attached.sas_address
4133                            != sas_address)
4134                                continue;
4135                        phy_info = &port_info->phy_info[i];
4136                        break;
4137                }
4138        }
4139        mutex_unlock(&ioc->sas_topology_mutex);
4140        return phy_info;
4141}
4142
4143/**
4144 *      mptsas_find_phyinfo_by_phys_disk_num -
4145 *      @ioc: Pointer to MPT_ADAPTER structure
4146 *      @phys_disk_num:
4147 *      @channel:
4148 *      @id:
4149 *
4150 **/
4151static struct mptsas_phyinfo *
4152mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 phys_disk_num,
4153        u8 channel, u8 id)
4154{
4155        struct mptsas_phyinfo *phy_info = NULL;
4156        struct mptsas_portinfo *port_info;
4157        RaidPhysDiskPage1_t *phys_disk = NULL;
4158        int num_paths;
4159        u64 sas_address = 0;
4160        int i;
4161
4162        phy_info = NULL;
4163        if (!ioc->raid_data.pIocPg3)
4164                return NULL;
4165        /* dual port support */
4166        num_paths = mpt_raid_phys_disk_get_num_paths(ioc, phys_disk_num);
4167        if (!num_paths)
4168                goto out;
4169        phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) +
4170           (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL);
4171        if (!phys_disk)
4172                goto out;
4173        mpt_raid_phys_disk_pg1(ioc, phys_disk_num, phys_disk);
4174        for (i = 0; i < num_paths; i++) {
4175                if ((phys_disk->Path[i].Flags & 1) != 0)
4176                        /* entry no longer valid */
4177                        continue;
4178                if ((id == phys_disk->Path[i].PhysDiskID) &&
4179                    (channel == phys_disk->Path[i].PhysDiskBus)) {
4180                        memcpy(&sas_address, &phys_disk->Path[i].WWID,
4181                                sizeof(u64));
4182                        phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
4183                                        sas_address);
4184                        goto out;
4185                }
4186        }
4187
4188 out:
4189        kfree(phys_disk);
4190        if (phy_info)
4191                return phy_info;
4192
4193        /*
4194         * Extra code to handle RAID0 case, where the sas_address is not updated
4195         * in phys_disk_page_1 when hotswapped
4196         */
4197        mutex_lock(&ioc->sas_topology_mutex);
4198        list_for_each_entry(port_info, &ioc->sas_topology, list) {
4199                for (i = 0; i < port_info->num_phys && !phy_info; i++) {
4200                        if (!mptsas_is_end_device(
4201                                &port_info->phy_info[i].attached))
4202                                continue;
4203                        if (port_info->phy_info[i].attached.phys_disk_num == ~0)
4204                                continue;
4205                        if ((port_info->phy_info[i].attached.phys_disk_num ==
4206                            phys_disk_num) &&
4207                            (port_info->phy_info[i].attached.id == id) &&
4208                            (port_info->phy_info[i].attached.channel ==
4209                             channel))
4210                                phy_info = &port_info->phy_info[i];
4211                }
4212        }
4213        mutex_unlock(&ioc->sas_topology_mutex);
4214        return phy_info;
4215}
4216
4217static void
4218mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
4219{
4220        int rc;
4221
4222        sdev->no_uld_attach = data ? 1 : 0;
4223        rc = scsi_device_reprobe(sdev);
4224}
4225
4226static void
4227mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
4228{
4229        starget_for_each_device(starget, uld_attach ? (void *)1 : NULL,
4230                        mptsas_reprobe_lun);
4231}
4232
4233static void
4234mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id)
4235{
4236        CONFIGPARMS                     cfg;
4237        ConfigPageHeader_t              hdr;
4238        dma_addr_t                      dma_handle;
4239        pRaidVolumePage0_t              buffer = NULL;
4240        RaidPhysDiskPage0_t             phys_disk;
4241        int                             i;
4242        struct mptsas_phyinfo   *phy_info;
4243        struct mptsas_devinfo           sas_device;
4244
4245        memset(&cfg, 0 , sizeof(CONFIGPARMS));
4246        memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
4247        hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
4248        cfg.pageAddr = (channel << 8) + id;
4249        cfg.cfghdr.hdr = &hdr;
4250        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4251        cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
4252
4253        if (mpt_config(ioc, &cfg) != 0)
4254                goto out;
4255
4256        if (!hdr.PageLength)
4257                goto out;
4258
4259        buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
4260            &dma_handle);
4261
4262        if (!buffer)
4263                goto out;
4264
4265        cfg.physAddr = dma_handle;
4266        cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4267
4268        if (mpt_config(ioc, &cfg) != 0)
4269                goto out;
4270
4271        if (!(buffer->VolumeStatus.Flags &
4272            MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE))
4273                goto out;
4274
4275        if (!buffer->NumPhysDisks)
4276                goto out;
4277
4278        for (i = 0; i < buffer->NumPhysDisks; i++) {
4279
4280                if (mpt_raid_phys_disk_pg0(ioc,
4281                    buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
4282                        continue;
4283
4284                if (mptsas_sas_device_pg0(ioc, &sas_device,
4285                    (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
4286                     MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
4287                        (phys_disk.PhysDiskBus << 8) +
4288                        phys_disk.PhysDiskID))
4289                        continue;
4290
4291                /* If there is no FW B_T mapping for this device then continue
4292                 * */
4293                if (!(sas_device.flags & MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)
4294                        || !(sas_device.flags &
4295                        MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED))
4296                        continue;
4297
4298
4299                phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
4300                    sas_device.sas_address);
4301                mptsas_add_end_device(ioc, phy_info);
4302        }
4303
4304 out:
4305        if (buffer)
4306                pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
4307                    dma_handle);
4308}
4309/*
4310 * Work queue thread to handle SAS hotplug events
4311 */
4312static void
4313mptsas_hotplug_work(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
4314    struct mptsas_hotplug_event *hot_plug_info)
4315{
4316        struct mptsas_phyinfo *phy_info;
4317        struct scsi_target * starget;
4318        struct mptsas_devinfo sas_device;
4319        VirtTarget *vtarget;
4320        int i;
4321        struct mptsas_portinfo *port_info;
4322
4323        switch (hot_plug_info->event_type) {
4324
4325        case MPTSAS_ADD_PHYSDISK:
4326
4327                if (!ioc->raid_data.pIocPg2)
4328                        break;
4329
4330                for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
4331                        if (ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID ==
4332                            hot_plug_info->id) {
4333                                printk(MYIOC_s_WARN_FMT "firmware bug: unable "
4334                                    "to add hidden disk - target_id matchs "
4335                                    "volume_id\n", ioc->name);
4336                                mptsas_free_fw_event(ioc, fw_event);
4337                                return;
4338                        }
4339                }
4340                mpt_findImVolumes(ioc);
4341
4342        case MPTSAS_ADD_DEVICE:
4343                memset(&sas_device, 0, sizeof(struct mptsas_devinfo));
4344                mptsas_sas_device_pg0(ioc, &sas_device,
4345                    (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
4346                    MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
4347                    (hot_plug_info->channel << 8) +
4348                    hot_plug_info->id);
4349
4350                /* If there is no FW B_T mapping for this device then break
4351                 * */
4352                if (!(sas_device.flags & MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)
4353                        || !(sas_device.flags &
4354                        MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED))
4355                        break;
4356
4357                if (!sas_device.handle)
4358                        return;
4359
4360                phy_info = mptsas_refreshing_device_handles(ioc, &sas_device);
4361                /* Only For SATA Device ADD */
4362                if (!phy_info && (sas_device.device_info &
4363                                MPI_SAS_DEVICE_INFO_SATA_DEVICE)) {
4364                        devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4365                                "%s %d SATA HOT PLUG: "
4366                                "parent handle of device %x\n", ioc->name,
4367                                __func__, __LINE__, sas_device.handle_parent));
4368                        port_info = mptsas_find_portinfo_by_handle(ioc,
4369                                sas_device.handle_parent);
4370
4371                        if (port_info == ioc->hba_port_info)
4372                                mptsas_probe_hba_phys(ioc);
4373                        else if (port_info)
4374                                mptsas_expander_refresh(ioc, port_info);
4375                        else {
4376                                dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4377                                        "%s %d port info is NULL\n",
4378                                        ioc->name, __func__, __LINE__));
4379                                break;
4380                        }
4381                        phy_info = mptsas_refreshing_device_handles
4382                                (ioc, &sas_device);
4383                }
4384
4385                if (!phy_info) {
4386                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4387                                "%s %d phy info is NULL\n",
4388                                ioc->name, __func__, __LINE__));
4389                        break;
4390                }
4391
4392                if (mptsas_get_rphy(phy_info))
4393                        break;
4394
4395                mptsas_add_end_device(ioc, phy_info);
4396                break;
4397
4398        case MPTSAS_DEL_DEVICE:
4399                phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
4400                    hot_plug_info->sas_address);
4401                mptsas_del_end_device(ioc, phy_info);
4402                break;
4403
4404        case MPTSAS_DEL_PHYSDISK:
4405
4406                mpt_findImVolumes(ioc);
4407
4408                phy_info = mptsas_find_phyinfo_by_phys_disk_num(
4409                                ioc, hot_plug_info->phys_disk_num,
4410                                hot_plug_info->channel,
4411                                hot_plug_info->id);
4412                mptsas_del_end_device(ioc, phy_info);
4413                break;
4414
4415        case MPTSAS_ADD_PHYSDISK_REPROBE:
4416
4417                if (mptsas_sas_device_pg0(ioc, &sas_device,
4418                    (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
4419                     MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
4420                    (hot_plug_info->channel << 8) + hot_plug_info->id)) {
4421                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4422                        "%s: fw_id=%d exit at line=%d\n", ioc->name,
4423                                 __func__, hot_plug_info->id, __LINE__));
4424                        break;
4425                }
4426
4427                /* If there is no FW B_T mapping for this device then break
4428                 * */
4429                if (!(sas_device.flags & MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)
4430                        || !(sas_device.flags &
4431                        MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED))
4432                        break;
4433
4434                phy_info = mptsas_find_phyinfo_by_sas_address(
4435                    ioc, sas_device.sas_address);
4436
4437                if (!phy_info) {
4438                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4439                                "%s: fw_id=%d exit at line=%d\n", ioc->name,
4440                                 __func__, hot_plug_info->id, __LINE__));
4441                        break;
4442                }
4443
4444                starget = mptsas_get_starget(phy_info);
4445                if (!starget) {
4446                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4447                                "%s: fw_id=%d exit at line=%d\n", ioc->name,
4448                                 __func__, hot_plug_info->id, __LINE__));
4449                        break;
4450                }
4451
4452                vtarget = starget->hostdata;
4453                if (!vtarget) {
4454                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4455                                "%s: fw_id=%d exit at line=%d\n", ioc->name,
4456                                 __func__, hot_plug_info->id, __LINE__));
4457                        break;
4458                }
4459
4460                mpt_findImVolumes(ioc);
4461
4462                starget_printk(KERN_INFO, starget, MYIOC_s_FMT "RAID Hidding: "
4463                    "fw_channel=%d, fw_id=%d, physdsk %d, sas_addr 0x%llx\n",
4464                    ioc->name, hot_plug_info->channel, hot_plug_info->id,
4465                    hot_plug_info->phys_disk_num, (unsigned long long)
4466                    sas_device.sas_address);
4467
4468                vtarget->id = hot_plug_info->phys_disk_num;
4469                vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
4470                phy_info->attached.phys_disk_num = hot_plug_info->phys_disk_num;
4471                mptsas_reprobe_target(starget, 1);
4472                break;
4473
4474        case MPTSAS_DEL_PHYSDISK_REPROBE:
4475
4476                if (mptsas_sas_device_pg0(ioc, &sas_device,
4477                    (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
4478                     MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
4479                        (hot_plug_info->channel << 8) + hot_plug_info->id)) {
4480                                dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4481                                    "%s: fw_id=%d exit at line=%d\n",
4482                                    ioc->name, __func__,
4483                                    hot_plug_info->id, __LINE__));
4484                        break;
4485                }
4486
4487                /* If there is no FW B_T mapping for this device then break
4488                 * */
4489                if (!(sas_device.flags & MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)
4490                        || !(sas_device.flags &
4491                        MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED))
4492                        break;
4493
4494                phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
4495                                sas_device.sas_address);
4496                if (!phy_info) {
4497                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4498                            "%s: fw_id=%d exit at line=%d\n", ioc->name,
4499                         __func__, hot_plug_info->id, __LINE__));
4500                        break;
4501                }
4502
4503                starget = mptsas_get_starget(phy_info);
4504                if (!starget) {
4505                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4506                            "%s: fw_id=%d exit at line=%d\n", ioc->name,
4507                         __func__, hot_plug_info->id, __LINE__));
4508                        break;
4509                }
4510
4511                vtarget = starget->hostdata;
4512                if (!vtarget) {
4513                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4514                            "%s: fw_id=%d exit at line=%d\n", ioc->name,
4515                         __func__, hot_plug_info->id, __LINE__));
4516                        break;
4517                }
4518
4519                if (!(vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)) {
4520                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4521                            "%s: fw_id=%d exit at line=%d\n", ioc->name,
4522                         __func__, hot_plug_info->id, __LINE__));
4523                        break;
4524                }
4525
4526                mpt_findImVolumes(ioc);
4527
4528                starget_printk(KERN_INFO, starget, MYIOC_s_FMT "RAID Exposing:"
4529                    " fw_channel=%d, fw_id=%d, physdsk %d, sas_addr 0x%llx\n",
4530                    ioc->name, hot_plug_info->channel, hot_plug_info->id,
4531                    hot_plug_info->phys_disk_num, (unsigned long long)
4532                    sas_device.sas_address);
4533
4534                vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
4535                vtarget->id = hot_plug_info->id;
4536                phy_info->attached.phys_disk_num = ~0;
4537                mptsas_reprobe_target(starget, 0);
4538                mptsas_add_device_component_by_fw(ioc,
4539                    hot_plug_info->channel, hot_plug_info->id);
4540                break;
4541
4542        case MPTSAS_ADD_RAID:
4543
4544                mpt_findImVolumes(ioc);
4545                printk(MYIOC_s_INFO_FMT "attaching raid volume, channel %d, "
4546                    "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL,
4547                    hot_plug_info->id);
4548                scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
4549                    hot_plug_info->id, 0);
4550                break;
4551
4552        case MPTSAS_DEL_RAID:
4553
4554                mpt_findImVolumes(ioc);
4555                printk(MYIOC_s_INFO_FMT "removing raid volume, channel %d, "
4556                    "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL,
4557                    hot_plug_info->id);
4558                scsi_remove_device(hot_plug_info->sdev);
4559                scsi_device_put(hot_plug_info->sdev);
4560                break;
4561
4562        case MPTSAS_ADD_INACTIVE_VOLUME:
4563
4564                mpt_findImVolumes(ioc);
4565                mptsas_adding_inactive_raid_components(ioc,
4566                    hot_plug_info->channel, hot_plug_info->id);
4567                break;
4568
4569        default:
4570                break;
4571        }
4572
4573        mptsas_free_fw_event(ioc, fw_event);
4574}
4575
4576static void
4577mptsas_send_sas_event(struct fw_event_work *fw_event)
4578{
4579        MPT_ADAPTER *ioc;
4580        struct mptsas_hotplug_event hot_plug_info;
4581        EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data;
4582        u32 device_info;
4583        u64 sas_address;
4584
4585        ioc = fw_event->ioc;
4586        sas_event_data = (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)
4587            fw_event->event_data;
4588        device_info = le32_to_cpu(sas_event_data->DeviceInfo);
4589
4590        if ((device_info &
4591                (MPI_SAS_DEVICE_INFO_SSP_TARGET |
4592                MPI_SAS_DEVICE_INFO_STP_TARGET |
4593                MPI_SAS_DEVICE_INFO_SATA_DEVICE)) == 0) {
4594                mptsas_free_fw_event(ioc, fw_event);
4595                return;
4596        }
4597
4598        if (sas_event_data->ReasonCode ==
4599                MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED) {
4600                mptbase_sas_persist_operation(ioc,
4601                MPI_SAS_OP_CLEAR_NOT_PRESENT);
4602                mptsas_free_fw_event(ioc, fw_event);
4603                return;
4604        }
4605
4606        switch (sas_event_data->ReasonCode) {
4607        case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
4608        case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
4609                memset(&hot_plug_info, 0, sizeof(struct mptsas_hotplug_event));
4610                hot_plug_info.handle = le16_to_cpu(sas_event_data->DevHandle);
4611                hot_plug_info.channel = sas_event_data->Bus;
4612                hot_plug_info.id = sas_event_data->TargetID;
4613                hot_plug_info.phy_id = sas_event_data->PhyNum;
4614                memcpy(&sas_address, &sas_event_data->SASAddress,
4615                    sizeof(u64));
4616                hot_plug_info.sas_address = le64_to_cpu(sas_address);
4617                hot_plug_info.device_info = device_info;
4618                if (sas_event_data->ReasonCode &
4619                    MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
4620                        hot_plug_info.event_type = MPTSAS_ADD_DEVICE;
4621                else
4622                        hot_plug_info.event_type = MPTSAS_DEL_DEVICE;
4623                mptsas_hotplug_work(ioc, fw_event, &hot_plug_info);
4624                break;
4625
4626        case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
4627                mptbase_sas_persist_operation(ioc,
4628                    MPI_SAS_OP_CLEAR_NOT_PRESENT);
4629                mptsas_free_fw_event(ioc, fw_event);
4630                break;
4631
4632        case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
4633        /* TODO */
4634        case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
4635        /* TODO */
4636        default:
4637                mptsas_free_fw_event(ioc, fw_event);
4638                break;
4639        }
4640}
4641
4642static void
4643mptsas_send_raid_event(struct fw_event_work *fw_event)
4644{
4645        MPT_ADAPTER *ioc;
4646        EVENT_DATA_RAID *raid_event_data;
4647        struct mptsas_hotplug_event hot_plug_info;
4648        int status;
4649        int state;
4650        struct scsi_device *sdev = NULL;
4651        VirtDevice *vdevice = NULL;
4652        RaidPhysDiskPage0_t phys_disk;
4653
4654        ioc = fw_event->ioc;
4655        raid_event_data = (EVENT_DATA_RAID *)fw_event->event_data;
4656        status = le32_to_cpu(raid_event_data->SettingsStatus);
4657        state = (status >> 8) & 0xff;
4658
4659        memset(&hot_plug_info, 0, sizeof(struct mptsas_hotplug_event));
4660        hot_plug_info.id = raid_event_data->VolumeID;
4661        hot_plug_info.channel = raid_event_data->VolumeBus;
4662        hot_plug_info.phys_disk_num = raid_event_data->PhysDiskNum;
4663
4664        if (raid_event_data->ReasonCode == MPI_EVENT_RAID_RC_VOLUME_DELETED ||
4665            raid_event_data->ReasonCode == MPI_EVENT_RAID_RC_VOLUME_CREATED ||
4666            raid_event_data->ReasonCode ==
4667            MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED) {
4668                sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
4669                    hot_plug_info.id, 0);
4670                hot_plug_info.sdev = sdev;
4671                if (sdev)
4672                        vdevice = sdev->hostdata;
4673        }
4674
4675        devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Entering %s: "
4676            "ReasonCode=%02x\n", ioc->name, __func__,
4677            raid_event_data->ReasonCode));
4678
4679        switch (raid_event_data->ReasonCode) {
4680        case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
4681                hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK_REPROBE;
4682                break;
4683        case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
4684                hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK_REPROBE;
4685                break;
4686        case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
4687                switch (state) {
4688                case MPI_PD_STATE_ONLINE:
4689                case MPI_PD_STATE_NOT_COMPATIBLE:
4690                        mpt_raid_phys_disk_pg0(ioc,
4691                            raid_event_data->PhysDiskNum, &phys_disk);
4692                        hot_plug_info.id = phys_disk.PhysDiskID;
4693                        hot_plug_info.channel = phys_disk.PhysDiskBus;
4694                        hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK;
4695                        break;
4696                case MPI_PD_STATE_FAILED:
4697                case MPI_PD_STATE_MISSING:
4698                case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
4699                case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
4700                case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
4701                        hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK;
4702                        break;
4703                default:
4704                        break;
4705                }
4706                break;
4707        case MPI_EVENT_RAID_RC_VOLUME_DELETED:
4708                if (!sdev)
4709                        break;
4710                vdevice->vtarget->deleted = 1; /* block IO */
4711                hot_plug_info.event_type = MPTSAS_DEL_RAID;
4712                break;
4713        case MPI_EVENT_RAID_RC_VOLUME_CREATED:
4714                if (sdev) {
4715                        scsi_device_put(sdev);
4716                        break;
4717                }
4718                hot_plug_info.event_type = MPTSAS_ADD_RAID;
4719                break;
4720        case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
4721                if (!(status & MPI_RAIDVOL0_STATUS_FLAG_ENABLED)) {
4722                        if (!sdev)
4723                                break;
4724                        vdevice->vtarget->deleted = 1; /* block IO */
4725                        hot_plug_info.event_type = MPTSAS_DEL_RAID;
4726                        break;
4727                }
4728                switch (state) {
4729                case MPI_RAIDVOL0_STATUS_STATE_FAILED:
4730                case MPI_RAIDVOL0_STATUS_STATE_MISSING:
4731                        if (!sdev)
4732                                break;
4733                        vdevice->vtarget->deleted = 1; /* block IO */
4734                        hot_plug_info.event_type = MPTSAS_DEL_RAID;
4735                        break;
4736                case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
4737                case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
4738                        if (sdev) {
4739                                scsi_device_put(sdev);
4740                                break;
4741                        }
4742                        hot_plug_info.event_type = MPTSAS_ADD_RAID;
4743                        break;
4744                default:
4745                        break;
4746                }
4747                break;
4748        default:
4749                break;
4750        }
4751
4752        if (hot_plug_info.event_type != MPTSAS_IGNORE_EVENT)
4753                mptsas_hotplug_work(ioc, fw_event, &hot_plug_info);
4754        else
4755                mptsas_free_fw_event(ioc, fw_event);
4756}
4757
4758/**
4759 *      mptsas_issue_tm - send mptsas internal tm request
4760 *      @ioc: Pointer to MPT_ADAPTER structure
4761 *      @type: Task Management type
4762 *      @channel: channel number for task management
4763 *      @id: Logical Target ID for reset (if appropriate)
4764 *      @lun: Logical unit for reset (if appropriate)
4765 *      @task_context: Context for the task to be aborted
4766 *      @timeout: timeout for task management control
4767 *
4768 *      return 0 on success and -1 on failure:
4769 *
4770 */
4771static int
4772mptsas_issue_tm(MPT_ADAPTER *ioc, u8 type, u8 channel, u8 id, u64 lun,
4773        int task_context, ulong timeout, u8 *issue_reset)
4774{
4775        MPT_FRAME_HDR   *mf;
4776        SCSITaskMgmt_t  *pScsiTm;
4777        int              retval;
4778        unsigned long    timeleft;
4779
4780        *issue_reset = 0;
4781        mf = mpt_get_msg_frame(mptsasDeviceResetCtx, ioc);
4782        if (mf == NULL) {
4783                retval = -1; /* return failure */
4784                dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "TaskMgmt request: no "
4785                    "msg frames!!\n", ioc->name));
4786                goto out;
4787        }
4788
4789        dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request: mr = %p, "
4790            "task_type = 0x%02X,\n\t timeout = %ld, fw_channel = %d, "
4791            "fw_id = %d, lun = %lld,\n\t task_context = 0x%x\n", ioc->name, mf,
4792             type, timeout, channel, id, (unsigned long long)lun,
4793             task_context));
4794
4795        pScsiTm = (SCSITaskMgmt_t *) mf;
4796        memset(pScsiTm, 0, sizeof(SCSITaskMgmt_t));
4797        pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
4798        pScsiTm->TaskType = type;
4799        pScsiTm->MsgFlags = 0;
4800        pScsiTm->TargetID = id;
4801        pScsiTm->Bus = channel;
4802        pScsiTm->ChainOffset = 0;
4803        pScsiTm->Reserved = 0;
4804        pScsiTm->Reserved1 = 0;
4805        pScsiTm->TaskMsgContext = task_context;
4806        int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN);
4807
4808        INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status)
4809        CLEAR_MGMT_STATUS(ioc->internal_cmds.status)
4810        retval = 0;
4811        mpt_put_msg_frame_hi_pri(mptsasDeviceResetCtx, ioc, mf);
4812
4813        /* Now wait for the command to complete */
4814        timeleft = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done,
4815            timeout*HZ);
4816        if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
4817                retval = -1; /* return failure */
4818                dtmprintk(ioc, printk(MYIOC_s_ERR_FMT
4819                    "TaskMgmt request: TIMED OUT!(mr=%p)\n", ioc->name, mf));
4820                mpt_free_msg_frame(ioc, mf);
4821                if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
4822                        goto out;
4823                *issue_reset = 1;
4824                goto out;
4825        }
4826
4827        if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
4828                retval = -1; /* return failure */
4829                dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4830                    "TaskMgmt request: failed with no reply\n", ioc->name));
4831                goto out;
4832        }
4833
4834 out:
4835        CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status)
4836        return retval;
4837}
4838
4839/**
4840 *      mptsas_broadcast_primative_work - Handle broadcast primitives
4841 *      @work: work queue payload containing info describing the event
4842 *
4843 *      this will be handled in workqueue context.
4844 */
4845static void
4846mptsas_broadcast_primative_work(struct fw_event_work *fw_event)
4847{
4848        MPT_ADAPTER *ioc = fw_event->ioc;
4849        MPT_FRAME_HDR   *mf;
4850        VirtDevice      *vdevice;
4851        int                     ii;
4852        struct scsi_cmnd        *sc;
4853        SCSITaskMgmtReply_t     *pScsiTmReply;
4854        u8                      issue_reset;
4855        int                     task_context;
4856        u8                      channel, id;
4857        int                      lun;
4858        u32                      termination_count;
4859        u32                      query_count;
4860
4861        dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4862            "%s - enter\n", ioc->name, __func__));
4863
4864        mutex_lock(&ioc->taskmgmt_cmds.mutex);
4865        if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) {
4866                mutex_unlock(&ioc->taskmgmt_cmds.mutex);
4867                mptsas_requeue_fw_event(ioc, fw_event, 1000);
4868                return;
4869        }
4870
4871        issue_reset = 0;
4872        termination_count = 0;
4873        query_count = 0;
4874        mpt_findImVolumes(ioc);
4875        pScsiTmReply = (SCSITaskMgmtReply_t *) ioc->taskmgmt_cmds.reply;
4876
4877        for (ii = 0; ii < ioc->req_depth; ii++) {
4878                if (ioc->fw_events_off)
4879                        goto out;
4880                sc = mptscsih_get_scsi_lookup(ioc, ii);
4881                if (!sc)
4882                        continue;
4883                mf = MPT_INDEX_2_MFPTR(ioc, ii);
4884                if (!mf)
4885                        continue;
4886                task_context = mf->u.frame.hwhdr.msgctxu.MsgContext;
4887                vdevice = sc->device->hostdata;
4888                if (!vdevice || !vdevice->vtarget)
4889                        continue;
4890                if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
4891                        continue; /* skip hidden raid components */
4892                if (vdevice->vtarget->raidVolume)
4893                        continue; /* skip hidden raid components */
4894                channel = vdevice->vtarget->channel;
4895                id = vdevice->vtarget->id;
4896                lun = vdevice->lun;
4897                if (mptsas_issue_tm(ioc, MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK,
4898                    channel, id, (u64)lun, task_context, 30, &issue_reset))
4899                        goto out;
4900                query_count++;
4901                termination_count +=
4902                    le32_to_cpu(pScsiTmReply->TerminationCount);
4903                if ((pScsiTmReply->IOCStatus == MPI_IOCSTATUS_SUCCESS) &&
4904                    (pScsiTmReply->ResponseCode ==
4905                    MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED ||
4906                    pScsiTmReply->ResponseCode ==
4907                    MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC))
4908                        continue;
4909                if (mptsas_issue_tm(ioc,
4910                    MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET,
4911                    channel, id, (u64)lun, 0, 30, &issue_reset))
4912                        goto out;
4913                termination_count +=
4914                    le32_to_cpu(pScsiTmReply->TerminationCount);
4915        }
4916
4917 out:
4918        dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4919            "%s - exit, query_count = %d termination_count = %d\n",
4920            ioc->name, __func__, query_count, termination_count));
4921
4922        ioc->broadcast_aen_busy = 0;
4923        mpt_clear_taskmgmt_in_progress_flag(ioc);
4924        mutex_unlock(&ioc->taskmgmt_cmds.mutex);
4925
4926        if (issue_reset) {
4927                printk(MYIOC_s_WARN_FMT
4928                       "Issuing Reset from %s!! doorbell=0x%08x\n",
4929                       ioc->name, __func__, mpt_GetIocState(ioc, 0));
4930                mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);
4931        }
4932        mptsas_free_fw_event(ioc, fw_event);
4933}
4934
4935/*
4936 * mptsas_send_ir2_event - handle exposing hidden disk when
4937 * an inactive raid volume is added
4938 *
4939 * @ioc: Pointer to MPT_ADAPTER structure
4940 * @ir2_data
4941 *
4942 */
4943static void
4944mptsas_send_ir2_event(struct fw_event_work *fw_event)
4945{
4946        MPT_ADAPTER     *ioc;
4947        struct mptsas_hotplug_event hot_plug_info;
4948        MPI_EVENT_DATA_IR2      *ir2_data;
4949        u8 reasonCode;
4950        RaidPhysDiskPage0_t phys_disk;
4951
4952        ioc = fw_event->ioc;
4953        ir2_data = (MPI_EVENT_DATA_IR2 *)fw_event->event_data;
4954        reasonCode = ir2_data->ReasonCode;
4955
4956        devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Entering %s: "
4957            "ReasonCode=%02x\n", ioc->name, __func__, reasonCode));
4958
4959        memset(&hot_plug_info, 0, sizeof(struct mptsas_hotplug_event));
4960        hot_plug_info.id = ir2_data->TargetID;
4961        hot_plug_info.channel = ir2_data->Bus;
4962        switch (reasonCode) {
4963        case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
4964                hot_plug_info.event_type = MPTSAS_ADD_INACTIVE_VOLUME;
4965                break;
4966        case MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED:
4967                hot_plug_info.phys_disk_num = ir2_data->PhysDiskNum;
4968                hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK;
4969                break;
4970        case MPI_EVENT_IR2_RC_DUAL_PORT_ADDED:
4971                hot_plug_info.phys_disk_num = ir2_data->PhysDiskNum;
4972                mpt_raid_phys_disk_pg0(ioc,
4973                    ir2_data->PhysDiskNum, &phys_disk);
4974                hot_plug_info.id = phys_disk.PhysDiskID;
4975                hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK;
4976                break;
4977        default:
4978                mptsas_free_fw_event(ioc, fw_event);
4979                return;
4980        }
4981        mptsas_hotplug_work(ioc, fw_event, &hot_plug_info);
4982}
4983
4984static int
4985mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
4986{
4987        u32 event = le32_to_cpu(reply->Event);
4988        int sz, event_data_sz;
4989        struct fw_event_work *fw_event;
4990        unsigned long delay;
4991
4992        if (ioc->bus_type != SAS)
4993                return 0;
4994
4995        /* events turned off due to host reset or driver unloading */
4996        if (ioc->fw_events_off)
4997                return 0;
4998
4999        delay = msecs_to_jiffies(1);
5000        switch (event) {
5001        case MPI_EVENT_SAS_BROADCAST_PRIMITIVE:
5002        {
5003                EVENT_DATA_SAS_BROADCAST_PRIMITIVE *broadcast_event_data =
5004                    (EVENT_DATA_SAS_BROADCAST_PRIMITIVE *)reply->Data;
5005                if (broadcast_event_data->Primitive !=
5006                    MPI_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT)
5007                        return 0;
5008                if (ioc->broadcast_aen_busy)
5009                        return 0;
5010                ioc->broadcast_aen_busy = 1;
5011                break;
5012        }
5013        case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
5014        {
5015                EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data =
5016                    (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data;
5017                u16     ioc_stat;
5018                ioc_stat = le16_to_cpu(reply->IOCStatus);
5019
5020                if (sas_event_data->ReasonCode ==
5021                    MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING) {
5022                        mptsas_target_reset_queue(ioc, sas_event_data);
5023                        return 0;
5024                }
5025                if (sas_event_data->ReasonCode ==
5026                        MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET &&
5027                        ioc->device_missing_delay &&
5028                        (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)) {
5029                        VirtTarget *vtarget = NULL;
5030                        u8              id, channel;
5031
5032                        id = sas_event_data->TargetID;
5033                        channel = sas_event_data->Bus;
5034
5035                        vtarget = mptsas_find_vtarget(ioc, channel, id);
5036                        if (vtarget) {
5037                                devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5038                                    "LogInfo (0x%x) available for "
5039                                   "INTERNAL_DEVICE_RESET"
5040                                   "fw_id %d fw_channel %d\n", ioc->name,
5041                                   le32_to_cpu(reply->IOCLogInfo),
5042                                   id, channel));
5043                                if (vtarget->raidVolume) {
5044                                        devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5045                                        "Skipping Raid Volume for inDMD\n",
5046                                        ioc->name));
5047                                } else {
5048                                        devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5049                                        "Setting device flag inDMD\n",
5050                                        ioc->name));
5051                                        vtarget->inDMD = 1;
5052                                }
5053
5054                        }
5055
5056                }
5057
5058                break;
5059        }
5060        case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE:
5061        {
5062                MpiEventDataSasExpanderStatusChange_t *expander_data =
5063                    (MpiEventDataSasExpanderStatusChange_t *)reply->Data;
5064
5065                if (ioc->old_sas_discovery_protocal)
5066                        return 0;
5067
5068                if (expander_data->ReasonCode ==
5069                    MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING &&
5070                    ioc->device_missing_delay)
5071                        delay = HZ * ioc->device_missing_delay;
5072                break;
5073        }
5074        case MPI_EVENT_SAS_DISCOVERY:
5075        {
5076                u32 discovery_status;
5077                EventDataSasDiscovery_t *discovery_data =
5078                    (EventDataSasDiscovery_t *)reply->Data;
5079
5080                discovery_status = le32_to_cpu(discovery_data->DiscoveryStatus);
5081                ioc->sas_discovery_quiesce_io = discovery_status ? 1 : 0;
5082                if (ioc->old_sas_discovery_protocal && !discovery_status)
5083                        mptsas_queue_rescan(ioc);
5084                return 0;
5085        }
5086        case MPI_EVENT_INTEGRATED_RAID:
5087        case MPI_EVENT_PERSISTENT_TABLE_FULL:
5088        case MPI_EVENT_IR2:
5089        case MPI_EVENT_SAS_PHY_LINK_STATUS:
5090        case MPI_EVENT_QUEUE_FULL:
5091                break;
5092        default:
5093                return 0;
5094        }
5095
5096        event_data_sz = ((reply->MsgLength * 4) -
5097            offsetof(EventNotificationReply_t, Data));
5098        sz = offsetof(struct fw_event_work, event_data) + event_data_sz;
5099        fw_event = kzalloc(sz, GFP_ATOMIC);
5100        if (!fw_event) {
5101                printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n", ioc->name,
5102                 __func__, __LINE__);
5103                return 0;
5104        }
5105        memcpy(fw_event->event_data, reply->Data, event_data_sz);
5106        fw_event->event = event;
5107        fw_event->ioc = ioc;
5108        mptsas_add_fw_event(ioc, fw_event, delay);
5109        return 0;
5110}
5111
5112/* Delete a volume when no longer listed in ioc pg2
5113 */
5114static void mptsas_volume_delete(MPT_ADAPTER *ioc, u8 id)
5115{
5116        struct scsi_device *sdev;
5117        int i;
5118
5119        sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL, id, 0);
5120        if (!sdev)
5121                return;
5122        if (!ioc->raid_data.pIocPg2)
5123                goto out;
5124        if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
5125                goto out;
5126        for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++)
5127                if (ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID == id)
5128                        goto release_sdev;
5129 out:
5130        printk(MYIOC_s_INFO_FMT "removing raid volume, channel %d, "
5131            "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL, id);
5132        scsi_remove_device(sdev);
5133 release_sdev:
5134        scsi_device_put(sdev);
5135}
5136
5137static int
5138mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
5139{
5140        struct Scsi_Host        *sh;
5141        MPT_SCSI_HOST           *hd;
5142        MPT_ADAPTER             *ioc;
5143        unsigned long            flags;
5144        int                      ii;
5145        int                      numSGE = 0;
5146        int                      scale;
5147        int                      ioc_cap;
5148        int                     error=0;
5149        int                     r;
5150
5151        r = mpt_attach(pdev,id);
5152        if (r)
5153                return r;
5154
5155        ioc = pci_get_drvdata(pdev);
5156        mptsas_fw_event_off(ioc);
5157        ioc->DoneCtx = mptsasDoneCtx;
5158        ioc->TaskCtx = mptsasTaskCtx;
5159        ioc->InternalCtx = mptsasInternalCtx;
5160        ioc->schedule_target_reset = &mptsas_schedule_target_reset;
5161        ioc->schedule_dead_ioc_flush_running_cmds =
5162                                &mptscsih_flush_running_cmds;
5163        /*  Added sanity check on readiness of the MPT adapter.
5164         */
5165        if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
5166                printk(MYIOC_s_WARN_FMT
5167                  "Skipping because it's not operational!\n",
5168                  ioc->name);
5169                error = -ENODEV;
5170                goto out_mptsas_probe;
5171        }
5172
5173        if (!ioc->active) {
5174                printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
5175                  ioc->name);
5176                error = -ENODEV;
5177                goto out_mptsas_probe;
5178        }
5179
5180        /*  Sanity check - ensure at least 1 port is INITIATOR capable
5181         */
5182        ioc_cap = 0;
5183        for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
5184                if (ioc->pfacts[ii].ProtocolFlags &
5185                                MPI_PORTFACTS_PROTOCOL_INITIATOR)
5186                        ioc_cap++;
5187        }
5188
5189        if (!ioc_cap) {
5190                printk(MYIOC_s_WARN_FMT
5191                        "Skipping ioc=%p because SCSI Initiator mode "
5192                        "is NOT enabled!\n", ioc->name, ioc);
5193                return 0;
5194        }
5195
5196        sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
5197        if (!sh) {
5198                printk(MYIOC_s_WARN_FMT
5199                        "Unable to register controller with SCSI subsystem\n",
5200                        ioc->name);
5201                error = -1;
5202                goto out_mptsas_probe;
5203        }
5204
5205        spin_lock_irqsave(&ioc->FreeQlock, flags);
5206
5207        /* Attach the SCSI Host to the IOC structure
5208         */
5209        ioc->sh = sh;
5210
5211        sh->io_port = 0;
5212        sh->n_io_port = 0;
5213        sh->irq = 0;
5214
5215        /* set 16 byte cdb's */
5216        sh->max_cmd_len = 16;
5217        sh->can_queue = min_t(int, ioc->req_depth - 10, sh->can_queue);
5218        sh->max_id = -1;
5219        sh->max_lun = max_lun;
5220        sh->transportt = mptsas_transport_template;
5221
5222        /* Required entry.
5223         */
5224        sh->unique_id = ioc->id;
5225
5226        INIT_LIST_HEAD(&ioc->sas_topology);
5227        mutex_init(&ioc->sas_topology_mutex);
5228        mutex_init(&ioc->sas_discovery_mutex);
5229        mutex_init(&ioc->sas_mgmt.mutex);
5230        init_completion(&ioc->sas_mgmt.done);
5231
5232        /* Verify that we won't exceed the maximum
5233         * number of chain buffers
5234         * We can optimize:  ZZ = req_sz/sizeof(SGE)
5235         * For 32bit SGE's:
5236         *  numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
5237         *               + (req_sz - 64)/sizeof(SGE)
5238         * A slightly different algorithm is required for
5239         * 64bit SGEs.
5240         */
5241        scale = ioc->req_sz/ioc->SGE_size;
5242        if (ioc->sg_addr_size == sizeof(u64)) {
5243                numSGE = (scale - 1) *
5244                  (ioc->facts.MaxChainDepth-1) + scale +
5245                  (ioc->req_sz - 60) / ioc->SGE_size;
5246        } else {
5247                numSGE = 1 + (scale - 1) *
5248                  (ioc->facts.MaxChainDepth-1) + scale +
5249                  (ioc->req_sz - 64) / ioc->SGE_size;
5250        }
5251
5252        if (numSGE < sh->sg_tablesize) {
5253                /* Reset this value */
5254                dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5255                  "Resetting sg_tablesize to %d from %d\n",
5256                  ioc->name, numSGE, sh->sg_tablesize));
5257                sh->sg_tablesize = numSGE;
5258        }
5259
5260        if (mpt_loadtime_max_sectors) {
5261                if (mpt_loadtime_max_sectors < 64 ||
5262                        mpt_loadtime_max_sectors > 8192) {
5263                        printk(MYIOC_s_INFO_FMT "Invalid value passed for"
5264                                "mpt_loadtime_max_sectors %d."
5265                                "Range from 64 to 8192\n", ioc->name,
5266                                mpt_loadtime_max_sectors);
5267                }
5268                mpt_loadtime_max_sectors &=  0xFFFFFFFE;
5269                dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5270                        "Resetting max sector to %d from %d\n",
5271                  ioc->name, mpt_loadtime_max_sectors, sh->max_sectors));
5272                sh->max_sectors = mpt_loadtime_max_sectors;
5273        }
5274
5275        hd = shost_priv(sh);
5276        hd->ioc = ioc;
5277
5278        /* SCSI needs scsi_cmnd lookup table!
5279         * (with size equal to req_depth*PtrSz!)
5280         */
5281        ioc->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
5282        if (!ioc->ScsiLookup) {
5283                error = -ENOMEM;
5284                spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5285                goto out_mptsas_probe;
5286        }
5287        spin_lock_init(&ioc->scsi_lookup_lock);
5288
5289        dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
5290                 ioc->name, ioc->ScsiLookup));
5291
5292        ioc->sas_data.ptClear = mpt_pt_clear;
5293
5294        hd->last_queue_full = 0;
5295        INIT_LIST_HEAD(&hd->target_reset_list);
5296        INIT_LIST_HEAD(&ioc->sas_device_info_list);
5297        mutex_init(&ioc->sas_device_info_mutex);
5298
5299        spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5300
5301        if (ioc->sas_data.ptClear==1) {
5302                mptbase_sas_persist_operation(
5303                    ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
5304        }
5305
5306        error = scsi_add_host(sh, &ioc->pcidev->dev);
5307        if (error) {
5308                dprintk(ioc, printk(MYIOC_s_ERR_FMT
5309                  "scsi_add_host failed\n", ioc->name));
5310                goto out_mptsas_probe;
5311        }
5312
5313        /* older firmware doesn't support expander events */
5314        if ((ioc->facts.HeaderVersion >> 8) < 0xE)
5315                ioc->old_sas_discovery_protocal = 1;
5316        mptsas_scan_sas_topology(ioc);
5317        mptsas_fw_event_on(ioc);
5318        return 0;
5319
5320 out_mptsas_probe:
5321
5322        mptscsih_remove(pdev);
5323        return error;
5324}
5325
5326void
5327mptsas_shutdown(struct pci_dev *pdev)
5328{
5329        MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
5330
5331        mptsas_fw_event_off(ioc);
5332        mptsas_cleanup_fw_event_q(ioc);
5333}
5334
5335static void __devexit mptsas_remove(struct pci_dev *pdev)
5336{
5337        MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
5338        struct mptsas_portinfo *p, *n;
5339        int i;
5340
5341        if (!ioc->sh) {
5342                printk(MYIOC_s_INFO_FMT "IOC is in Target mode\n", ioc->name);
5343                mpt_detach(pdev);
5344                return;
5345        }
5346
5347        mptsas_shutdown(pdev);
5348
5349        mptsas_del_device_components(ioc);
5350
5351        ioc->sas_discovery_ignore_events = 1;
5352        sas_remove_host(ioc->sh);
5353
5354        mutex_lock(&ioc->sas_topology_mutex);
5355        list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
5356                list_del(&p->list);
5357                for (i = 0 ; i < p->num_phys ; i++)
5358                        mptsas_port_delete(ioc, p->phy_info[i].port_details);
5359
5360                kfree(p->phy_info);
5361                kfree(p);
5362        }
5363        mutex_unlock(&ioc->sas_topology_mutex);
5364        ioc->hba_port_info = NULL;
5365        mptscsih_remove(pdev);
5366}
5367
5368static struct pci_device_id mptsas_pci_table[] = {
5369        { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064,
5370                PCI_ANY_ID, PCI_ANY_ID },
5371        { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068,
5372                PCI_ANY_ID, PCI_ANY_ID },
5373        { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064E,
5374                PCI_ANY_ID, PCI_ANY_ID },
5375        { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068E,
5376                PCI_ANY_ID, PCI_ANY_ID },
5377        { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1078,
5378                PCI_ANY_ID, PCI_ANY_ID },
5379        {0}     /* Terminating entry */
5380};
5381MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
5382
5383
5384static struct pci_driver mptsas_driver = {
5385        .name           = "mptsas",
5386        .id_table       = mptsas_pci_table,
5387        .probe          = mptsas_probe,
5388        .remove         = __devexit_p(mptsas_remove),
5389        .shutdown       = mptsas_shutdown,
5390#ifdef CONFIG_PM
5391        .suspend        = mptscsih_suspend,
5392        .resume         = mptscsih_resume,
5393#endif
5394};
5395
5396static int __init
5397mptsas_init(void)
5398{
5399        int error;
5400
5401        show_mptmod_ver(my_NAME, my_VERSION);
5402
5403        mptsas_transport_template =
5404            sas_attach_transport(&mptsas_transport_functions);
5405        if (!mptsas_transport_template)
5406                return -ENODEV;
5407        mptsas_transport_template->eh_timed_out = mptsas_eh_timed_out;
5408
5409        mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER,
5410            "mptscsih_io_done");
5411        mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER,
5412            "mptscsih_taskmgmt_complete");
5413        mptsasInternalCtx =
5414                mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER,
5415                    "mptscsih_scandv_complete");
5416        mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER,
5417            "mptsas_mgmt_done");
5418        mptsasDeviceResetCtx =
5419                mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER,
5420                    "mptsas_taskmgmt_complete");
5421
5422        mpt_event_register(mptsasDoneCtx, mptsas_event_process);
5423        mpt_reset_register(mptsasDoneCtx, mptsas_ioc_reset);
5424
5425        error = pci_register_driver(&mptsas_driver);
5426        if (error)
5427                sas_release_transport(mptsas_transport_template);
5428
5429        return error;
5430}
5431
5432static void __exit
5433mptsas_exit(void)
5434{
5435        pci_unregister_driver(&mptsas_driver);
5436        sas_release_transport(mptsas_transport_template);
5437
5438        mpt_reset_deregister(mptsasDoneCtx);
5439        mpt_event_deregister(mptsasDoneCtx);
5440
5441        mpt_deregister(mptsasMgmtCtx);
5442        mpt_deregister(mptsasInternalCtx);
5443        mpt_deregister(mptsasTaskCtx);
5444        mpt_deregister(mptsasDoneCtx);
5445        mpt_deregister(mptsasDeviceResetCtx);
5446}
5447
5448module_init(mptsas_init);
5449module_exit(mptsas_exit);
5450