brintos

brintos / linux-shallow public Read only

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