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