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