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