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