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