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