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