PageRenderTime 68ms CodeModel.GetById 8ms app.highlight 42ms RepoModel.GetById 1ms app.codeStats 1ms

/drivers/message/fusion/mptsas.c

https://bitbucket.org/wisechild/galaxy-nexus
C | 5416 lines | 4279 code | 669 blank | 468 comment | 596 complexity | 71677b1d80352a180e7c6361b27e0e19 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0

Large files files are truncated, but you can click here to view the full file

   1/*
   2 *  linux/drivers/message/fusion/mptsas.c
   3 *      For use with LSI PCI chip/adapter(s)
   4 *      running LSI Fusion MPT (Message Passing Technology) firmware.
   5 *
   6 *  Copyright (c) 1999-2008 LSI Corporation
   7 *  (mailto:DL-MPTFusionLinux@lsi.com)
   8 */
   9/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  10/*
  11    This program is free software; you can redistribute it and/or modify
  12    it under the terms of the GNU General Public License as published by
  13    the Free Software Foundation; version 2 of the License.
  14
  15    This program is distributed in the hope that it will be useful,
  16    but WITHOUT ANY WARRANTY; without even the implied warranty of
  17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18    GNU General Public License for more details.
  19
  20    NO WARRANTY
  21    THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
  22    CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
  23    LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
  24    MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
  25    solely responsible for determining the appropriateness of using and
  26    distributing the Program and assumes all risks associated with its
  27    exercise of rights under this Agreement, including but not limited to
  28    the risks and costs of program errors, damage to or loss of data,
  29    programs or equipment, and unavailability or interruption of operations.
  30
  31    DISCLAIMER OF LIABILITY
  32    NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
  33    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  34    DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
  35    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
  36    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  37    USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
  38    HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
  39
  40    You should have received a copy of the GNU General Public License
  41    along with this program; if not, write to the Free Software
  42    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  43*/
  44/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  45
  46#include <linux/module.h>
  47#include <linux/kernel.h>
  48#include <linux/slab.h>
  49#include <linux/init.h>
  50#include <linux/errno.h>
  51#include <linux/jiffies.h>
  52#include <linux/workqueue.h>
  53#include <linux/delay.h>	/* for mdelay */
  54
  55#include <scsi/scsi.h>
  56#include <scsi/scsi_cmnd.h>
  57#include <scsi/scsi_device.h>
  58#include <scsi/scsi_host.h>
  59#include <scsi/scsi_transport_sas.h>
  60#include <scsi/scsi_transport.h>
  61#include <scsi/scsi_dbg.h>
  62
  63#include "mptbase.h"
  64#include "mptscsih.h"
  65#include "mptsas.h"
  66
  67
  68#define my_NAME		"Fusion MPT SAS Host driver"
  69#define my_VERSION	MPT_LINUX_VERSION_COMMON
  70#define MYNAM		"mptsas"
  71
  72/*
  73 * Reserved channel for integrated raid
  74 */
  75#define MPTSAS_RAID_CHANNEL	1
  76
  77#define SAS_CONFIG_PAGE_TIMEOUT		30
  78MODULE_AUTHOR(MODULEAUTHOR);
  79MODULE_DESCRIPTION(my_NAME);
  80MODULE_LICENSE("GPL");
  81MODULE_VERSION(my_VERSION);
  82
  83static int mpt_pt_clear;
  84module_param(mpt_pt_clear, int, 0);
  85MODULE_PARM_DESC(mpt_pt_clear,
  86		" Clear persistency table: enable=1  "
  87		"(default=MPTSCSIH_PT_CLEAR=0)");
  88
  89/* scsi-mid layer global parmeter is max_report_luns, which is 511 */
  90#define MPTSAS_MAX_LUN (16895)
  91static int max_lun = MPTSAS_MAX_LUN;
  92module_param(max_lun, int, 0);
  93MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
  94
  95static u8	mptsasDoneCtx = MPT_MAX_PROTOCOL_DRIVERS;
  96static u8	mptsasTaskCtx = MPT_MAX_PROTOCOL_DRIVERS;
  97static u8	mptsasInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; /* Used only for internal commands */
  98static u8	mptsasMgmtCtx = MPT_MAX_PROTOCOL_DRIVERS;
  99static u8	mptsasDeviceResetCtx = MPT_MAX_PROTOCOL_DRIVERS;
 100
 101static void mptsas_firmware_event_work(struct work_struct *work);
 102static void mptsas_send_sas_event(struct fw_event_work *fw_event);
 103static void mptsas_send_raid_event(struct fw_event_work *fw_event);
 104static void mptsas_send_ir2_event(struct fw_event_work *fw_event);
 105static void mptsas_parse_device_info(struct sas_identify *identify,
 106		struct mptsas_devinfo *device_info);
 107static inline void mptsas_set_rphy(MPT_ADAPTER *ioc,
 108		struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy);
 109static struct mptsas_phyinfo	*mptsas_find_phyinfo_by_sas_address
 110		(MPT_ADAPTER *ioc, u64 sas_address);
 111static int mptsas_sas_device_pg0(MPT_ADAPTER *ioc,
 112	struct mptsas_devinfo *device_info, u32 form, u32 form_specific);
 113static int mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc,
 114	struct mptsas_enclosure *enclosure, u32 form, u32 form_specific);
 115static int mptsas_add_end_device(MPT_ADAPTER *ioc,
 116	struct mptsas_phyinfo *phy_info);
 117static void mptsas_del_end_device(MPT_ADAPTER *ioc,
 118	struct mptsas_phyinfo *phy_info);
 119static void mptsas_send_link_status_event(struct fw_event_work *fw_event);
 120static struct mptsas_portinfo	*mptsas_find_portinfo_by_sas_address
 121		(MPT_ADAPTER *ioc, u64 sas_address);
 122static void mptsas_expander_delete(MPT_ADAPTER *ioc,
 123		struct mptsas_portinfo *port_info, u8 force);
 124static void mptsas_send_expander_event(struct fw_event_work *fw_event);
 125static void mptsas_not_responding_devices(MPT_ADAPTER *ioc);
 126static void mptsas_scan_sas_topology(MPT_ADAPTER *ioc);
 127static void mptsas_broadcast_primative_work(struct fw_event_work *fw_event);
 128static void mptsas_handle_queue_full_event(struct fw_event_work *fw_event);
 129static void mptsas_volume_delete(MPT_ADAPTER *ioc, u8 id);
 130void	mptsas_schedule_target_reset(void *ioc);
 131
 132static void mptsas_print_phy_data(MPT_ADAPTER *ioc,
 133					MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
 134{
 135	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 136	    "---- IO UNIT PAGE 0 ------------\n", ioc->name));
 137	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handle=0x%X\n",
 138	    ioc->name, le16_to_cpu(phy_data->AttachedDeviceHandle)));
 139	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Controller Handle=0x%X\n",
 140	    ioc->name, le16_to_cpu(phy_data->ControllerDevHandle)));
 141	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Port=0x%X\n",
 142	    ioc->name, phy_data->Port));
 143	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Port Flags=0x%X\n",
 144	    ioc->name, phy_data->PortFlags));
 145	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Flags=0x%X\n",
 146	    ioc->name, phy_data->PhyFlags));
 147	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Negotiated Link Rate=0x%X\n",
 148	    ioc->name, phy_data->NegotiatedLinkRate));
 149	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 150	    "Controller PHY Device Info=0x%X\n", ioc->name,
 151	    le32_to_cpu(phy_data->ControllerPhyDeviceInfo)));
 152	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DiscoveryStatus=0x%X\n\n",
 153	    ioc->name, le32_to_cpu(phy_data->DiscoveryStatus)));
 154}
 155
 156static void mptsas_print_phy_pg0(MPT_ADAPTER *ioc, SasPhyPage0_t *pg0)
 157{
 158	__le64 sas_address;
 159
 160	memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
 161
 162	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 163	    "---- SAS PHY PAGE 0 ------------\n", ioc->name));
 164	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 165	    "Attached Device Handle=0x%X\n", ioc->name,
 166	    le16_to_cpu(pg0->AttachedDevHandle)));
 167	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SAS Address=0x%llX\n",
 168	    ioc->name, (unsigned long long)le64_to_cpu(sas_address)));
 169	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 170	    "Attached PHY Identifier=0x%X\n", ioc->name,
 171	    pg0->AttachedPhyIdentifier));
 172	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Attached Device Info=0x%X\n",
 173	    ioc->name, le32_to_cpu(pg0->AttachedDeviceInfo)));
 174	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Programmed Link Rate=0x%X\n",
 175	    ioc->name,  pg0->ProgrammedLinkRate));
 176	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Change Count=0x%X\n",
 177	    ioc->name, pg0->ChangeCount));
 178	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Info=0x%X\n\n",
 179	    ioc->name, le32_to_cpu(pg0->PhyInfo)));
 180}
 181
 182static void mptsas_print_phy_pg1(MPT_ADAPTER *ioc, SasPhyPage1_t *pg1)
 183{
 184	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 185	    "---- SAS PHY PAGE 1 ------------\n", ioc->name));
 186	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Invalid Dword Count=0x%x\n",
 187	    ioc->name,  pg1->InvalidDwordCount));
 188	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 189	    "Running Disparity Error Count=0x%x\n", ioc->name,
 190	    pg1->RunningDisparityErrorCount));
 191	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 192	    "Loss Dword Synch Count=0x%x\n", ioc->name,
 193	    pg1->LossDwordSynchCount));
 194	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 195	    "PHY Reset Problem Count=0x%x\n\n", ioc->name,
 196	    pg1->PhyResetProblemCount));
 197}
 198
 199static void mptsas_print_device_pg0(MPT_ADAPTER *ioc, SasDevicePage0_t *pg0)
 200{
 201	__le64 sas_address;
 202
 203	memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
 204
 205	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 206	    "---- SAS DEVICE PAGE 0 ---------\n", ioc->name));
 207	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handle=0x%X\n",
 208	    ioc->name, le16_to_cpu(pg0->DevHandle)));
 209	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Parent Handle=0x%X\n",
 210	    ioc->name, le16_to_cpu(pg0->ParentDevHandle)));
 211	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Enclosure Handle=0x%X\n",
 212	    ioc->name, le16_to_cpu(pg0->EnclosureHandle)));
 213	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Slot=0x%X\n",
 214	    ioc->name, le16_to_cpu(pg0->Slot)));
 215	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SAS Address=0x%llX\n",
 216	    ioc->name, (unsigned long long)le64_to_cpu(sas_address)));
 217	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Target ID=0x%X\n",
 218	    ioc->name, pg0->TargetID));
 219	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Bus=0x%X\n",
 220	    ioc->name, pg0->Bus));
 221	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Parent Phy Num=0x%X\n",
 222	    ioc->name, pg0->PhyNum));
 223	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Access Status=0x%X\n",
 224	    ioc->name, le16_to_cpu(pg0->AccessStatus)));
 225	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Device Info=0x%X\n",
 226	    ioc->name, le32_to_cpu(pg0->DeviceInfo)));
 227	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Flags=0x%X\n",
 228	    ioc->name, le16_to_cpu(pg0->Flags)));
 229	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Physical Port=0x%X\n\n",
 230	    ioc->name, pg0->PhysicalPort));
 231}
 232
 233static void mptsas_print_expander_pg1(MPT_ADAPTER *ioc, SasExpanderPage1_t *pg1)
 234{
 235	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 236	    "---- SAS EXPANDER PAGE 1 ------------\n", ioc->name));
 237	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Physical Port=0x%X\n",
 238	    ioc->name, pg1->PhysicalPort));
 239	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Identifier=0x%X\n",
 240	    ioc->name, pg1->PhyIdentifier));
 241	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Negotiated Link Rate=0x%X\n",
 242	    ioc->name, pg1->NegotiatedLinkRate));
 243	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Programmed Link Rate=0x%X\n",
 244	    ioc->name, pg1->ProgrammedLinkRate));
 245	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Hardware Link Rate=0x%X\n",
 246	    ioc->name, pg1->HwLinkRate));
 247	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Owner Device Handle=0x%X\n",
 248	    ioc->name, le16_to_cpu(pg1->OwnerDevHandle)));
 249	dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 250	    "Attached Device Handle=0x%X\n\n", ioc->name,
 251	    le16_to_cpu(pg1->AttachedDevHandle)));
 252}
 253
 254/* inhibit sas firmware event handling */
 255static void
 256mptsas_fw_event_off(MPT_ADAPTER *ioc)
 257{
 258	unsigned long flags;
 259
 260	spin_lock_irqsave(&ioc->fw_event_lock, flags);
 261	ioc->fw_events_off = 1;
 262	ioc->sas_discovery_quiesce_io = 0;
 263	spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
 264
 265}
 266
 267/* enable sas firmware event handling */
 268static void
 269mptsas_fw_event_on(MPT_ADAPTER *ioc)
 270{
 271	unsigned long flags;
 272
 273	spin_lock_irqsave(&ioc->fw_event_lock, flags);
 274	ioc->fw_events_off = 0;
 275	spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
 276}
 277
 278/* queue a sas firmware event */
 279static void
 280mptsas_add_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
 281    unsigned long delay)
 282{
 283	unsigned long flags;
 284
 285	spin_lock_irqsave(&ioc->fw_event_lock, flags);
 286	list_add_tail(&fw_event->list, &ioc->fw_event_list);
 287	INIT_DELAYED_WORK(&fw_event->work, mptsas_firmware_event_work);
 288	devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: add (fw_event=0x%p)\n",
 289	    ioc->name, __func__, fw_event));
 290	queue_delayed_work(ioc->fw_event_q, &fw_event->work,
 291	    delay);
 292	spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
 293}
 294
 295/* requeue a sas firmware event */
 296static void
 297mptsas_requeue_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
 298    unsigned long delay)
 299{
 300	unsigned long flags;
 301	spin_lock_irqsave(&ioc->fw_event_lock, flags);
 302	devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: reschedule task "
 303	    "(fw_event=0x%p)\n", ioc->name, __func__, fw_event));
 304	fw_event->retries++;
 305	queue_delayed_work(ioc->fw_event_q, &fw_event->work,
 306	    msecs_to_jiffies(delay));
 307	spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
 308}
 309
 310/* free memory associated to a sas firmware event */
 311static void
 312mptsas_free_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event)
 313{
 314	unsigned long flags;
 315
 316	spin_lock_irqsave(&ioc->fw_event_lock, flags);
 317	devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: kfree (fw_event=0x%p)\n",
 318	    ioc->name, __func__, fw_event));
 319	list_del(&fw_event->list);
 320	kfree(fw_event);
 321	spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
 322}
 323
 324/* walk the firmware event queue, and either stop or wait for
 325 * outstanding events to complete */
 326static void
 327mptsas_cleanup_fw_event_q(MPT_ADAPTER *ioc)
 328{
 329	struct fw_event_work *fw_event, *next;
 330	struct mptsas_target_reset_event *target_reset_list, *n;
 331	MPT_SCSI_HOST	*hd = shost_priv(ioc->sh);
 332
 333	/* flush the target_reset_list */
 334	if (!list_empty(&hd->target_reset_list)) {
 335		list_for_each_entry_safe(target_reset_list, n,
 336		    &hd->target_reset_list, list) {
 337			dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 338			    "%s: removing target reset for id=%d\n",
 339			    ioc->name, __func__,
 340			   target_reset_list->sas_event_data.TargetID));
 341			list_del(&target_reset_list->list);
 342			kfree(target_reset_list);
 343		}
 344	}
 345
 346	if (list_empty(&ioc->fw_event_list) ||
 347	     !ioc->fw_event_q || in_interrupt())
 348		return;
 349
 350	list_for_each_entry_safe(fw_event, next, &ioc->fw_event_list, list) {
 351		if (cancel_delayed_work(&fw_event->work))
 352			mptsas_free_fw_event(ioc, fw_event);
 353	}
 354}
 355
 356
 357static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
 358{
 359	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
 360	return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
 361}
 362
 363static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
 364{
 365	struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
 366	return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
 367}
 368
 369/*
 370 * mptsas_find_portinfo_by_handle
 371 *
 372 * This function should be called with the sas_topology_mutex already held
 373 */
 374static struct mptsas_portinfo *
 375mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
 376{
 377	struct mptsas_portinfo *port_info, *rc=NULL;
 378	int i;
 379
 380	list_for_each_entry(port_info, &ioc->sas_topology, list)
 381		for (i = 0; i < port_info->num_phys; i++)
 382			if (port_info->phy_info[i].identify.handle == handle) {
 383				rc = port_info;
 384				goto out;
 385			}
 386 out:
 387	return rc;
 388}
 389
 390/**
 391 *	mptsas_find_portinfo_by_sas_address -
 392 *	@ioc: Pointer to MPT_ADAPTER structure
 393 *	@handle:
 394 *
 395 *	This function should be called with the sas_topology_mutex already held
 396 *
 397 **/
 398static struct mptsas_portinfo *
 399mptsas_find_portinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
 400{
 401	struct mptsas_portinfo *port_info, *rc = NULL;
 402	int i;
 403
 404	if (sas_address >= ioc->hba_port_sas_addr &&
 405	    sas_address < (ioc->hba_port_sas_addr +
 406	    ioc->hba_port_num_phy))
 407		return ioc->hba_port_info;
 408
 409	mutex_lock(&ioc->sas_topology_mutex);
 410	list_for_each_entry(port_info, &ioc->sas_topology, list)
 411		for (i = 0; i < port_info->num_phys; i++)
 412			if (port_info->phy_info[i].identify.sas_address ==
 413			    sas_address) {
 414				rc = port_info;
 415				goto out;
 416			}
 417 out:
 418	mutex_unlock(&ioc->sas_topology_mutex);
 419	return rc;
 420}
 421
 422/*
 423 * Returns true if there is a scsi end device
 424 */
 425static inline int
 426mptsas_is_end_device(struct mptsas_devinfo * attached)
 427{
 428	if ((attached->sas_address) &&
 429	    (attached->device_info &
 430	    MPI_SAS_DEVICE_INFO_END_DEVICE) &&
 431	    ((attached->device_info &
 432	    MPI_SAS_DEVICE_INFO_SSP_TARGET) |
 433	    (attached->device_info &
 434	    MPI_SAS_DEVICE_INFO_STP_TARGET) |
 435	    (attached->device_info &
 436	    MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
 437		return 1;
 438	else
 439		return 0;
 440}
 441
 442/* no mutex */
 443static void
 444mptsas_port_delete(MPT_ADAPTER *ioc, struct mptsas_portinfo_details * port_details)
 445{
 446	struct mptsas_portinfo *port_info;
 447	struct mptsas_phyinfo *phy_info;
 448	u8	i;
 449
 450	if (!port_details)
 451		return;
 452
 453	port_info = port_details->port_info;
 454	phy_info = port_info->phy_info;
 455
 456	dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: [%p]: num_phys=%02d "
 457	    "bitmask=0x%016llX\n", ioc->name, __func__, port_details,
 458	    port_details->num_phys, (unsigned long long)
 459	    port_details->phy_bitmask));
 460
 461	for (i = 0; i < port_info->num_phys; i++, phy_info++) {
 462		if(phy_info->port_details != port_details)
 463			continue;
 464		memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
 465		mptsas_set_rphy(ioc, phy_info, NULL);
 466		phy_info->port_details = NULL;
 467	}
 468	kfree(port_details);
 469}
 470
 471static inline struct sas_rphy *
 472mptsas_get_rphy(struct mptsas_phyinfo *phy_info)
 473{
 474	if (phy_info->port_details)
 475		return phy_info->port_details->rphy;
 476	else
 477		return NULL;
 478}
 479
 480static inline void
 481mptsas_set_rphy(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy)
 482{
 483	if (phy_info->port_details) {
 484		phy_info->port_details->rphy = rphy;
 485		dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sas_rphy_add: rphy=%p\n",
 486		    ioc->name, rphy));
 487	}
 488
 489	if (rphy) {
 490		dsaswideprintk(ioc, dev_printk(KERN_DEBUG,
 491		    &rphy->dev, MYIOC_s_FMT "add:", ioc->name));
 492		dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "rphy=%p release=%p\n",
 493		    ioc->name, rphy, rphy->dev.release));
 494	}
 495}
 496
 497static inline struct sas_port *
 498mptsas_get_port(struct mptsas_phyinfo *phy_info)
 499{
 500	if (phy_info->port_details)
 501		return phy_info->port_details->port;
 502	else
 503		return NULL;
 504}
 505
 506static inline void
 507mptsas_set_port(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_port *port)
 508{
 509	if (phy_info->port_details)
 510		phy_info->port_details->port = port;
 511
 512	if (port) {
 513		dsaswideprintk(ioc, dev_printk(KERN_DEBUG,
 514		    &port->dev, MYIOC_s_FMT "add:", ioc->name));
 515		dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "port=%p release=%p\n",
 516		    ioc->name, port, port->dev.release));
 517	}
 518}
 519
 520static inline struct scsi_target *
 521mptsas_get_starget(struct mptsas_phyinfo *phy_info)
 522{
 523	if (phy_info->port_details)
 524		return phy_info->port_details->starget;
 525	else
 526		return NULL;
 527}
 528
 529static inline void
 530mptsas_set_starget(struct mptsas_phyinfo *phy_info, struct scsi_target *
 531starget)
 532{
 533	if (phy_info->port_details)
 534		phy_info->port_details->starget = starget;
 535}
 536
 537/**
 538 *	mptsas_add_device_component -
 539 *	@ioc: Pointer to MPT_ADAPTER structure
 540 *	@channel: fw mapped id's
 541 *	@id:
 542 *	@sas_address:
 543 *	@device_info:
 544 *
 545 **/
 546static void
 547mptsas_add_device_component(MPT_ADAPTER *ioc, u8 channel, u8 id,
 548	u64 sas_address, u32 device_info, u16 slot, u64 enclosure_logical_id)
 549{
 550	struct mptsas_device_info	*sas_info, *next;
 551	struct scsi_device	*sdev;
 552	struct scsi_target	*starget;
 553	struct sas_rphy	*rphy;
 554
 555	/*
 556	 * Delete all matching devices out of the list
 557	 */
 558	mutex_lock(&ioc->sas_device_info_mutex);
 559	list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
 560	    list) {
 561		if (!sas_info->is_logical_volume &&
 562		    (sas_info->sas_address == sas_address ||
 563		    (sas_info->fw.channel == channel &&
 564		     sas_info->fw.id == id))) {
 565			list_del(&sas_info->list);
 566			kfree(sas_info);
 567		}
 568	}
 569
 570	sas_info = kzalloc(sizeof(struct mptsas_device_info), GFP_KERNEL);
 571	if (!sas_info)
 572		goto out;
 573
 574	/*
 575	 * Set Firmware mapping
 576	 */
 577	sas_info->fw.id = id;
 578	sas_info->fw.channel = channel;
 579
 580	sas_info->sas_address = sas_address;
 581	sas_info->device_info = device_info;
 582	sas_info->slot = slot;
 583	sas_info->enclosure_logical_id = enclosure_logical_id;
 584	INIT_LIST_HEAD(&sas_info->list);
 585	list_add_tail(&sas_info->list, &ioc->sas_device_info_list);
 586
 587	/*
 588	 * Set OS mapping
 589	 */
 590	shost_for_each_device(sdev, ioc->sh) {
 591		starget = scsi_target(sdev);
 592		rphy = dev_to_rphy(starget->dev.parent);
 593		if (rphy->identify.sas_address == sas_address) {
 594			sas_info->os.id = starget->id;
 595			sas_info->os.channel = starget->channel;
 596		}
 597	}
 598
 599 out:
 600	mutex_unlock(&ioc->sas_device_info_mutex);
 601	return;
 602}
 603
 604/**
 605 *	mptsas_add_device_component_by_fw -
 606 *	@ioc: Pointer to MPT_ADAPTER structure
 607 *	@channel:  fw mapped id's
 608 *	@id:
 609 *
 610 **/
 611static void
 612mptsas_add_device_component_by_fw(MPT_ADAPTER *ioc, u8 channel, u8 id)
 613{
 614	struct mptsas_devinfo sas_device;
 615	struct mptsas_enclosure enclosure_info;
 616	int rc;
 617
 618	rc = mptsas_sas_device_pg0(ioc, &sas_device,
 619	    (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
 620	     MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
 621	    (channel << 8) + id);
 622	if (rc)
 623		return;
 624
 625	memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
 626	mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
 627	    (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
 628	     MPI_SAS_ENCLOS_PGAD_FORM_SHIFT),
 629	     sas_device.handle_enclosure);
 630
 631	mptsas_add_device_component(ioc, sas_device.channel,
 632	    sas_device.id, sas_device.sas_address, sas_device.device_info,
 633	    sas_device.slot, enclosure_info.enclosure_logical_id);
 634}
 635
 636/**
 637 *	mptsas_add_device_component_starget_ir - Handle Integrated RAID, adding each individual device to list
 638 *	@ioc: Pointer to MPT_ADAPTER structure
 639 *	@channel: fw mapped id's
 640 *	@id:
 641 *
 642 **/
 643static void
 644mptsas_add_device_component_starget_ir(MPT_ADAPTER *ioc,
 645		struct scsi_target *starget)
 646{
 647	CONFIGPARMS			cfg;
 648	ConfigPageHeader_t		hdr;
 649	dma_addr_t			dma_handle;
 650	pRaidVolumePage0_t		buffer = NULL;
 651	int				i;
 652	RaidPhysDiskPage0_t 		phys_disk;
 653	struct mptsas_device_info	*sas_info, *next;
 654
 655	memset(&cfg, 0 , sizeof(CONFIGPARMS));
 656	memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
 657	hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
 658	/* assumption that all volumes on channel = 0 */
 659	cfg.pageAddr = starget->id;
 660	cfg.cfghdr.hdr = &hdr;
 661	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
 662	cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
 663
 664	if (mpt_config(ioc, &cfg) != 0)
 665		goto out;
 666
 667	if (!hdr.PageLength)
 668		goto out;
 669
 670	buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
 671	    &dma_handle);
 672
 673	if (!buffer)
 674		goto out;
 675
 676	cfg.physAddr = dma_handle;
 677	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
 678
 679	if (mpt_config(ioc, &cfg) != 0)
 680		goto out;
 681
 682	if (!buffer->NumPhysDisks)
 683		goto out;
 684
 685	/*
 686	 * Adding entry for hidden components
 687	 */
 688	for (i = 0; i < buffer->NumPhysDisks; i++) {
 689
 690		if (mpt_raid_phys_disk_pg0(ioc,
 691		    buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
 692			continue;
 693
 694		mptsas_add_device_component_by_fw(ioc, phys_disk.PhysDiskBus,
 695		    phys_disk.PhysDiskID);
 696
 697		mutex_lock(&ioc->sas_device_info_mutex);
 698		list_for_each_entry(sas_info, &ioc->sas_device_info_list,
 699		    list) {
 700			if (!sas_info->is_logical_volume &&
 701			    (sas_info->fw.channel == phys_disk.PhysDiskBus &&
 702			    sas_info->fw.id == phys_disk.PhysDiskID)) {
 703				sas_info->is_hidden_raid_component = 1;
 704				sas_info->volume_id = starget->id;
 705			}
 706		}
 707		mutex_unlock(&ioc->sas_device_info_mutex);
 708
 709	}
 710
 711	/*
 712	 * Delete all matching devices out of the list
 713	 */
 714	mutex_lock(&ioc->sas_device_info_mutex);
 715	list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
 716	    list) {
 717		if (sas_info->is_logical_volume && sas_info->fw.id ==
 718		    starget->id) {
 719			list_del(&sas_info->list);
 720			kfree(sas_info);
 721		}
 722	}
 723
 724	sas_info = kzalloc(sizeof(struct mptsas_device_info), GFP_KERNEL);
 725	if (sas_info) {
 726		sas_info->fw.id = starget->id;
 727		sas_info->os.id = starget->id;
 728		sas_info->os.channel = starget->channel;
 729		sas_info->is_logical_volume = 1;
 730		INIT_LIST_HEAD(&sas_info->list);
 731		list_add_tail(&sas_info->list, &ioc->sas_device_info_list);
 732	}
 733	mutex_unlock(&ioc->sas_device_info_mutex);
 734
 735 out:
 736	if (buffer)
 737		pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
 738		    dma_handle);
 739}
 740
 741/**
 742 *	mptsas_add_device_component_starget -
 743 *	@ioc: Pointer to MPT_ADAPTER structure
 744 *	@starget:
 745 *
 746 **/
 747static void
 748mptsas_add_device_component_starget(MPT_ADAPTER *ioc,
 749	struct scsi_target *starget)
 750{
 751	VirtTarget	*vtarget;
 752	struct sas_rphy	*rphy;
 753	struct mptsas_phyinfo	*phy_info = NULL;
 754	struct mptsas_enclosure	enclosure_info;
 755
 756	rphy = dev_to_rphy(starget->dev.parent);
 757	vtarget = starget->hostdata;
 758	phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
 759			rphy->identify.sas_address);
 760	if (!phy_info)
 761		return;
 762
 763	memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
 764	mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
 765		(MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
 766		MPI_SAS_ENCLOS_PGAD_FORM_SHIFT),
 767		phy_info->attached.handle_enclosure);
 768
 769	mptsas_add_device_component(ioc, phy_info->attached.channel,
 770		phy_info->attached.id, phy_info->attached.sas_address,
 771		phy_info->attached.device_info,
 772		phy_info->attached.slot, enclosure_info.enclosure_logical_id);
 773}
 774
 775/**
 776 *	mptsas_del_device_component_by_os - Once a device has been removed, we mark the entry in the list as being cached
 777 *	@ioc: Pointer to MPT_ADAPTER structure
 778 *	@channel: os mapped id's
 779 *	@id:
 780 *
 781 **/
 782static void
 783mptsas_del_device_component_by_os(MPT_ADAPTER *ioc, u8 channel, u8 id)
 784{
 785	struct mptsas_device_info	*sas_info, *next;
 786
 787	/*
 788	 * Set is_cached flag
 789	 */
 790	list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
 791		list) {
 792		if (sas_info->os.channel == channel && sas_info->os.id == id)
 793			sas_info->is_cached = 1;
 794	}
 795}
 796
 797/**
 798 *	mptsas_del_device_components - Cleaning the list
 799 *	@ioc: Pointer to MPT_ADAPTER structure
 800 *
 801 **/
 802static void
 803mptsas_del_device_components(MPT_ADAPTER *ioc)
 804{
 805	struct mptsas_device_info	*sas_info, *next;
 806
 807	mutex_lock(&ioc->sas_device_info_mutex);
 808	list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
 809		list) {
 810		list_del(&sas_info->list);
 811		kfree(sas_info);
 812	}
 813	mutex_unlock(&ioc->sas_device_info_mutex);
 814}
 815
 816
 817/*
 818 * mptsas_setup_wide_ports
 819 *
 820 * Updates for new and existing narrow/wide port configuration
 821 * in the sas_topology
 822 */
 823static void
 824mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
 825{
 826	struct mptsas_portinfo_details * port_details;
 827	struct mptsas_phyinfo *phy_info, *phy_info_cmp;
 828	u64	sas_address;
 829	int	i, j;
 830
 831	mutex_lock(&ioc->sas_topology_mutex);
 832
 833	phy_info = port_info->phy_info;
 834	for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
 835		if (phy_info->attached.handle)
 836			continue;
 837		port_details = phy_info->port_details;
 838		if (!port_details)
 839			continue;
 840		if (port_details->num_phys < 2)
 841			continue;
 842		/*
 843		 * Removing a phy from a port, letting the last
 844		 * phy be removed by firmware events.
 845		 */
 846		dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 847		    "%s: [%p]: deleting phy = %d\n",
 848		    ioc->name, __func__, port_details, i));
 849		port_details->num_phys--;
 850		port_details->phy_bitmask &= ~ (1 << phy_info->phy_id);
 851		memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
 852		if (phy_info->phy) {
 853			devtprintk(ioc, dev_printk(KERN_DEBUG,
 854				&phy_info->phy->dev, MYIOC_s_FMT
 855				"delete phy %d, phy-obj (0x%p)\n", ioc->name,
 856				phy_info->phy_id, phy_info->phy));
 857			sas_port_delete_phy(port_details->port, phy_info->phy);
 858		}
 859		phy_info->port_details = NULL;
 860	}
 861
 862	/*
 863	 * Populate and refresh the tree
 864	 */
 865	phy_info = port_info->phy_info;
 866	for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
 867		sas_address = phy_info->attached.sas_address;
 868		dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "phy_id=%d sas_address=0x%018llX\n",
 869		    ioc->name, i, (unsigned long long)sas_address));
 870		if (!sas_address)
 871			continue;
 872		port_details = phy_info->port_details;
 873		/*
 874		 * Forming a port
 875		 */
 876		if (!port_details) {
 877			port_details = kzalloc(sizeof(struct
 878				mptsas_portinfo_details), GFP_KERNEL);
 879			if (!port_details)
 880				goto out;
 881			port_details->num_phys = 1;
 882			port_details->port_info = port_info;
 883			if (phy_info->phy_id < 64 )
 884				port_details->phy_bitmask |=
 885				    (1 << phy_info->phy_id);
 886			phy_info->sas_port_add_phy=1;
 887			dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tForming port\n\t\t"
 888			    "phy_id=%d sas_address=0x%018llX\n",
 889			    ioc->name, i, (unsigned long long)sas_address));
 890			phy_info->port_details = port_details;
 891		}
 892
 893		if (i == port_info->num_phys - 1)
 894			continue;
 895		phy_info_cmp = &port_info->phy_info[i + 1];
 896		for (j = i + 1 ; j < port_info->num_phys ; j++,
 897		    phy_info_cmp++) {
 898			if (!phy_info_cmp->attached.sas_address)
 899				continue;
 900			if (sas_address != phy_info_cmp->attached.sas_address)
 901				continue;
 902			if (phy_info_cmp->port_details == port_details )
 903				continue;
 904			dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 905			    "\t\tphy_id=%d sas_address=0x%018llX\n",
 906			    ioc->name, j, (unsigned long long)
 907			    phy_info_cmp->attached.sas_address));
 908			if (phy_info_cmp->port_details) {
 909				port_details->rphy =
 910				    mptsas_get_rphy(phy_info_cmp);
 911				port_details->port =
 912				    mptsas_get_port(phy_info_cmp);
 913				port_details->starget =
 914				    mptsas_get_starget(phy_info_cmp);
 915				port_details->num_phys =
 916					phy_info_cmp->port_details->num_phys;
 917				if (!phy_info_cmp->port_details->num_phys)
 918					kfree(phy_info_cmp->port_details);
 919			} else
 920				phy_info_cmp->sas_port_add_phy=1;
 921			/*
 922			 * Adding a phy to a port
 923			 */
 924			phy_info_cmp->port_details = port_details;
 925			if (phy_info_cmp->phy_id < 64 )
 926				port_details->phy_bitmask |=
 927				(1 << phy_info_cmp->phy_id);
 928			port_details->num_phys++;
 929		}
 930	}
 931
 932 out:
 933
 934	for (i = 0; i < port_info->num_phys; i++) {
 935		port_details = port_info->phy_info[i].port_details;
 936		if (!port_details)
 937			continue;
 938		dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 939		    "%s: [%p]: phy_id=%02d num_phys=%02d "
 940		    "bitmask=0x%016llX\n", ioc->name, __func__,
 941		    port_details, i, port_details->num_phys,
 942		    (unsigned long long)port_details->phy_bitmask));
 943		dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tport = %p rphy=%p\n",
 944		    ioc->name, port_details->port, port_details->rphy));
 945	}
 946	dsaswideprintk(ioc, printk("\n"));
 947	mutex_unlock(&ioc->sas_topology_mutex);
 948}
 949
 950/**
 951 * csmisas_find_vtarget
 952 *
 953 * @ioc
 954 * @volume_id
 955 * @volume_bus
 956 *
 957 **/
 958static VirtTarget *
 959mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id)
 960{
 961	struct scsi_device 		*sdev;
 962	VirtDevice			*vdevice;
 963	VirtTarget 			*vtarget = NULL;
 964
 965	shost_for_each_device(sdev, ioc->sh) {
 966		vdevice = sdev->hostdata;
 967		if ((vdevice == NULL) ||
 968			(vdevice->vtarget == NULL))
 969			continue;
 970		if ((vdevice->vtarget->tflags &
 971		    MPT_TARGET_FLAGS_RAID_COMPONENT ||
 972		    vdevice->vtarget->raidVolume))
 973			continue;
 974		if (vdevice->vtarget->id == id &&
 975			vdevice->vtarget->channel == channel)
 976			vtarget = vdevice->vtarget;
 977	}
 978	return vtarget;
 979}
 980
 981static void
 982mptsas_queue_device_delete(MPT_ADAPTER *ioc,
 983	MpiEventDataSasDeviceStatusChange_t *sas_event_data)
 984{
 985	struct fw_event_work *fw_event;
 986	int sz;
 987
 988	sz = offsetof(struct fw_event_work, event_data) +
 989	    sizeof(MpiEventDataSasDeviceStatusChange_t);
 990	fw_event = kzalloc(sz, GFP_ATOMIC);
 991	if (!fw_event) {
 992		printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n",
 993		    ioc->name, __func__, __LINE__);
 994		return;
 995	}
 996	memcpy(fw_event->event_data, sas_event_data,
 997	    sizeof(MpiEventDataSasDeviceStatusChange_t));
 998	fw_event->event = MPI_EVENT_SAS_DEVICE_STATUS_CHANGE;
 999	fw_event->ioc = ioc;
1000	mptsas_add_fw_event(ioc, fw_event, msecs_to_jiffies(1));
1001}
1002
1003static void
1004mptsas_queue_rescan(MPT_ADAPTER *ioc)
1005{
1006	struct fw_event_work *fw_event;
1007	int sz;
1008
1009	sz = offsetof(struct fw_event_work, event_data);
1010	fw_event = kzalloc(sz, GFP_ATOMIC);
1011	if (!fw_event) {
1012		printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n",
1013		    ioc->name, __func__, __LINE__);
1014		return;
1015	}
1016	fw_event->event = -1;
1017	fw_event->ioc = ioc;
1018	mptsas_add_fw_event(ioc, fw_event, msecs_to_jiffies(1));
1019}
1020
1021
1022/**
1023 * mptsas_target_reset
1024 *
1025 * Issues TARGET_RESET to end device using handshaking method
1026 *
1027 * @ioc
1028 * @channel
1029 * @id
1030 *
1031 * Returns (1) success
1032 *         (0) failure
1033 *
1034 **/
1035static int
1036mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id)
1037{
1038	MPT_FRAME_HDR	*mf;
1039	SCSITaskMgmt_t	*pScsiTm;
1040	if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0)
1041		return 0;
1042
1043
1044	mf = mpt_get_msg_frame(mptsasDeviceResetCtx, ioc);
1045	if (mf == NULL) {
1046		dfailprintk(ioc, printk(MYIOC_s_WARN_FMT
1047			"%s, no msg frames @%d!!\n", ioc->name,
1048			__func__, __LINE__));
1049		goto out_fail;
1050	}
1051
1052	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n",
1053		ioc->name, mf));
1054
1055	/* Format the Request
1056	 */
1057	pScsiTm = (SCSITaskMgmt_t *) mf;
1058	memset (pScsiTm, 0, sizeof(SCSITaskMgmt_t));
1059	pScsiTm->TargetID = id;
1060	pScsiTm->Bus = channel;
1061	pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
1062	pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
1063	pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION;
1064
1065	DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf);
1066
1067	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1068	   "TaskMgmt type=%d (sas device delete) fw_channel = %d fw_id = %d)\n",
1069	   ioc->name, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, channel, id));
1070
1071	mpt_put_msg_frame_hi_pri(mptsasDeviceResetCtx, ioc, mf);
1072
1073	return 1;
1074
1075 out_fail:
1076
1077	mpt_clear_taskmgmt_in_progress_flag(ioc);
1078	return 0;
1079}
1080
1081static void
1082mptsas_block_io_sdev(struct scsi_device *sdev, void *data)
1083{
1084	scsi_device_set_state(sdev, SDEV_BLOCK);
1085}
1086
1087static void
1088mptsas_block_io_starget(struct scsi_target *starget)
1089{
1090	if (starget)
1091		starget_for_each_device(starget, NULL, mptsas_block_io_sdev);
1092}
1093
1094/**
1095 * mptsas_target_reset_queue
1096 *
1097 * Receive request for TARGET_RESET after receiving an firmware
1098 * event NOT_RESPONDING_EVENT, then put command in link list
1099 * and queue if task_queue already in use.
1100 *
1101 * @ioc
1102 * @sas_event_data
1103 *
1104 **/
1105static void
1106mptsas_target_reset_queue(MPT_ADAPTER *ioc,
1107    EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
1108{
1109	MPT_SCSI_HOST	*hd = shost_priv(ioc->sh);
1110	VirtTarget *vtarget = NULL;
1111	struct mptsas_target_reset_event *target_reset_list;
1112	u8		id, channel;
1113
1114	id = sas_event_data->TargetID;
1115	channel = sas_event_data->Bus;
1116
1117	vtarget = mptsas_find_vtarget(ioc, channel, id);
1118	if (vtarget) {
1119		mptsas_block_io_starget(vtarget->starget);
1120		vtarget->deleted = 1; /* block IO */
1121	}
1122
1123	target_reset_list = kzalloc(sizeof(struct mptsas_target_reset_event),
1124	    GFP_ATOMIC);
1125	if (!target_reset_list) {
1126		dfailprintk(ioc, printk(MYIOC_s_WARN_FMT
1127			"%s, failed to allocate mem @%d..!!\n",
1128			ioc->name, __func__, __LINE__));
1129		return;
1130	}
1131
1132	memcpy(&target_reset_list->sas_event_data, sas_event_data,
1133		sizeof(*sas_event_data));
1134	list_add_tail(&target_reset_list->list, &hd->target_reset_list);
1135
1136	target_reset_list->time_count = jiffies;
1137
1138	if (mptsas_target_reset(ioc, channel, id)) {
1139		target_reset_list->target_reset_issued = 1;
1140	}
1141}
1142
1143/**
1144 * mptsas_schedule_target_reset- send pending target reset
1145 * @iocp: per adapter object
1146 *
1147 * This function will delete scheduled target reset from the list and
1148 * try to send next target reset. This will be called from completion
1149 * context of any Task management command.
1150 */
1151
1152void
1153mptsas_schedule_target_reset(void *iocp)
1154{
1155	MPT_ADAPTER *ioc = (MPT_ADAPTER *)(iocp);
1156	MPT_SCSI_HOST	*hd = shost_priv(ioc->sh);
1157	struct list_head *head = &hd->target_reset_list;
1158	struct mptsas_target_reset_event	*target_reset_list;
1159	u8		id, channel;
1160	/*
1161	 * issue target reset to next device in the queue
1162	 */
1163
1164	head = &hd->target_reset_list;
1165	if (list_empty(head))
1166		return;
1167
1168	target_reset_list = list_entry(head->next,
1169		struct mptsas_target_reset_event, list);
1170
1171	id = target_reset_list->sas_event_data.TargetID;
1172	channel = target_reset_list->sas_event_data.Bus;
1173	target_reset_list->time_count = jiffies;
1174
1175	if (mptsas_target_reset(ioc, channel, id))
1176		target_reset_list->target_reset_issued = 1;
1177	return;
1178}
1179
1180
1181/**
1182 *	mptsas_taskmgmt_complete - complete SAS task management function
1183 *	@ioc: Pointer to MPT_ADAPTER structure
1184 *
1185 *	Completion for TARGET_RESET after NOT_RESPONDING_EVENT, enable work
1186 *	queue to finish off removing device from upper layers. then send next
1187 *	TARGET_RESET in the queue.
1188 **/
1189static int
1190mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
1191{
1192	MPT_SCSI_HOST	*hd = shost_priv(ioc->sh);
1193        struct list_head *head = &hd->target_reset_list;
1194	u8		id, channel;
1195	struct mptsas_target_reset_event	*target_reset_list;
1196	SCSITaskMgmtReply_t *pScsiTmReply;
1197
1198	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt completed: "
1199	    "(mf = %p, mr = %p)\n", ioc->name, mf, mr));
1200
1201	pScsiTmReply = (SCSITaskMgmtReply_t *)mr;
1202	if (pScsiTmReply) {
1203		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1204		    "\tTaskMgmt completed: fw_channel = %d, fw_id = %d,\n"
1205		    "\ttask_type = 0x%02X, iocstatus = 0x%04X "
1206		    "loginfo = 0x%08X,\n\tresponse_code = 0x%02X, "
1207		    "term_cmnds = %d\n", ioc->name,
1208		    pScsiTmReply->Bus, pScsiTmReply->TargetID,
1209		    pScsiTmReply->TaskType,
1210		    le16_to_cpu(pScsiTmReply->IOCStatus),
1211		    le32_to_cpu(pScsiTmReply->IOCLogInfo),
1212		    pScsiTmReply->ResponseCode,
1213		    le32_to_cpu(pScsiTmReply->TerminationCount)));
1214
1215		if (pScsiTmReply->ResponseCode)
1216			mptscsih_taskmgmt_response_code(ioc,
1217			pScsiTmReply->ResponseCode);
1218	}
1219
1220	if (pScsiTmReply && (pScsiTmReply->TaskType ==
1221	    MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK || pScsiTmReply->TaskType ==
1222	     MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET)) {
1223		ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
1224		ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
1225		memcpy(ioc->taskmgmt_cmds.reply, mr,
1226		    min(MPT_DEFAULT_FRAME_SIZE, 4 * mr->u.reply.MsgLength));
1227		if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_PENDING) {
1228			ioc->taskmgmt_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
1229			complete(&ioc->taskmgmt_cmds.done);
1230			return 1;
1231		}
1232		return 0;
1233	}
1234
1235	mpt_clear_taskmgmt_in_progress_flag(ioc);
1236
1237	if (list_empty(head))
1238		return 1;
1239
1240	target_reset_list = list_entry(head->next,
1241	    struct mptsas_target_reset_event, list);
1242
1243	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1244	    "TaskMgmt: completed (%d seconds)\n",
1245	    ioc->name, jiffies_to_msecs(jiffies -
1246	    target_reset_list->time_count)/1000));
1247
1248	id = pScsiTmReply->TargetID;
1249	channel = pScsiTmReply->Bus;
1250	target_reset_list->time_count = jiffies;
1251
1252	/*
1253	 * retry target reset
1254	 */
1255	if (!target_reset_list->target_reset_issued) {
1256		if (mptsas_target_reset(ioc, channel, id))
1257			target_reset_list->target_reset_issued = 1;
1258		return 1;
1259	}
1260
1261	/*
1262	 * enable work queue to remove device from upper layers
1263	 */
1264	list_del(&target_reset_list->list);
1265	if (!ioc->fw_events_off)
1266		mptsas_queue_device_delete(ioc,
1267			&target_reset_list->sas_event_data);
1268
1269
1270	ioc->schedule_target_reset(ioc);
1271
1272	return 1;
1273}
1274
1275/**
1276 * mptscsih_ioc_reset
1277 *
1278 * @ioc
1279 * @reset_phase
1280 *
1281 **/
1282static int
1283mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
1284{
1285	MPT_SCSI_HOST	*hd;
1286	int rc;
1287
1288	rc = mptscsih_ioc_reset(ioc, reset_phase);
1289	if ((ioc->bus_type != SAS) || (!rc))
1290		return rc;
1291
1292	hd = shost_priv(ioc->sh);
1293	if (!hd->ioc)
1294		goto out;
1295
1296	switch (reset_phase) {
1297	case MPT_IOC_SETUP_RESET:
1298		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1299		    "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __func__));
1300		mptsas_fw_event_off(ioc);
1301		break;
1302	case MPT_IOC_PRE_RESET:
1303		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1304		    "%s: MPT_IOC_PRE_RESET\n", ioc->name, __func__));
1305		break;
1306	case MPT_IOC_POST_RESET:
1307		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1308		    "%s: MPT_IOC_POST_RESET\n", ioc->name, __func__));
1309		if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_PENDING) {
1310			ioc->sas_mgmt.status |= MPT_MGMT_STATUS_DID_IOCRESET;
1311			complete(&ioc->sas_mgmt.done);
1312		}
1313		mptsas_cleanup_fw_event_q(ioc);
1314		mptsas_queue_rescan(ioc);
1315		break;
1316	default:
1317		break;
1318	}
1319
1320 out:
1321	return rc;
1322}
1323
1324
1325/**
1326 * enum device_state -
1327 * @DEVICE_RETRY: need to retry the TUR
1328 * @DEVICE_ERROR: TUR return error, don't add device
1329 * @DEVICE_READY: device can be added
1330 *
1331 */
1332enum device_state{
1333	DEVICE_RETRY,
1334	DEVICE_ERROR,
1335	DEVICE_READY,
1336};
1337
1338static int
1339mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
1340		u32 form, u32 form_specific)
1341{
1342	ConfigExtendedPageHeader_t hdr;
1343	CONFIGPARMS cfg;
1344	SasEnclosurePage0_t *buffer;
1345	dma_addr_t dma_handle;
1346	int error;
1347	__le64 le_identifier;
1348
1349	memset(&hdr, 0, sizeof(hdr));
1350	hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
1351	hdr.PageNumber = 0;
1352	hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1353	hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
1354
1355	cfg.cfghdr.ehdr = &hdr;
1356	cfg.physAddr = -1;
1357	cfg.pageAddr = form + form_specific;
1358	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1359	cfg.dir = 0;	/* read */
1360	cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
1361
1362	error = mpt_config(ioc, &cfg);
1363	if (error)
1364		goto out;
1365	if (!hdr.ExtPageLength) {
1366		error = -ENXIO;
1367		goto out;
1368	}
1369
1370	buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1371			&dma_handle);
1372	if (!buffer) {
1373		error = -ENOMEM;
1374		goto out;
1375	}
1376
1377	cfg.physAddr = dma_handle;
1378	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1379
1380	error = mpt_config(ioc, &cfg);
1381	if (error)
1382		goto out_free_consistent;
1383
1384	/* save config data */
1385	memcpy(&le_identifier, &buffer->EnclosureLogicalID, sizeof(__le64));
1386	enclosure->enclosure_logical_id = le64_to_cpu(le_identifier);
1387	enclosure->enclosure_handle = le16_to_cpu(buffer->EnclosureHandle);
1388	enclosure->flags = le16_to_cpu(buffer->Flags);
1389	enclosure->num_slot = le16_to_cpu(buffer->NumSlots);
1390	enclosure->start_slot = le16_to_cpu(buffer->StartSlot);
1391	enclosure->start_id = buffer->StartTargetID;
1392	enclosure->start_channel = buffer->StartBus;
1393	enclosure->sep_id = buffer->SEPTargetID;
1394	enclosure->sep_channel = buffer->SEPBus;
1395
1396 out_free_consistent:
1397	pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1398			    buffer, dma_handle);
1399 out:
1400	return error;
1401}
1402
1403/**
1404 *	mptsas_add_end_device - report a new end device to sas transport layer
1405 *	@ioc: Pointer to MPT_ADAPTER structure
1406 *	@phy_info: describes attached device
1407 *
1408 *	return (0) success (1) failure
1409 *
1410 **/
1411static int
1412mptsas_add_end_device(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info)
1413{
1414	struct sas_rphy *rphy;
1415	struct sas_port *port;
1416	struct sas_identify identify;
1417	char *ds = NULL;
1418	u8 fw_id;
1419
1420	if (!phy_info) {
1421		dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1422			"%s: exit at line=%d\n", ioc->name,
1423			 __func__, __LINE__));
1424		return 1;
1425	}
1426
1427	fw_id = phy_info->attached.id;
1428
1429	if (mptsas_get_rphy(phy_info)) {
1430		dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1431			"%s: fw_id=%d exit at line=%d\n", ioc->name,
1432			 __func__, fw_id, __LINE__));
1433		return 2;
1434	}
1435
1436	port = mptsas_get_port(phy_info);
1437	if (!port) {
1438		dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1439			"%s: fw_id=%d exit at line=%d\n", ioc->name,
1440			 __func__, fw_id, __LINE__));
1441		return 3;
1442	}
1443
1444	if (phy_info->attached.device_info &
1445	    MPI_SAS_DEVICE_INFO_SSP_TARGET)
1446		ds = "ssp";
1447	if (phy_info->attached.device_info &
1448	    MPI_SAS_DEVICE_INFO_STP_TARGET)
1449		ds = "stp";
1450	if (phy_info->attached.device_info &
1451	    MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1452		ds = "sata";
1453
1454	printk(MYIOC_s_INFO_FMT "attaching %s device: fw_channel %d, fw_id %d,"
1455	    " phy %d, sas_addr 0x%llx\n", ioc->name, ds,
1456	    phy_info->attached.channel, phy_info->attached.id,
1457	    phy_info->attached.phy_id, (unsigned long long)
1458	    phy_info->attached.sas_address);
1459
1460	mptsas_parse_device_info(&identify, &phy_info->attached);
1461	rphy = sas_end_device_alloc(port);
1462	if (!rphy) {
1463		dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1464			"%s: fw_id=%d exit at line=%d\n", ioc->name,
1465			 __func__, fw_id, __LINE__));
1466		return 5; /* non-fatal: an rphy can be added later */
1467	}
1468
1469	rphy->identify = identify;
1470	if (sas_rphy_add(rphy)) {
1471		dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1472			"%s: fw_id=%d exit at line=%d\n", ioc->name,
1473			 __func__, fw_id, __LINE__));
1474		sas_rphy_free(rphy);
1475		return 6;
1476	}
1477	mptsas_set_rphy(ioc, phy_info, rphy);
1478	return 0;
1479}
1480
1481/**
1482 *	mptsas_del_end_device - report a deleted end device to sas transport layer
1483 *	@ioc: Pointer to MPT_ADAPTER structure
1484 *	@phy_info: describes attached device
1485 *
1486 **/
1487static void
1488mptsas_del_end_device(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info)
1489{
1490	struct sas_rphy *rphy;
1491	struct sas_port *port;
1492	struct mptsas_portinfo *port_info;
1493	struct mptsas_phyinfo *phy_info_parent;
1494	int i;
1495	char *ds = NULL;
1496	u8 fw_id;
1497	u64 sas_address;
1498
1499	if (!phy_info)
1500		return;
1501
1502	fw_id = phy_info->attached.id;
1503	sas_address = phy_info->attached.sas_address;
1504
1505	if (!phy_info->port_details) {
1506		dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1507			"%s: fw_id=%d exit at line=%d\n", ioc->name,
1508			 __func__, fw_id, __LINE__));
1509		return;
1510	}
1511	rphy = mptsas_get_rphy(phy_info);
1512	if (!rphy) {
1513		dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1514			"%s: fw_id=%d exit at line=%d\n", ioc->name,
1515			 __func__, fw_id, __LINE__));
1516		return;
1517	}
1518
1519	if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_INITIATOR
1520		|| phy_info->attached.device_info
1521			& MPI_SAS_DEVICE_INFO_SMP_INITIATOR
1522		|| phy_info->attached.device_info
1523			& MPI_SAS_DEVICE_INFO_STP_INITIATOR)
1524		ds = "initiator";
1525	if (phy_info->attached.device_info &
1526	    MPI_SAS_DEVICE_INFO_SSP_TARGET)
1527		ds = "ssp";
1528	if (phy_info->attached.device_info &
1529	    MPI_SAS_DEVICE_INFO_STP_TARGET)
1530		ds = "stp";
1531	if (phy_info->attached.device_info &
1532	    MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1533		ds = "sata";
1534
1535	dev_printk(KERN_DEBUG, &rphy->dev, MYIOC_s_FMT
1536	    "removing %s device: fw_channel %d, fw_id %d, phy %d,"
1537	    "sas_addr 0x%llx\n", ioc->name, ds, phy_info->attached.channel,
1538	    phy_info->attached.id, phy_info->attached.phy_id,
1539	    (unsigned long long) sas_address);
1540
1541	port = mptsas_get_port(phy_info);
1542	if (!port) {
1543		dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1544			"%s: fw_id=%d exit at line=%d\n", ioc->name,
1545			 __func__, fw_id, __LINE__));
1546		return;
1547	}
1548	port_info = phy_info->portinfo;
1549	phy_info_parent = port_info->phy_info;
1550	for (i = 0; i < port_info->num_phys; i++, phy_info_parent++) {
1551		if (!phy_info_parent->phy)
1552			continue;
1553		if (phy_info_parent->attached.sas_address !=
1554		    sas_address)
1555			continue;
1556		dev_printk(KERN_DEBUG, &phy_info_parent->phy->dev,
1557		    MYIOC_s_FMT "delete phy %d, phy-obj (0x%p)\n",
1558		    ioc->name, phy_info_parent->phy_id,
1559		    phy_info_parent->phy);
1560		sas_port_delete_phy(port, phy_info_parent->phy);
1561	}
1562
1563	dev_printk(KERN_DEBUG, &port->dev, MYIOC_s_FMT
1564	    "delete port %d, sas_addr (0x%llx)\n", ioc->name,
1565	     port->port_identifier, (unsigned long long)sas_address);
1566	sas_port_delete(port);
1567	mptsas_set_port(ioc, phy_info, NULL);
1568	mptsas_port_delete(ioc, phy_info->port_details);
1569}
1570
1571struct mptsas_phyinfo *
1572mptsas_refreshing_device_handles(MPT_ADAPTER *ioc,
1573	struct mptsas_devinfo *sas_device)
1574{
1575	struct mptsas_phyinfo *phy_info;
1576	struct mptsas_portinfo *port_info;
1577	int i;
1578
1579	phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
1580	    sas_device->sas_address);
1581	if (!phy_info)
1582		goto out;
1583	port_info = phy_info->portinfo;
1584	if (!port_info)
1585		goto out;
1586	mutex_lock(&ioc->sas_topology_mutex);
1587	for (i = 0; i < port_info->num_phys; i++) {
1588		if (port_info->phy_info[i].attached.sas_address !=
1589			sas_device->sas_address)
1590			continue;
1591		port_info->phy_info[i].attached.channel = sas_device->channel;
1592		port_info->phy_info[i].attached.id = sas_device->id;
1593		port_info->phy_info[i].attached.sas_address =
1594		    sas_device->sas_address;
1595		port_info->phy_info[i].attached.handle = sas_device->handle;
1596		port_info->phy_info[i].attached.handle_parent =
1597		    sas_device->handle_parent;
1598		port_info->phy_info[i].attached.handle_enclosure =
1599		    sas_device->handle_enclosure;
1600	}
1601	mutex_unlock(&ioc->sas_topology_mutex);
1602 out:
1603	return phy_info;
1604}
1605
1606/**
1607 * mptsas_firmware_event_work - work thread for processing fw events
1608 * @work: work queue payload containing info describing the event
1609 * Context: user
1610 *
1611 */
1612static void
1613mptsas_firmware_event_work(struct work_struct *work)
1614{
1615	struct fw_event_work *fw_event =
1616		container_of(work, struct fw_event_work, work.work);
1617	MPT_ADAPTER *ioc = fw_event->ioc;
1618
1619	/* special rescan topology handling */
1620	if (fw_event->event == -1) {
1621		if (ioc->in_rescan) {
1622			devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1623				"%s: rescan ignored as it is in progress\n",
1624				ioc->name, __func__));
1625			return;
1626		}
1627		devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: rescan after "
1628		    "reset\n", ioc->name, __func__));
1629		ioc->in_rescan = 1;
1630		mptsas_not_responding_devices(ioc);
1631		mptsas_scan_sas_topology(ioc);
1632		ioc->in_rescan = 0;
1633		mptsas_free_fw_event(ioc, fw_event);
1634		mptsas_fw_event_on(ioc);
1635		return;
1636	}
1637
1638	/* events handling turned off during host reset */
1639	if (ioc->fw_events_off) {
1640		mptsas_free_fw_event(ioc, fw_event);
1641		return;
1642	}
1643
1644	devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: fw_event=(0x%p), "
1645	    "event = (0x%02x)\n", ioc->name, __func__, fw_event,
1646	    (fw_event->event & 0xFF)));
1647
1648	switch (fw_event->event) {
1649	case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
1650		mptsas_send_sas_event(fw_event);
1651		break;
1652	case MPI_EVENT_INTEGRATED_RAID:
1653		mptsas_send_raid_event(fw_event);
1654		break;
1655	case MPI_EVENT_IR2:
1656		mptsas_send_ir2_event(fw_event);
1657		break;
1658	case MPI_EVENT_PERSISTENT_TABLE_FULL:
1659		mptbase_sas_persist_operation(ioc,
1660		    MPI_SAS_OP_CLEAR_NOT_PRESENT);
1661		mptsas_free_fw_event(ioc, fw_event);
1662		break;
1663	case MPI_EVENT_SAS_BROADCAST_PRIMITIVE:
1664		mptsas_broadcast_primative_work(fw_event);
1665		break;
1666	case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE:
1667		mptsas_send_expander_event(fw_event);
1668		break;
1669	case MPI_EVENT_SAS_PHY_LINK_STATUS:
1670		mptsas_send_link_status_event(fw_event);
1671		break;
1672	case MPI_EVENT_QUEUE_FULL:
1673		mptsas_handle_queue_full_event(fw_event);
1674		break;
1675	}
1676}
1677
1678
1679
1680static int
1681mptsas_slave_configure(struct scsi_device *sdev)
1682{
1683	struct Scsi_Host	*host = sdev->host;
1684	MPT_SCSI_HOST	*hd = shost_priv(host);
1685	MPT_ADAPTER	*ioc = hd->ioc;
1686	VirtDevice	*vdevice = sdev->hostdata;
1687
1688	if (vdevice->vtarget->deleted) {
1689		sdev_printk(KERN_INFO, sdev, "clearing deleted flag\n");
1690		vdevice->vtarget->deleted = 0;
1691	}
1692
1693	/*
1694	 * RAID volumes placed beyond the last expected port.
1695	 * Ignore sending sas mode pages in that case..
1696	 */
1697	if (sdev->channel == MPTSAS_RAID_CHANNEL) {
1698		mptsas_add_device_component_starget_ir(ioc, scsi_target(sdev));
1699		goto out;
1700	}
1701
1702	sas_read_port_mode_page(sdev);
1703
1704	mptsas_add_device_component_starget(ioc, scsi_target(sdev));
1705
1706 out:
1707	return mptscsih_slave_configure(sdev);
1708}
1709
1710static int
1711mptsas_target_alloc(struct scsi_target *starget)
1712{
1713	struct Scsi_Host *host = dev_to_shost(&starget->dev);
1714	MPT_SCSI_HOST		*hd = shost_priv(host);
1715	VirtTarget		*vtarget;
1716	u8			id, channel;
1717	struct sas_rphy		*rphy;
1718	struct mptsas_portinfo	*p;
1719	int 			 i;
1720	MPT_ADAPTER		*ioc 

Large files files are truncated, but you can click here to view the full file