Linux Audio

Check our new training course

Loading...
v6.8
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Driver for Broadcom MPI3 Storage Controllers
   4 *
   5 * Copyright (C) 2017-2023 Broadcom Inc.
   6 *  (mailto: mpi3mr-linuxdrv.pdl@broadcom.com)
   7 *
   8 */
   9
 
 
  10#include "mpi3mr.h"
  11
  12/**
  13 * mpi3mr_post_transport_req - Issue transport requests and wait
  14 * @mrioc: Adapter instance reference
  15 * @request: Properly populated MPI3 request
  16 * @request_sz: Size of the MPI3 request
  17 * @reply: Pointer to return MPI3 reply
  18 * @reply_sz: Size of the MPI3 reply buffer
  19 * @timeout: Timeout in seconds
  20 * @ioc_status: Pointer to return ioc status
  21 *
  22 * A generic function for posting MPI3 requests from the SAS
  23 * transport layer that uses transport command infrastructure.
  24 * This blocks for the completion of request for timeout seconds
  25 * and if the request times out this function faults the
  26 * controller with proper reason code.
  27 *
  28 * On successful completion of the request this function returns
  29 * appropriate ioc status from the firmware back to the caller.
  30 *
  31 * Return: 0 on success, non-zero on failure.
  32 */
  33static int mpi3mr_post_transport_req(struct mpi3mr_ioc *mrioc, void *request,
  34	u16 request_sz, void *reply, u16 reply_sz, int timeout,
  35	u16 *ioc_status)
  36{
  37	int retval = 0;
  38
  39	mutex_lock(&mrioc->transport_cmds.mutex);
  40	if (mrioc->transport_cmds.state & MPI3MR_CMD_PENDING) {
  41		retval = -1;
  42		ioc_err(mrioc, "sending transport request failed due to command in use\n");
  43		mutex_unlock(&mrioc->transport_cmds.mutex);
  44		goto out;
  45	}
  46	mrioc->transport_cmds.state = MPI3MR_CMD_PENDING;
  47	mrioc->transport_cmds.is_waiting = 1;
  48	mrioc->transport_cmds.callback = NULL;
  49	mrioc->transport_cmds.ioc_status = 0;
  50	mrioc->transport_cmds.ioc_loginfo = 0;
  51
  52	init_completion(&mrioc->transport_cmds.done);
  53	dprint_cfg_info(mrioc, "posting transport request\n");
  54	if (mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO)
  55		dprint_dump(request, request_sz, "transport_req");
  56	retval = mpi3mr_admin_request_post(mrioc, request, request_sz, 1);
  57	if (retval) {
  58		ioc_err(mrioc, "posting transport request failed\n");
  59		goto out_unlock;
  60	}
  61	wait_for_completion_timeout(&mrioc->transport_cmds.done,
  62	    (timeout * HZ));
  63	if (!(mrioc->transport_cmds.state & MPI3MR_CMD_COMPLETE)) {
  64		mpi3mr_check_rh_fault_ioc(mrioc,
  65		    MPI3MR_RESET_FROM_SAS_TRANSPORT_TIMEOUT);
  66		ioc_err(mrioc, "transport request timed out\n");
  67		retval = -1;
  68		goto out_unlock;
  69	}
  70	*ioc_status = mrioc->transport_cmds.ioc_status &
  71		MPI3_IOCSTATUS_STATUS_MASK;
  72	if ((*ioc_status) != MPI3_IOCSTATUS_SUCCESS)
  73		dprint_transport_err(mrioc,
  74		    "transport request returned with ioc_status(0x%04x), log_info(0x%08x)\n",
  75		    *ioc_status, mrioc->transport_cmds.ioc_loginfo);
  76
  77	if ((reply) && (mrioc->transport_cmds.state & MPI3MR_CMD_REPLY_VALID))
  78		memcpy((u8 *)reply, mrioc->transport_cmds.reply, reply_sz);
  79
  80out_unlock:
  81	mrioc->transport_cmds.state = MPI3MR_CMD_NOTUSED;
  82	mutex_unlock(&mrioc->transport_cmds.mutex);
  83
  84out:
  85	return retval;
  86}
  87
  88/* report manufacture request structure */
  89struct rep_manu_request {
  90	u8 smp_frame_type;
  91	u8 function;
  92	u8 reserved;
  93	u8 request_length;
  94};
  95
  96/* report manufacture reply structure */
  97struct rep_manu_reply {
  98	u8 smp_frame_type; /* 0x41 */
  99	u8 function; /* 0x01 */
 100	u8 function_result;
 101	u8 response_length;
 102	u16 expander_change_count;
 103	u8 reserved0[2];
 104	u8 sas_format;
 105	u8 reserved2[3];
 106	u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN];
 107	u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN];
 108	u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN];
 109	u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN];
 110	u16 component_id;
 111	u8 component_revision_id;
 112	u8 reserved3;
 113	u8 vendor_specific[8];
 114};
 115
 116/**
 117 * mpi3mr_report_manufacture - obtain SMP report_manufacture
 118 * @mrioc: Adapter instance reference
 119 * @sas_address: SAS address of the expander device
 120 * @edev: SAS transport layer sas_expander_device object
 121 * @port_id: ID of the HBA port
 122 *
 123 * Fills in the sas_expander_device with manufacturing info.
 124 *
 125 * Return: 0 for success, non-zero for failure.
 126 */
 127static int mpi3mr_report_manufacture(struct mpi3mr_ioc *mrioc,
 128	u64 sas_address, struct sas_expander_device *edev, u8 port_id)
 129{
 130	struct mpi3_smp_passthrough_request mpi_request;
 131	struct mpi3_smp_passthrough_reply mpi_reply;
 132	struct rep_manu_reply *manufacture_reply;
 133	struct rep_manu_request *manufacture_request;
 134	int rc = 0;
 135	void *psge;
 136	void *data_out = NULL;
 137	dma_addr_t data_out_dma;
 138	dma_addr_t data_in_dma;
 139	size_t data_in_sz;
 140	size_t data_out_sz;
 141	u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST;
 142	u16 request_sz = sizeof(struct mpi3_smp_passthrough_request);
 143	u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply);
 144	u16 ioc_status;
 145	u8 *tmp;
 146
 147	if (mrioc->reset_in_progress) {
 148		ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
 149		return -EFAULT;
 150	}
 151
 
 
 
 
 
 152	data_out_sz = sizeof(struct rep_manu_request);
 153	data_in_sz = sizeof(struct rep_manu_reply);
 154	data_out = dma_alloc_coherent(&mrioc->pdev->dev,
 155	    data_out_sz + data_in_sz, &data_out_dma, GFP_KERNEL);
 156	if (!data_out) {
 157		rc = -ENOMEM;
 158		goto out;
 159	}
 160
 161	data_in_dma = data_out_dma + data_out_sz;
 162	manufacture_reply = data_out + data_out_sz;
 163
 164	manufacture_request = data_out;
 165	manufacture_request->smp_frame_type = 0x40;
 166	manufacture_request->function = 1;
 167	manufacture_request->reserved = 0;
 168	manufacture_request->request_length = 0;
 169
 170	memset(&mpi_request, 0, request_sz);
 171	memset(&mpi_reply, 0, reply_sz);
 172	mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
 173	mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH;
 174	mpi_request.io_unit_port = (u8) port_id;
 175	mpi_request.sas_address = cpu_to_le64(sas_address);
 176
 177	psge = &mpi_request.request_sge;
 178	mpi3mr_add_sg_single(psge, sgl_flags, data_out_sz, data_out_dma);
 179
 180	psge = &mpi_request.response_sge;
 181	mpi3mr_add_sg_single(psge, sgl_flags, data_in_sz, data_in_dma);
 182
 183	dprint_transport_info(mrioc,
 184	    "sending report manufacturer SMP request to sas_address(0x%016llx), port(%d)\n",
 185	    (unsigned long long)sas_address, port_id);
 186
 187	rc = mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
 188				       &mpi_reply, reply_sz,
 189				       MPI3MR_INTADMCMD_TIMEOUT, &ioc_status);
 190	if (rc)
 191		goto out;
 192
 193	dprint_transport_info(mrioc,
 194	    "report manufacturer SMP request completed with ioc_status(0x%04x)\n",
 195	    ioc_status);
 196
 197	if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
 198		rc = -EINVAL;
 199		goto out;
 200	}
 201
 202	dprint_transport_info(mrioc,
 203	    "report manufacturer - reply data transfer size(%d)\n",
 204	    le16_to_cpu(mpi_reply.response_data_length));
 205
 206	if (le16_to_cpu(mpi_reply.response_data_length) !=
 207	    sizeof(struct rep_manu_reply)) {
 208		rc = -EINVAL;
 209		goto out;
 210	}
 211
 212	strscpy(edev->vendor_id, manufacture_reply->vendor_id,
 213	     SAS_EXPANDER_VENDOR_ID_LEN);
 214	strscpy(edev->product_id, manufacture_reply->product_id,
 215	     SAS_EXPANDER_PRODUCT_ID_LEN);
 216	strscpy(edev->product_rev, manufacture_reply->product_rev,
 217	     SAS_EXPANDER_PRODUCT_REV_LEN);
 218	edev->level = manufacture_reply->sas_format & 1;
 219	if (edev->level) {
 220		strscpy(edev->component_vendor_id,
 221		    manufacture_reply->component_vendor_id,
 222		     SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN);
 223		tmp = (u8 *)&manufacture_reply->component_id;
 224		edev->component_id = tmp[0] << 8 | tmp[1];
 225		edev->component_revision_id =
 226		    manufacture_reply->component_revision_id;
 227	}
 228
 229out:
 230	if (data_out)
 231		dma_free_coherent(&mrioc->pdev->dev, data_out_sz + data_in_sz,
 232		    data_out, data_out_dma);
 233
 234	return rc;
 235}
 236
 237/**
 238 * __mpi3mr_expander_find_by_handle - expander search by handle
 239 * @mrioc: Adapter instance reference
 240 * @handle: Firmware device handle of the expander
 241 *
 242 * Context: The caller should acquire sas_node_lock
 243 *
 244 * This searches for expander device based on handle, then
 245 * returns the sas_node object.
 246 *
 247 * Return: Expander sas_node object reference or NULL
 248 */
 249struct mpi3mr_sas_node *__mpi3mr_expander_find_by_handle(struct mpi3mr_ioc
 250	*mrioc, u16 handle)
 251{
 252	struct mpi3mr_sas_node *sas_expander, *r;
 253
 254	r = NULL;
 255	list_for_each_entry(sas_expander, &mrioc->sas_expander_list, list) {
 256		if (sas_expander->handle != handle)
 257			continue;
 258		r = sas_expander;
 259		goto out;
 260	}
 261 out:
 262	return r;
 263}
 264
 265/**
 266 * mpi3mr_is_expander_device - if device is an expander
 267 * @device_info: Bitfield providing information about the device
 268 *
 269 * Return: 1 if the device is expander device, else 0.
 270 */
 271u8 mpi3mr_is_expander_device(u16 device_info)
 272{
 273	if ((device_info & MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_MASK) ==
 274	     MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_EXPANDER)
 275		return 1;
 276	else
 277		return 0;
 278}
 279
 280/**
 281 * mpi3mr_get_sas_address - retrieve sas_address for handle
 282 * @mrioc: Adapter instance reference
 283 * @handle: Firmware device handle
 284 * @sas_address: Address to hold sas address
 285 *
 286 * This function issues device page0 read for a given device
 287 * handle and gets the SAS address and return it back
 288 *
 289 * Return: 0 for success, non-zero for failure
 290 */
 291static int mpi3mr_get_sas_address(struct mpi3mr_ioc *mrioc, u16 handle,
 292	u64 *sas_address)
 293{
 294	struct mpi3_device_page0 dev_pg0;
 295	u16 ioc_status;
 296	struct mpi3_device0_sas_sata_format *sasinf;
 297
 298	*sas_address = 0;
 299
 300	if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &dev_pg0,
 301	    sizeof(dev_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE,
 302	    handle))) {
 303		ioc_err(mrioc, "%s: device page0 read failed\n", __func__);
 304		return -ENXIO;
 305	}
 306
 307	if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
 308		ioc_err(mrioc, "device page read failed for handle(0x%04x), with ioc_status(0x%04x) failure at %s:%d/%s()!\n",
 309		    handle, ioc_status, __FILE__, __LINE__, __func__);
 310		return -ENXIO;
 311	}
 312
 313	if (le16_to_cpu(dev_pg0.flags) &
 314	    MPI3_DEVICE0_FLAGS_CONTROLLER_DEV_HANDLE)
 315		*sas_address = mrioc->sas_hba.sas_address;
 316	else if (dev_pg0.device_form == MPI3_DEVICE_DEVFORM_SAS_SATA) {
 317		sasinf = &dev_pg0.device_specific.sas_sata_format;
 318		*sas_address = le64_to_cpu(sasinf->sas_address);
 319	} else {
 320		ioc_err(mrioc, "%s: device_form(%d) is not SAS_SATA\n",
 321		    __func__, dev_pg0.device_form);
 322		return -ENXIO;
 323	}
 324	return 0;
 325}
 326
 327/**
 328 * __mpi3mr_get_tgtdev_by_addr - target device search
 329 * @mrioc: Adapter instance reference
 330 * @sas_address: SAS address of the device
 331 * @hba_port: HBA port entry
 332 *
 333 * This searches for target device from sas address and hba port
 334 * pointer then return mpi3mr_tgt_dev object.
 335 *
 336 * Return: Valid tget_dev or NULL
 337 */
 338static struct mpi3mr_tgt_dev *__mpi3mr_get_tgtdev_by_addr(struct mpi3mr_ioc *mrioc,
 339	u64 sas_address, struct mpi3mr_hba_port *hba_port)
 340{
 341	struct mpi3mr_tgt_dev *tgtdev;
 342
 343	assert_spin_locked(&mrioc->tgtdev_lock);
 344
 345	list_for_each_entry(tgtdev, &mrioc->tgtdev_list, list)
 346		if ((tgtdev->dev_type == MPI3_DEVICE_DEVFORM_SAS_SATA) &&
 347		    (tgtdev->dev_spec.sas_sata_inf.sas_address == sas_address)
 348		    && (tgtdev->dev_spec.sas_sata_inf.hba_port == hba_port))
 349			goto found_device;
 350	return NULL;
 351found_device:
 352	mpi3mr_tgtdev_get(tgtdev);
 353	return tgtdev;
 354}
 355
 356/**
 357 * mpi3mr_get_tgtdev_by_addr - target device search
 358 * @mrioc: Adapter instance reference
 359 * @sas_address: SAS address of the device
 360 * @hba_port: HBA port entry
 361 *
 362 * This searches for target device from sas address and hba port
 363 * pointer then return mpi3mr_tgt_dev object.
 364 *
 365 * Context: This function will acquire tgtdev_lock and will
 366 * release before returning the mpi3mr_tgt_dev object.
 367 *
 368 * Return: Valid tget_dev or NULL
 369 */
 370static struct mpi3mr_tgt_dev *mpi3mr_get_tgtdev_by_addr(struct mpi3mr_ioc *mrioc,
 371	u64 sas_address, struct mpi3mr_hba_port *hba_port)
 372{
 373	struct mpi3mr_tgt_dev *tgtdev = NULL;
 374	unsigned long flags;
 375
 376	if (!hba_port)
 377		goto out;
 378
 379	spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
 380	tgtdev = __mpi3mr_get_tgtdev_by_addr(mrioc, sas_address, hba_port);
 381	spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
 382
 383out:
 384	return tgtdev;
 385}
 386
 387/**
 388 * mpi3mr_remove_device_by_sas_address - remove the device
 389 * @mrioc: Adapter instance reference
 390 * @sas_address: SAS address of the device
 391 * @hba_port: HBA port entry
 392 *
 393 * This searches for target device using sas address and hba
 394 * port pointer then removes it from the OS.
 395 *
 396 * Return: None
 397 */
 398static void mpi3mr_remove_device_by_sas_address(struct mpi3mr_ioc *mrioc,
 399	u64 sas_address, struct mpi3mr_hba_port *hba_port)
 400{
 401	struct mpi3mr_tgt_dev *tgtdev = NULL;
 402	unsigned long flags;
 403	u8 was_on_tgtdev_list = 0;
 404
 405	if (!hba_port)
 406		return;
 407
 408	spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
 409	tgtdev = __mpi3mr_get_tgtdev_by_addr(mrioc,
 410			 sas_address, hba_port);
 411	if (tgtdev) {
 412		if (!list_empty(&tgtdev->list)) {
 413			list_del_init(&tgtdev->list);
 414			was_on_tgtdev_list = 1;
 415			mpi3mr_tgtdev_put(tgtdev);
 416		}
 417	}
 418	spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
 419	if (was_on_tgtdev_list) {
 420		if (tgtdev->host_exposed)
 421			mpi3mr_remove_tgtdev_from_host(mrioc, tgtdev);
 422		mpi3mr_tgtdev_put(tgtdev);
 423	}
 424}
 425
 426/**
 427 * __mpi3mr_get_tgtdev_by_addr_and_rphy - target device search
 428 * @mrioc: Adapter instance reference
 429 * @sas_address: SAS address of the device
 430 * @rphy: SAS transport layer rphy object
 431 *
 432 * This searches for target device from sas address and rphy
 433 * pointer then return mpi3mr_tgt_dev object.
 434 *
 435 * Return: Valid tget_dev or NULL
 436 */
 437struct mpi3mr_tgt_dev *__mpi3mr_get_tgtdev_by_addr_and_rphy(
 438	struct mpi3mr_ioc *mrioc, u64 sas_address, struct sas_rphy *rphy)
 439{
 440	struct mpi3mr_tgt_dev *tgtdev;
 441
 442	assert_spin_locked(&mrioc->tgtdev_lock);
 443
 444	list_for_each_entry(tgtdev, &mrioc->tgtdev_list, list)
 445		if ((tgtdev->dev_type == MPI3_DEVICE_DEVFORM_SAS_SATA) &&
 446		    (tgtdev->dev_spec.sas_sata_inf.sas_address == sas_address)
 447		    && (tgtdev->dev_spec.sas_sata_inf.rphy == rphy))
 448			goto found_device;
 449	return NULL;
 450found_device:
 451	mpi3mr_tgtdev_get(tgtdev);
 452	return tgtdev;
 453}
 454
 455/**
 456 * mpi3mr_expander_find_by_sas_address - sas expander search
 457 * @mrioc: Adapter instance reference
 458 * @sas_address: SAS address of expander
 459 * @hba_port: HBA port entry
 460 *
 461 * Return: A valid SAS expander node or NULL.
 462 *
 463 */
 464static struct mpi3mr_sas_node *mpi3mr_expander_find_by_sas_address(
 465	struct mpi3mr_ioc *mrioc, u64 sas_address,
 466	struct mpi3mr_hba_port *hba_port)
 467{
 468	struct mpi3mr_sas_node *sas_expander, *r = NULL;
 469
 470	if (!hba_port)
 471		goto out;
 472
 473	list_for_each_entry(sas_expander, &mrioc->sas_expander_list, list) {
 474		if ((sas_expander->sas_address != sas_address) ||
 475					 (sas_expander->hba_port != hba_port))
 476			continue;
 477		r = sas_expander;
 478		goto out;
 479	}
 480out:
 481	return r;
 482}
 483
 484/**
 485 * __mpi3mr_sas_node_find_by_sas_address - sas node search
 486 * @mrioc: Adapter instance reference
 487 * @sas_address: SAS address of expander or sas host
 488 * @hba_port: HBA port entry
 489 * Context: Caller should acquire mrioc->sas_node_lock.
 490 *
 491 * If the SAS address indicates the device is direct attached to
 492 * the controller (controller's SAS address) then the SAS node
 493 * associated with the controller is returned back else the SAS
 494 * address and hba port are used to identify the exact expander
 495 * and the associated sas_node object is returned. If there is
 496 * no match NULL is returned.
 497 *
 498 * Return: A valid SAS node or NULL.
 499 *
 500 */
 501static struct mpi3mr_sas_node *__mpi3mr_sas_node_find_by_sas_address(
 502	struct mpi3mr_ioc *mrioc, u64 sas_address,
 503	struct mpi3mr_hba_port *hba_port)
 504{
 505
 506	if (mrioc->sas_hba.sas_address == sas_address)
 507		return &mrioc->sas_hba;
 508	return mpi3mr_expander_find_by_sas_address(mrioc, sas_address,
 509	    hba_port);
 510}
 511
 512/**
 513 * mpi3mr_parent_present - Is parent present for a phy
 514 * @mrioc: Adapter instance reference
 515 * @phy: SAS transport layer phy object
 516 *
 517 * Return: 0 if parent is present else non-zero
 518 */
 519static int mpi3mr_parent_present(struct mpi3mr_ioc *mrioc, struct sas_phy *phy)
 520{
 521	unsigned long flags;
 522	struct mpi3mr_hba_port *hba_port = phy->hostdata;
 523
 524	spin_lock_irqsave(&mrioc->sas_node_lock, flags);
 525	if (__mpi3mr_sas_node_find_by_sas_address(mrioc,
 526	    phy->identify.sas_address,
 527	    hba_port) == NULL) {
 528		spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
 529		return -1;
 530	}
 531	spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
 532	return 0;
 533}
 534
 535/**
 536 * mpi3mr_convert_phy_link_rate -
 537 * @link_rate: link rate as defined in the MPI header
 538 *
 539 * Convert link_rate from mpi format into sas_transport layer
 540 * form.
 541 *
 542 * Return: A valid SAS transport layer defined link rate
 543 */
 544static enum sas_linkrate mpi3mr_convert_phy_link_rate(u8 link_rate)
 545{
 546	enum sas_linkrate rc;
 547
 548	switch (link_rate) {
 549	case MPI3_SAS_NEG_LINK_RATE_1_5:
 550		rc = SAS_LINK_RATE_1_5_GBPS;
 551		break;
 552	case MPI3_SAS_NEG_LINK_RATE_3_0:
 553		rc = SAS_LINK_RATE_3_0_GBPS;
 554		break;
 555	case MPI3_SAS_NEG_LINK_RATE_6_0:
 556		rc = SAS_LINK_RATE_6_0_GBPS;
 557		break;
 558	case MPI3_SAS_NEG_LINK_RATE_12_0:
 559		rc = SAS_LINK_RATE_12_0_GBPS;
 560		break;
 561	case MPI3_SAS_NEG_LINK_RATE_22_5:
 562		rc = SAS_LINK_RATE_22_5_GBPS;
 563		break;
 564	case MPI3_SAS_NEG_LINK_RATE_PHY_DISABLED:
 565		rc = SAS_PHY_DISABLED;
 566		break;
 567	case MPI3_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED:
 568		rc = SAS_LINK_RATE_FAILED;
 569		break;
 570	case MPI3_SAS_NEG_LINK_RATE_PORT_SELECTOR:
 571		rc = SAS_SATA_PORT_SELECTOR;
 572		break;
 573	case MPI3_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS:
 574		rc = SAS_PHY_RESET_IN_PROGRESS;
 575		break;
 576	case MPI3_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE:
 577	case MPI3_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE:
 578	default:
 579		rc = SAS_LINK_RATE_UNKNOWN;
 580		break;
 581	}
 582	return rc;
 583}
 584
 585/**
 586 * mpi3mr_delete_sas_phy - Remove a single phy from port
 587 * @mrioc: Adapter instance reference
 588 * @mr_sas_port: Internal Port object
 589 * @mr_sas_phy: Internal Phy object
 
 590 *
 591 * Return: None.
 592 */
 593static void mpi3mr_delete_sas_phy(struct mpi3mr_ioc *mrioc,
 594	struct mpi3mr_sas_port *mr_sas_port,
 595	struct mpi3mr_sas_phy *mr_sas_phy)
 596{
 597	u64 sas_address = mr_sas_port->remote_identify.sas_address;
 598
 599	dev_info(&mr_sas_phy->phy->dev,
 600	    "remove: sas_address(0x%016llx), phy(%d)\n",
 601	    (unsigned long long) sas_address, mr_sas_phy->phy_id);
 602
 603	list_del(&mr_sas_phy->port_siblings);
 604	mr_sas_port->num_phys--;
 605	mr_sas_port->phy_mask &= ~(1 << mr_sas_phy->phy_id);
 606	if (mr_sas_port->lowest_phy == mr_sas_phy->phy_id)
 607		mr_sas_port->lowest_phy = ffs(mr_sas_port->phy_mask) - 1;
 
 
 
 
 608	sas_port_delete_phy(mr_sas_port->port, mr_sas_phy->phy);
 609	mr_sas_phy->phy_belongs_to_port = 0;
 610}
 611
 612/**
 613 * mpi3mr_add_sas_phy - Adding a single phy to a port
 614 * @mrioc: Adapter instance reference
 615 * @mr_sas_port: Internal Port object
 616 * @mr_sas_phy: Internal Phy object
 
 617 *
 618 * Return: None.
 619 */
 620static void mpi3mr_add_sas_phy(struct mpi3mr_ioc *mrioc,
 621	struct mpi3mr_sas_port *mr_sas_port,
 622	struct mpi3mr_sas_phy *mr_sas_phy)
 623{
 624	u64 sas_address = mr_sas_port->remote_identify.sas_address;
 625
 626	dev_info(&mr_sas_phy->phy->dev,
 627	    "add: sas_address(0x%016llx), phy(%d)\n", (unsigned long long)
 628	    sas_address, mr_sas_phy->phy_id);
 629
 630	list_add_tail(&mr_sas_phy->port_siblings, &mr_sas_port->phy_list);
 631	mr_sas_port->num_phys++;
 632	mr_sas_port->phy_mask |= (1 << mr_sas_phy->phy_id);
 633	if (mr_sas_phy->phy_id < mr_sas_port->lowest_phy)
 634		mr_sas_port->lowest_phy = ffs(mr_sas_port->phy_mask) - 1;
 
 
 
 635	sas_port_add_phy(mr_sas_port->port, mr_sas_phy->phy);
 636	mr_sas_phy->phy_belongs_to_port = 1;
 637}
 638
 639/**
 640 * mpi3mr_add_phy_to_an_existing_port - add phy to existing port
 641 * @mrioc: Adapter instance reference
 642 * @mr_sas_node: Internal sas node object (expander or host)
 643 * @mr_sas_phy: Internal Phy object *
 644 * @sas_address: SAS address of device/expander were phy needs
 645 *             to be added to
 646 * @hba_port: HBA port entry
 647 *
 648 * Return: None.
 649 */
 650static void mpi3mr_add_phy_to_an_existing_port(struct mpi3mr_ioc *mrioc,
 651	struct mpi3mr_sas_node *mr_sas_node, struct mpi3mr_sas_phy *mr_sas_phy,
 652	u64 sas_address, struct mpi3mr_hba_port *hba_port)
 653{
 654	struct mpi3mr_sas_port *mr_sas_port;
 655	struct mpi3mr_sas_phy *srch_phy;
 656
 657	if (mr_sas_phy->phy_belongs_to_port == 1)
 658		return;
 659
 660	if (!hba_port)
 661		return;
 662
 663	list_for_each_entry(mr_sas_port, &mr_sas_node->sas_port_list,
 664	    port_list) {
 665		if (mr_sas_port->remote_identify.sas_address !=
 666		    sas_address)
 667			continue;
 668		if (mr_sas_port->hba_port != hba_port)
 669			continue;
 670		list_for_each_entry(srch_phy, &mr_sas_port->phy_list,
 671		    port_siblings) {
 672			if (srch_phy == mr_sas_phy)
 673				return;
 674		}
 675		mpi3mr_add_sas_phy(mrioc, mr_sas_port, mr_sas_phy);
 676		return;
 677	}
 678}
 679
 680/**
 681 * mpi3mr_delete_sas_port - helper function to removing a port
 682 * @mrioc: Adapter instance reference
 683 * @mr_sas_port: Internal Port object
 684 *
 685 * Return: None.
 686 */
 687static void  mpi3mr_delete_sas_port(struct mpi3mr_ioc *mrioc,
 688	struct mpi3mr_sas_port *mr_sas_port)
 689{
 690	u64 sas_address = mr_sas_port->remote_identify.sas_address;
 691	struct mpi3mr_hba_port *hba_port = mr_sas_port->hba_port;
 692	enum sas_device_type device_type =
 693	    mr_sas_port->remote_identify.device_type;
 694
 695	dev_info(&mr_sas_port->port->dev,
 696	    "remove: sas_address(0x%016llx)\n",
 697	    (unsigned long long) sas_address);
 698
 699	if (device_type == SAS_END_DEVICE)
 700		mpi3mr_remove_device_by_sas_address(mrioc, sas_address,
 701		    hba_port);
 702
 703	else if (device_type == SAS_EDGE_EXPANDER_DEVICE ||
 704	    device_type == SAS_FANOUT_EXPANDER_DEVICE)
 705		mpi3mr_expander_remove(mrioc, sas_address, hba_port);
 706}
 707
 708/**
 709 * mpi3mr_del_phy_from_an_existing_port - del phy from a port
 710 * @mrioc: Adapter instance reference
 711 * @mr_sas_node: Internal sas node object (expander or host)
 712 * @mr_sas_phy: Internal Phy object
 713 *
 714 * Return: None.
 715 */
 716static void mpi3mr_del_phy_from_an_existing_port(struct mpi3mr_ioc *mrioc,
 717	struct mpi3mr_sas_node *mr_sas_node, struct mpi3mr_sas_phy *mr_sas_phy)
 718{
 719	struct mpi3mr_sas_port *mr_sas_port, *next;
 720	struct mpi3mr_sas_phy *srch_phy;
 721
 722	if (mr_sas_phy->phy_belongs_to_port == 0)
 723		return;
 724
 725	list_for_each_entry_safe(mr_sas_port, next, &mr_sas_node->sas_port_list,
 726	    port_list) {
 727		list_for_each_entry(srch_phy, &mr_sas_port->phy_list,
 728		    port_siblings) {
 729			if (srch_phy != mr_sas_phy)
 730				continue;
 731			if ((mr_sas_port->num_phys == 1) &&
 732			    !mrioc->reset_in_progress)
 733				mpi3mr_delete_sas_port(mrioc, mr_sas_port);
 734			else
 735				mpi3mr_delete_sas_phy(mrioc, mr_sas_port,
 736				    mr_sas_phy);
 737			return;
 738		}
 739	}
 740}
 741
 742/**
 743 * mpi3mr_sas_port_sanity_check - sanity check while adding port
 744 * @mrioc: Adapter instance reference
 745 * @mr_sas_node: Internal sas node object (expander or host)
 746 * @sas_address: SAS address of device/expander
 747 * @hba_port: HBA port entry
 748 *
 749 * Verifies whether the Phys attached to a device with the given
 750 * SAS address already belongs to an existing sas port if so
 751 * will remove those phys from the sas port
 752 *
 753 * Return: None.
 754 */
 755static void mpi3mr_sas_port_sanity_check(struct mpi3mr_ioc *mrioc,
 756	struct mpi3mr_sas_node *mr_sas_node, u64 sas_address,
 757	struct mpi3mr_hba_port *hba_port)
 758{
 759	int i;
 760
 761	for (i = 0; i < mr_sas_node->num_phys; i++) {
 762		if ((mr_sas_node->phy[i].remote_identify.sas_address !=
 763		    sas_address) || (mr_sas_node->phy[i].hba_port != hba_port))
 764			continue;
 765		if (mr_sas_node->phy[i].phy_belongs_to_port == 1)
 766			mpi3mr_del_phy_from_an_existing_port(mrioc,
 767			    mr_sas_node, &mr_sas_node->phy[i]);
 768	}
 769}
 770
 771/**
 772 * mpi3mr_set_identify - set identify for phys and end devices
 773 * @mrioc: Adapter instance reference
 774 * @handle: Firmware device handle
 775 * @identify: SAS transport layer's identify info
 776 *
 777 * Populates sas identify info for a specific device.
 778 *
 779 * Return: 0 for success, non-zero for failure.
 780 */
 781static int mpi3mr_set_identify(struct mpi3mr_ioc *mrioc, u16 handle,
 782	struct sas_identify *identify)
 783{
 784
 785	struct mpi3_device_page0 device_pg0;
 786	struct mpi3_device0_sas_sata_format *sasinf;
 787	u16 device_info;
 788	u16 ioc_status;
 789
 790	if (mrioc->reset_in_progress) {
 791		ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
 792		return -EFAULT;
 793	}
 794
 
 
 
 
 
 
 795	if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &device_pg0,
 796	    sizeof(device_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE, handle))) {
 797		ioc_err(mrioc, "%s: device page0 read failed\n", __func__);
 798		return -ENXIO;
 799	}
 800
 801	if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
 802		ioc_err(mrioc, "device page read failed for handle(0x%04x), with ioc_status(0x%04x) failure at %s:%d/%s()!\n",
 803		    handle, ioc_status, __FILE__, __LINE__, __func__);
 804		return -EIO;
 805	}
 806
 807	memset(identify, 0, sizeof(struct sas_identify));
 808	sasinf = &device_pg0.device_specific.sas_sata_format;
 809	device_info = le16_to_cpu(sasinf->device_info);
 810
 811	/* sas_address */
 812	identify->sas_address = le64_to_cpu(sasinf->sas_address);
 813
 814	/* phy number of the parent device this device is linked to */
 815	identify->phy_identifier = sasinf->phy_num;
 816
 817	/* device_type */
 818	switch (device_info & MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_MASK) {
 819	case MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_NO_DEVICE:
 820		identify->device_type = SAS_PHY_UNUSED;
 821		break;
 822	case MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_END_DEVICE:
 823		identify->device_type = SAS_END_DEVICE;
 824		break;
 825	case MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_EXPANDER:
 826		identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
 827		break;
 828	}
 829
 830	/* initiator_port_protocols */
 831	if (device_info & MPI3_SAS_DEVICE_INFO_SSP_INITIATOR)
 832		identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
 833	/* MPI3.0 doesn't have define for SATA INIT so setting both here*/
 834	if (device_info & MPI3_SAS_DEVICE_INFO_STP_INITIATOR)
 835		identify->initiator_port_protocols |= (SAS_PROTOCOL_STP |
 836		    SAS_PROTOCOL_SATA);
 837	if (device_info & MPI3_SAS_DEVICE_INFO_SMP_INITIATOR)
 838		identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
 839
 840	/* target_port_protocols */
 841	if (device_info & MPI3_SAS_DEVICE_INFO_SSP_TARGET)
 842		identify->target_port_protocols |= SAS_PROTOCOL_SSP;
 843	/* MPI3.0 doesn't have define for STP Target so setting both here*/
 844	if (device_info & MPI3_SAS_DEVICE_INFO_STP_SATA_TARGET)
 845		identify->target_port_protocols |= (SAS_PROTOCOL_STP |
 846		    SAS_PROTOCOL_SATA);
 847	if (device_info & MPI3_SAS_DEVICE_INFO_SMP_TARGET)
 848		identify->target_port_protocols |= SAS_PROTOCOL_SMP;
 849	return 0;
 850}
 851
 852/**
 853 * mpi3mr_add_host_phy - report sas_host phy to SAS transport
 854 * @mrioc: Adapter instance reference
 855 * @mr_sas_phy: Internal Phy object
 856 * @phy_pg0: SAS phy page 0
 857 * @parent_dev: Prent device class object
 858 *
 859 * Return: 0 for success, non-zero for failure.
 860 */
 861static int mpi3mr_add_host_phy(struct mpi3mr_ioc *mrioc,
 862	struct mpi3mr_sas_phy *mr_sas_phy, struct mpi3_sas_phy_page0 phy_pg0,
 863	struct device *parent_dev)
 864{
 865	struct sas_phy *phy;
 866	int phy_index = mr_sas_phy->phy_id;
 867
 868
 869	INIT_LIST_HEAD(&mr_sas_phy->port_siblings);
 870	phy = sas_phy_alloc(parent_dev, phy_index);
 871	if (!phy) {
 872		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
 873		    __FILE__, __LINE__, __func__);
 874		return -1;
 875	}
 876	if ((mpi3mr_set_identify(mrioc, mr_sas_phy->handle,
 877	    &mr_sas_phy->identify))) {
 878		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
 879		    __FILE__, __LINE__, __func__);
 880		sas_phy_free(phy);
 881		return -1;
 882	}
 883	phy->identify = mr_sas_phy->identify;
 884	mr_sas_phy->attached_handle = le16_to_cpu(phy_pg0.attached_dev_handle);
 885	if (mr_sas_phy->attached_handle)
 886		mpi3mr_set_identify(mrioc, mr_sas_phy->attached_handle,
 887		    &mr_sas_phy->remote_identify);
 888	phy->identify.phy_identifier = mr_sas_phy->phy_id;
 889	phy->negotiated_linkrate = mpi3mr_convert_phy_link_rate(
 890	    (phy_pg0.negotiated_link_rate &
 891	    MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
 892	    MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT);
 893	phy->minimum_linkrate_hw = mpi3mr_convert_phy_link_rate(
 894	    phy_pg0.hw_link_rate & MPI3_SAS_HWRATE_MIN_RATE_MASK);
 895	phy->maximum_linkrate_hw = mpi3mr_convert_phy_link_rate(
 896	    phy_pg0.hw_link_rate >> 4);
 897	phy->minimum_linkrate = mpi3mr_convert_phy_link_rate(
 898	    phy_pg0.programmed_link_rate & MPI3_SAS_PRATE_MIN_RATE_MASK);
 899	phy->maximum_linkrate = mpi3mr_convert_phy_link_rate(
 900	    phy_pg0.programmed_link_rate >> 4);
 901	phy->hostdata = mr_sas_phy->hba_port;
 902
 903	if ((sas_phy_add(phy))) {
 904		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
 905		    __FILE__, __LINE__, __func__);
 906		sas_phy_free(phy);
 907		return -1;
 908	}
 909	if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO))
 910		dev_info(&phy->dev,
 911		    "add: handle(0x%04x), sas_address(0x%016llx)\n"
 912		    "\tattached_handle(0x%04x), sas_address(0x%016llx)\n",
 913		    mr_sas_phy->handle, (unsigned long long)
 914		    mr_sas_phy->identify.sas_address,
 915		    mr_sas_phy->attached_handle,
 916		    (unsigned long long)
 917		    mr_sas_phy->remote_identify.sas_address);
 918	mr_sas_phy->phy = phy;
 919	return 0;
 920}
 921
 922/**
 923 * mpi3mr_add_expander_phy - report expander phy to transport
 924 * @mrioc: Adapter instance reference
 925 * @mr_sas_phy: Internal Phy object
 926 * @expander_pg1: SAS Expander page 1
 927 * @parent_dev: Parent device class object
 928 *
 929 * Return: 0 for success, non-zero for failure.
 930 */
 931static int mpi3mr_add_expander_phy(struct mpi3mr_ioc *mrioc,
 932	struct mpi3mr_sas_phy *mr_sas_phy,
 933	struct mpi3_sas_expander_page1 expander_pg1,
 934	struct device *parent_dev)
 935{
 936	struct sas_phy *phy;
 937	int phy_index = mr_sas_phy->phy_id;
 938
 939	INIT_LIST_HEAD(&mr_sas_phy->port_siblings);
 940	phy = sas_phy_alloc(parent_dev, phy_index);
 941	if (!phy) {
 942		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
 943		    __FILE__, __LINE__, __func__);
 944		return -1;
 945	}
 946	if ((mpi3mr_set_identify(mrioc, mr_sas_phy->handle,
 947	    &mr_sas_phy->identify))) {
 948		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
 949		    __FILE__, __LINE__, __func__);
 950		sas_phy_free(phy);
 951		return -1;
 952	}
 953	phy->identify = mr_sas_phy->identify;
 954	mr_sas_phy->attached_handle =
 955	    le16_to_cpu(expander_pg1.attached_dev_handle);
 956	if (mr_sas_phy->attached_handle)
 957		mpi3mr_set_identify(mrioc, mr_sas_phy->attached_handle,
 958		    &mr_sas_phy->remote_identify);
 959	phy->identify.phy_identifier = mr_sas_phy->phy_id;
 960	phy->negotiated_linkrate = mpi3mr_convert_phy_link_rate(
 961	    (expander_pg1.negotiated_link_rate &
 962	    MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
 963	    MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT);
 964	phy->minimum_linkrate_hw = mpi3mr_convert_phy_link_rate(
 965	    expander_pg1.hw_link_rate & MPI3_SAS_HWRATE_MIN_RATE_MASK);
 966	phy->maximum_linkrate_hw = mpi3mr_convert_phy_link_rate(
 967	    expander_pg1.hw_link_rate >> 4);
 968	phy->minimum_linkrate = mpi3mr_convert_phy_link_rate(
 969	    expander_pg1.programmed_link_rate & MPI3_SAS_PRATE_MIN_RATE_MASK);
 970	phy->maximum_linkrate = mpi3mr_convert_phy_link_rate(
 971	    expander_pg1.programmed_link_rate >> 4);
 972	phy->hostdata = mr_sas_phy->hba_port;
 973
 974	if ((sas_phy_add(phy))) {
 975		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
 976		    __FILE__, __LINE__, __func__);
 977		sas_phy_free(phy);
 978		return -1;
 979	}
 980	if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO))
 981		dev_info(&phy->dev,
 982		    "add: handle(0x%04x), sas_address(0x%016llx)\n"
 983		    "\tattached_handle(0x%04x), sas_address(0x%016llx)\n",
 984		    mr_sas_phy->handle, (unsigned long long)
 985		    mr_sas_phy->identify.sas_address,
 986		    mr_sas_phy->attached_handle,
 987		    (unsigned long long)
 988		    mr_sas_phy->remote_identify.sas_address);
 989	mr_sas_phy->phy = phy;
 990	return 0;
 991}
 992
 993/**
 994 * mpi3mr_alloc_hba_port - alloc hba port object
 995 * @mrioc: Adapter instance reference
 996 * @port_id: Port number
 997 *
 998 * Alloc memory for hba port object.
 999 */
1000static struct mpi3mr_hba_port *
1001mpi3mr_alloc_hba_port(struct mpi3mr_ioc *mrioc, u16 port_id)
1002{
1003	struct mpi3mr_hba_port *hba_port;
1004
1005	hba_port = kzalloc(sizeof(struct mpi3mr_hba_port),
1006	    GFP_KERNEL);
1007	if (!hba_port)
1008		return NULL;
1009	hba_port->port_id = port_id;
1010	ioc_info(mrioc, "hba_port entry: %p, port: %d is added to hba_port list\n",
1011	    hba_port, hba_port->port_id);
 
 
 
1012	list_add_tail(&hba_port->list, &mrioc->hba_port_table_list);
1013	return hba_port;
1014}
1015
1016/**
1017 * mpi3mr_get_hba_port_by_id - find hba port by id
1018 * @mrioc: Adapter instance reference
1019 * @port_id - Port ID to search
1020 *
1021 * Return: mpi3mr_hba_port reference for the matched port
1022 */
1023
1024struct mpi3mr_hba_port *mpi3mr_get_hba_port_by_id(struct mpi3mr_ioc *mrioc,
1025	u8 port_id)
1026{
1027	struct mpi3mr_hba_port *port, *port_next;
1028
1029	list_for_each_entry_safe(port, port_next,
1030	    &mrioc->hba_port_table_list, list) {
1031		if (port->port_id != port_id)
1032			continue;
1033		if (port->flags & MPI3MR_HBA_PORT_FLAG_DIRTY)
1034			continue;
1035		return port;
1036	}
1037
1038	return NULL;
1039}
1040
1041/**
1042 * mpi3mr_update_links - refreshing SAS phy link changes
1043 * @mrioc: Adapter instance reference
1044 * @sas_address_parent: SAS address of parent expander or host
1045 * @handle: Firmware device handle of attached device
1046 * @phy_number: Phy number
1047 * @link_rate: New link rate
1048 * @hba_port: HBA port entry
1049 *
1050 * Return: None.
1051 */
1052void mpi3mr_update_links(struct mpi3mr_ioc *mrioc,
1053	u64 sas_address_parent, u16 handle, u8 phy_number, u8 link_rate,
1054	struct mpi3mr_hba_port *hba_port)
1055{
1056	unsigned long flags;
1057	struct mpi3mr_sas_node *mr_sas_node;
1058	struct mpi3mr_sas_phy *mr_sas_phy;
1059
1060	if (mrioc->reset_in_progress)
1061		return;
1062
1063	spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1064	mr_sas_node = __mpi3mr_sas_node_find_by_sas_address(mrioc,
1065	    sas_address_parent, hba_port);
1066	if (!mr_sas_node) {
1067		spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1068		return;
1069	}
1070
1071	mr_sas_phy = &mr_sas_node->phy[phy_number];
1072	mr_sas_phy->attached_handle = handle;
1073	spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1074	if (handle && (link_rate >= MPI3_SAS_NEG_LINK_RATE_1_5)) {
1075		mpi3mr_set_identify(mrioc, handle,
1076		    &mr_sas_phy->remote_identify);
1077		mpi3mr_add_phy_to_an_existing_port(mrioc, mr_sas_node,
1078		    mr_sas_phy, mr_sas_phy->remote_identify.sas_address,
1079		    hba_port);
1080	} else
1081		memset(&mr_sas_phy->remote_identify, 0, sizeof(struct
1082		    sas_identify));
1083
1084	if (mr_sas_phy->phy)
1085		mr_sas_phy->phy->negotiated_linkrate =
1086		    mpi3mr_convert_phy_link_rate(link_rate);
1087
1088	if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO))
1089		dev_info(&mr_sas_phy->phy->dev,
1090		    "refresh: parent sas_address(0x%016llx),\n"
1091		    "\tlink_rate(0x%02x), phy(%d)\n"
1092		    "\tattached_handle(0x%04x), sas_address(0x%016llx)\n",
1093		    (unsigned long long)sas_address_parent,
1094		    link_rate, phy_number, handle, (unsigned long long)
1095		    mr_sas_phy->remote_identify.sas_address);
1096}
1097
1098/**
1099 * mpi3mr_sas_host_refresh - refreshing sas host object contents
1100 * @mrioc: Adapter instance reference
1101 *
1102 * This function refreshes the controllers phy information and
1103 * updates the SAS transport layer with updated information,
1104 * this is executed for each device addition or device info
1105 * change events
1106 *
1107 * Return: None.
1108 */
1109void mpi3mr_sas_host_refresh(struct mpi3mr_ioc *mrioc)
1110{
1111	int i;
1112	u8 link_rate;
1113	u16 sz, port_id, attached_handle;
1114	struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL;
1115
1116	dprint_transport_info(mrioc,
1117	    "updating handles for sas_host(0x%016llx)\n",
1118	    (unsigned long long)mrioc->sas_hba.sas_address);
1119
1120	sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) +
1121	    (mrioc->sas_hba.num_phys *
1122	     sizeof(struct mpi3_sas_io_unit0_phy_data));
1123	sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
1124	if (!sas_io_unit_pg0)
1125		return;
1126	if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
1127		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1128		    __FILE__, __LINE__, __func__);
1129		goto out;
1130	}
1131
1132	mrioc->sas_hba.handle = 0;
1133	for (i = 0; i < mrioc->sas_hba.num_phys; i++) {
1134		if (sas_io_unit_pg0->phy_data[i].phy_flags &
1135		    (MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY |
1136		     MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY))
1137			continue;
1138		link_rate =
1139		    sas_io_unit_pg0->phy_data[i].negotiated_link_rate >> 4;
1140		if (!mrioc->sas_hba.handle)
1141			mrioc->sas_hba.handle = le16_to_cpu(
1142			    sas_io_unit_pg0->phy_data[i].controller_dev_handle);
1143		port_id = sas_io_unit_pg0->phy_data[i].io_unit_port;
1144		if (!(mpi3mr_get_hba_port_by_id(mrioc, port_id)))
1145			if (!mpi3mr_alloc_hba_port(mrioc, port_id))
1146				goto out;
1147
1148		mrioc->sas_hba.phy[i].handle = mrioc->sas_hba.handle;
1149		attached_handle = le16_to_cpu(
1150		    sas_io_unit_pg0->phy_data[i].attached_dev_handle);
1151		if (attached_handle && link_rate < MPI3_SAS_NEG_LINK_RATE_1_5)
1152			link_rate = MPI3_SAS_NEG_LINK_RATE_1_5;
1153		mrioc->sas_hba.phy[i].hba_port =
1154			mpi3mr_get_hba_port_by_id(mrioc, port_id);
1155		mpi3mr_update_links(mrioc, mrioc->sas_hba.sas_address,
1156		    attached_handle, i, link_rate,
1157		    mrioc->sas_hba.phy[i].hba_port);
1158	}
1159 out:
1160	kfree(sas_io_unit_pg0);
1161}
1162
1163/**
1164 * mpi3mr_sas_host_add - create sas host object
1165 * @mrioc: Adapter instance reference
1166 *
1167 * This function creates the controllers phy information and
1168 * updates the SAS transport layer with updated information,
1169 * this is executed for first device addition or device info
1170 * change event.
1171 *
1172 * Return: None.
1173 */
1174void mpi3mr_sas_host_add(struct mpi3mr_ioc *mrioc)
1175{
1176	int i;
1177	u16 sz, num_phys = 1, port_id, ioc_status;
1178	struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL;
1179	struct mpi3_sas_phy_page0 phy_pg0;
1180	struct mpi3_device_page0 dev_pg0;
1181	struct mpi3_enclosure_page0 encl_pg0;
1182	struct mpi3_device0_sas_sata_format *sasinf;
1183
1184	sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) +
1185	    (num_phys * sizeof(struct mpi3_sas_io_unit0_phy_data));
1186	sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
1187	if (!sas_io_unit_pg0)
1188		return;
1189
1190	if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
1191		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1192		    __FILE__, __LINE__, __func__);
1193		goto out;
1194	}
1195	num_phys = sas_io_unit_pg0->num_phys;
1196	kfree(sas_io_unit_pg0);
1197
1198	mrioc->sas_hba.host_node = 1;
1199	INIT_LIST_HEAD(&mrioc->sas_hba.sas_port_list);
1200	mrioc->sas_hba.parent_dev = &mrioc->shost->shost_gendev;
1201	mrioc->sas_hba.phy = kcalloc(num_phys,
1202	    sizeof(struct mpi3mr_sas_phy), GFP_KERNEL);
1203	if (!mrioc->sas_hba.phy)
1204		return;
1205
1206	mrioc->sas_hba.num_phys = num_phys;
1207
1208	sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) +
1209	    (num_phys * sizeof(struct mpi3_sas_io_unit0_phy_data));
1210	sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
1211	if (!sas_io_unit_pg0)
1212		return;
1213
1214	if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
1215		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1216		    __FILE__, __LINE__, __func__);
1217		goto out;
1218	}
1219
1220	mrioc->sas_hba.handle = 0;
1221	for (i = 0; i < mrioc->sas_hba.num_phys; i++) {
1222		if (sas_io_unit_pg0->phy_data[i].phy_flags &
1223		    (MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY |
1224		    MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY))
1225			continue;
1226		if (mpi3mr_cfg_get_sas_phy_pg0(mrioc, &ioc_status, &phy_pg0,
1227		    sizeof(struct mpi3_sas_phy_page0),
1228		    MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, i)) {
1229			ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1230			    __FILE__, __LINE__, __func__);
1231			goto out;
1232		}
1233		if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
1234			ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1235			    __FILE__, __LINE__, __func__);
1236			goto out;
1237		}
1238
1239		if (!mrioc->sas_hba.handle)
1240			mrioc->sas_hba.handle = le16_to_cpu(
1241			    sas_io_unit_pg0->phy_data[i].controller_dev_handle);
1242		port_id = sas_io_unit_pg0->phy_data[i].io_unit_port;
1243
1244		if (!(mpi3mr_get_hba_port_by_id(mrioc, port_id)))
1245			if (!mpi3mr_alloc_hba_port(mrioc, port_id))
1246				goto out;
1247
1248		mrioc->sas_hba.phy[i].handle = mrioc->sas_hba.handle;
1249		mrioc->sas_hba.phy[i].phy_id = i;
1250		mrioc->sas_hba.phy[i].hba_port =
1251		    mpi3mr_get_hba_port_by_id(mrioc, port_id);
1252		mpi3mr_add_host_phy(mrioc, &mrioc->sas_hba.phy[i],
1253		    phy_pg0, mrioc->sas_hba.parent_dev);
1254	}
1255	if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &dev_pg0,
1256	    sizeof(dev_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE,
1257	    mrioc->sas_hba.handle))) {
1258		ioc_err(mrioc, "%s: device page0 read failed\n", __func__);
1259		goto out;
1260	}
1261	if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
1262		ioc_err(mrioc, "device page read failed for handle(0x%04x), with ioc_status(0x%04x) failure at %s:%d/%s()!\n",
1263		    mrioc->sas_hba.handle, ioc_status, __FILE__, __LINE__,
1264		    __func__);
1265		goto out;
1266	}
1267	mrioc->sas_hba.enclosure_handle =
1268	    le16_to_cpu(dev_pg0.enclosure_handle);
1269	sasinf = &dev_pg0.device_specific.sas_sata_format;
1270	mrioc->sas_hba.sas_address =
1271	    le64_to_cpu(sasinf->sas_address);
1272	ioc_info(mrioc,
1273	    "host_add: handle(0x%04x), sas_addr(0x%016llx), phys(%d)\n",
1274	    mrioc->sas_hba.handle,
1275	    (unsigned long long) mrioc->sas_hba.sas_address,
1276	    mrioc->sas_hba.num_phys);
1277
1278	if (mrioc->sas_hba.enclosure_handle) {
1279		if (!(mpi3mr_cfg_get_enclosure_pg0(mrioc, &ioc_status,
1280		    &encl_pg0, sizeof(encl_pg0),
1281		    MPI3_ENCLOS_PGAD_FORM_HANDLE,
1282		    mrioc->sas_hba.enclosure_handle)) &&
1283		    (ioc_status == MPI3_IOCSTATUS_SUCCESS))
1284			mrioc->sas_hba.enclosure_logical_id =
1285				le64_to_cpu(encl_pg0.enclosure_logical_id);
1286	}
1287
1288out:
1289	kfree(sas_io_unit_pg0);
1290}
1291
1292/**
1293 * mpi3mr_sas_port_add - Expose the SAS device to the SAS TL
1294 * @mrioc: Adapter instance reference
1295 * @handle: Firmware device handle of the attached device
1296 * @sas_address_parent: sas address of parent expander or host
1297 * @hba_port: HBA port entry
1298 *
1299 * This function creates a new sas port object for the given end
1300 * device matching sas address and hba_port and adds it to the
1301 * sas_node's sas_port_list and expose the attached sas device
1302 * to the SAS transport layer through sas_rphy_add.
1303 *
1304 * Returns a valid mpi3mr_sas_port reference or NULL.
1305 */
1306static struct mpi3mr_sas_port *mpi3mr_sas_port_add(struct mpi3mr_ioc *mrioc,
1307	u16 handle, u64 sas_address_parent, struct mpi3mr_hba_port *hba_port)
1308{
1309	struct mpi3mr_sas_phy *mr_sas_phy, *next;
1310	struct mpi3mr_sas_port *mr_sas_port;
1311	unsigned long flags;
1312	struct mpi3mr_sas_node *mr_sas_node;
1313	struct sas_rphy *rphy;
1314	struct mpi3mr_tgt_dev *tgtdev = NULL;
1315	int i;
1316	struct sas_port *port;
1317
1318	if (!hba_port) {
1319		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1320		    __FILE__, __LINE__, __func__);
1321		return NULL;
1322	}
1323
1324	mr_sas_port = kzalloc(sizeof(struct mpi3mr_sas_port), GFP_KERNEL);
1325	if (!mr_sas_port)
1326		return NULL;
1327
1328	INIT_LIST_HEAD(&mr_sas_port->port_list);
1329	INIT_LIST_HEAD(&mr_sas_port->phy_list);
1330	spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1331	mr_sas_node = __mpi3mr_sas_node_find_by_sas_address(mrioc,
1332	    sas_address_parent, hba_port);
1333	spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1334
1335	if (!mr_sas_node) {
1336		ioc_err(mrioc, "%s:could not find parent sas_address(0x%016llx)!\n",
1337		    __func__, (unsigned long long)sas_address_parent);
1338		goto out_fail;
1339	}
1340
1341	if ((mpi3mr_set_identify(mrioc, handle,
1342	    &mr_sas_port->remote_identify))) {
1343		ioc_err(mrioc,  "failure at %s:%d/%s()!\n",
1344		    __FILE__, __LINE__, __func__);
1345		goto out_fail;
1346	}
1347
1348	if (mr_sas_port->remote_identify.device_type == SAS_PHY_UNUSED) {
1349		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1350		    __FILE__, __LINE__, __func__);
1351		goto out_fail;
1352	}
1353
1354	mr_sas_port->hba_port = hba_port;
1355	mpi3mr_sas_port_sanity_check(mrioc, mr_sas_node,
1356	    mr_sas_port->remote_identify.sas_address, hba_port);
1357
 
 
 
 
 
1358	for (i = 0; i < mr_sas_node->num_phys; i++) {
1359		if ((mr_sas_node->phy[i].remote_identify.sas_address !=
1360		    mr_sas_port->remote_identify.sas_address) ||
1361		    (mr_sas_node->phy[i].hba_port != hba_port))
1362			continue;
 
 
 
 
 
 
1363		list_add_tail(&mr_sas_node->phy[i].port_siblings,
1364		    &mr_sas_port->phy_list);
1365		mr_sas_port->num_phys++;
1366		mr_sas_port->phy_mask |= (1 << i);
 
1367	}
1368
1369	if (!mr_sas_port->num_phys) {
1370		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1371		    __FILE__, __LINE__, __func__);
1372		goto out_fail;
1373	}
1374
1375	mr_sas_port->lowest_phy = ffs(mr_sas_port->phy_mask) - 1;
 
1376
1377	if (mr_sas_port->remote_identify.device_type == SAS_END_DEVICE) {
1378		tgtdev = mpi3mr_get_tgtdev_by_addr(mrioc,
1379		    mr_sas_port->remote_identify.sas_address,
1380		    mr_sas_port->hba_port);
1381
1382		if (!tgtdev) {
1383			ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1384			    __FILE__, __LINE__, __func__);
1385			goto out_fail;
1386		}
1387		tgtdev->dev_spec.sas_sata_inf.pend_sas_rphy_add = 1;
1388	}
1389
1390	if (!mr_sas_node->parent_dev) {
1391		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1392		    __FILE__, __LINE__, __func__);
1393		goto out_fail;
1394	}
1395
1396	port = sas_port_alloc_num(mr_sas_node->parent_dev);
1397	if ((sas_port_add(port))) {
1398		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1399		    __FILE__, __LINE__, __func__);
1400		goto out_fail;
1401	}
1402
1403	list_for_each_entry(mr_sas_phy, &mr_sas_port->phy_list,
1404	    port_siblings) {
1405		if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO))
1406			dev_info(&port->dev,
1407			    "add: handle(0x%04x), sas_address(0x%016llx), phy(%d)\n",
1408			    handle, (unsigned long long)
1409			    mr_sas_port->remote_identify.sas_address,
1410			    mr_sas_phy->phy_id);
1411		sas_port_add_phy(port, mr_sas_phy->phy);
1412		mr_sas_phy->phy_belongs_to_port = 1;
1413		mr_sas_phy->hba_port = hba_port;
1414	}
1415
1416	mr_sas_port->port = port;
1417	if (mr_sas_port->remote_identify.device_type == SAS_END_DEVICE) {
1418		rphy = sas_end_device_alloc(port);
1419		tgtdev->dev_spec.sas_sata_inf.rphy = rphy;
1420	} else {
1421		rphy = sas_expander_alloc(port,
1422		    mr_sas_port->remote_identify.device_type);
1423	}
1424	rphy->identify = mr_sas_port->remote_identify;
1425
1426	if (mrioc->current_event)
1427		mrioc->current_event->pending_at_sml = 1;
1428
1429	if ((sas_rphy_add(rphy))) {
1430		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1431		    __FILE__, __LINE__, __func__);
1432	}
1433	if (mr_sas_port->remote_identify.device_type == SAS_END_DEVICE) {
1434		tgtdev->dev_spec.sas_sata_inf.pend_sas_rphy_add = 0;
1435		tgtdev->dev_spec.sas_sata_inf.sas_transport_attached = 1;
1436		mpi3mr_tgtdev_put(tgtdev);
1437	}
1438
1439	dev_info(&rphy->dev,
1440	    "%s: added: handle(0x%04x), sas_address(0x%016llx)\n",
1441	    __func__, handle, (unsigned long long)
1442	    mr_sas_port->remote_identify.sas_address);
1443
1444	mr_sas_port->rphy = rphy;
1445	spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1446	list_add_tail(&mr_sas_port->port_list, &mr_sas_node->sas_port_list);
1447	spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1448
1449	if (mrioc->current_event) {
1450		mrioc->current_event->pending_at_sml = 0;
1451		if (mrioc->current_event->discard)
1452			mpi3mr_print_device_event_notice(mrioc, true);
1453	}
1454
1455	/* fill in report manufacture */
1456	if (mr_sas_port->remote_identify.device_type ==
1457	    SAS_EDGE_EXPANDER_DEVICE ||
1458	    mr_sas_port->remote_identify.device_type ==
1459	    SAS_FANOUT_EXPANDER_DEVICE)
1460		mpi3mr_report_manufacture(mrioc,
1461		    mr_sas_port->remote_identify.sas_address,
1462		    rphy_to_expander_device(rphy), hba_port->port_id);
1463
1464	return mr_sas_port;
1465
1466 out_fail:
1467	list_for_each_entry_safe(mr_sas_phy, next, &mr_sas_port->phy_list,
1468	    port_siblings)
1469		list_del(&mr_sas_phy->port_siblings);
1470	kfree(mr_sas_port);
1471	return NULL;
1472}
1473
1474/**
1475 * mpi3mr_sas_port_remove - remove port from the list
1476 * @mrioc: Adapter instance reference
1477 * @sas_address: SAS address of attached device
1478 * @sas_address_parent: SAS address of parent expander or host
1479 * @hba_port: HBA port entry
1480 *
1481 * Removing object and freeing associated memory from the
1482 * sas_port_list.
1483 *
1484 * Return: None
1485 */
1486static void mpi3mr_sas_port_remove(struct mpi3mr_ioc *mrioc, u64 sas_address,
1487	u64 sas_address_parent, struct mpi3mr_hba_port *hba_port)
1488{
1489	int i;
1490	unsigned long flags;
1491	struct mpi3mr_sas_port *mr_sas_port, *next;
1492	struct mpi3mr_sas_node *mr_sas_node;
1493	u8 found = 0;
1494	struct mpi3mr_sas_phy *mr_sas_phy, *next_phy;
1495	struct mpi3mr_hba_port *srch_port, *hba_port_next = NULL;
1496
1497	if (!hba_port)
1498		return;
1499
1500	spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1501	mr_sas_node = __mpi3mr_sas_node_find_by_sas_address(mrioc,
1502	    sas_address_parent, hba_port);
1503	if (!mr_sas_node) {
1504		spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1505		return;
1506	}
1507	list_for_each_entry_safe(mr_sas_port, next, &mr_sas_node->sas_port_list,
1508	    port_list) {
1509		if (mr_sas_port->remote_identify.sas_address != sas_address)
1510			continue;
1511		if (mr_sas_port->hba_port != hba_port)
1512			continue;
1513		found = 1;
1514		list_del(&mr_sas_port->port_list);
1515		goto out;
1516	}
1517
1518 out:
1519	if (!found) {
1520		spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1521		return;
1522	}
1523
1524	if (mr_sas_node->host_node) {
1525		list_for_each_entry_safe(srch_port, hba_port_next,
1526		    &mrioc->hba_port_table_list, list) {
1527			if (srch_port != hba_port)
1528				continue;
1529			ioc_info(mrioc,
1530			    "removing hba_port entry: %p port: %d from hba_port list\n",
1531			    srch_port, srch_port->port_id);
1532			list_del(&hba_port->list);
1533			kfree(hba_port);
1534			break;
1535		}
1536	}
1537
1538	for (i = 0; i < mr_sas_node->num_phys; i++) {
1539		if (mr_sas_node->phy[i].remote_identify.sas_address ==
1540		    sas_address)
1541			memset(&mr_sas_node->phy[i].remote_identify, 0,
1542			    sizeof(struct sas_identify));
1543	}
1544
1545	spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1546
1547	if (mrioc->current_event)
1548		mrioc->current_event->pending_at_sml = 1;
1549
1550	list_for_each_entry_safe(mr_sas_phy, next_phy,
1551	    &mr_sas_port->phy_list, port_siblings) {
1552		if ((!mrioc->stop_drv_processing) &&
1553		    (mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO))
1554			dev_info(&mr_sas_port->port->dev,
1555			    "remove: sas_address(0x%016llx), phy(%d)\n",
1556			    (unsigned long long)
1557			    mr_sas_port->remote_identify.sas_address,
1558			    mr_sas_phy->phy_id);
1559		mr_sas_phy->phy_belongs_to_port = 0;
1560		if (!mrioc->stop_drv_processing)
1561			sas_port_delete_phy(mr_sas_port->port,
1562			    mr_sas_phy->phy);
1563		list_del(&mr_sas_phy->port_siblings);
1564	}
1565	if (!mrioc->stop_drv_processing)
1566		sas_port_delete(mr_sas_port->port);
1567	ioc_info(mrioc, "%s: removed sas_address(0x%016llx)\n",
1568	    __func__, (unsigned long long)sas_address);
1569
1570	if (mrioc->current_event) {
1571		mrioc->current_event->pending_at_sml = 0;
1572		if (mrioc->current_event->discard)
1573			mpi3mr_print_device_event_notice(mrioc, false);
1574	}
1575
1576	kfree(mr_sas_port);
1577}
1578
1579/**
1580 * struct host_port - host port details
1581 * @sas_address: SAS Address of the attached device
1582 * @phy_mask: phy mask of host port
1583 * @handle: Device Handle of attached device
1584 * @iounit_port_id: port ID
1585 * @used: host port is already matched with sas port from sas_port_list
1586 * @lowest_phy: lowest phy ID of host port
1587 */
1588struct host_port {
1589	u64	sas_address;
1590	u64	phy_mask;
1591	u16	handle;
1592	u8	iounit_port_id;
1593	u8	used;
1594	u8	lowest_phy;
1595};
1596
1597/**
1598 * mpi3mr_update_mr_sas_port - update sas port objects during reset
1599 * @mrioc: Adapter instance reference
1600 * @h_port: host_port object
1601 * @mr_sas_port: sas_port objects which needs to be updated
1602 *
1603 * Update the port ID of sas port object. Also add the phys if new phys got
1604 * added to current sas port and remove the phys if some phys are moved
1605 * out of the current sas port.
1606 *
1607 * Return: Nothing.
1608 */
1609static void
1610mpi3mr_update_mr_sas_port(struct mpi3mr_ioc *mrioc, struct host_port *h_port,
1611	struct mpi3mr_sas_port *mr_sas_port)
1612{
1613	struct mpi3mr_sas_phy *mr_sas_phy;
1614	u64 phy_mask_xor;
1615	u64 phys_to_be_added, phys_to_be_removed;
1616	int i;
1617
1618	h_port->used = 1;
1619	mr_sas_port->marked_responding = 1;
1620
1621	dev_info(&mr_sas_port->port->dev,
1622	    "sas_address(0x%016llx), old: port_id %d phy_mask 0x%llx, new: port_id %d phy_mask:0x%llx\n",
1623	    mr_sas_port->remote_identify.sas_address,
1624	    mr_sas_port->hba_port->port_id, mr_sas_port->phy_mask,
1625	    h_port->iounit_port_id, h_port->phy_mask);
1626
1627	mr_sas_port->hba_port->port_id = h_port->iounit_port_id;
1628	mr_sas_port->hba_port->flags &= ~MPI3MR_HBA_PORT_FLAG_DIRTY;
1629
1630	/* Get the newly added phys bit map & removed phys bit map */
1631	phy_mask_xor = mr_sas_port->phy_mask ^ h_port->phy_mask;
1632	phys_to_be_added = h_port->phy_mask & phy_mask_xor;
1633	phys_to_be_removed = mr_sas_port->phy_mask & phy_mask_xor;
1634
1635	/*
1636	 * Register these new phys to current mr_sas_port's port.
1637	 * if these phys are previously registered with another port
1638	 * then delete these phys from that port first.
1639	 */
1640	for_each_set_bit(i, (ulong *) &phys_to_be_added, BITS_PER_TYPE(u64)) {
1641		mr_sas_phy = &mrioc->sas_hba.phy[i];
1642		if (mr_sas_phy->phy_belongs_to_port)
1643			mpi3mr_del_phy_from_an_existing_port(mrioc,
1644			    &mrioc->sas_hba, mr_sas_phy);
1645		mpi3mr_add_phy_to_an_existing_port(mrioc,
1646		    &mrioc->sas_hba, mr_sas_phy,
1647		    mr_sas_port->remote_identify.sas_address,
1648		    mr_sas_port->hba_port);
1649	}
1650
1651	/* Delete the phys which are not part of current mr_sas_port's port. */
1652	for_each_set_bit(i, (ulong *) &phys_to_be_removed, BITS_PER_TYPE(u64)) {
1653		mr_sas_phy = &mrioc->sas_hba.phy[i];
1654		if (mr_sas_phy->phy_belongs_to_port)
1655			mpi3mr_del_phy_from_an_existing_port(mrioc,
1656			    &mrioc->sas_hba, mr_sas_phy);
1657	}
1658}
1659
1660/**
1661 * mpi3mr_refresh_sas_ports - update host's sas ports during reset
1662 * @mrioc: Adapter instance reference
1663 *
1664 * Update the host's sas ports during reset by checking whether
1665 * sas ports are still intact or not. Add/remove phys if any hba
1666 * phys are (moved in)/(moved out) of sas port. Also update
1667 * io_unit_port if it got changed during reset.
1668 *
1669 * Return: Nothing.
1670 */
1671void
1672mpi3mr_refresh_sas_ports(struct mpi3mr_ioc *mrioc)
1673{
1674	struct host_port *h_port = NULL;
1675	int i, j, found, host_port_count = 0, port_idx;
1676	u16 sz, attached_handle, ioc_status;
1677	struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL;
1678	struct mpi3_device_page0 dev_pg0;
1679	struct mpi3_device0_sas_sata_format *sasinf;
1680	struct mpi3mr_sas_port *mr_sas_port;
1681
1682	sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) +
1683		(mrioc->sas_hba.num_phys *
1684		 sizeof(struct mpi3_sas_io_unit0_phy_data));
1685	sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
1686	if (!sas_io_unit_pg0)
1687		return;
1688	h_port = kcalloc(64, sizeof(struct host_port), GFP_KERNEL);
1689	if (!h_port)
1690		goto out;
1691
1692	if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
1693		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1694		    __FILE__, __LINE__, __func__);
1695		goto out;
1696	}
1697
1698	/* Create a new expander port table */
1699	for (i = 0; i < mrioc->sas_hba.num_phys; i++) {
1700		attached_handle = le16_to_cpu(
1701		    sas_io_unit_pg0->phy_data[i].attached_dev_handle);
1702		if (!attached_handle)
1703			continue;
1704		found = 0;
1705		for (j = 0; j < host_port_count; j++) {
1706			if (h_port[j].handle == attached_handle) {
1707				h_port[j].phy_mask |= (1 << i);
1708				found = 1;
1709				break;
1710			}
1711		}
1712		if (found)
1713			continue;
1714		if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &dev_pg0,
1715		    sizeof(dev_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE,
1716		    attached_handle))) {
1717			dprint_reset(mrioc,
1718			    "failed to read dev_pg0 for handle(0x%04x) at %s:%d/%s()!\n",
1719			    attached_handle, __FILE__, __LINE__, __func__);
1720			continue;
1721		}
1722		if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
1723			dprint_reset(mrioc,
1724			    "ioc_status(0x%x) while reading dev_pg0 for handle(0x%04x) at %s:%d/%s()!\n",
1725			    ioc_status, attached_handle,
1726			    __FILE__, __LINE__, __func__);
1727			continue;
1728		}
1729		sasinf = &dev_pg0.device_specific.sas_sata_format;
1730
1731		port_idx = host_port_count;
1732		h_port[port_idx].sas_address = le64_to_cpu(sasinf->sas_address);
1733		h_port[port_idx].handle = attached_handle;
1734		h_port[port_idx].phy_mask = (1 << i);
1735		h_port[port_idx].iounit_port_id = sas_io_unit_pg0->phy_data[i].io_unit_port;
1736		h_port[port_idx].lowest_phy = sasinf->phy_num;
1737		h_port[port_idx].used = 0;
1738		host_port_count++;
1739	}
1740
1741	if (!host_port_count)
1742		goto out;
1743
1744	if (mrioc->logging_level & MPI3_DEBUG_RESET) {
1745		ioc_info(mrioc, "Host port details before reset\n");
1746		list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1747		    port_list) {
1748			ioc_info(mrioc,
1749			    "port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%llx), lowest phy id:%d\n",
1750			    mr_sas_port->hba_port->port_id,
1751			    mr_sas_port->remote_identify.sas_address,
1752			    mr_sas_port->phy_mask, mr_sas_port->lowest_phy);
1753		}
1754		mr_sas_port = NULL;
1755		ioc_info(mrioc, "Host port details after reset\n");
1756		for (i = 0; i < host_port_count; i++) {
1757			ioc_info(mrioc,
1758			    "port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%llx), lowest phy id:%d\n",
1759			    h_port[i].iounit_port_id, h_port[i].sas_address,
1760			    h_port[i].phy_mask, h_port[i].lowest_phy);
1761		}
1762	}
1763
1764	/* mark all host sas port entries as dirty */
1765	list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1766	    port_list) {
1767		mr_sas_port->marked_responding = 0;
1768		mr_sas_port->hba_port->flags |= MPI3MR_HBA_PORT_FLAG_DIRTY;
1769	}
1770
1771	/* First check for matching lowest phy */
1772	for (i = 0; i < host_port_count; i++) {
1773		mr_sas_port = NULL;
1774		list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1775		    port_list) {
1776			if (mr_sas_port->marked_responding)
1777				continue;
1778			if (h_port[i].sas_address != mr_sas_port->remote_identify.sas_address)
1779				continue;
1780			if (h_port[i].lowest_phy == mr_sas_port->lowest_phy) {
1781				mpi3mr_update_mr_sas_port(mrioc, &h_port[i], mr_sas_port);
1782				break;
1783			}
1784		}
1785	}
1786
1787	/* In case if lowest phy is got enabled or disabled during reset */
1788	for (i = 0; i < host_port_count; i++) {
1789		if (h_port[i].used)
1790			continue;
1791		mr_sas_port = NULL;
1792		list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1793		    port_list) {
1794			if (mr_sas_port->marked_responding)
1795				continue;
1796			if (h_port[i].sas_address != mr_sas_port->remote_identify.sas_address)
1797				continue;
1798			if (h_port[i].phy_mask & mr_sas_port->phy_mask) {
1799				mpi3mr_update_mr_sas_port(mrioc, &h_port[i], mr_sas_port);
1800				break;
1801			}
1802		}
1803	}
1804
1805	/* In case if expander cable is removed & connected to another HBA port during reset */
1806	for (i = 0; i < host_port_count; i++) {
1807		if (h_port[i].used)
1808			continue;
1809		mr_sas_port = NULL;
1810		list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1811		    port_list) {
1812			if (mr_sas_port->marked_responding)
1813				continue;
1814			if (h_port[i].sas_address != mr_sas_port->remote_identify.sas_address)
1815				continue;
1816			mpi3mr_update_mr_sas_port(mrioc, &h_port[i], mr_sas_port);
1817			break;
1818		}
1819	}
1820out:
1821	kfree(h_port);
1822	kfree(sas_io_unit_pg0);
1823}
1824
1825/**
1826 * mpi3mr_refresh_expanders - Refresh expander device exposure
1827 * @mrioc: Adapter instance reference
1828 *
1829 * This is executed post controller reset to identify any
1830 * missing expander devices during reset and remove from the upper layers
1831 * or expose any newly detected expander device to the upper layers.
1832 *
1833 * Return: Nothing.
1834 */
1835void
1836mpi3mr_refresh_expanders(struct mpi3mr_ioc *mrioc)
1837{
1838	struct mpi3mr_sas_node *sas_expander, *sas_expander_next;
1839	struct mpi3_sas_expander_page0 expander_pg0;
1840	u16 ioc_status, handle;
1841	u64 sas_address;
1842	int i;
1843	unsigned long flags;
1844	struct mpi3mr_hba_port *hba_port;
1845
1846	spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1847	list_for_each_entry(sas_expander, &mrioc->sas_expander_list, list) {
1848		sas_expander->non_responding = 1;
1849	}
1850	spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1851
1852	sas_expander = NULL;
1853
1854	handle = 0xffff;
1855
1856	/* Search for responding expander devices and add them if they are newly got added */
1857	while (true) {
1858		if ((mpi3mr_cfg_get_sas_exp_pg0(mrioc, &ioc_status, &expander_pg0,
1859		    sizeof(struct mpi3_sas_expander_page0),
1860		    MPI3_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
1861			dprint_reset(mrioc,
1862			    "failed to read exp pg0 for handle(0x%04x) at %s:%d/%s()!\n",
1863			    handle, __FILE__, __LINE__, __func__);
1864			break;
1865		}
1866
1867		if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
1868			dprint_reset(mrioc,
1869			   "ioc_status(0x%x) while reading exp pg0 for handle:(0x%04x), %s:%d/%s()!\n",
1870			   ioc_status, handle, __FILE__, __LINE__, __func__);
1871			break;
1872		}
1873
1874		handle = le16_to_cpu(expander_pg0.dev_handle);
1875		sas_address = le64_to_cpu(expander_pg0.sas_address);
1876		hba_port = mpi3mr_get_hba_port_by_id(mrioc, expander_pg0.io_unit_port);
1877
1878		if (!hba_port) {
1879			mpi3mr_sas_host_refresh(mrioc);
1880			mpi3mr_expander_add(mrioc, handle);
1881			continue;
1882		}
1883
1884		spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1885		sas_expander =
1886		    mpi3mr_expander_find_by_sas_address(mrioc,
1887		    sas_address, hba_port);
1888		spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1889
1890		if (!sas_expander) {
1891			mpi3mr_sas_host_refresh(mrioc);
1892			mpi3mr_expander_add(mrioc, handle);
1893			continue;
1894		}
1895
1896		sas_expander->non_responding = 0;
1897		if (sas_expander->handle == handle)
1898			continue;
1899
1900		sas_expander->handle = handle;
1901		for (i = 0 ; i < sas_expander->num_phys ; i++)
1902			sas_expander->phy[i].handle = handle;
1903	}
1904
1905	/*
1906	 * Delete non responding expander devices and the corresponding
1907	 * hba_port if the non responding expander device's parent device
1908	 * is a host node.
1909	 */
1910	sas_expander = NULL;
1911	spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1912	list_for_each_entry_safe_reverse(sas_expander, sas_expander_next,
1913	    &mrioc->sas_expander_list, list) {
1914		if (sas_expander->non_responding) {
1915			spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1916			mpi3mr_expander_node_remove(mrioc, sas_expander);
1917			spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1918		}
1919	}
1920	spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1921}
1922
1923/**
1924 * mpi3mr_expander_node_add - insert an expander to the list.
1925 * @mrioc: Adapter instance reference
1926 * @sas_expander: Expander sas node
1927 * Context: This function will acquire sas_node_lock.
1928 *
1929 * Adding new object to the ioc->sas_expander_list.
1930 *
1931 * Return: None.
1932 */
1933static void mpi3mr_expander_node_add(struct mpi3mr_ioc *mrioc,
1934	struct mpi3mr_sas_node *sas_expander)
1935{
1936	unsigned long flags;
1937
1938	spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1939	list_add_tail(&sas_expander->list, &mrioc->sas_expander_list);
1940	spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1941}
1942
1943/**
1944 * mpi3mr_expander_add -  Create expander object
1945 * @mrioc: Adapter instance reference
1946 * @handle: Expander firmware device handle
1947 *
1948 * This function creating expander object, stored in
1949 * sas_expander_list and expose it to the SAS transport
1950 * layer.
1951 *
1952 * Return: 0 for success, non-zero for failure.
1953 */
1954int mpi3mr_expander_add(struct mpi3mr_ioc *mrioc, u16 handle)
1955{
1956	struct mpi3mr_sas_node *sas_expander;
1957	struct mpi3mr_enclosure_node *enclosure_dev;
1958	struct mpi3_sas_expander_page0 expander_pg0;
1959	struct mpi3_sas_expander_page1 expander_pg1;
1960	u16 ioc_status, parent_handle, temp_handle;
1961	u64 sas_address, sas_address_parent = 0;
1962	int i;
1963	unsigned long flags;
1964	u8 port_id, link_rate;
1965	struct mpi3mr_sas_port *mr_sas_port = NULL;
1966	struct mpi3mr_hba_port *hba_port;
1967	u32 phynum_handle;
1968	int rc = 0;
1969
1970	if (!handle)
1971		return -1;
1972
1973	if (mrioc->reset_in_progress)
1974		return -1;
1975
1976	if ((mpi3mr_cfg_get_sas_exp_pg0(mrioc, &ioc_status, &expander_pg0,
1977	    sizeof(expander_pg0), MPI3_SAS_EXPAND_PGAD_FORM_HANDLE, handle))) {
1978		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1979		    __FILE__, __LINE__, __func__);
1980		return -1;
1981	}
1982
1983	if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
1984		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1985		    __FILE__, __LINE__, __func__);
1986		return -1;
1987	}
1988
1989	parent_handle = le16_to_cpu(expander_pg0.parent_dev_handle);
1990	if (mpi3mr_get_sas_address(mrioc, parent_handle, &sas_address_parent)
1991	    != 0) {
1992		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1993		    __FILE__, __LINE__, __func__);
1994		return -1;
1995	}
1996
1997	port_id = expander_pg0.io_unit_port;
1998	hba_port = mpi3mr_get_hba_port_by_id(mrioc, port_id);
1999	if (!hba_port) {
2000		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2001		    __FILE__, __LINE__, __func__);
2002		return -1;
2003	}
2004
2005	if (sas_address_parent != mrioc->sas_hba.sas_address) {
2006		spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2007		sas_expander =
2008		   mpi3mr_expander_find_by_sas_address(mrioc,
2009		    sas_address_parent, hba_port);
2010		spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2011		if (!sas_expander) {
2012			rc = mpi3mr_expander_add(mrioc, parent_handle);
2013			if (rc != 0)
2014				return rc;
2015		} else {
2016			/*
2017			 * When there is a parent expander present, update it's
2018			 * phys where child expander is connected with the link
2019			 * speed, attached dev handle and sas address.
2020			 */
2021			for (i = 0 ; i < sas_expander->num_phys ; i++) {
2022				phynum_handle =
2023				    (i << MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT) |
2024				    parent_handle;
2025				if (mpi3mr_cfg_get_sas_exp_pg1(mrioc,
2026				    &ioc_status, &expander_pg1,
2027				    sizeof(expander_pg1),
2028				    MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM,
2029				    phynum_handle)) {
2030					ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2031					    __FILE__, __LINE__, __func__);
2032					rc = -1;
2033					return rc;
2034				}
2035				if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2036					ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2037					    __FILE__, __LINE__, __func__);
2038					rc = -1;
2039					return rc;
2040				}
2041				temp_handle = le16_to_cpu(
2042				    expander_pg1.attached_dev_handle);
2043				if (temp_handle != handle)
2044					continue;
2045				link_rate = (expander_pg1.negotiated_link_rate &
2046				    MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
2047				    MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT;
2048				mpi3mr_update_links(mrioc, sas_address_parent,
2049				    handle, i, link_rate, hba_port);
2050			}
2051		}
2052	}
2053
2054	spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2055	sas_address = le64_to_cpu(expander_pg0.sas_address);
2056	sas_expander = mpi3mr_expander_find_by_sas_address(mrioc,
2057	    sas_address, hba_port);
2058	spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2059
2060	if (sas_expander)
2061		return 0;
2062
2063	sas_expander = kzalloc(sizeof(struct mpi3mr_sas_node),
2064	    GFP_KERNEL);
2065	if (!sas_expander)
2066		return -ENOMEM;
2067
2068	sas_expander->handle = handle;
2069	sas_expander->num_phys = expander_pg0.num_phys;
2070	sas_expander->sas_address_parent = sas_address_parent;
2071	sas_expander->sas_address = sas_address;
2072	sas_expander->hba_port = hba_port;
2073
2074	ioc_info(mrioc,
2075	    "expander_add: handle(0x%04x), parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n",
2076	    handle, parent_handle, (unsigned long long)
2077	    sas_expander->sas_address, sas_expander->num_phys);
2078
2079	if (!sas_expander->num_phys) {
2080		rc = -1;
2081		goto out_fail;
2082	}
2083	sas_expander->phy = kcalloc(sas_expander->num_phys,
2084	    sizeof(struct mpi3mr_sas_phy), GFP_KERNEL);
2085	if (!sas_expander->phy) {
2086		rc = -1;
2087		goto out_fail;
2088	}
2089
2090	INIT_LIST_HEAD(&sas_expander->sas_port_list);
2091	mr_sas_port = mpi3mr_sas_port_add(mrioc, handle, sas_address_parent,
2092	    sas_expander->hba_port);
2093	if (!mr_sas_port) {
2094		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2095		    __FILE__, __LINE__, __func__);
2096		rc = -1;
2097		goto out_fail;
2098	}
2099	sas_expander->parent_dev = &mr_sas_port->rphy->dev;
2100	sas_expander->rphy = mr_sas_port->rphy;
2101
2102	for (i = 0 ; i < sas_expander->num_phys ; i++) {
2103		phynum_handle = (i << MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT) |
2104		    handle;
2105		if (mpi3mr_cfg_get_sas_exp_pg1(mrioc, &ioc_status,
2106		    &expander_pg1, sizeof(expander_pg1),
2107		    MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM,
2108		    phynum_handle)) {
2109			ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2110			    __FILE__, __LINE__, __func__);
2111			rc = -1;
2112			goto out_fail;
2113		}
2114		if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2115			ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2116			    __FILE__, __LINE__, __func__);
2117			rc = -1;
2118			goto out_fail;
2119		}
2120
2121		sas_expander->phy[i].handle = handle;
2122		sas_expander->phy[i].phy_id = i;
2123		sas_expander->phy[i].hba_port = hba_port;
2124
2125		if ((mpi3mr_add_expander_phy(mrioc, &sas_expander->phy[i],
2126		    expander_pg1, sas_expander->parent_dev))) {
2127			ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2128			    __FILE__, __LINE__, __func__);
2129			rc = -1;
2130			goto out_fail;
2131		}
2132	}
2133
2134	if (sas_expander->enclosure_handle) {
2135		enclosure_dev =
2136			mpi3mr_enclosure_find_by_handle(mrioc,
2137						sas_expander->enclosure_handle);
2138		if (enclosure_dev)
2139			sas_expander->enclosure_logical_id = le64_to_cpu(
2140			    enclosure_dev->pg0.enclosure_logical_id);
2141	}
2142
2143	mpi3mr_expander_node_add(mrioc, sas_expander);
2144	return 0;
2145
2146out_fail:
2147
2148	if (mr_sas_port)
2149		mpi3mr_sas_port_remove(mrioc,
2150		    sas_expander->sas_address,
2151		    sas_address_parent, sas_expander->hba_port);
2152	kfree(sas_expander->phy);
2153	kfree(sas_expander);
2154	return rc;
2155}
2156
2157/**
2158 * mpi3mr_expander_node_remove - recursive removal of expander.
2159 * @mrioc: Adapter instance reference
2160 * @sas_expander: Expander device object
2161 *
2162 * Removes expander object and freeing associated memory from
2163 * the sas_expander_list and removes the same from SAS TL, if
2164 * one of the attached device is an expander then it recursively
2165 * removes the expander device too.
2166 *
2167 * Return nothing.
2168 */
2169void mpi3mr_expander_node_remove(struct mpi3mr_ioc *mrioc,
2170	struct mpi3mr_sas_node *sas_expander)
2171{
2172	struct mpi3mr_sas_port *mr_sas_port, *next;
2173	unsigned long flags;
2174	u8 port_id;
2175
2176	/* remove sibling ports attached to this expander */
2177	list_for_each_entry_safe(mr_sas_port, next,
2178	   &sas_expander->sas_port_list, port_list) {
2179		if (mrioc->reset_in_progress)
2180			return;
2181		if (mr_sas_port->remote_identify.device_type ==
2182		    SAS_END_DEVICE)
2183			mpi3mr_remove_device_by_sas_address(mrioc,
2184			    mr_sas_port->remote_identify.sas_address,
2185			    mr_sas_port->hba_port);
2186		else if (mr_sas_port->remote_identify.device_type ==
2187		    SAS_EDGE_EXPANDER_DEVICE ||
2188		    mr_sas_port->remote_identify.device_type ==
2189		    SAS_FANOUT_EXPANDER_DEVICE)
2190			mpi3mr_expander_remove(mrioc,
2191			    mr_sas_port->remote_identify.sas_address,
2192			    mr_sas_port->hba_port);
2193	}
2194
2195	port_id = sas_expander->hba_port->port_id;
2196	mpi3mr_sas_port_remove(mrioc, sas_expander->sas_address,
2197	    sas_expander->sas_address_parent, sas_expander->hba_port);
2198
2199	ioc_info(mrioc, "expander_remove: handle(0x%04x), sas_addr(0x%016llx), port:%d\n",
2200	    sas_expander->handle, (unsigned long long)
2201	    sas_expander->sas_address, port_id);
2202
2203	spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2204	list_del(&sas_expander->list);
2205	spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2206
2207	kfree(sas_expander->phy);
2208	kfree(sas_expander);
2209}
2210
2211/**
2212 * mpi3mr_expander_remove - Remove expander object
2213 * @mrioc: Adapter instance reference
2214 * @sas_address: Remove expander sas_address
2215 * @hba_port: HBA port reference
2216 *
2217 * This function remove expander object, stored in
2218 * mrioc->sas_expander_list and removes it from the SAS TL by
2219 * calling mpi3mr_expander_node_remove().
2220 *
2221 * Return: None
2222 */
2223void mpi3mr_expander_remove(struct mpi3mr_ioc *mrioc, u64 sas_address,
2224	struct mpi3mr_hba_port *hba_port)
2225{
2226	struct mpi3mr_sas_node *sas_expander;
2227	unsigned long flags;
2228
2229	if (mrioc->reset_in_progress)
2230		return;
2231
2232	if (!hba_port)
2233		return;
2234
2235	spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2236	sas_expander = mpi3mr_expander_find_by_sas_address(mrioc, sas_address,
2237	    hba_port);
2238	spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2239	if (sas_expander)
2240		mpi3mr_expander_node_remove(mrioc, sas_expander);
2241
2242}
2243
2244/**
2245 * mpi3mr_get_sas_negotiated_logical_linkrate - get linkrate
2246 * @mrioc: Adapter instance reference
2247 * @tgtdev: Target device
2248 *
2249 * This function identifies whether the target device is
2250 * attached directly or through expander and issues sas phy
2251 * page0 or expander phy page1 and gets the link rate, if there
2252 * is any failure in reading the pages then this returns link
2253 * rate of 1.5.
2254 *
2255 * Return: logical link rate.
2256 */
2257static u8 mpi3mr_get_sas_negotiated_logical_linkrate(struct mpi3mr_ioc *mrioc,
2258	struct mpi3mr_tgt_dev *tgtdev)
2259{
2260	u8 link_rate = MPI3_SAS_NEG_LINK_RATE_1_5, phy_number;
2261	struct mpi3_sas_expander_page1 expander_pg1;
2262	struct mpi3_sas_phy_page0 phy_pg0;
2263	u32 phynum_handle;
2264	u16 ioc_status;
2265
2266	phy_number = tgtdev->dev_spec.sas_sata_inf.phy_id;
2267	if (!(tgtdev->devpg0_flag & MPI3_DEVICE0_FLAGS_ATT_METHOD_DIR_ATTACHED)) {
2268		phynum_handle = ((phy_number<<MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT)
2269				 | tgtdev->parent_handle);
2270		if (mpi3mr_cfg_get_sas_exp_pg1(mrioc, &ioc_status,
2271		    &expander_pg1, sizeof(expander_pg1),
2272		    MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM,
2273		    phynum_handle)) {
2274			ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2275			    __FILE__, __LINE__, __func__);
2276			goto out;
2277		}
2278		if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2279			ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2280			    __FILE__, __LINE__, __func__);
2281			goto out;
2282		}
2283		link_rate = (expander_pg1.negotiated_link_rate &
2284			     MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
2285			MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT;
2286		goto out;
2287	}
2288	if (mpi3mr_cfg_get_sas_phy_pg0(mrioc, &ioc_status, &phy_pg0,
2289	    sizeof(struct mpi3_sas_phy_page0),
2290	    MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, phy_number)) {
2291		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2292		    __FILE__, __LINE__, __func__);
2293		goto out;
2294	}
2295	if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2296		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2297		    __FILE__, __LINE__, __func__);
2298		goto out;
2299	}
2300	link_rate = (phy_pg0.negotiated_link_rate &
2301		     MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
2302		MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT;
2303out:
2304	return link_rate;
2305}
2306
2307/**
2308 * mpi3mr_report_tgtdev_to_sas_transport - expose dev to SAS TL
2309 * @mrioc: Adapter instance reference
2310 * @tgtdev: Target device
2311 *
2312 * This function exposes the target device after
2313 * preparing host_phy, setting up link rate etc.
2314 *
2315 * Return: 0 on success, non-zero for failure.
2316 */
2317int mpi3mr_report_tgtdev_to_sas_transport(struct mpi3mr_ioc *mrioc,
2318	struct mpi3mr_tgt_dev *tgtdev)
2319{
2320	int retval = 0;
2321	u8 link_rate, parent_phy_number;
2322	u64 sas_address_parent, sas_address;
2323	struct mpi3mr_hba_port *hba_port;
2324	u8 port_id;
2325
2326	if ((tgtdev->dev_type != MPI3_DEVICE_DEVFORM_SAS_SATA) ||
2327	    !mrioc->sas_transport_enabled)
2328		return -1;
2329
2330	sas_address = tgtdev->dev_spec.sas_sata_inf.sas_address;
2331	if (!mrioc->sas_hba.num_phys)
2332		mpi3mr_sas_host_add(mrioc);
2333	else
2334		mpi3mr_sas_host_refresh(mrioc);
2335
2336	if (mpi3mr_get_sas_address(mrioc, tgtdev->parent_handle,
2337	    &sas_address_parent) != 0) {
2338		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2339		    __FILE__, __LINE__, __func__);
2340		return -1;
2341	}
2342	tgtdev->dev_spec.sas_sata_inf.sas_address_parent = sas_address_parent;
2343
2344	parent_phy_number = tgtdev->dev_spec.sas_sata_inf.phy_id;
2345	port_id = tgtdev->io_unit_port;
2346
2347	hba_port = mpi3mr_get_hba_port_by_id(mrioc, port_id);
2348	if (!hba_port) {
2349		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2350		    __FILE__, __LINE__, __func__);
2351		return -1;
2352	}
2353	tgtdev->dev_spec.sas_sata_inf.hba_port = hba_port;
2354
2355	link_rate = mpi3mr_get_sas_negotiated_logical_linkrate(mrioc, tgtdev);
2356
2357	mpi3mr_update_links(mrioc, sas_address_parent, tgtdev->dev_handle,
2358	    parent_phy_number, link_rate, hba_port);
2359
2360	tgtdev->host_exposed = 1;
2361	if (!mpi3mr_sas_port_add(mrioc, tgtdev->dev_handle,
2362	    sas_address_parent, hba_port)) {
2363		retval = -1;
2364		} else if ((!tgtdev->starget) && (!mrioc->is_driver_loading)) {
2365			mpi3mr_sas_port_remove(mrioc, sas_address,
2366			    sas_address_parent, hba_port);
2367		retval = -1;
2368	}
2369	if (retval) {
2370		tgtdev->dev_spec.sas_sata_inf.hba_port = NULL;
2371		tgtdev->host_exposed = 0;
2372	}
2373	return retval;
2374}
2375
2376/**
2377 * mpi3mr_remove_tgtdev_from_sas_transport - remove from SAS TL
2378 * @mrioc: Adapter instance reference
2379 * @tgtdev: Target device
2380 *
2381 * This function removes the target device
2382 *
2383 * Return: None.
2384 */
2385void mpi3mr_remove_tgtdev_from_sas_transport(struct mpi3mr_ioc *mrioc,
2386	struct mpi3mr_tgt_dev *tgtdev)
2387{
2388	u64 sas_address_parent, sas_address;
2389	struct mpi3mr_hba_port *hba_port;
2390
2391	if ((tgtdev->dev_type != MPI3_DEVICE_DEVFORM_SAS_SATA) ||
2392	    !mrioc->sas_transport_enabled)
2393		return;
2394
2395	hba_port = tgtdev->dev_spec.sas_sata_inf.hba_port;
2396	sas_address = tgtdev->dev_spec.sas_sata_inf.sas_address;
2397	sas_address_parent = tgtdev->dev_spec.sas_sata_inf.sas_address_parent;
2398	mpi3mr_sas_port_remove(mrioc, sas_address, sas_address_parent,
2399	    hba_port);
2400	tgtdev->host_exposed = 0;
2401	tgtdev->dev_spec.sas_sata_inf.hba_port = NULL;
2402}
2403
2404/**
2405 * mpi3mr_get_port_id_by_sas_phy -  Get port ID of the given phy
2406 * @phy: SAS transport layer phy object
2407 *
2408 * Return: Port number for valid ID else 0xFFFF
2409 */
2410static inline u8 mpi3mr_get_port_id_by_sas_phy(struct sas_phy *phy)
2411{
2412	u8 port_id = 0xFF;
2413	struct mpi3mr_hba_port *hba_port = phy->hostdata;
2414
2415	if (hba_port)
2416		port_id = hba_port->port_id;
2417
2418	return port_id;
2419}
2420
2421/**
2422 * mpi3mr_get_port_id_by_rphy - Get Port number from SAS rphy
2423 *
2424 * @mrioc: Adapter instance reference
2425 * @rphy: SAS transport layer remote phy object
2426 *
2427 * Retrieves HBA port number in which the device pointed by the
2428 * rphy object is attached with.
2429 *
2430 * Return: Valid port number on success else OxFFFF.
2431 */
2432static u8 mpi3mr_get_port_id_by_rphy(struct mpi3mr_ioc *mrioc, struct sas_rphy *rphy)
2433{
2434	struct mpi3mr_sas_node *sas_expander;
2435	struct mpi3mr_tgt_dev *tgtdev;
2436	unsigned long flags;
2437	u8 port_id = 0xFF;
2438
2439	if (!rphy)
2440		return port_id;
2441
2442	if (rphy->identify.device_type == SAS_EDGE_EXPANDER_DEVICE ||
2443	    rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE) {
2444		spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2445		list_for_each_entry(sas_expander, &mrioc->sas_expander_list,
2446		    list) {
2447			if (sas_expander->rphy == rphy) {
2448				port_id = sas_expander->hba_port->port_id;
2449				break;
2450			}
2451		}
2452		spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2453	} else if (rphy->identify.device_type == SAS_END_DEVICE) {
2454		spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
2455
2456		tgtdev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc,
2457			    rphy->identify.sas_address, rphy);
2458		if (tgtdev && tgtdev->dev_spec.sas_sata_inf.hba_port) {
2459			port_id =
2460				tgtdev->dev_spec.sas_sata_inf.hba_port->port_id;
2461			mpi3mr_tgtdev_put(tgtdev);
2462		}
2463		spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
2464	}
2465	return port_id;
2466}
2467
2468static inline struct mpi3mr_ioc *phy_to_mrioc(struct sas_phy *phy)
2469{
2470	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
2471
2472	return shost_priv(shost);
2473}
2474
2475static inline struct mpi3mr_ioc *rphy_to_mrioc(struct sas_rphy *rphy)
2476{
2477	struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
2478
2479	return shost_priv(shost);
2480}
2481
2482/* report phy error log structure */
2483struct phy_error_log_request {
2484	u8 smp_frame_type; /* 0x40 */
2485	u8 function; /* 0x11 */
2486	u8 allocated_response_length;
2487	u8 request_length; /* 02 */
2488	u8 reserved_1[5];
2489	u8 phy_identifier;
2490	u8 reserved_2[2];
2491};
2492
2493/* report phy error log reply structure */
2494struct phy_error_log_reply {
2495	u8 smp_frame_type; /* 0x41 */
2496	u8 function; /* 0x11 */
2497	u8 function_result;
2498	u8 response_length;
2499	__be16 expander_change_count;
2500	u8 reserved_1[3];
2501	u8 phy_identifier;
2502	u8 reserved_2[2];
2503	__be32 invalid_dword;
2504	__be32 running_disparity_error;
2505	__be32 loss_of_dword_sync;
2506	__be32 phy_reset_problem;
2507};
2508
2509
2510/**
2511 * mpi3mr_get_expander_phy_error_log - return expander counters:
2512 * @mrioc: Adapter instance reference
2513 * @phy: The SAS transport layer phy object
2514 *
2515 * Return: 0 for success, non-zero for failure.
2516 *
2517 */
2518static int mpi3mr_get_expander_phy_error_log(struct mpi3mr_ioc *mrioc,
2519	struct sas_phy *phy)
2520{
2521	struct mpi3_smp_passthrough_request mpi_request;
2522	struct mpi3_smp_passthrough_reply mpi_reply;
2523	struct phy_error_log_request *phy_error_log_request;
2524	struct phy_error_log_reply *phy_error_log_reply;
2525	int rc;
2526	void *psge;
2527	void *data_out = NULL;
2528	dma_addr_t data_out_dma, data_in_dma;
2529	u32 data_out_sz, data_in_sz, sz;
2530	u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST;
2531	u16 request_sz = sizeof(struct mpi3_smp_passthrough_request);
2532	u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply);
2533	u16 ioc_status;
2534
2535	if (mrioc->reset_in_progress) {
2536		ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
2537		return -EFAULT;
2538	}
2539
 
 
 
 
 
2540	data_out_sz = sizeof(struct phy_error_log_request);
2541	data_in_sz = sizeof(struct phy_error_log_reply);
2542	sz = data_out_sz + data_in_sz;
2543	data_out = dma_alloc_coherent(&mrioc->pdev->dev, sz, &data_out_dma,
2544	    GFP_KERNEL);
2545	if (!data_out) {
2546		rc = -ENOMEM;
2547		goto out;
2548	}
2549
2550	data_in_dma = data_out_dma + data_out_sz;
2551	phy_error_log_reply = data_out + data_out_sz;
2552
2553	rc = -EINVAL;
2554	memset(data_out, 0, sz);
2555	phy_error_log_request = data_out;
2556	phy_error_log_request->smp_frame_type = 0x40;
2557	phy_error_log_request->function = 0x11;
2558	phy_error_log_request->request_length = 2;
2559	phy_error_log_request->allocated_response_length = 0;
2560	phy_error_log_request->phy_identifier = phy->number;
2561
2562	memset(&mpi_request, 0, request_sz);
2563	memset(&mpi_reply, 0, reply_sz);
2564	mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
2565	mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH;
2566	mpi_request.io_unit_port = (u8) mpi3mr_get_port_id_by_sas_phy(phy);
2567	mpi_request.sas_address = cpu_to_le64(phy->identify.sas_address);
2568
2569	psge = &mpi_request.request_sge;
2570	mpi3mr_add_sg_single(psge, sgl_flags, data_out_sz, data_out_dma);
2571
2572	psge = &mpi_request.response_sge;
2573	mpi3mr_add_sg_single(psge, sgl_flags, data_in_sz, data_in_dma);
2574
2575	dprint_transport_info(mrioc,
2576	    "sending phy error log SMP request to sas_address(0x%016llx), phy_id(%d)\n",
2577	    (unsigned long long)phy->identify.sas_address, phy->number);
2578
2579	if (mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
2580	    &mpi_reply, reply_sz, MPI3MR_INTADMCMD_TIMEOUT, &ioc_status))
2581		goto out;
2582
2583	dprint_transport_info(mrioc,
2584	    "phy error log SMP request completed with ioc_status(0x%04x)\n",
2585	    ioc_status);
2586
2587	if (ioc_status == MPI3_IOCSTATUS_SUCCESS) {
2588		dprint_transport_info(mrioc,
2589		    "phy error log - reply data transfer size(%d)\n",
2590		    le16_to_cpu(mpi_reply.response_data_length));
2591
2592		if (le16_to_cpu(mpi_reply.response_data_length) !=
2593		    sizeof(struct phy_error_log_reply))
2594			goto out;
2595
2596		dprint_transport_info(mrioc,
2597		    "phy error log - function_result(%d)\n",
2598		    phy_error_log_reply->function_result);
2599
2600		phy->invalid_dword_count =
2601		    be32_to_cpu(phy_error_log_reply->invalid_dword);
2602		phy->running_disparity_error_count =
2603		    be32_to_cpu(phy_error_log_reply->running_disparity_error);
2604		phy->loss_of_dword_sync_count =
2605		    be32_to_cpu(phy_error_log_reply->loss_of_dword_sync);
2606		phy->phy_reset_problem_count =
2607		    be32_to_cpu(phy_error_log_reply->phy_reset_problem);
2608		rc = 0;
2609	}
2610
2611out:
2612	if (data_out)
2613		dma_free_coherent(&mrioc->pdev->dev, sz, data_out,
2614		    data_out_dma);
2615
2616	return rc;
2617}
2618
2619/**
2620 * mpi3mr_transport_get_linkerrors - return phy error counters
2621 * @phy: The SAS transport layer phy object
2622 *
2623 * This function retrieves the phy error log information of the
2624 * HBA or expander for which the phy belongs to
2625 *
2626 * Return: 0 for success, non-zero for failure.
2627 */
2628static int mpi3mr_transport_get_linkerrors(struct sas_phy *phy)
2629{
2630	struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy);
2631	struct mpi3_sas_phy_page1 phy_pg1;
2632	int rc = 0;
2633	u16 ioc_status;
2634
2635	rc = mpi3mr_parent_present(mrioc, phy);
2636	if (rc)
2637		return rc;
2638
2639	if (phy->identify.sas_address != mrioc->sas_hba.sas_address)
2640		return mpi3mr_get_expander_phy_error_log(mrioc, phy);
2641
2642	memset(&phy_pg1, 0, sizeof(struct mpi3_sas_phy_page1));
2643	/* get hba phy error logs */
2644	if ((mpi3mr_cfg_get_sas_phy_pg1(mrioc, &ioc_status, &phy_pg1,
2645	    sizeof(struct mpi3_sas_phy_page1),
2646	    MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, phy->number))) {
2647		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2648		    __FILE__, __LINE__, __func__);
2649		return -ENXIO;
2650	}
2651
2652	if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2653		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2654		    __FILE__, __LINE__, __func__);
2655		return -ENXIO;
2656	}
2657	phy->invalid_dword_count = le32_to_cpu(phy_pg1.invalid_dword_count);
2658	phy->running_disparity_error_count =
2659		le32_to_cpu(phy_pg1.running_disparity_error_count);
2660	phy->loss_of_dword_sync_count =
2661		le32_to_cpu(phy_pg1.loss_dword_synch_count);
2662	phy->phy_reset_problem_count =
2663		le32_to_cpu(phy_pg1.phy_reset_problem_count);
2664	return 0;
2665}
2666
2667/**
2668 * mpi3mr_transport_get_enclosure_identifier - Get Enclosure ID
2669 * @rphy: The SAS transport layer remote phy object
2670 * @identifier: Enclosure identifier to be returned
2671 *
2672 * Returns the enclosure id for the device pointed by the remote
2673 * phy object.
2674 *
2675 * Return: 0 on success or -ENXIO
2676 */
2677static int
2678mpi3mr_transport_get_enclosure_identifier(struct sas_rphy *rphy,
2679	u64 *identifier)
2680{
2681	struct mpi3mr_ioc *mrioc = rphy_to_mrioc(rphy);
2682	struct mpi3mr_tgt_dev *tgtdev = NULL;
2683	unsigned long flags;
2684	int rc;
2685
2686	spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
2687	tgtdev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc,
2688	    rphy->identify.sas_address, rphy);
2689	if (tgtdev) {
2690		*identifier =
2691			tgtdev->enclosure_logical_id;
2692		rc = 0;
2693		mpi3mr_tgtdev_put(tgtdev);
2694	} else {
2695		*identifier = 0;
2696		rc = -ENXIO;
2697	}
2698	spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
2699
2700	return rc;
2701}
2702
2703/**
2704 * mpi3mr_transport_get_bay_identifier - Get bay ID
2705 * @rphy: The SAS transport layer remote phy object
2706 *
2707 * Returns the slot id for the device pointed by the remote phy
2708 * object.
2709 *
2710 * Return: Valid slot ID on success or -ENXIO
2711 */
2712static int
2713mpi3mr_transport_get_bay_identifier(struct sas_rphy *rphy)
2714{
2715	struct mpi3mr_ioc *mrioc = rphy_to_mrioc(rphy);
2716	struct mpi3mr_tgt_dev *tgtdev = NULL;
2717	unsigned long flags;
2718	int rc;
2719
2720	spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
2721	tgtdev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc,
2722	    rphy->identify.sas_address, rphy);
2723	if (tgtdev) {
2724		rc = tgtdev->slot;
2725		mpi3mr_tgtdev_put(tgtdev);
2726	} else
2727		rc = -ENXIO;
2728	spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
2729
2730	return rc;
2731}
2732
2733/* phy control request structure */
2734struct phy_control_request {
2735	u8 smp_frame_type; /* 0x40 */
2736	u8 function; /* 0x91 */
2737	u8 allocated_response_length;
2738	u8 request_length; /* 0x09 */
2739	u16 expander_change_count;
2740	u8 reserved_1[3];
2741	u8 phy_identifier;
2742	u8 phy_operation;
2743	u8 reserved_2[13];
2744	u64 attached_device_name;
2745	u8 programmed_min_physical_link_rate;
2746	u8 programmed_max_physical_link_rate;
2747	u8 reserved_3[6];
2748};
2749
2750/* phy control reply structure */
2751struct phy_control_reply {
2752	u8 smp_frame_type; /* 0x41 */
2753	u8 function; /* 0x11 */
2754	u8 function_result;
2755	u8 response_length;
2756};
2757
2758#define SMP_PHY_CONTROL_LINK_RESET	(0x01)
2759#define SMP_PHY_CONTROL_HARD_RESET	(0x02)
2760#define SMP_PHY_CONTROL_DISABLE		(0x03)
2761
2762/**
2763 * mpi3mr_expander_phy_control - expander phy control
2764 * @mrioc: Adapter instance reference
2765 * @phy: The SAS transport layer phy object
2766 * @phy_operation: The phy operation to be executed
2767 *
2768 * Issues SMP passthru phy control request to execute a specific
2769 * phy operation for a given expander device.
2770 *
2771 * Return: 0 for success, non-zero for failure.
2772 */
2773static int
2774mpi3mr_expander_phy_control(struct mpi3mr_ioc *mrioc,
2775	struct sas_phy *phy, u8 phy_operation)
2776{
2777	struct mpi3_smp_passthrough_request mpi_request;
2778	struct mpi3_smp_passthrough_reply mpi_reply;
2779	struct phy_control_request *phy_control_request;
2780	struct phy_control_reply *phy_control_reply;
2781	int rc;
2782	void *psge;
2783	void *data_out = NULL;
2784	dma_addr_t data_out_dma;
2785	dma_addr_t data_in_dma;
2786	size_t data_in_sz;
2787	size_t data_out_sz;
2788	u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST;
2789	u16 request_sz = sizeof(struct mpi3_smp_passthrough_request);
2790	u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply);
2791	u16 ioc_status;
2792	u16 sz;
2793
2794	if (mrioc->reset_in_progress) {
2795		ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
2796		return -EFAULT;
2797	}
2798
 
 
 
 
 
 
2799	data_out_sz = sizeof(struct phy_control_request);
2800	data_in_sz = sizeof(struct phy_control_reply);
2801	sz = data_out_sz + data_in_sz;
2802	data_out = dma_alloc_coherent(&mrioc->pdev->dev, sz, &data_out_dma,
2803	    GFP_KERNEL);
2804	if (!data_out) {
2805		rc = -ENOMEM;
2806		goto out;
2807	}
2808
2809	data_in_dma = data_out_dma + data_out_sz;
2810	phy_control_reply = data_out + data_out_sz;
2811
2812	rc = -EINVAL;
2813	memset(data_out, 0, sz);
2814
2815	phy_control_request = data_out;
2816	phy_control_request->smp_frame_type = 0x40;
2817	phy_control_request->function = 0x91;
2818	phy_control_request->request_length = 9;
2819	phy_control_request->allocated_response_length = 0;
2820	phy_control_request->phy_identifier = phy->number;
2821	phy_control_request->phy_operation = phy_operation;
2822	phy_control_request->programmed_min_physical_link_rate =
2823	    phy->minimum_linkrate << 4;
2824	phy_control_request->programmed_max_physical_link_rate =
2825	    phy->maximum_linkrate << 4;
2826
2827	memset(&mpi_request, 0, request_sz);
2828	memset(&mpi_reply, 0, reply_sz);
2829	mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
2830	mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH;
2831	mpi_request.io_unit_port = (u8) mpi3mr_get_port_id_by_sas_phy(phy);
2832	mpi_request.sas_address = cpu_to_le64(phy->identify.sas_address);
2833
2834	psge = &mpi_request.request_sge;
2835	mpi3mr_add_sg_single(psge, sgl_flags, data_out_sz, data_out_dma);
2836
2837	psge = &mpi_request.response_sge;
2838	mpi3mr_add_sg_single(psge, sgl_flags, data_in_sz, data_in_dma);
2839
2840	dprint_transport_info(mrioc,
2841	    "sending phy control SMP request to sas_address(0x%016llx), phy_id(%d) opcode(%d)\n",
2842	    (unsigned long long)phy->identify.sas_address, phy->number,
2843	    phy_operation);
2844
2845	if (mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
2846	    &mpi_reply, reply_sz, MPI3MR_INTADMCMD_TIMEOUT, &ioc_status))
2847		goto out;
2848
2849	dprint_transport_info(mrioc,
2850	    "phy control SMP request completed with ioc_status(0x%04x)\n",
2851	    ioc_status);
2852
2853	if (ioc_status == MPI3_IOCSTATUS_SUCCESS) {
2854		dprint_transport_info(mrioc,
2855		    "phy control - reply data transfer size(%d)\n",
2856		    le16_to_cpu(mpi_reply.response_data_length));
2857
2858		if (le16_to_cpu(mpi_reply.response_data_length) !=
2859		    sizeof(struct phy_control_reply))
2860			goto out;
2861		dprint_transport_info(mrioc,
2862		    "phy control - function_result(%d)\n",
2863		    phy_control_reply->function_result);
2864		rc = 0;
2865	}
2866 out:
2867	if (data_out)
2868		dma_free_coherent(&mrioc->pdev->dev, sz, data_out,
2869		    data_out_dma);
2870
2871	return rc;
2872}
2873
2874/**
2875 * mpi3mr_transport_phy_reset - Reset a given phy
2876 * @phy: The SAS transport layer phy object
2877 * @hard_reset: Flag to indicate the type of reset
2878 *
2879 * Return: 0 for success, non-zero for failure.
2880 */
2881static int
2882mpi3mr_transport_phy_reset(struct sas_phy *phy, int hard_reset)
2883{
2884	struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy);
2885	struct mpi3_iounit_control_request mpi_request;
2886	struct mpi3_iounit_control_reply mpi_reply;
2887	u16 request_sz = sizeof(struct mpi3_iounit_control_request);
2888	u16 reply_sz = sizeof(struct mpi3_iounit_control_reply);
2889	int rc = 0;
2890	u16 ioc_status;
2891
2892	rc = mpi3mr_parent_present(mrioc, phy);
2893	if (rc)
2894		return rc;
2895
2896	/* handle expander phys */
2897	if (phy->identify.sas_address != mrioc->sas_hba.sas_address)
2898		return mpi3mr_expander_phy_control(mrioc, phy,
2899		    (hard_reset == 1) ? SMP_PHY_CONTROL_HARD_RESET :
2900		    SMP_PHY_CONTROL_LINK_RESET);
2901
2902	/* handle hba phys */
2903	memset(&mpi_request, 0, request_sz);
2904	mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
2905	mpi_request.function = MPI3_FUNCTION_IO_UNIT_CONTROL;
2906	mpi_request.operation = MPI3_CTRL_OP_SAS_PHY_CONTROL;
2907	mpi_request.param8[MPI3_CTRL_OP_SAS_PHY_CONTROL_PARAM8_ACTION_INDEX] =
2908		(hard_reset ? MPI3_CTRL_ACTION_HARD_RESET :
2909		 MPI3_CTRL_ACTION_LINK_RESET);
2910	mpi_request.param8[MPI3_CTRL_OP_SAS_PHY_CONTROL_PARAM8_PHY_INDEX] =
2911		phy->number;
2912
2913	dprint_transport_info(mrioc,
2914	    "sending phy reset request to sas_address(0x%016llx), phy_id(%d) hard_reset(%d)\n",
2915	    (unsigned long long)phy->identify.sas_address, phy->number,
2916	    hard_reset);
2917
2918	if (mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
2919	    &mpi_reply, reply_sz, MPI3MR_INTADMCMD_TIMEOUT, &ioc_status)) {
2920		rc = -EAGAIN;
2921		goto out;
2922	}
2923
2924	dprint_transport_info(mrioc,
2925	    "phy reset request completed with ioc_status(0x%04x)\n",
2926	    ioc_status);
2927out:
2928	return rc;
2929}
2930
2931/**
2932 * mpi3mr_transport_phy_enable - enable/disable phys
2933 * @phy: The SAS transport layer phy object
2934 * @enable: flag to enable/disable, enable phy when true
2935 *
2936 * This function enables/disables a given by executing required
2937 * configuration page changes or expander phy control command
2938 *
2939 * Return: 0 for success, non-zero for failure.
2940 */
2941static int
2942mpi3mr_transport_phy_enable(struct sas_phy *phy, int enable)
2943{
2944	struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy);
2945	struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL;
2946	struct mpi3_sas_io_unit_page1 *sas_io_unit_pg1 = NULL;
2947	u16 sz;
2948	int rc = 0;
2949	int i, discovery_active;
2950
2951	rc = mpi3mr_parent_present(mrioc, phy);
2952	if (rc)
2953		return rc;
2954
2955	/* handle expander phys */
2956	if (phy->identify.sas_address != mrioc->sas_hba.sas_address)
2957		return mpi3mr_expander_phy_control(mrioc, phy,
2958		    (enable == 1) ? SMP_PHY_CONTROL_LINK_RESET :
2959		    SMP_PHY_CONTROL_DISABLE);
2960
2961	/* handle hba phys */
2962	sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) +
2963		(mrioc->sas_hba.num_phys *
2964		 sizeof(struct mpi3_sas_io_unit0_phy_data));
2965	sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
2966	if (!sas_io_unit_pg0) {
2967		rc = -ENOMEM;
2968		goto out;
2969	}
2970	if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
2971		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2972		    __FILE__, __LINE__, __func__);
2973		rc = -ENXIO;
2974		goto out;
2975	}
2976
2977	/* unable to enable/disable phys when discovery is active */
2978	for (i = 0, discovery_active = 0; i < mrioc->sas_hba.num_phys ; i++) {
2979		if (sas_io_unit_pg0->phy_data[i].port_flags &
2980		    MPI3_SASIOUNIT0_PORTFLAGS_DISC_IN_PROGRESS) {
2981			ioc_err(mrioc,
2982			    "discovery is active on port = %d, phy = %d\n"
2983			    "\tunable to enable/disable phys, try again later!\n",
2984			    sas_io_unit_pg0->phy_data[i].io_unit_port, i);
2985			discovery_active = 1;
2986		}
2987	}
2988
2989	if (discovery_active) {
2990		rc = -EAGAIN;
2991		goto out;
2992	}
2993
2994	if ((sas_io_unit_pg0->phy_data[phy->number].phy_flags &
2995	     (MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY |
2996	      MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY))) {
2997		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2998		    __FILE__, __LINE__, __func__);
2999		rc = -ENXIO;
3000		goto out;
3001	}
3002
3003	/* read sas_iounit page 1 */
3004	sz = offsetof(struct mpi3_sas_io_unit_page1, phy_data) +
3005		(mrioc->sas_hba.num_phys *
3006		 sizeof(struct mpi3_sas_io_unit1_phy_data));
3007	sas_io_unit_pg1 = kzalloc(sz, GFP_KERNEL);
3008	if (!sas_io_unit_pg1) {
3009		rc = -ENOMEM;
3010		goto out;
3011	}
3012
3013	if (mpi3mr_cfg_get_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz)) {
3014		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
3015		    __FILE__, __LINE__, __func__);
3016		rc = -ENXIO;
3017		goto out;
3018	}
3019
3020	if (enable)
3021		sas_io_unit_pg1->phy_data[phy->number].phy_flags
3022		    &= ~MPI3_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
3023	else
3024		sas_io_unit_pg1->phy_data[phy->number].phy_flags
3025		    |= MPI3_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
3026
3027	mpi3mr_cfg_set_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz);
3028
3029	/* link reset */
3030	if (enable)
3031		mpi3mr_transport_phy_reset(phy, 0);
3032
3033 out:
3034	kfree(sas_io_unit_pg1);
3035	kfree(sas_io_unit_pg0);
3036	return rc;
3037}
3038
3039/**
3040 * mpi3mr_transport_phy_speed - set phy min/max speed
3041 * @phy: The SAS transport later phy object
3042 * @rates: Rates defined as in sas_phy_linkrates
3043 *
3044 * This function sets the link rates given in the rates
3045 * argument to the given phy by executing required configuration
3046 * page changes or expander phy control command
3047 *
3048 * Return: 0 for success, non-zero for failure.
3049 */
3050static int
3051mpi3mr_transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
3052{
3053	struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy);
3054	struct mpi3_sas_io_unit_page1 *sas_io_unit_pg1 = NULL;
3055	struct mpi3_sas_phy_page0 phy_pg0;
3056	u16 sz, ioc_status;
3057	int rc = 0;
3058
3059	rc = mpi3mr_parent_present(mrioc, phy);
3060	if (rc)
3061		return rc;
3062
3063	if (!rates->minimum_linkrate)
3064		rates->minimum_linkrate = phy->minimum_linkrate;
3065	else if (rates->minimum_linkrate < phy->minimum_linkrate_hw)
3066		rates->minimum_linkrate = phy->minimum_linkrate_hw;
3067
3068	if (!rates->maximum_linkrate)
3069		rates->maximum_linkrate = phy->maximum_linkrate;
3070	else if (rates->maximum_linkrate > phy->maximum_linkrate_hw)
3071		rates->maximum_linkrate = phy->maximum_linkrate_hw;
3072
3073	/* handle expander phys */
3074	if (phy->identify.sas_address != mrioc->sas_hba.sas_address) {
3075		phy->minimum_linkrate = rates->minimum_linkrate;
3076		phy->maximum_linkrate = rates->maximum_linkrate;
3077		return mpi3mr_expander_phy_control(mrioc, phy,
3078		    SMP_PHY_CONTROL_LINK_RESET);
3079	}
3080
3081	/* handle hba phys */
3082	sz = offsetof(struct mpi3_sas_io_unit_page1, phy_data) +
3083		(mrioc->sas_hba.num_phys *
3084		 sizeof(struct mpi3_sas_io_unit1_phy_data));
3085	sas_io_unit_pg1 = kzalloc(sz, GFP_KERNEL);
3086	if (!sas_io_unit_pg1) {
3087		rc = -ENOMEM;
3088		goto out;
3089	}
3090
3091	if (mpi3mr_cfg_get_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz)) {
3092		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
3093		    __FILE__, __LINE__, __func__);
3094		rc = -ENXIO;
3095		goto out;
3096	}
3097
3098	sas_io_unit_pg1->phy_data[phy->number].max_min_link_rate =
3099		(rates->minimum_linkrate + (rates->maximum_linkrate << 4));
3100
3101	if (mpi3mr_cfg_set_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz)) {
3102		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
3103		    __FILE__, __LINE__, __func__);
3104		rc = -ENXIO;
3105		goto out;
3106	}
3107
3108	/* link reset */
3109	mpi3mr_transport_phy_reset(phy, 0);
3110
3111	/* read phy page 0, then update the rates in the sas transport phy */
3112	if (!mpi3mr_cfg_get_sas_phy_pg0(mrioc, &ioc_status, &phy_pg0,
3113	    sizeof(struct mpi3_sas_phy_page0),
3114	    MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, phy->number) &&
3115	    (ioc_status == MPI3_IOCSTATUS_SUCCESS)) {
3116		phy->minimum_linkrate = mpi3mr_convert_phy_link_rate(
3117		    phy_pg0.programmed_link_rate &
3118		    MPI3_SAS_PRATE_MIN_RATE_MASK);
3119		phy->maximum_linkrate = mpi3mr_convert_phy_link_rate(
3120		    phy_pg0.programmed_link_rate >> 4);
3121		phy->negotiated_linkrate =
3122			mpi3mr_convert_phy_link_rate(
3123			    (phy_pg0.negotiated_link_rate &
3124			    MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK)
3125			    >> MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT);
3126	}
3127
3128out:
3129	kfree(sas_io_unit_pg1);
3130	return rc;
3131}
3132
3133/**
3134 * mpi3mr_map_smp_buffer - map BSG dma buffer
3135 * @dev: Generic device reference
3136 * @buf: BSG buffer pointer
3137 * @dma_addr: Physical address holder
3138 * @dma_len: Mapped DMA buffer length.
3139 * @p: Virtual address holder
3140 *
3141 * This function maps the DMAable buffer
3142 *
3143 * Return: 0 on success, non-zero on failure
3144 */
3145static int
3146mpi3mr_map_smp_buffer(struct device *dev, struct bsg_buffer *buf,
3147		dma_addr_t *dma_addr, size_t *dma_len, void **p)
3148{
3149	/* Check if the request is split across multiple segments */
3150	if (buf->sg_cnt > 1) {
3151		*p = dma_alloc_coherent(dev, buf->payload_len, dma_addr,
3152				GFP_KERNEL);
3153		if (!*p)
3154			return -ENOMEM;
3155		*dma_len = buf->payload_len;
3156	} else {
3157		if (!dma_map_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL))
3158			return -ENOMEM;
3159		*dma_addr = sg_dma_address(buf->sg_list);
3160		*dma_len = sg_dma_len(buf->sg_list);
3161		*p = NULL;
3162	}
3163
3164	return 0;
3165}
3166
3167/**
3168 * mpi3mr_unmap_smp_buffer - unmap BSG dma buffer
3169 * @dev: Generic device reference
3170 * @buf: BSG buffer pointer
3171 * @dma_addr: Physical address to be unmapped
3172 * @p: Virtual address
3173 *
3174 * This function unmaps the DMAable buffer
3175 */
3176static void
3177mpi3mr_unmap_smp_buffer(struct device *dev, struct bsg_buffer *buf,
3178		dma_addr_t dma_addr, void *p)
3179{
3180	if (p)
3181		dma_free_coherent(dev, buf->payload_len, p, dma_addr);
3182	else
3183		dma_unmap_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL);
3184}
3185
3186/**
3187 * mpi3mr_transport_smp_handler - handler for smp passthru
3188 * @job: BSG job reference
3189 * @shost: SCSI host object reference
3190 * @rphy: SAS transport rphy object pointing the expander
3191 *
3192 * This is used primarily by smp utils for sending the SMP
3193 * commands to the expanders attached to the controller
3194 */
3195static void
3196mpi3mr_transport_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
3197	struct sas_rphy *rphy)
3198{
3199	struct mpi3mr_ioc *mrioc = shost_priv(shost);
3200	struct mpi3_smp_passthrough_request mpi_request;
3201	struct mpi3_smp_passthrough_reply mpi_reply;
3202	int rc;
3203	void *psge;
3204	dma_addr_t dma_addr_in;
3205	dma_addr_t dma_addr_out;
3206	void *addr_in = NULL;
3207	void *addr_out = NULL;
3208	size_t dma_len_in;
3209	size_t dma_len_out;
3210	unsigned int reslen = 0;
3211	u16 request_sz = sizeof(struct mpi3_smp_passthrough_request);
3212	u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply);
3213	u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST;
3214	u16 ioc_status;
3215
3216	if (mrioc->reset_in_progress) {
3217		ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
 
 
 
 
 
 
3218		rc = -EFAULT;
3219		goto out;
3220	}
3221
3222	rc = mpi3mr_map_smp_buffer(&mrioc->pdev->dev, &job->request_payload,
3223	    &dma_addr_out, &dma_len_out, &addr_out);
3224	if (rc)
3225		goto out;
3226
3227	if (addr_out)
3228		sg_copy_to_buffer(job->request_payload.sg_list,
3229		    job->request_payload.sg_cnt, addr_out,
3230		    job->request_payload.payload_len);
3231
3232	rc = mpi3mr_map_smp_buffer(&mrioc->pdev->dev, &job->reply_payload,
3233			&dma_addr_in, &dma_len_in, &addr_in);
3234	if (rc)
3235		goto unmap_out;
3236
3237	memset(&mpi_request, 0, request_sz);
3238	memset(&mpi_reply, 0, reply_sz);
3239	mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
3240	mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH;
3241	mpi_request.io_unit_port = (u8) mpi3mr_get_port_id_by_rphy(mrioc, rphy);
3242	mpi_request.sas_address = ((rphy) ?
3243	    cpu_to_le64(rphy->identify.sas_address) :
3244	    cpu_to_le64(mrioc->sas_hba.sas_address));
3245	psge = &mpi_request.request_sge;
3246	mpi3mr_add_sg_single(psge, sgl_flags, dma_len_out - 4, dma_addr_out);
3247
3248	psge = &mpi_request.response_sge;
3249	mpi3mr_add_sg_single(psge, sgl_flags, dma_len_in - 4, dma_addr_in);
3250
3251	dprint_transport_info(mrioc, "sending SMP request\n");
3252
3253	rc = mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
3254				       &mpi_reply, reply_sz,
3255				       MPI3MR_INTADMCMD_TIMEOUT, &ioc_status);
3256	if (rc)
3257		goto unmap_in;
3258
3259	dprint_transport_info(mrioc,
3260	    "SMP request completed with ioc_status(0x%04x)\n", ioc_status);
3261
3262	dprint_transport_info(mrioc,
3263		    "SMP request - reply data transfer size(%d)\n",
3264		    le16_to_cpu(mpi_reply.response_data_length));
3265
3266	memcpy(job->reply, &mpi_reply, reply_sz);
3267	job->reply_len = reply_sz;
3268	reslen = le16_to_cpu(mpi_reply.response_data_length);
3269
3270	if (addr_in)
3271		sg_copy_from_buffer(job->reply_payload.sg_list,
3272				job->reply_payload.sg_cnt, addr_in,
3273				job->reply_payload.payload_len);
3274
3275	rc = 0;
3276unmap_in:
3277	mpi3mr_unmap_smp_buffer(&mrioc->pdev->dev, &job->reply_payload,
3278			dma_addr_in, addr_in);
3279unmap_out:
3280	mpi3mr_unmap_smp_buffer(&mrioc->pdev->dev, &job->request_payload,
3281			dma_addr_out, addr_out);
3282out:
3283	bsg_job_done(job, rc, reslen);
3284}
3285
3286struct sas_function_template mpi3mr_transport_functions = {
3287	.get_linkerrors		= mpi3mr_transport_get_linkerrors,
3288	.get_enclosure_identifier = mpi3mr_transport_get_enclosure_identifier,
3289	.get_bay_identifier	= mpi3mr_transport_get_bay_identifier,
3290	.phy_reset		= mpi3mr_transport_phy_reset,
3291	.phy_enable		= mpi3mr_transport_phy_enable,
3292	.set_phy_speed		= mpi3mr_transport_phy_speed,
3293	.smp_handler		= mpi3mr_transport_smp_handler,
3294};
3295
3296struct scsi_transport_template *mpi3mr_transport_template;
v6.13.7
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Driver for Broadcom MPI3 Storage Controllers
   4 *
   5 * Copyright (C) 2017-2023 Broadcom Inc.
   6 *  (mailto: mpi3mr-linuxdrv.pdl@broadcom.com)
   7 *
   8 */
   9
  10#include <linux/vmalloc.h>
  11
  12#include "mpi3mr.h"
  13
  14/**
  15 * mpi3mr_post_transport_req - Issue transport requests and wait
  16 * @mrioc: Adapter instance reference
  17 * @request: Properly populated MPI3 request
  18 * @request_sz: Size of the MPI3 request
  19 * @reply: Pointer to return MPI3 reply
  20 * @reply_sz: Size of the MPI3 reply buffer
  21 * @timeout: Timeout in seconds
  22 * @ioc_status: Pointer to return ioc status
  23 *
  24 * A generic function for posting MPI3 requests from the SAS
  25 * transport layer that uses transport command infrastructure.
  26 * This blocks for the completion of request for timeout seconds
  27 * and if the request times out this function faults the
  28 * controller with proper reason code.
  29 *
  30 * On successful completion of the request this function returns
  31 * appropriate ioc status from the firmware back to the caller.
  32 *
  33 * Return: 0 on success, non-zero on failure.
  34 */
  35static int mpi3mr_post_transport_req(struct mpi3mr_ioc *mrioc, void *request,
  36	u16 request_sz, void *reply, u16 reply_sz, int timeout,
  37	u16 *ioc_status)
  38{
  39	int retval = 0;
  40
  41	mutex_lock(&mrioc->transport_cmds.mutex);
  42	if (mrioc->transport_cmds.state & MPI3MR_CMD_PENDING) {
  43		retval = -1;
  44		ioc_err(mrioc, "sending transport request failed due to command in use\n");
  45		mutex_unlock(&mrioc->transport_cmds.mutex);
  46		goto out;
  47	}
  48	mrioc->transport_cmds.state = MPI3MR_CMD_PENDING;
  49	mrioc->transport_cmds.is_waiting = 1;
  50	mrioc->transport_cmds.callback = NULL;
  51	mrioc->transport_cmds.ioc_status = 0;
  52	mrioc->transport_cmds.ioc_loginfo = 0;
  53
  54	init_completion(&mrioc->transport_cmds.done);
  55	dprint_cfg_info(mrioc, "posting transport request\n");
  56	if (mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO)
  57		dprint_dump(request, request_sz, "transport_req");
  58	retval = mpi3mr_admin_request_post(mrioc, request, request_sz, 1);
  59	if (retval) {
  60		ioc_err(mrioc, "posting transport request failed\n");
  61		goto out_unlock;
  62	}
  63	wait_for_completion_timeout(&mrioc->transport_cmds.done,
  64	    (timeout * HZ));
  65	if (!(mrioc->transport_cmds.state & MPI3MR_CMD_COMPLETE)) {
  66		mpi3mr_check_rh_fault_ioc(mrioc,
  67		    MPI3MR_RESET_FROM_SAS_TRANSPORT_TIMEOUT);
  68		ioc_err(mrioc, "transport request timed out\n");
  69		retval = -1;
  70		goto out_unlock;
  71	}
  72	*ioc_status = mrioc->transport_cmds.ioc_status &
  73		MPI3_IOCSTATUS_STATUS_MASK;
  74	if ((*ioc_status) != MPI3_IOCSTATUS_SUCCESS)
  75		dprint_transport_err(mrioc,
  76		    "transport request returned with ioc_status(0x%04x), log_info(0x%08x)\n",
  77		    *ioc_status, mrioc->transport_cmds.ioc_loginfo);
  78
  79	if ((reply) && (mrioc->transport_cmds.state & MPI3MR_CMD_REPLY_VALID))
  80		memcpy((u8 *)reply, mrioc->transport_cmds.reply, reply_sz);
  81
  82out_unlock:
  83	mrioc->transport_cmds.state = MPI3MR_CMD_NOTUSED;
  84	mutex_unlock(&mrioc->transport_cmds.mutex);
  85
  86out:
  87	return retval;
  88}
  89
  90/* report manufacture request structure */
  91struct rep_manu_request {
  92	u8 smp_frame_type;
  93	u8 function;
  94	u8 reserved;
  95	u8 request_length;
  96};
  97
  98/* report manufacture reply structure */
  99struct rep_manu_reply {
 100	u8 smp_frame_type; /* 0x41 */
 101	u8 function; /* 0x01 */
 102	u8 function_result;
 103	u8 response_length;
 104	u16 expander_change_count;
 105	u8 reserved0[2];
 106	u8 sas_format;
 107	u8 reserved2[3];
 108	u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN];
 109	u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN];
 110	u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN];
 111	u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN];
 112	u16 component_id;
 113	u8 component_revision_id;
 114	u8 reserved3;
 115	u8 vendor_specific[8];
 116};
 117
 118/**
 119 * mpi3mr_report_manufacture - obtain SMP report_manufacture
 120 * @mrioc: Adapter instance reference
 121 * @sas_address: SAS address of the expander device
 122 * @edev: SAS transport layer sas_expander_device object
 123 * @port_id: ID of the HBA port
 124 *
 125 * Fills in the sas_expander_device with manufacturing info.
 126 *
 127 * Return: 0 for success, non-zero for failure.
 128 */
 129static int mpi3mr_report_manufacture(struct mpi3mr_ioc *mrioc,
 130	u64 sas_address, struct sas_expander_device *edev, u8 port_id)
 131{
 132	struct mpi3_smp_passthrough_request mpi_request;
 133	struct mpi3_smp_passthrough_reply mpi_reply;
 134	struct rep_manu_reply *manufacture_reply;
 135	struct rep_manu_request *manufacture_request;
 136	int rc = 0;
 137	void *psge;
 138	void *data_out = NULL;
 139	dma_addr_t data_out_dma;
 140	dma_addr_t data_in_dma;
 141	size_t data_in_sz;
 142	size_t data_out_sz;
 143	u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST;
 144	u16 request_sz = sizeof(struct mpi3_smp_passthrough_request);
 145	u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply);
 146	u16 ioc_status;
 147	u8 *tmp;
 148
 149	if (mrioc->reset_in_progress) {
 150		ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
 151		return -EFAULT;
 152	}
 153
 154	if (mrioc->pci_err_recovery) {
 155		ioc_err(mrioc, "%s: pci error recovery in progress!\n", __func__);
 156		return -EFAULT;
 157	}
 158
 159	data_out_sz = sizeof(struct rep_manu_request);
 160	data_in_sz = sizeof(struct rep_manu_reply);
 161	data_out = dma_alloc_coherent(&mrioc->pdev->dev,
 162	    data_out_sz + data_in_sz, &data_out_dma, GFP_KERNEL);
 163	if (!data_out) {
 164		rc = -ENOMEM;
 165		goto out;
 166	}
 167
 168	data_in_dma = data_out_dma + data_out_sz;
 169	manufacture_reply = data_out + data_out_sz;
 170
 171	manufacture_request = data_out;
 172	manufacture_request->smp_frame_type = 0x40;
 173	manufacture_request->function = 1;
 174	manufacture_request->reserved = 0;
 175	manufacture_request->request_length = 0;
 176
 177	memset(&mpi_request, 0, request_sz);
 178	memset(&mpi_reply, 0, reply_sz);
 179	mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
 180	mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH;
 181	mpi_request.io_unit_port = (u8) port_id;
 182	mpi_request.sas_address = cpu_to_le64(sas_address);
 183
 184	psge = &mpi_request.request_sge;
 185	mpi3mr_add_sg_single(psge, sgl_flags, data_out_sz, data_out_dma);
 186
 187	psge = &mpi_request.response_sge;
 188	mpi3mr_add_sg_single(psge, sgl_flags, data_in_sz, data_in_dma);
 189
 190	dprint_transport_info(mrioc,
 191	    "sending report manufacturer SMP request to sas_address(0x%016llx), port(%d)\n",
 192	    (unsigned long long)sas_address, port_id);
 193
 194	rc = mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
 195				       &mpi_reply, reply_sz,
 196				       MPI3MR_INTADMCMD_TIMEOUT, &ioc_status);
 197	if (rc)
 198		goto out;
 199
 200	dprint_transport_info(mrioc,
 201	    "report manufacturer SMP request completed with ioc_status(0x%04x)\n",
 202	    ioc_status);
 203
 204	if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
 205		rc = -EINVAL;
 206		goto out;
 207	}
 208
 209	dprint_transport_info(mrioc,
 210	    "report manufacturer - reply data transfer size(%d)\n",
 211	    le16_to_cpu(mpi_reply.response_data_length));
 212
 213	if (le16_to_cpu(mpi_reply.response_data_length) !=
 214	    sizeof(struct rep_manu_reply)) {
 215		rc = -EINVAL;
 216		goto out;
 217	}
 218
 219	memtostr(edev->vendor_id, manufacture_reply->vendor_id);
 220	memtostr(edev->product_id, manufacture_reply->product_id);
 221	memtostr(edev->product_rev, manufacture_reply->product_rev);
 
 
 
 222	edev->level = manufacture_reply->sas_format & 1;
 223	if (edev->level) {
 224		memtostr(edev->component_vendor_id,
 225			 manufacture_reply->component_vendor_id);
 
 226		tmp = (u8 *)&manufacture_reply->component_id;
 227		edev->component_id = tmp[0] << 8 | tmp[1];
 228		edev->component_revision_id =
 229		    manufacture_reply->component_revision_id;
 230	}
 231
 232out:
 233	if (data_out)
 234		dma_free_coherent(&mrioc->pdev->dev, data_out_sz + data_in_sz,
 235		    data_out, data_out_dma);
 236
 237	return rc;
 238}
 239
 240/**
 241 * __mpi3mr_expander_find_by_handle - expander search by handle
 242 * @mrioc: Adapter instance reference
 243 * @handle: Firmware device handle of the expander
 244 *
 245 * Context: The caller should acquire sas_node_lock
 246 *
 247 * This searches for expander device based on handle, then
 248 * returns the sas_node object.
 249 *
 250 * Return: Expander sas_node object reference or NULL
 251 */
 252struct mpi3mr_sas_node *__mpi3mr_expander_find_by_handle(struct mpi3mr_ioc
 253	*mrioc, u16 handle)
 254{
 255	struct mpi3mr_sas_node *sas_expander, *r;
 256
 257	r = NULL;
 258	list_for_each_entry(sas_expander, &mrioc->sas_expander_list, list) {
 259		if (sas_expander->handle != handle)
 260			continue;
 261		r = sas_expander;
 262		goto out;
 263	}
 264 out:
 265	return r;
 266}
 267
 268/**
 269 * mpi3mr_is_expander_device - if device is an expander
 270 * @device_info: Bitfield providing information about the device
 271 *
 272 * Return: 1 if the device is expander device, else 0.
 273 */
 274u8 mpi3mr_is_expander_device(u16 device_info)
 275{
 276	if ((device_info & MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_MASK) ==
 277	     MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_EXPANDER)
 278		return 1;
 279	else
 280		return 0;
 281}
 282
 283/**
 284 * mpi3mr_get_sas_address - retrieve sas_address for handle
 285 * @mrioc: Adapter instance reference
 286 * @handle: Firmware device handle
 287 * @sas_address: Address to hold sas address
 288 *
 289 * This function issues device page0 read for a given device
 290 * handle and gets the SAS address and return it back
 291 *
 292 * Return: 0 for success, non-zero for failure
 293 */
 294static int mpi3mr_get_sas_address(struct mpi3mr_ioc *mrioc, u16 handle,
 295	u64 *sas_address)
 296{
 297	struct mpi3_device_page0 dev_pg0;
 298	u16 ioc_status;
 299	struct mpi3_device0_sas_sata_format *sasinf;
 300
 301	*sas_address = 0;
 302
 303	if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &dev_pg0,
 304	    sizeof(dev_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE,
 305	    handle))) {
 306		ioc_err(mrioc, "%s: device page0 read failed\n", __func__);
 307		return -ENXIO;
 308	}
 309
 310	if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
 311		ioc_err(mrioc, "device page read failed for handle(0x%04x), with ioc_status(0x%04x) failure at %s:%d/%s()!\n",
 312		    handle, ioc_status, __FILE__, __LINE__, __func__);
 313		return -ENXIO;
 314	}
 315
 316	if (le16_to_cpu(dev_pg0.flags) &
 317	    MPI3_DEVICE0_FLAGS_CONTROLLER_DEV_HANDLE)
 318		*sas_address = mrioc->sas_hba.sas_address;
 319	else if (dev_pg0.device_form == MPI3_DEVICE_DEVFORM_SAS_SATA) {
 320		sasinf = &dev_pg0.device_specific.sas_sata_format;
 321		*sas_address = le64_to_cpu(sasinf->sas_address);
 322	} else {
 323		ioc_err(mrioc, "%s: device_form(%d) is not SAS_SATA\n",
 324		    __func__, dev_pg0.device_form);
 325		return -ENXIO;
 326	}
 327	return 0;
 328}
 329
 330/**
 331 * __mpi3mr_get_tgtdev_by_addr - target device search
 332 * @mrioc: Adapter instance reference
 333 * @sas_address: SAS address of the device
 334 * @hba_port: HBA port entry
 335 *
 336 * This searches for target device from sas address and hba port
 337 * pointer then return mpi3mr_tgt_dev object.
 338 *
 339 * Return: Valid tget_dev or NULL
 340 */
 341static struct mpi3mr_tgt_dev *__mpi3mr_get_tgtdev_by_addr(struct mpi3mr_ioc *mrioc,
 342	u64 sas_address, struct mpi3mr_hba_port *hba_port)
 343{
 344	struct mpi3mr_tgt_dev *tgtdev;
 345
 346	assert_spin_locked(&mrioc->tgtdev_lock);
 347
 348	list_for_each_entry(tgtdev, &mrioc->tgtdev_list, list)
 349		if ((tgtdev->dev_type == MPI3_DEVICE_DEVFORM_SAS_SATA) &&
 350		    (tgtdev->dev_spec.sas_sata_inf.sas_address == sas_address)
 351		    && (tgtdev->dev_spec.sas_sata_inf.hba_port == hba_port))
 352			goto found_device;
 353	return NULL;
 354found_device:
 355	mpi3mr_tgtdev_get(tgtdev);
 356	return tgtdev;
 357}
 358
 359/**
 360 * mpi3mr_get_tgtdev_by_addr - target device search
 361 * @mrioc: Adapter instance reference
 362 * @sas_address: SAS address of the device
 363 * @hba_port: HBA port entry
 364 *
 365 * This searches for target device from sas address and hba port
 366 * pointer then return mpi3mr_tgt_dev object.
 367 *
 368 * Context: This function will acquire tgtdev_lock and will
 369 * release before returning the mpi3mr_tgt_dev object.
 370 *
 371 * Return: Valid tget_dev or NULL
 372 */
 373static struct mpi3mr_tgt_dev *mpi3mr_get_tgtdev_by_addr(struct mpi3mr_ioc *mrioc,
 374	u64 sas_address, struct mpi3mr_hba_port *hba_port)
 375{
 376	struct mpi3mr_tgt_dev *tgtdev = NULL;
 377	unsigned long flags;
 378
 379	if (!hba_port)
 380		goto out;
 381
 382	spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
 383	tgtdev = __mpi3mr_get_tgtdev_by_addr(mrioc, sas_address, hba_port);
 384	spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
 385
 386out:
 387	return tgtdev;
 388}
 389
 390/**
 391 * mpi3mr_remove_device_by_sas_address - remove the device
 392 * @mrioc: Adapter instance reference
 393 * @sas_address: SAS address of the device
 394 * @hba_port: HBA port entry
 395 *
 396 * This searches for target device using sas address and hba
 397 * port pointer then removes it from the OS.
 398 *
 399 * Return: None
 400 */
 401static void mpi3mr_remove_device_by_sas_address(struct mpi3mr_ioc *mrioc,
 402	u64 sas_address, struct mpi3mr_hba_port *hba_port)
 403{
 404	struct mpi3mr_tgt_dev *tgtdev = NULL;
 405	unsigned long flags;
 406	u8 was_on_tgtdev_list = 0;
 407
 408	if (!hba_port)
 409		return;
 410
 411	spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
 412	tgtdev = __mpi3mr_get_tgtdev_by_addr(mrioc,
 413			 sas_address, hba_port);
 414	if (tgtdev) {
 415		if (!list_empty(&tgtdev->list)) {
 416			list_del_init(&tgtdev->list);
 417			was_on_tgtdev_list = 1;
 418			mpi3mr_tgtdev_put(tgtdev);
 419		}
 420	}
 421	spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
 422	if (was_on_tgtdev_list) {
 423		if (tgtdev->host_exposed)
 424			mpi3mr_remove_tgtdev_from_host(mrioc, tgtdev);
 425		mpi3mr_tgtdev_put(tgtdev);
 426	}
 427}
 428
 429/**
 430 * __mpi3mr_get_tgtdev_by_addr_and_rphy - target device search
 431 * @mrioc: Adapter instance reference
 432 * @sas_address: SAS address of the device
 433 * @rphy: SAS transport layer rphy object
 434 *
 435 * This searches for target device from sas address and rphy
 436 * pointer then return mpi3mr_tgt_dev object.
 437 *
 438 * Return: Valid tget_dev or NULL
 439 */
 440struct mpi3mr_tgt_dev *__mpi3mr_get_tgtdev_by_addr_and_rphy(
 441	struct mpi3mr_ioc *mrioc, u64 sas_address, struct sas_rphy *rphy)
 442{
 443	struct mpi3mr_tgt_dev *tgtdev;
 444
 445	assert_spin_locked(&mrioc->tgtdev_lock);
 446
 447	list_for_each_entry(tgtdev, &mrioc->tgtdev_list, list)
 448		if ((tgtdev->dev_type == MPI3_DEVICE_DEVFORM_SAS_SATA) &&
 449		    (tgtdev->dev_spec.sas_sata_inf.sas_address == sas_address)
 450		    && (tgtdev->dev_spec.sas_sata_inf.rphy == rphy))
 451			goto found_device;
 452	return NULL;
 453found_device:
 454	mpi3mr_tgtdev_get(tgtdev);
 455	return tgtdev;
 456}
 457
 458/**
 459 * mpi3mr_expander_find_by_sas_address - sas expander search
 460 * @mrioc: Adapter instance reference
 461 * @sas_address: SAS address of expander
 462 * @hba_port: HBA port entry
 463 *
 464 * Return: A valid SAS expander node or NULL.
 465 *
 466 */
 467static struct mpi3mr_sas_node *mpi3mr_expander_find_by_sas_address(
 468	struct mpi3mr_ioc *mrioc, u64 sas_address,
 469	struct mpi3mr_hba_port *hba_port)
 470{
 471	struct mpi3mr_sas_node *sas_expander, *r = NULL;
 472
 473	if (!hba_port)
 474		goto out;
 475
 476	list_for_each_entry(sas_expander, &mrioc->sas_expander_list, list) {
 477		if ((sas_expander->sas_address != sas_address) ||
 478					 (sas_expander->hba_port != hba_port))
 479			continue;
 480		r = sas_expander;
 481		goto out;
 482	}
 483out:
 484	return r;
 485}
 486
 487/**
 488 * __mpi3mr_sas_node_find_by_sas_address - sas node search
 489 * @mrioc: Adapter instance reference
 490 * @sas_address: SAS address of expander or sas host
 491 * @hba_port: HBA port entry
 492 * Context: Caller should acquire mrioc->sas_node_lock.
 493 *
 494 * If the SAS address indicates the device is direct attached to
 495 * the controller (controller's SAS address) then the SAS node
 496 * associated with the controller is returned back else the SAS
 497 * address and hba port are used to identify the exact expander
 498 * and the associated sas_node object is returned. If there is
 499 * no match NULL is returned.
 500 *
 501 * Return: A valid SAS node or NULL.
 502 *
 503 */
 504static struct mpi3mr_sas_node *__mpi3mr_sas_node_find_by_sas_address(
 505	struct mpi3mr_ioc *mrioc, u64 sas_address,
 506	struct mpi3mr_hba_port *hba_port)
 507{
 508
 509	if (mrioc->sas_hba.sas_address == sas_address)
 510		return &mrioc->sas_hba;
 511	return mpi3mr_expander_find_by_sas_address(mrioc, sas_address,
 512	    hba_port);
 513}
 514
 515/**
 516 * mpi3mr_parent_present - Is parent present for a phy
 517 * @mrioc: Adapter instance reference
 518 * @phy: SAS transport layer phy object
 519 *
 520 * Return: 0 if parent is present else non-zero
 521 */
 522static int mpi3mr_parent_present(struct mpi3mr_ioc *mrioc, struct sas_phy *phy)
 523{
 524	unsigned long flags;
 525	struct mpi3mr_hba_port *hba_port = phy->hostdata;
 526
 527	spin_lock_irqsave(&mrioc->sas_node_lock, flags);
 528	if (__mpi3mr_sas_node_find_by_sas_address(mrioc,
 529	    phy->identify.sas_address,
 530	    hba_port) == NULL) {
 531		spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
 532		return -1;
 533	}
 534	spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
 535	return 0;
 536}
 537
 538/**
 539 * mpi3mr_convert_phy_link_rate -
 540 * @link_rate: link rate as defined in the MPI header
 541 *
 542 * Convert link_rate from mpi format into sas_transport layer
 543 * form.
 544 *
 545 * Return: A valid SAS transport layer defined link rate
 546 */
 547static enum sas_linkrate mpi3mr_convert_phy_link_rate(u8 link_rate)
 548{
 549	enum sas_linkrate rc;
 550
 551	switch (link_rate) {
 552	case MPI3_SAS_NEG_LINK_RATE_1_5:
 553		rc = SAS_LINK_RATE_1_5_GBPS;
 554		break;
 555	case MPI3_SAS_NEG_LINK_RATE_3_0:
 556		rc = SAS_LINK_RATE_3_0_GBPS;
 557		break;
 558	case MPI3_SAS_NEG_LINK_RATE_6_0:
 559		rc = SAS_LINK_RATE_6_0_GBPS;
 560		break;
 561	case MPI3_SAS_NEG_LINK_RATE_12_0:
 562		rc = SAS_LINK_RATE_12_0_GBPS;
 563		break;
 564	case MPI3_SAS_NEG_LINK_RATE_22_5:
 565		rc = SAS_LINK_RATE_22_5_GBPS;
 566		break;
 567	case MPI3_SAS_NEG_LINK_RATE_PHY_DISABLED:
 568		rc = SAS_PHY_DISABLED;
 569		break;
 570	case MPI3_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED:
 571		rc = SAS_LINK_RATE_FAILED;
 572		break;
 573	case MPI3_SAS_NEG_LINK_RATE_PORT_SELECTOR:
 574		rc = SAS_SATA_PORT_SELECTOR;
 575		break;
 576	case MPI3_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS:
 577		rc = SAS_PHY_RESET_IN_PROGRESS;
 578		break;
 579	case MPI3_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE:
 580	case MPI3_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE:
 581	default:
 582		rc = SAS_LINK_RATE_UNKNOWN;
 583		break;
 584	}
 585	return rc;
 586}
 587
 588/**
 589 * mpi3mr_delete_sas_phy - Remove a single phy from port
 590 * @mrioc: Adapter instance reference
 591 * @mr_sas_port: Internal Port object
 592 * @mr_sas_phy: Internal Phy object
 593 * @host_node: Flag to indicate this is a host_node
 594 *
 595 * Return: None.
 596 */
 597static void mpi3mr_delete_sas_phy(struct mpi3mr_ioc *mrioc,
 598	struct mpi3mr_sas_port *mr_sas_port,
 599	struct mpi3mr_sas_phy *mr_sas_phy, u8 host_node)
 600{
 601	u64 sas_address = mr_sas_port->remote_identify.sas_address;
 602
 603	dev_info(&mr_sas_phy->phy->dev,
 604	    "remove: sas_address(0x%016llx), phy(%d)\n",
 605	    (unsigned long long) sas_address, mr_sas_phy->phy_id);
 606
 607	list_del(&mr_sas_phy->port_siblings);
 608	mr_sas_port->num_phys--;
 609
 610	if (host_node) {
 611		mr_sas_port->phy_mask &= ~(1 << mr_sas_phy->phy_id);
 612
 613		if (mr_sas_port->lowest_phy == mr_sas_phy->phy_id)
 614			mr_sas_port->lowest_phy = ffs(mr_sas_port->phy_mask) - 1;
 615	}
 616	sas_port_delete_phy(mr_sas_port->port, mr_sas_phy->phy);
 617	mr_sas_phy->phy_belongs_to_port = 0;
 618}
 619
 620/**
 621 * mpi3mr_add_sas_phy - Adding a single phy to a port
 622 * @mrioc: Adapter instance reference
 623 * @mr_sas_port: Internal Port object
 624 * @mr_sas_phy: Internal Phy object
 625 * @host_node: Flag to indicate this is a host_node
 626 *
 627 * Return: None.
 628 */
 629static void mpi3mr_add_sas_phy(struct mpi3mr_ioc *mrioc,
 630	struct mpi3mr_sas_port *mr_sas_port,
 631	struct mpi3mr_sas_phy *mr_sas_phy, u8 host_node)
 632{
 633	u64 sas_address = mr_sas_port->remote_identify.sas_address;
 634
 635	dev_info(&mr_sas_phy->phy->dev,
 636	    "add: sas_address(0x%016llx), phy(%d)\n", (unsigned long long)
 637	    sas_address, mr_sas_phy->phy_id);
 638
 639	list_add_tail(&mr_sas_phy->port_siblings, &mr_sas_port->phy_list);
 640	mr_sas_port->num_phys++;
 641	if (host_node) {
 642		mr_sas_port->phy_mask |= (1 << mr_sas_phy->phy_id);
 643
 644		if (mr_sas_phy->phy_id < mr_sas_port->lowest_phy)
 645			mr_sas_port->lowest_phy = ffs(mr_sas_port->phy_mask) - 1;
 646	}
 647	sas_port_add_phy(mr_sas_port->port, mr_sas_phy->phy);
 648	mr_sas_phy->phy_belongs_to_port = 1;
 649}
 650
 651/**
 652 * mpi3mr_add_phy_to_an_existing_port - add phy to existing port
 653 * @mrioc: Adapter instance reference
 654 * @mr_sas_node: Internal sas node object (expander or host)
 655 * @mr_sas_phy: Internal Phy object *
 656 * @sas_address: SAS address of device/expander were phy needs
 657 *             to be added to
 658 * @hba_port: HBA port entry
 659 *
 660 * Return: None.
 661 */
 662static void mpi3mr_add_phy_to_an_existing_port(struct mpi3mr_ioc *mrioc,
 663	struct mpi3mr_sas_node *mr_sas_node, struct mpi3mr_sas_phy *mr_sas_phy,
 664	u64 sas_address, struct mpi3mr_hba_port *hba_port)
 665{
 666	struct mpi3mr_sas_port *mr_sas_port;
 667	struct mpi3mr_sas_phy *srch_phy;
 668
 669	if (mr_sas_phy->phy_belongs_to_port == 1)
 670		return;
 671
 672	if (!hba_port)
 673		return;
 674
 675	list_for_each_entry(mr_sas_port, &mr_sas_node->sas_port_list,
 676	    port_list) {
 677		if (mr_sas_port->remote_identify.sas_address !=
 678		    sas_address)
 679			continue;
 680		if (mr_sas_port->hba_port != hba_port)
 681			continue;
 682		list_for_each_entry(srch_phy, &mr_sas_port->phy_list,
 683		    port_siblings) {
 684			if (srch_phy == mr_sas_phy)
 685				return;
 686		}
 687		mpi3mr_add_sas_phy(mrioc, mr_sas_port, mr_sas_phy, mr_sas_node->host_node);
 688		return;
 689	}
 690}
 691
 692/**
 693 * mpi3mr_delete_sas_port - helper function to removing a port
 694 * @mrioc: Adapter instance reference
 695 * @mr_sas_port: Internal Port object
 696 *
 697 * Return: None.
 698 */
 699static void  mpi3mr_delete_sas_port(struct mpi3mr_ioc *mrioc,
 700	struct mpi3mr_sas_port *mr_sas_port)
 701{
 702	u64 sas_address = mr_sas_port->remote_identify.sas_address;
 703	struct mpi3mr_hba_port *hba_port = mr_sas_port->hba_port;
 704	enum sas_device_type device_type =
 705	    mr_sas_port->remote_identify.device_type;
 706
 707	dev_info(&mr_sas_port->port->dev,
 708	    "remove: sas_address(0x%016llx)\n",
 709	    (unsigned long long) sas_address);
 710
 711	if (device_type == SAS_END_DEVICE)
 712		mpi3mr_remove_device_by_sas_address(mrioc, sas_address,
 713		    hba_port);
 714
 715	else if (device_type == SAS_EDGE_EXPANDER_DEVICE ||
 716	    device_type == SAS_FANOUT_EXPANDER_DEVICE)
 717		mpi3mr_expander_remove(mrioc, sas_address, hba_port);
 718}
 719
 720/**
 721 * mpi3mr_del_phy_from_an_existing_port - del phy from a port
 722 * @mrioc: Adapter instance reference
 723 * @mr_sas_node: Internal sas node object (expander or host)
 724 * @mr_sas_phy: Internal Phy object
 725 *
 726 * Return: None.
 727 */
 728static void mpi3mr_del_phy_from_an_existing_port(struct mpi3mr_ioc *mrioc,
 729	struct mpi3mr_sas_node *mr_sas_node, struct mpi3mr_sas_phy *mr_sas_phy)
 730{
 731	struct mpi3mr_sas_port *mr_sas_port, *next;
 732	struct mpi3mr_sas_phy *srch_phy;
 733
 734	if (mr_sas_phy->phy_belongs_to_port == 0)
 735		return;
 736
 737	list_for_each_entry_safe(mr_sas_port, next, &mr_sas_node->sas_port_list,
 738	    port_list) {
 739		list_for_each_entry(srch_phy, &mr_sas_port->phy_list,
 740		    port_siblings) {
 741			if (srch_phy != mr_sas_phy)
 742				continue;
 743			if ((mr_sas_port->num_phys == 1) &&
 744			    !mrioc->reset_in_progress)
 745				mpi3mr_delete_sas_port(mrioc, mr_sas_port);
 746			else
 747				mpi3mr_delete_sas_phy(mrioc, mr_sas_port,
 748				    mr_sas_phy, mr_sas_node->host_node);
 749			return;
 750		}
 751	}
 752}
 753
 754/**
 755 * mpi3mr_sas_port_sanity_check - sanity check while adding port
 756 * @mrioc: Adapter instance reference
 757 * @mr_sas_node: Internal sas node object (expander or host)
 758 * @sas_address: SAS address of device/expander
 759 * @hba_port: HBA port entry
 760 *
 761 * Verifies whether the Phys attached to a device with the given
 762 * SAS address already belongs to an existing sas port if so
 763 * will remove those phys from the sas port
 764 *
 765 * Return: None.
 766 */
 767static void mpi3mr_sas_port_sanity_check(struct mpi3mr_ioc *mrioc,
 768	struct mpi3mr_sas_node *mr_sas_node, u64 sas_address,
 769	struct mpi3mr_hba_port *hba_port)
 770{
 771	int i;
 772
 773	for (i = 0; i < mr_sas_node->num_phys; i++) {
 774		if ((mr_sas_node->phy[i].remote_identify.sas_address !=
 775		    sas_address) || (mr_sas_node->phy[i].hba_port != hba_port))
 776			continue;
 777		if (mr_sas_node->phy[i].phy_belongs_to_port == 1)
 778			mpi3mr_del_phy_from_an_existing_port(mrioc,
 779			    mr_sas_node, &mr_sas_node->phy[i]);
 780	}
 781}
 782
 783/**
 784 * mpi3mr_set_identify - set identify for phys and end devices
 785 * @mrioc: Adapter instance reference
 786 * @handle: Firmware device handle
 787 * @identify: SAS transport layer's identify info
 788 *
 789 * Populates sas identify info for a specific device.
 790 *
 791 * Return: 0 for success, non-zero for failure.
 792 */
 793static int mpi3mr_set_identify(struct mpi3mr_ioc *mrioc, u16 handle,
 794	struct sas_identify *identify)
 795{
 796
 797	struct mpi3_device_page0 device_pg0;
 798	struct mpi3_device0_sas_sata_format *sasinf;
 799	u16 device_info;
 800	u16 ioc_status;
 801
 802	if (mrioc->reset_in_progress) {
 803		ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
 804		return -EFAULT;
 805	}
 806
 807	if (mrioc->pci_err_recovery) {
 808		ioc_err(mrioc, "%s: pci error recovery in progress!\n",
 809		    __func__);
 810		return -EFAULT;
 811	}
 812
 813	if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &device_pg0,
 814	    sizeof(device_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE, handle))) {
 815		ioc_err(mrioc, "%s: device page0 read failed\n", __func__);
 816		return -ENXIO;
 817	}
 818
 819	if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
 820		ioc_err(mrioc, "device page read failed for handle(0x%04x), with ioc_status(0x%04x) failure at %s:%d/%s()!\n",
 821		    handle, ioc_status, __FILE__, __LINE__, __func__);
 822		return -EIO;
 823	}
 824
 825	memset(identify, 0, sizeof(struct sas_identify));
 826	sasinf = &device_pg0.device_specific.sas_sata_format;
 827	device_info = le16_to_cpu(sasinf->device_info);
 828
 829	/* sas_address */
 830	identify->sas_address = le64_to_cpu(sasinf->sas_address);
 831
 832	/* phy number of the parent device this device is linked to */
 833	identify->phy_identifier = sasinf->phy_num;
 834
 835	/* device_type */
 836	switch (device_info & MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_MASK) {
 837	case MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_NO_DEVICE:
 838		identify->device_type = SAS_PHY_UNUSED;
 839		break;
 840	case MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_END_DEVICE:
 841		identify->device_type = SAS_END_DEVICE;
 842		break;
 843	case MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_EXPANDER:
 844		identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
 845		break;
 846	}
 847
 848	/* initiator_port_protocols */
 849	if (device_info & MPI3_SAS_DEVICE_INFO_SSP_INITIATOR)
 850		identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
 851	/* MPI3.0 doesn't have define for SATA INIT so setting both here*/
 852	if (device_info & MPI3_SAS_DEVICE_INFO_STP_INITIATOR)
 853		identify->initiator_port_protocols |= (SAS_PROTOCOL_STP |
 854		    SAS_PROTOCOL_SATA);
 855	if (device_info & MPI3_SAS_DEVICE_INFO_SMP_INITIATOR)
 856		identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
 857
 858	/* target_port_protocols */
 859	if (device_info & MPI3_SAS_DEVICE_INFO_SSP_TARGET)
 860		identify->target_port_protocols |= SAS_PROTOCOL_SSP;
 861	/* MPI3.0 doesn't have define for STP Target so setting both here*/
 862	if (device_info & MPI3_SAS_DEVICE_INFO_STP_SATA_TARGET)
 863		identify->target_port_protocols |= (SAS_PROTOCOL_STP |
 864		    SAS_PROTOCOL_SATA);
 865	if (device_info & MPI3_SAS_DEVICE_INFO_SMP_TARGET)
 866		identify->target_port_protocols |= SAS_PROTOCOL_SMP;
 867	return 0;
 868}
 869
 870/**
 871 * mpi3mr_add_host_phy - report sas_host phy to SAS transport
 872 * @mrioc: Adapter instance reference
 873 * @mr_sas_phy: Internal Phy object
 874 * @phy_pg0: SAS phy page 0
 875 * @parent_dev: Prent device class object
 876 *
 877 * Return: 0 for success, non-zero for failure.
 878 */
 879static int mpi3mr_add_host_phy(struct mpi3mr_ioc *mrioc,
 880	struct mpi3mr_sas_phy *mr_sas_phy, struct mpi3_sas_phy_page0 phy_pg0,
 881	struct device *parent_dev)
 882{
 883	struct sas_phy *phy;
 884	int phy_index = mr_sas_phy->phy_id;
 885
 886
 887	INIT_LIST_HEAD(&mr_sas_phy->port_siblings);
 888	phy = sas_phy_alloc(parent_dev, phy_index);
 889	if (!phy) {
 890		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
 891		    __FILE__, __LINE__, __func__);
 892		return -1;
 893	}
 894	if ((mpi3mr_set_identify(mrioc, mr_sas_phy->handle,
 895	    &mr_sas_phy->identify))) {
 896		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
 897		    __FILE__, __LINE__, __func__);
 898		sas_phy_free(phy);
 899		return -1;
 900	}
 901	phy->identify = mr_sas_phy->identify;
 902	mr_sas_phy->attached_handle = le16_to_cpu(phy_pg0.attached_dev_handle);
 903	if (mr_sas_phy->attached_handle)
 904		mpi3mr_set_identify(mrioc, mr_sas_phy->attached_handle,
 905		    &mr_sas_phy->remote_identify);
 906	phy->identify.phy_identifier = mr_sas_phy->phy_id;
 907	phy->negotiated_linkrate = mpi3mr_convert_phy_link_rate(
 908	    (phy_pg0.negotiated_link_rate &
 909	    MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
 910	    MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT);
 911	phy->minimum_linkrate_hw = mpi3mr_convert_phy_link_rate(
 912	    phy_pg0.hw_link_rate & MPI3_SAS_HWRATE_MIN_RATE_MASK);
 913	phy->maximum_linkrate_hw = mpi3mr_convert_phy_link_rate(
 914	    phy_pg0.hw_link_rate >> 4);
 915	phy->minimum_linkrate = mpi3mr_convert_phy_link_rate(
 916	    phy_pg0.programmed_link_rate & MPI3_SAS_PRATE_MIN_RATE_MASK);
 917	phy->maximum_linkrate = mpi3mr_convert_phy_link_rate(
 918	    phy_pg0.programmed_link_rate >> 4);
 919	phy->hostdata = mr_sas_phy->hba_port;
 920
 921	if ((sas_phy_add(phy))) {
 922		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
 923		    __FILE__, __LINE__, __func__);
 924		sas_phy_free(phy);
 925		return -1;
 926	}
 927	if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO))
 928		dev_info(&phy->dev,
 929		    "add: handle(0x%04x), sas_address(0x%016llx)\n"
 930		    "\tattached_handle(0x%04x), sas_address(0x%016llx)\n",
 931		    mr_sas_phy->handle, (unsigned long long)
 932		    mr_sas_phy->identify.sas_address,
 933		    mr_sas_phy->attached_handle,
 934		    (unsigned long long)
 935		    mr_sas_phy->remote_identify.sas_address);
 936	mr_sas_phy->phy = phy;
 937	return 0;
 938}
 939
 940/**
 941 * mpi3mr_add_expander_phy - report expander phy to transport
 942 * @mrioc: Adapter instance reference
 943 * @mr_sas_phy: Internal Phy object
 944 * @expander_pg1: SAS Expander page 1
 945 * @parent_dev: Parent device class object
 946 *
 947 * Return: 0 for success, non-zero for failure.
 948 */
 949static int mpi3mr_add_expander_phy(struct mpi3mr_ioc *mrioc,
 950	struct mpi3mr_sas_phy *mr_sas_phy,
 951	struct mpi3_sas_expander_page1 expander_pg1,
 952	struct device *parent_dev)
 953{
 954	struct sas_phy *phy;
 955	int phy_index = mr_sas_phy->phy_id;
 956
 957	INIT_LIST_HEAD(&mr_sas_phy->port_siblings);
 958	phy = sas_phy_alloc(parent_dev, phy_index);
 959	if (!phy) {
 960		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
 961		    __FILE__, __LINE__, __func__);
 962		return -1;
 963	}
 964	if ((mpi3mr_set_identify(mrioc, mr_sas_phy->handle,
 965	    &mr_sas_phy->identify))) {
 966		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
 967		    __FILE__, __LINE__, __func__);
 968		sas_phy_free(phy);
 969		return -1;
 970	}
 971	phy->identify = mr_sas_phy->identify;
 972	mr_sas_phy->attached_handle =
 973	    le16_to_cpu(expander_pg1.attached_dev_handle);
 974	if (mr_sas_phy->attached_handle)
 975		mpi3mr_set_identify(mrioc, mr_sas_phy->attached_handle,
 976		    &mr_sas_phy->remote_identify);
 977	phy->identify.phy_identifier = mr_sas_phy->phy_id;
 978	phy->negotiated_linkrate = mpi3mr_convert_phy_link_rate(
 979	    (expander_pg1.negotiated_link_rate &
 980	    MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
 981	    MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT);
 982	phy->minimum_linkrate_hw = mpi3mr_convert_phy_link_rate(
 983	    expander_pg1.hw_link_rate & MPI3_SAS_HWRATE_MIN_RATE_MASK);
 984	phy->maximum_linkrate_hw = mpi3mr_convert_phy_link_rate(
 985	    expander_pg1.hw_link_rate >> 4);
 986	phy->minimum_linkrate = mpi3mr_convert_phy_link_rate(
 987	    expander_pg1.programmed_link_rate & MPI3_SAS_PRATE_MIN_RATE_MASK);
 988	phy->maximum_linkrate = mpi3mr_convert_phy_link_rate(
 989	    expander_pg1.programmed_link_rate >> 4);
 990	phy->hostdata = mr_sas_phy->hba_port;
 991
 992	if ((sas_phy_add(phy))) {
 993		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
 994		    __FILE__, __LINE__, __func__);
 995		sas_phy_free(phy);
 996		return -1;
 997	}
 998	if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO))
 999		dev_info(&phy->dev,
1000		    "add: handle(0x%04x), sas_address(0x%016llx)\n"
1001		    "\tattached_handle(0x%04x), sas_address(0x%016llx)\n",
1002		    mr_sas_phy->handle, (unsigned long long)
1003		    mr_sas_phy->identify.sas_address,
1004		    mr_sas_phy->attached_handle,
1005		    (unsigned long long)
1006		    mr_sas_phy->remote_identify.sas_address);
1007	mr_sas_phy->phy = phy;
1008	return 0;
1009}
1010
1011/**
1012 * mpi3mr_alloc_hba_port - alloc hba port object
1013 * @mrioc: Adapter instance reference
1014 * @port_id: Port number
1015 *
1016 * Alloc memory for hba port object.
1017 */
1018static struct mpi3mr_hba_port *
1019mpi3mr_alloc_hba_port(struct mpi3mr_ioc *mrioc, u16 port_id)
1020{
1021	struct mpi3mr_hba_port *hba_port;
1022
1023	hba_port = kzalloc(sizeof(struct mpi3mr_hba_port),
1024	    GFP_KERNEL);
1025	if (!hba_port)
1026		return NULL;
1027	hba_port->port_id = port_id;
1028	ioc_info(mrioc, "hba_port entry: %p, port: %d is added to hba_port list\n",
1029	    hba_port, hba_port->port_id);
1030	if (mrioc->reset_in_progress ||
1031		mrioc->pci_err_recovery)
1032		hba_port->flags = MPI3MR_HBA_PORT_FLAG_NEW;
1033	list_add_tail(&hba_port->list, &mrioc->hba_port_table_list);
1034	return hba_port;
1035}
1036
1037/**
1038 * mpi3mr_get_hba_port_by_id - find hba port by id
1039 * @mrioc: Adapter instance reference
1040 * @port_id: Port ID to search
1041 *
1042 * Return: mpi3mr_hba_port reference for the matched port
1043 */
1044
1045struct mpi3mr_hba_port *mpi3mr_get_hba_port_by_id(struct mpi3mr_ioc *mrioc,
1046	u8 port_id)
1047{
1048	struct mpi3mr_hba_port *port, *port_next;
1049
1050	list_for_each_entry_safe(port, port_next,
1051	    &mrioc->hba_port_table_list, list) {
1052		if (port->port_id != port_id)
1053			continue;
1054		if (port->flags & MPI3MR_HBA_PORT_FLAG_DIRTY)
1055			continue;
1056		return port;
1057	}
1058
1059	return NULL;
1060}
1061
1062/**
1063 * mpi3mr_update_links - refreshing SAS phy link changes
1064 * @mrioc: Adapter instance reference
1065 * @sas_address_parent: SAS address of parent expander or host
1066 * @handle: Firmware device handle of attached device
1067 * @phy_number: Phy number
1068 * @link_rate: New link rate
1069 * @hba_port: HBA port entry
1070 *
1071 * Return: None.
1072 */
1073void mpi3mr_update_links(struct mpi3mr_ioc *mrioc,
1074	u64 sas_address_parent, u16 handle, u8 phy_number, u8 link_rate,
1075	struct mpi3mr_hba_port *hba_port)
1076{
1077	unsigned long flags;
1078	struct mpi3mr_sas_node *mr_sas_node;
1079	struct mpi3mr_sas_phy *mr_sas_phy;
1080
1081	if (mrioc->reset_in_progress || mrioc->pci_err_recovery)
1082		return;
1083
1084	spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1085	mr_sas_node = __mpi3mr_sas_node_find_by_sas_address(mrioc,
1086	    sas_address_parent, hba_port);
1087	if (!mr_sas_node) {
1088		spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1089		return;
1090	}
1091
1092	mr_sas_phy = &mr_sas_node->phy[phy_number];
1093	mr_sas_phy->attached_handle = handle;
1094	spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1095	if (handle && (link_rate >= MPI3_SAS_NEG_LINK_RATE_1_5)) {
1096		mpi3mr_set_identify(mrioc, handle,
1097		    &mr_sas_phy->remote_identify);
1098		mpi3mr_add_phy_to_an_existing_port(mrioc, mr_sas_node,
1099		    mr_sas_phy, mr_sas_phy->remote_identify.sas_address,
1100		    hba_port);
1101	} else
1102		memset(&mr_sas_phy->remote_identify, 0, sizeof(struct
1103		    sas_identify));
1104
1105	if (mr_sas_phy->phy)
1106		mr_sas_phy->phy->negotiated_linkrate =
1107		    mpi3mr_convert_phy_link_rate(link_rate);
1108
1109	if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO))
1110		dev_info(&mr_sas_phy->phy->dev,
1111		    "refresh: parent sas_address(0x%016llx),\n"
1112		    "\tlink_rate(0x%02x), phy(%d)\n"
1113		    "\tattached_handle(0x%04x), sas_address(0x%016llx)\n",
1114		    (unsigned long long)sas_address_parent,
1115		    link_rate, phy_number, handle, (unsigned long long)
1116		    mr_sas_phy->remote_identify.sas_address);
1117}
1118
1119/**
1120 * mpi3mr_sas_host_refresh - refreshing sas host object contents
1121 * @mrioc: Adapter instance reference
1122 *
1123 * This function refreshes the controllers phy information and
1124 * updates the SAS transport layer with updated information,
1125 * this is executed for each device addition or device info
1126 * change events
1127 *
1128 * Return: None.
1129 */
1130void mpi3mr_sas_host_refresh(struct mpi3mr_ioc *mrioc)
1131{
1132	int i;
1133	u8 link_rate;
1134	u16 sz, port_id, attached_handle;
1135	struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL;
1136
1137	dprint_transport_info(mrioc,
1138	    "updating handles for sas_host(0x%016llx)\n",
1139	    (unsigned long long)mrioc->sas_hba.sas_address);
1140
1141	sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) +
1142	    (mrioc->sas_hba.num_phys *
1143	     sizeof(struct mpi3_sas_io_unit0_phy_data));
1144	sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
1145	if (!sas_io_unit_pg0)
1146		return;
1147	if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
1148		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1149		    __FILE__, __LINE__, __func__);
1150		goto out;
1151	}
1152
1153	mrioc->sas_hba.handle = 0;
1154	for (i = 0; i < mrioc->sas_hba.num_phys; i++) {
1155		if (sas_io_unit_pg0->phy_data[i].phy_flags &
1156		    (MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY |
1157		     MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY))
1158			continue;
1159		link_rate =
1160		    sas_io_unit_pg0->phy_data[i].negotiated_link_rate >> 4;
1161		if (!mrioc->sas_hba.handle)
1162			mrioc->sas_hba.handle = le16_to_cpu(
1163			    sas_io_unit_pg0->phy_data[i].controller_dev_handle);
1164		port_id = sas_io_unit_pg0->phy_data[i].io_unit_port;
1165		if (!(mpi3mr_get_hba_port_by_id(mrioc, port_id)))
1166			if (!mpi3mr_alloc_hba_port(mrioc, port_id))
1167				goto out;
1168
1169		mrioc->sas_hba.phy[i].handle = mrioc->sas_hba.handle;
1170		attached_handle = le16_to_cpu(
1171		    sas_io_unit_pg0->phy_data[i].attached_dev_handle);
1172		if (attached_handle && link_rate < MPI3_SAS_NEG_LINK_RATE_1_5)
1173			link_rate = MPI3_SAS_NEG_LINK_RATE_1_5;
1174		mrioc->sas_hba.phy[i].hba_port =
1175			mpi3mr_get_hba_port_by_id(mrioc, port_id);
1176		mpi3mr_update_links(mrioc, mrioc->sas_hba.sas_address,
1177		    attached_handle, i, link_rate,
1178		    mrioc->sas_hba.phy[i].hba_port);
1179	}
1180 out:
1181	kfree(sas_io_unit_pg0);
1182}
1183
1184/**
1185 * mpi3mr_sas_host_add - create sas host object
1186 * @mrioc: Adapter instance reference
1187 *
1188 * This function creates the controllers phy information and
1189 * updates the SAS transport layer with updated information,
1190 * this is executed for first device addition or device info
1191 * change event.
1192 *
1193 * Return: None.
1194 */
1195void mpi3mr_sas_host_add(struct mpi3mr_ioc *mrioc)
1196{
1197	int i;
1198	u16 sz, num_phys = 1, port_id, ioc_status;
1199	struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL;
1200	struct mpi3_sas_phy_page0 phy_pg0;
1201	struct mpi3_device_page0 dev_pg0;
1202	struct mpi3_enclosure_page0 encl_pg0;
1203	struct mpi3_device0_sas_sata_format *sasinf;
1204
1205	sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) +
1206	    (num_phys * sizeof(struct mpi3_sas_io_unit0_phy_data));
1207	sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
1208	if (!sas_io_unit_pg0)
1209		return;
1210
1211	if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
1212		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1213		    __FILE__, __LINE__, __func__);
1214		goto out;
1215	}
1216	num_phys = sas_io_unit_pg0->num_phys;
1217	kfree(sas_io_unit_pg0);
1218
1219	mrioc->sas_hba.host_node = 1;
1220	INIT_LIST_HEAD(&mrioc->sas_hba.sas_port_list);
1221	mrioc->sas_hba.parent_dev = &mrioc->shost->shost_gendev;
1222	mrioc->sas_hba.phy = kcalloc(num_phys,
1223	    sizeof(struct mpi3mr_sas_phy), GFP_KERNEL);
1224	if (!mrioc->sas_hba.phy)
1225		return;
1226
1227	mrioc->sas_hba.num_phys = num_phys;
1228
1229	sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) +
1230	    (num_phys * sizeof(struct mpi3_sas_io_unit0_phy_data));
1231	sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
1232	if (!sas_io_unit_pg0)
1233		return;
1234
1235	if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
1236		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1237		    __FILE__, __LINE__, __func__);
1238		goto out;
1239	}
1240
1241	mrioc->sas_hba.handle = 0;
1242	for (i = 0; i < mrioc->sas_hba.num_phys; i++) {
1243		if (sas_io_unit_pg0->phy_data[i].phy_flags &
1244		    (MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY |
1245		    MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY))
1246			continue;
1247		if (mpi3mr_cfg_get_sas_phy_pg0(mrioc, &ioc_status, &phy_pg0,
1248		    sizeof(struct mpi3_sas_phy_page0),
1249		    MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, i)) {
1250			ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1251			    __FILE__, __LINE__, __func__);
1252			goto out;
1253		}
1254		if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
1255			ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1256			    __FILE__, __LINE__, __func__);
1257			goto out;
1258		}
1259
1260		if (!mrioc->sas_hba.handle)
1261			mrioc->sas_hba.handle = le16_to_cpu(
1262			    sas_io_unit_pg0->phy_data[i].controller_dev_handle);
1263		port_id = sas_io_unit_pg0->phy_data[i].io_unit_port;
1264
1265		if (!(mpi3mr_get_hba_port_by_id(mrioc, port_id)))
1266			if (!mpi3mr_alloc_hba_port(mrioc, port_id))
1267				goto out;
1268
1269		mrioc->sas_hba.phy[i].handle = mrioc->sas_hba.handle;
1270		mrioc->sas_hba.phy[i].phy_id = i;
1271		mrioc->sas_hba.phy[i].hba_port =
1272		    mpi3mr_get_hba_port_by_id(mrioc, port_id);
1273		mpi3mr_add_host_phy(mrioc, &mrioc->sas_hba.phy[i],
1274		    phy_pg0, mrioc->sas_hba.parent_dev);
1275	}
1276	if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &dev_pg0,
1277	    sizeof(dev_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE,
1278	    mrioc->sas_hba.handle))) {
1279		ioc_err(mrioc, "%s: device page0 read failed\n", __func__);
1280		goto out;
1281	}
1282	if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
1283		ioc_err(mrioc, "device page read failed for handle(0x%04x), with ioc_status(0x%04x) failure at %s:%d/%s()!\n",
1284		    mrioc->sas_hba.handle, ioc_status, __FILE__, __LINE__,
1285		    __func__);
1286		goto out;
1287	}
1288	mrioc->sas_hba.enclosure_handle =
1289	    le16_to_cpu(dev_pg0.enclosure_handle);
1290	sasinf = &dev_pg0.device_specific.sas_sata_format;
1291	mrioc->sas_hba.sas_address =
1292	    le64_to_cpu(sasinf->sas_address);
1293	ioc_info(mrioc,
1294	    "host_add: handle(0x%04x), sas_addr(0x%016llx), phys(%d)\n",
1295	    mrioc->sas_hba.handle,
1296	    (unsigned long long) mrioc->sas_hba.sas_address,
1297	    mrioc->sas_hba.num_phys);
1298
1299	if (mrioc->sas_hba.enclosure_handle) {
1300		if (!(mpi3mr_cfg_get_enclosure_pg0(mrioc, &ioc_status,
1301		    &encl_pg0, sizeof(encl_pg0),
1302		    MPI3_ENCLOS_PGAD_FORM_HANDLE,
1303		    mrioc->sas_hba.enclosure_handle)) &&
1304		    (ioc_status == MPI3_IOCSTATUS_SUCCESS))
1305			mrioc->sas_hba.enclosure_logical_id =
1306				le64_to_cpu(encl_pg0.enclosure_logical_id);
1307	}
1308
1309out:
1310	kfree(sas_io_unit_pg0);
1311}
1312
1313/**
1314 * mpi3mr_sas_port_add - Expose the SAS device to the SAS TL
1315 * @mrioc: Adapter instance reference
1316 * @handle: Firmware device handle of the attached device
1317 * @sas_address_parent: sas address of parent expander or host
1318 * @hba_port: HBA port entry
1319 *
1320 * This function creates a new sas port object for the given end
1321 * device matching sas address and hba_port and adds it to the
1322 * sas_node's sas_port_list and expose the attached sas device
1323 * to the SAS transport layer through sas_rphy_add.
1324 *
1325 * Returns a valid mpi3mr_sas_port reference or NULL.
1326 */
1327static struct mpi3mr_sas_port *mpi3mr_sas_port_add(struct mpi3mr_ioc *mrioc,
1328	u16 handle, u64 sas_address_parent, struct mpi3mr_hba_port *hba_port)
1329{
1330	struct mpi3mr_sas_phy *mr_sas_phy, *next;
1331	struct mpi3mr_sas_port *mr_sas_port;
1332	unsigned long flags;
1333	struct mpi3mr_sas_node *mr_sas_node;
1334	struct sas_rphy *rphy;
1335	struct mpi3mr_tgt_dev *tgtdev = NULL;
1336	int i;
1337	struct sas_port *port;
1338
1339	if (!hba_port) {
1340		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1341		    __FILE__, __LINE__, __func__);
1342		return NULL;
1343	}
1344
1345	mr_sas_port = kzalloc(sizeof(struct mpi3mr_sas_port), GFP_KERNEL);
1346	if (!mr_sas_port)
1347		return NULL;
1348
1349	INIT_LIST_HEAD(&mr_sas_port->port_list);
1350	INIT_LIST_HEAD(&mr_sas_port->phy_list);
1351	spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1352	mr_sas_node = __mpi3mr_sas_node_find_by_sas_address(mrioc,
1353	    sas_address_parent, hba_port);
1354	spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1355
1356	if (!mr_sas_node) {
1357		ioc_err(mrioc, "%s:could not find parent sas_address(0x%016llx)!\n",
1358		    __func__, (unsigned long long)sas_address_parent);
1359		goto out_fail;
1360	}
1361
1362	if ((mpi3mr_set_identify(mrioc, handle,
1363	    &mr_sas_port->remote_identify))) {
1364		ioc_err(mrioc,  "failure at %s:%d/%s()!\n",
1365		    __FILE__, __LINE__, __func__);
1366		goto out_fail;
1367	}
1368
1369	if (mr_sas_port->remote_identify.device_type == SAS_PHY_UNUSED) {
1370		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1371		    __FILE__, __LINE__, __func__);
1372		goto out_fail;
1373	}
1374
1375	mr_sas_port->hba_port = hba_port;
1376	mpi3mr_sas_port_sanity_check(mrioc, mr_sas_node,
1377	    mr_sas_port->remote_identify.sas_address, hba_port);
1378
1379	if (mr_sas_node->host_node && mr_sas_node->num_phys >=
1380			sizeof(mr_sas_port->phy_mask) * 8)
1381		ioc_info(mrioc, "max port count %u could be too high\n",
1382		    mr_sas_node->num_phys);
1383
1384	for (i = 0; i < mr_sas_node->num_phys; i++) {
1385		if ((mr_sas_node->phy[i].remote_identify.sas_address !=
1386		    mr_sas_port->remote_identify.sas_address) ||
1387		    (mr_sas_node->phy[i].hba_port != hba_port))
1388			continue;
1389
1390		if (mr_sas_node->host_node && (i >= sizeof(mr_sas_port->phy_mask) * 8)) {
1391			ioc_warn(mrioc, "skipping port %u, max allowed value is %zu\n",
1392			    i, sizeof(mr_sas_port->phy_mask) * 8);
1393			goto out_fail;
1394		}
1395		list_add_tail(&mr_sas_node->phy[i].port_siblings,
1396		    &mr_sas_port->phy_list);
1397		mr_sas_port->num_phys++;
1398		if (mr_sas_node->host_node)
1399			mr_sas_port->phy_mask |= (1 << i);
1400	}
1401
1402	if (!mr_sas_port->num_phys) {
1403		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1404		    __FILE__, __LINE__, __func__);
1405		goto out_fail;
1406	}
1407
1408	if (mr_sas_node->host_node)
1409		mr_sas_port->lowest_phy = ffs(mr_sas_port->phy_mask) - 1;
1410
1411	if (mr_sas_port->remote_identify.device_type == SAS_END_DEVICE) {
1412		tgtdev = mpi3mr_get_tgtdev_by_addr(mrioc,
1413		    mr_sas_port->remote_identify.sas_address,
1414		    mr_sas_port->hba_port);
1415
1416		if (!tgtdev) {
1417			ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1418			    __FILE__, __LINE__, __func__);
1419			goto out_fail;
1420		}
1421		tgtdev->dev_spec.sas_sata_inf.pend_sas_rphy_add = 1;
1422	}
1423
1424	if (!mr_sas_node->parent_dev) {
1425		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1426		    __FILE__, __LINE__, __func__);
1427		goto out_fail;
1428	}
1429
1430	port = sas_port_alloc_num(mr_sas_node->parent_dev);
1431	if ((sas_port_add(port))) {
1432		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1433		    __FILE__, __LINE__, __func__);
1434		goto out_fail;
1435	}
1436
1437	list_for_each_entry(mr_sas_phy, &mr_sas_port->phy_list,
1438	    port_siblings) {
1439		if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO))
1440			dev_info(&port->dev,
1441			    "add: handle(0x%04x), sas_address(0x%016llx), phy(%d)\n",
1442			    handle, (unsigned long long)
1443			    mr_sas_port->remote_identify.sas_address,
1444			    mr_sas_phy->phy_id);
1445		sas_port_add_phy(port, mr_sas_phy->phy);
1446		mr_sas_phy->phy_belongs_to_port = 1;
1447		mr_sas_phy->hba_port = hba_port;
1448	}
1449
1450	mr_sas_port->port = port;
1451	if (mr_sas_port->remote_identify.device_type == SAS_END_DEVICE) {
1452		rphy = sas_end_device_alloc(port);
1453		tgtdev->dev_spec.sas_sata_inf.rphy = rphy;
1454	} else {
1455		rphy = sas_expander_alloc(port,
1456		    mr_sas_port->remote_identify.device_type);
1457	}
1458	rphy->identify = mr_sas_port->remote_identify;
1459
1460	if (mrioc->current_event)
1461		mrioc->current_event->pending_at_sml = 1;
1462
1463	if ((sas_rphy_add(rphy))) {
1464		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1465		    __FILE__, __LINE__, __func__);
1466	}
1467	if (mr_sas_port->remote_identify.device_type == SAS_END_DEVICE) {
1468		tgtdev->dev_spec.sas_sata_inf.pend_sas_rphy_add = 0;
1469		tgtdev->dev_spec.sas_sata_inf.sas_transport_attached = 1;
1470		mpi3mr_tgtdev_put(tgtdev);
1471	}
1472
1473	dev_info(&rphy->dev,
1474	    "%s: added: handle(0x%04x), sas_address(0x%016llx)\n",
1475	    __func__, handle, (unsigned long long)
1476	    mr_sas_port->remote_identify.sas_address);
1477
1478	mr_sas_port->rphy = rphy;
1479	spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1480	list_add_tail(&mr_sas_port->port_list, &mr_sas_node->sas_port_list);
1481	spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1482
1483	if (mrioc->current_event) {
1484		mrioc->current_event->pending_at_sml = 0;
1485		if (mrioc->current_event->discard)
1486			mpi3mr_print_device_event_notice(mrioc, true);
1487	}
1488
1489	/* fill in report manufacture */
1490	if (mr_sas_port->remote_identify.device_type ==
1491	    SAS_EDGE_EXPANDER_DEVICE ||
1492	    mr_sas_port->remote_identify.device_type ==
1493	    SAS_FANOUT_EXPANDER_DEVICE)
1494		mpi3mr_report_manufacture(mrioc,
1495		    mr_sas_port->remote_identify.sas_address,
1496		    rphy_to_expander_device(rphy), hba_port->port_id);
1497
1498	return mr_sas_port;
1499
1500 out_fail:
1501	list_for_each_entry_safe(mr_sas_phy, next, &mr_sas_port->phy_list,
1502	    port_siblings)
1503		list_del(&mr_sas_phy->port_siblings);
1504	kfree(mr_sas_port);
1505	return NULL;
1506}
1507
1508/**
1509 * mpi3mr_sas_port_remove - remove port from the list
1510 * @mrioc: Adapter instance reference
1511 * @sas_address: SAS address of attached device
1512 * @sas_address_parent: SAS address of parent expander or host
1513 * @hba_port: HBA port entry
1514 *
1515 * Removing object and freeing associated memory from the
1516 * sas_port_list.
1517 *
1518 * Return: None
1519 */
1520static void mpi3mr_sas_port_remove(struct mpi3mr_ioc *mrioc, u64 sas_address,
1521	u64 sas_address_parent, struct mpi3mr_hba_port *hba_port)
1522{
1523	int i;
1524	unsigned long flags;
1525	struct mpi3mr_sas_port *mr_sas_port, *next;
1526	struct mpi3mr_sas_node *mr_sas_node;
1527	u8 found = 0;
1528	struct mpi3mr_sas_phy *mr_sas_phy, *next_phy;
1529	struct mpi3mr_hba_port *srch_port, *hba_port_next = NULL;
1530
1531	if (!hba_port)
1532		return;
1533
1534	spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1535	mr_sas_node = __mpi3mr_sas_node_find_by_sas_address(mrioc,
1536	    sas_address_parent, hba_port);
1537	if (!mr_sas_node) {
1538		spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1539		return;
1540	}
1541	list_for_each_entry_safe(mr_sas_port, next, &mr_sas_node->sas_port_list,
1542	    port_list) {
1543		if (mr_sas_port->remote_identify.sas_address != sas_address)
1544			continue;
1545		if (mr_sas_port->hba_port != hba_port)
1546			continue;
1547		found = 1;
1548		list_del(&mr_sas_port->port_list);
1549		goto out;
1550	}
1551
1552 out:
1553	if (!found) {
1554		spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1555		return;
1556	}
1557
1558	if (mr_sas_node->host_node) {
1559		list_for_each_entry_safe(srch_port, hba_port_next,
1560		    &mrioc->hba_port_table_list, list) {
1561			if (srch_port != hba_port)
1562				continue;
1563			ioc_info(mrioc,
1564			    "removing hba_port entry: %p port: %d from hba_port list\n",
1565			    srch_port, srch_port->port_id);
1566			list_del(&hba_port->list);
1567			kfree(hba_port);
1568			break;
1569		}
1570	}
1571
1572	for (i = 0; i < mr_sas_node->num_phys; i++) {
1573		if (mr_sas_node->phy[i].remote_identify.sas_address ==
1574		    sas_address)
1575			memset(&mr_sas_node->phy[i].remote_identify, 0,
1576			    sizeof(struct sas_identify));
1577	}
1578
1579	spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1580
1581	if (mrioc->current_event)
1582		mrioc->current_event->pending_at_sml = 1;
1583
1584	list_for_each_entry_safe(mr_sas_phy, next_phy,
1585	    &mr_sas_port->phy_list, port_siblings) {
1586		if ((!mrioc->stop_drv_processing) &&
1587		    (mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO))
1588			dev_info(&mr_sas_port->port->dev,
1589			    "remove: sas_address(0x%016llx), phy(%d)\n",
1590			    (unsigned long long)
1591			    mr_sas_port->remote_identify.sas_address,
1592			    mr_sas_phy->phy_id);
1593		mr_sas_phy->phy_belongs_to_port = 0;
1594		if (!mrioc->stop_drv_processing)
1595			sas_port_delete_phy(mr_sas_port->port,
1596			    mr_sas_phy->phy);
1597		list_del(&mr_sas_phy->port_siblings);
1598	}
1599	if (!mrioc->stop_drv_processing)
1600		sas_port_delete(mr_sas_port->port);
1601	ioc_info(mrioc, "%s: removed sas_address(0x%016llx)\n",
1602	    __func__, (unsigned long long)sas_address);
1603
1604	if (mrioc->current_event) {
1605		mrioc->current_event->pending_at_sml = 0;
1606		if (mrioc->current_event->discard)
1607			mpi3mr_print_device_event_notice(mrioc, false);
1608	}
1609
1610	kfree(mr_sas_port);
1611}
1612
1613/**
1614 * struct host_port - host port details
1615 * @sas_address: SAS Address of the attached device
1616 * @phy_mask: phy mask of host port
1617 * @handle: Device Handle of attached device
1618 * @iounit_port_id: port ID
1619 * @used: host port is already matched with sas port from sas_port_list
1620 * @lowest_phy: lowest phy ID of host port
1621 */
1622struct host_port {
1623	u64	sas_address;
1624	u64	phy_mask;
1625	u16	handle;
1626	u8	iounit_port_id;
1627	u8	used;
1628	u8	lowest_phy;
1629};
1630
1631/**
1632 * mpi3mr_update_mr_sas_port - update sas port objects during reset
1633 * @mrioc: Adapter instance reference
1634 * @h_port: host_port object
1635 * @mr_sas_port: sas_port objects which needs to be updated
1636 *
1637 * Update the port ID of sas port object. Also add the phys if new phys got
1638 * added to current sas port and remove the phys if some phys are moved
1639 * out of the current sas port.
1640 *
1641 * Return: Nothing.
1642 */
1643static void
1644mpi3mr_update_mr_sas_port(struct mpi3mr_ioc *mrioc, struct host_port *h_port,
1645	struct mpi3mr_sas_port *mr_sas_port)
1646{
1647	struct mpi3mr_sas_phy *mr_sas_phy;
1648	u64 phy_mask_xor;
1649	u64 phys_to_be_added, phys_to_be_removed;
1650	int i;
1651
1652	h_port->used = 1;
1653	mr_sas_port->marked_responding = 1;
1654
1655	dev_info(&mr_sas_port->port->dev,
1656	    "sas_address(0x%016llx), old: port_id %d phy_mask 0x%llx, new: port_id %d phy_mask:0x%llx\n",
1657	    mr_sas_port->remote_identify.sas_address,
1658	    mr_sas_port->hba_port->port_id, mr_sas_port->phy_mask,
1659	    h_port->iounit_port_id, h_port->phy_mask);
1660
1661	mr_sas_port->hba_port->port_id = h_port->iounit_port_id;
1662	mr_sas_port->hba_port->flags &= ~MPI3MR_HBA_PORT_FLAG_DIRTY;
1663
1664	/* Get the newly added phys bit map & removed phys bit map */
1665	phy_mask_xor = mr_sas_port->phy_mask ^ h_port->phy_mask;
1666	phys_to_be_added = h_port->phy_mask & phy_mask_xor;
1667	phys_to_be_removed = mr_sas_port->phy_mask & phy_mask_xor;
1668
1669	/*
1670	 * Register these new phys to current mr_sas_port's port.
1671	 * if these phys are previously registered with another port
1672	 * then delete these phys from that port first.
1673	 */
1674	for_each_set_bit(i, (ulong *) &phys_to_be_added, BITS_PER_TYPE(u64)) {
1675		mr_sas_phy = &mrioc->sas_hba.phy[i];
1676		if (mr_sas_phy->phy_belongs_to_port)
1677			mpi3mr_del_phy_from_an_existing_port(mrioc,
1678			    &mrioc->sas_hba, mr_sas_phy);
1679		mpi3mr_add_phy_to_an_existing_port(mrioc,
1680		    &mrioc->sas_hba, mr_sas_phy,
1681		    mr_sas_port->remote_identify.sas_address,
1682		    mr_sas_port->hba_port);
1683	}
1684
1685	/* Delete the phys which are not part of current mr_sas_port's port. */
1686	for_each_set_bit(i, (ulong *) &phys_to_be_removed, BITS_PER_TYPE(u64)) {
1687		mr_sas_phy = &mrioc->sas_hba.phy[i];
1688		if (mr_sas_phy->phy_belongs_to_port)
1689			mpi3mr_del_phy_from_an_existing_port(mrioc,
1690			    &mrioc->sas_hba, mr_sas_phy);
1691	}
1692}
1693
1694/**
1695 * mpi3mr_refresh_sas_ports - update host's sas ports during reset
1696 * @mrioc: Adapter instance reference
1697 *
1698 * Update the host's sas ports during reset by checking whether
1699 * sas ports are still intact or not. Add/remove phys if any hba
1700 * phys are (moved in)/(moved out) of sas port. Also update
1701 * io_unit_port if it got changed during reset.
1702 *
1703 * Return: Nothing.
1704 */
1705void
1706mpi3mr_refresh_sas_ports(struct mpi3mr_ioc *mrioc)
1707{
1708	struct host_port *h_port = NULL;
1709	int i, j, found, host_port_count = 0, port_idx;
1710	u16 sz, attached_handle, ioc_status;
1711	struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL;
1712	struct mpi3_device_page0 dev_pg0;
1713	struct mpi3_device0_sas_sata_format *sasinf;
1714	struct mpi3mr_sas_port *mr_sas_port;
1715
1716	sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) +
1717		(mrioc->sas_hba.num_phys *
1718		 sizeof(struct mpi3_sas_io_unit0_phy_data));
1719	sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
1720	if (!sas_io_unit_pg0)
1721		return;
1722	h_port = kcalloc(64, sizeof(struct host_port), GFP_KERNEL);
1723	if (!h_port)
1724		goto out;
1725
1726	if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
1727		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1728		    __FILE__, __LINE__, __func__);
1729		goto out;
1730	}
1731
1732	/* Create a new expander port table */
1733	for (i = 0; i < mrioc->sas_hba.num_phys; i++) {
1734		attached_handle = le16_to_cpu(
1735		    sas_io_unit_pg0->phy_data[i].attached_dev_handle);
1736		if (!attached_handle)
1737			continue;
1738		found = 0;
1739		for (j = 0; j < host_port_count; j++) {
1740			if (h_port[j].handle == attached_handle) {
1741				h_port[j].phy_mask |= (1 << i);
1742				found = 1;
1743				break;
1744			}
1745		}
1746		if (found)
1747			continue;
1748		if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &dev_pg0,
1749		    sizeof(dev_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE,
1750		    attached_handle))) {
1751			dprint_reset(mrioc,
1752			    "failed to read dev_pg0 for handle(0x%04x) at %s:%d/%s()!\n",
1753			    attached_handle, __FILE__, __LINE__, __func__);
1754			continue;
1755		}
1756		if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
1757			dprint_reset(mrioc,
1758			    "ioc_status(0x%x) while reading dev_pg0 for handle(0x%04x) at %s:%d/%s()!\n",
1759			    ioc_status, attached_handle,
1760			    __FILE__, __LINE__, __func__);
1761			continue;
1762		}
1763		sasinf = &dev_pg0.device_specific.sas_sata_format;
1764
1765		port_idx = host_port_count;
1766		h_port[port_idx].sas_address = le64_to_cpu(sasinf->sas_address);
1767		h_port[port_idx].handle = attached_handle;
1768		h_port[port_idx].phy_mask = (1 << i);
1769		h_port[port_idx].iounit_port_id = sas_io_unit_pg0->phy_data[i].io_unit_port;
1770		h_port[port_idx].lowest_phy = sasinf->phy_num;
1771		h_port[port_idx].used = 0;
1772		host_port_count++;
1773	}
1774
1775	if (!host_port_count)
1776		goto out;
1777
1778	if (mrioc->logging_level & MPI3_DEBUG_RESET) {
1779		ioc_info(mrioc, "Host port details before reset\n");
1780		list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1781		    port_list) {
1782			ioc_info(mrioc,
1783			    "port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%llx), lowest phy id:%d\n",
1784			    mr_sas_port->hba_port->port_id,
1785			    mr_sas_port->remote_identify.sas_address,
1786			    mr_sas_port->phy_mask, mr_sas_port->lowest_phy);
1787		}
1788		mr_sas_port = NULL;
1789		ioc_info(mrioc, "Host port details after reset\n");
1790		for (i = 0; i < host_port_count; i++) {
1791			ioc_info(mrioc,
1792			    "port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%llx), lowest phy id:%d\n",
1793			    h_port[i].iounit_port_id, h_port[i].sas_address,
1794			    h_port[i].phy_mask, h_port[i].lowest_phy);
1795		}
1796	}
1797
1798	/* mark all host sas port entries as dirty */
1799	list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1800	    port_list) {
1801		mr_sas_port->marked_responding = 0;
1802		mr_sas_port->hba_port->flags |= MPI3MR_HBA_PORT_FLAG_DIRTY;
1803	}
1804
1805	/* First check for matching lowest phy */
1806	for (i = 0; i < host_port_count; i++) {
1807		mr_sas_port = NULL;
1808		list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1809		    port_list) {
1810			if (mr_sas_port->marked_responding)
1811				continue;
1812			if (h_port[i].sas_address != mr_sas_port->remote_identify.sas_address)
1813				continue;
1814			if (h_port[i].lowest_phy == mr_sas_port->lowest_phy) {
1815				mpi3mr_update_mr_sas_port(mrioc, &h_port[i], mr_sas_port);
1816				break;
1817			}
1818		}
1819	}
1820
1821	/* In case if lowest phy is got enabled or disabled during reset */
1822	for (i = 0; i < host_port_count; i++) {
1823		if (h_port[i].used)
1824			continue;
1825		mr_sas_port = NULL;
1826		list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1827		    port_list) {
1828			if (mr_sas_port->marked_responding)
1829				continue;
1830			if (h_port[i].sas_address != mr_sas_port->remote_identify.sas_address)
1831				continue;
1832			if (h_port[i].phy_mask & mr_sas_port->phy_mask) {
1833				mpi3mr_update_mr_sas_port(mrioc, &h_port[i], mr_sas_port);
1834				break;
1835			}
1836		}
1837	}
1838
1839	/* In case if expander cable is removed & connected to another HBA port during reset */
1840	for (i = 0; i < host_port_count; i++) {
1841		if (h_port[i].used)
1842			continue;
1843		mr_sas_port = NULL;
1844		list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1845		    port_list) {
1846			if (mr_sas_port->marked_responding)
1847				continue;
1848			if (h_port[i].sas_address != mr_sas_port->remote_identify.sas_address)
1849				continue;
1850			mpi3mr_update_mr_sas_port(mrioc, &h_port[i], mr_sas_port);
1851			break;
1852		}
1853	}
1854out:
1855	kfree(h_port);
1856	kfree(sas_io_unit_pg0);
1857}
1858
1859/**
1860 * mpi3mr_refresh_expanders - Refresh expander device exposure
1861 * @mrioc: Adapter instance reference
1862 *
1863 * This is executed post controller reset to identify any
1864 * missing expander devices during reset and remove from the upper layers
1865 * or expose any newly detected expander device to the upper layers.
1866 *
1867 * Return: Nothing.
1868 */
1869void
1870mpi3mr_refresh_expanders(struct mpi3mr_ioc *mrioc)
1871{
1872	struct mpi3mr_sas_node *sas_expander, *sas_expander_next;
1873	struct mpi3_sas_expander_page0 expander_pg0;
1874	u16 ioc_status, handle;
1875	u64 sas_address;
1876	int i;
1877	unsigned long flags;
1878	struct mpi3mr_hba_port *hba_port;
1879
1880	spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1881	list_for_each_entry(sas_expander, &mrioc->sas_expander_list, list) {
1882		sas_expander->non_responding = 1;
1883	}
1884	spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1885
1886	sas_expander = NULL;
1887
1888	handle = 0xffff;
1889
1890	/* Search for responding expander devices and add them if they are newly got added */
1891	while (true) {
1892		if ((mpi3mr_cfg_get_sas_exp_pg0(mrioc, &ioc_status, &expander_pg0,
1893		    sizeof(struct mpi3_sas_expander_page0),
1894		    MPI3_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
1895			dprint_reset(mrioc,
1896			    "failed to read exp pg0 for handle(0x%04x) at %s:%d/%s()!\n",
1897			    handle, __FILE__, __LINE__, __func__);
1898			break;
1899		}
1900
1901		if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
1902			dprint_reset(mrioc,
1903			   "ioc_status(0x%x) while reading exp pg0 for handle:(0x%04x), %s:%d/%s()!\n",
1904			   ioc_status, handle, __FILE__, __LINE__, __func__);
1905			break;
1906		}
1907
1908		handle = le16_to_cpu(expander_pg0.dev_handle);
1909		sas_address = le64_to_cpu(expander_pg0.sas_address);
1910		hba_port = mpi3mr_get_hba_port_by_id(mrioc, expander_pg0.io_unit_port);
1911
1912		if (!hba_port) {
1913			mpi3mr_sas_host_refresh(mrioc);
1914			mpi3mr_expander_add(mrioc, handle);
1915			continue;
1916		}
1917
1918		spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1919		sas_expander =
1920		    mpi3mr_expander_find_by_sas_address(mrioc,
1921		    sas_address, hba_port);
1922		spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1923
1924		if (!sas_expander) {
1925			mpi3mr_sas_host_refresh(mrioc);
1926			mpi3mr_expander_add(mrioc, handle);
1927			continue;
1928		}
1929
1930		sas_expander->non_responding = 0;
1931		if (sas_expander->handle == handle)
1932			continue;
1933
1934		sas_expander->handle = handle;
1935		for (i = 0 ; i < sas_expander->num_phys ; i++)
1936			sas_expander->phy[i].handle = handle;
1937	}
1938
1939	/*
1940	 * Delete non responding expander devices and the corresponding
1941	 * hba_port if the non responding expander device's parent device
1942	 * is a host node.
1943	 */
1944	sas_expander = NULL;
1945	spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1946	list_for_each_entry_safe_reverse(sas_expander, sas_expander_next,
1947	    &mrioc->sas_expander_list, list) {
1948		if (sas_expander->non_responding) {
1949			spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1950			mpi3mr_expander_node_remove(mrioc, sas_expander);
1951			spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1952		}
1953	}
1954	spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1955}
1956
1957/**
1958 * mpi3mr_expander_node_add - insert an expander to the list.
1959 * @mrioc: Adapter instance reference
1960 * @sas_expander: Expander sas node
1961 * Context: This function will acquire sas_node_lock.
1962 *
1963 * Adding new object to the ioc->sas_expander_list.
1964 *
1965 * Return: None.
1966 */
1967static void mpi3mr_expander_node_add(struct mpi3mr_ioc *mrioc,
1968	struct mpi3mr_sas_node *sas_expander)
1969{
1970	unsigned long flags;
1971
1972	spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1973	list_add_tail(&sas_expander->list, &mrioc->sas_expander_list);
1974	spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1975}
1976
1977/**
1978 * mpi3mr_expander_add -  Create expander object
1979 * @mrioc: Adapter instance reference
1980 * @handle: Expander firmware device handle
1981 *
1982 * This function creating expander object, stored in
1983 * sas_expander_list and expose it to the SAS transport
1984 * layer.
1985 *
1986 * Return: 0 for success, non-zero for failure.
1987 */
1988int mpi3mr_expander_add(struct mpi3mr_ioc *mrioc, u16 handle)
1989{
1990	struct mpi3mr_sas_node *sas_expander;
1991	struct mpi3mr_enclosure_node *enclosure_dev;
1992	struct mpi3_sas_expander_page0 expander_pg0;
1993	struct mpi3_sas_expander_page1 expander_pg1;
1994	u16 ioc_status, parent_handle, temp_handle;
1995	u64 sas_address, sas_address_parent = 0;
1996	int i;
1997	unsigned long flags;
1998	u8 port_id, link_rate;
1999	struct mpi3mr_sas_port *mr_sas_port = NULL;
2000	struct mpi3mr_hba_port *hba_port;
2001	u32 phynum_handle;
2002	int rc = 0;
2003
2004	if (!handle)
2005		return -1;
2006
2007	if (mrioc->reset_in_progress || mrioc->pci_err_recovery)
2008		return -1;
2009
2010	if ((mpi3mr_cfg_get_sas_exp_pg0(mrioc, &ioc_status, &expander_pg0,
2011	    sizeof(expander_pg0), MPI3_SAS_EXPAND_PGAD_FORM_HANDLE, handle))) {
2012		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2013		    __FILE__, __LINE__, __func__);
2014		return -1;
2015	}
2016
2017	if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2018		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2019		    __FILE__, __LINE__, __func__);
2020		return -1;
2021	}
2022
2023	parent_handle = le16_to_cpu(expander_pg0.parent_dev_handle);
2024	if (mpi3mr_get_sas_address(mrioc, parent_handle, &sas_address_parent)
2025	    != 0) {
2026		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2027		    __FILE__, __LINE__, __func__);
2028		return -1;
2029	}
2030
2031	port_id = expander_pg0.io_unit_port;
2032	hba_port = mpi3mr_get_hba_port_by_id(mrioc, port_id);
2033	if (!hba_port) {
2034		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2035		    __FILE__, __LINE__, __func__);
2036		return -1;
2037	}
2038
2039	if (sas_address_parent != mrioc->sas_hba.sas_address) {
2040		spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2041		sas_expander =
2042		   mpi3mr_expander_find_by_sas_address(mrioc,
2043		    sas_address_parent, hba_port);
2044		spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2045		if (!sas_expander) {
2046			rc = mpi3mr_expander_add(mrioc, parent_handle);
2047			if (rc != 0)
2048				return rc;
2049		} else {
2050			/*
2051			 * When there is a parent expander present, update it's
2052			 * phys where child expander is connected with the link
2053			 * speed, attached dev handle and sas address.
2054			 */
2055			for (i = 0 ; i < sas_expander->num_phys ; i++) {
2056				phynum_handle =
2057				    (i << MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT) |
2058				    parent_handle;
2059				if (mpi3mr_cfg_get_sas_exp_pg1(mrioc,
2060				    &ioc_status, &expander_pg1,
2061				    sizeof(expander_pg1),
2062				    MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM,
2063				    phynum_handle)) {
2064					ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2065					    __FILE__, __LINE__, __func__);
2066					rc = -1;
2067					return rc;
2068				}
2069				if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2070					ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2071					    __FILE__, __LINE__, __func__);
2072					rc = -1;
2073					return rc;
2074				}
2075				temp_handle = le16_to_cpu(
2076				    expander_pg1.attached_dev_handle);
2077				if (temp_handle != handle)
2078					continue;
2079				link_rate = (expander_pg1.negotiated_link_rate &
2080				    MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
2081				    MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT;
2082				mpi3mr_update_links(mrioc, sas_address_parent,
2083				    handle, i, link_rate, hba_port);
2084			}
2085		}
2086	}
2087
2088	spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2089	sas_address = le64_to_cpu(expander_pg0.sas_address);
2090	sas_expander = mpi3mr_expander_find_by_sas_address(mrioc,
2091	    sas_address, hba_port);
2092	spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2093
2094	if (sas_expander)
2095		return 0;
2096
2097	sas_expander = kzalloc(sizeof(struct mpi3mr_sas_node),
2098	    GFP_KERNEL);
2099	if (!sas_expander)
2100		return -ENOMEM;
2101
2102	sas_expander->handle = handle;
2103	sas_expander->num_phys = expander_pg0.num_phys;
2104	sas_expander->sas_address_parent = sas_address_parent;
2105	sas_expander->sas_address = sas_address;
2106	sas_expander->hba_port = hba_port;
2107
2108	ioc_info(mrioc,
2109	    "expander_add: handle(0x%04x), parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n",
2110	    handle, parent_handle, (unsigned long long)
2111	    sas_expander->sas_address, sas_expander->num_phys);
2112
2113	if (!sas_expander->num_phys) {
2114		rc = -1;
2115		goto out_fail;
2116	}
2117	sas_expander->phy = kcalloc(sas_expander->num_phys,
2118	    sizeof(struct mpi3mr_sas_phy), GFP_KERNEL);
2119	if (!sas_expander->phy) {
2120		rc = -1;
2121		goto out_fail;
2122	}
2123
2124	INIT_LIST_HEAD(&sas_expander->sas_port_list);
2125	mr_sas_port = mpi3mr_sas_port_add(mrioc, handle, sas_address_parent,
2126	    sas_expander->hba_port);
2127	if (!mr_sas_port) {
2128		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2129		    __FILE__, __LINE__, __func__);
2130		rc = -1;
2131		goto out_fail;
2132	}
2133	sas_expander->parent_dev = &mr_sas_port->rphy->dev;
2134	sas_expander->rphy = mr_sas_port->rphy;
2135
2136	for (i = 0 ; i < sas_expander->num_phys ; i++) {
2137		phynum_handle = (i << MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT) |
2138		    handle;
2139		if (mpi3mr_cfg_get_sas_exp_pg1(mrioc, &ioc_status,
2140		    &expander_pg1, sizeof(expander_pg1),
2141		    MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM,
2142		    phynum_handle)) {
2143			ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2144			    __FILE__, __LINE__, __func__);
2145			rc = -1;
2146			goto out_fail;
2147		}
2148		if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2149			ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2150			    __FILE__, __LINE__, __func__);
2151			rc = -1;
2152			goto out_fail;
2153		}
2154
2155		sas_expander->phy[i].handle = handle;
2156		sas_expander->phy[i].phy_id = i;
2157		sas_expander->phy[i].hba_port = hba_port;
2158
2159		if ((mpi3mr_add_expander_phy(mrioc, &sas_expander->phy[i],
2160		    expander_pg1, sas_expander->parent_dev))) {
2161			ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2162			    __FILE__, __LINE__, __func__);
2163			rc = -1;
2164			goto out_fail;
2165		}
2166	}
2167
2168	if (sas_expander->enclosure_handle) {
2169		enclosure_dev =
2170			mpi3mr_enclosure_find_by_handle(mrioc,
2171						sas_expander->enclosure_handle);
2172		if (enclosure_dev)
2173			sas_expander->enclosure_logical_id = le64_to_cpu(
2174			    enclosure_dev->pg0.enclosure_logical_id);
2175	}
2176
2177	mpi3mr_expander_node_add(mrioc, sas_expander);
2178	return 0;
2179
2180out_fail:
2181
2182	if (mr_sas_port)
2183		mpi3mr_sas_port_remove(mrioc,
2184		    sas_expander->sas_address,
2185		    sas_address_parent, sas_expander->hba_port);
2186	kfree(sas_expander->phy);
2187	kfree(sas_expander);
2188	return rc;
2189}
2190
2191/**
2192 * mpi3mr_expander_node_remove - recursive removal of expander.
2193 * @mrioc: Adapter instance reference
2194 * @sas_expander: Expander device object
2195 *
2196 * Removes expander object and freeing associated memory from
2197 * the sas_expander_list and removes the same from SAS TL, if
2198 * one of the attached device is an expander then it recursively
2199 * removes the expander device too.
2200 *
2201 * Return nothing.
2202 */
2203void mpi3mr_expander_node_remove(struct mpi3mr_ioc *mrioc,
2204	struct mpi3mr_sas_node *sas_expander)
2205{
2206	struct mpi3mr_sas_port *mr_sas_port, *next;
2207	unsigned long flags;
2208	u8 port_id;
2209
2210	/* remove sibling ports attached to this expander */
2211	list_for_each_entry_safe(mr_sas_port, next,
2212	   &sas_expander->sas_port_list, port_list) {
2213		if (mrioc->reset_in_progress || mrioc->pci_err_recovery)
2214			return;
2215		if (mr_sas_port->remote_identify.device_type ==
2216		    SAS_END_DEVICE)
2217			mpi3mr_remove_device_by_sas_address(mrioc,
2218			    mr_sas_port->remote_identify.sas_address,
2219			    mr_sas_port->hba_port);
2220		else if (mr_sas_port->remote_identify.device_type ==
2221		    SAS_EDGE_EXPANDER_DEVICE ||
2222		    mr_sas_port->remote_identify.device_type ==
2223		    SAS_FANOUT_EXPANDER_DEVICE)
2224			mpi3mr_expander_remove(mrioc,
2225			    mr_sas_port->remote_identify.sas_address,
2226			    mr_sas_port->hba_port);
2227	}
2228
2229	port_id = sas_expander->hba_port->port_id;
2230	mpi3mr_sas_port_remove(mrioc, sas_expander->sas_address,
2231	    sas_expander->sas_address_parent, sas_expander->hba_port);
2232
2233	ioc_info(mrioc, "expander_remove: handle(0x%04x), sas_addr(0x%016llx), port:%d\n",
2234	    sas_expander->handle, (unsigned long long)
2235	    sas_expander->sas_address, port_id);
2236
2237	spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2238	list_del(&sas_expander->list);
2239	spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2240
2241	kfree(sas_expander->phy);
2242	kfree(sas_expander);
2243}
2244
2245/**
2246 * mpi3mr_expander_remove - Remove expander object
2247 * @mrioc: Adapter instance reference
2248 * @sas_address: Remove expander sas_address
2249 * @hba_port: HBA port reference
2250 *
2251 * This function remove expander object, stored in
2252 * mrioc->sas_expander_list and removes it from the SAS TL by
2253 * calling mpi3mr_expander_node_remove().
2254 *
2255 * Return: None
2256 */
2257void mpi3mr_expander_remove(struct mpi3mr_ioc *mrioc, u64 sas_address,
2258	struct mpi3mr_hba_port *hba_port)
2259{
2260	struct mpi3mr_sas_node *sas_expander;
2261	unsigned long flags;
2262
2263	if (mrioc->reset_in_progress || mrioc->pci_err_recovery)
2264		return;
2265
2266	if (!hba_port)
2267		return;
2268
2269	spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2270	sas_expander = mpi3mr_expander_find_by_sas_address(mrioc, sas_address,
2271	    hba_port);
2272	spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2273	if (sas_expander)
2274		mpi3mr_expander_node_remove(mrioc, sas_expander);
2275
2276}
2277
2278/**
2279 * mpi3mr_get_sas_negotiated_logical_linkrate - get linkrate
2280 * @mrioc: Adapter instance reference
2281 * @tgtdev: Target device
2282 *
2283 * This function identifies whether the target device is
2284 * attached directly or through expander and issues sas phy
2285 * page0 or expander phy page1 and gets the link rate, if there
2286 * is any failure in reading the pages then this returns link
2287 * rate of 1.5.
2288 *
2289 * Return: logical link rate.
2290 */
2291static u8 mpi3mr_get_sas_negotiated_logical_linkrate(struct mpi3mr_ioc *mrioc,
2292	struct mpi3mr_tgt_dev *tgtdev)
2293{
2294	u8 link_rate = MPI3_SAS_NEG_LINK_RATE_1_5, phy_number;
2295	struct mpi3_sas_expander_page1 expander_pg1;
2296	struct mpi3_sas_phy_page0 phy_pg0;
2297	u32 phynum_handle;
2298	u16 ioc_status;
2299
2300	phy_number = tgtdev->dev_spec.sas_sata_inf.phy_id;
2301	if (!(tgtdev->devpg0_flag & MPI3_DEVICE0_FLAGS_ATT_METHOD_DIR_ATTACHED)) {
2302		phynum_handle = ((phy_number<<MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT)
2303				 | tgtdev->parent_handle);
2304		if (mpi3mr_cfg_get_sas_exp_pg1(mrioc, &ioc_status,
2305		    &expander_pg1, sizeof(expander_pg1),
2306		    MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM,
2307		    phynum_handle)) {
2308			ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2309			    __FILE__, __LINE__, __func__);
2310			goto out;
2311		}
2312		if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2313			ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2314			    __FILE__, __LINE__, __func__);
2315			goto out;
2316		}
2317		link_rate = (expander_pg1.negotiated_link_rate &
2318			     MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
2319			MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT;
2320		goto out;
2321	}
2322	if (mpi3mr_cfg_get_sas_phy_pg0(mrioc, &ioc_status, &phy_pg0,
2323	    sizeof(struct mpi3_sas_phy_page0),
2324	    MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, phy_number)) {
2325		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2326		    __FILE__, __LINE__, __func__);
2327		goto out;
2328	}
2329	if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2330		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2331		    __FILE__, __LINE__, __func__);
2332		goto out;
2333	}
2334	link_rate = (phy_pg0.negotiated_link_rate &
2335		     MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
2336		MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT;
2337out:
2338	return link_rate;
2339}
2340
2341/**
2342 * mpi3mr_report_tgtdev_to_sas_transport - expose dev to SAS TL
2343 * @mrioc: Adapter instance reference
2344 * @tgtdev: Target device
2345 *
2346 * This function exposes the target device after
2347 * preparing host_phy, setting up link rate etc.
2348 *
2349 * Return: 0 on success, non-zero for failure.
2350 */
2351int mpi3mr_report_tgtdev_to_sas_transport(struct mpi3mr_ioc *mrioc,
2352	struct mpi3mr_tgt_dev *tgtdev)
2353{
2354	int retval = 0;
2355	u8 link_rate, parent_phy_number;
2356	u64 sas_address_parent, sas_address;
2357	struct mpi3mr_hba_port *hba_port;
2358	u8 port_id;
2359
2360	if ((tgtdev->dev_type != MPI3_DEVICE_DEVFORM_SAS_SATA) ||
2361	    !mrioc->sas_transport_enabled)
2362		return -1;
2363
2364	sas_address = tgtdev->dev_spec.sas_sata_inf.sas_address;
2365	if (!mrioc->sas_hba.num_phys)
2366		mpi3mr_sas_host_add(mrioc);
2367	else
2368		mpi3mr_sas_host_refresh(mrioc);
2369
2370	if (mpi3mr_get_sas_address(mrioc, tgtdev->parent_handle,
2371	    &sas_address_parent) != 0) {
2372		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2373		    __FILE__, __LINE__, __func__);
2374		return -1;
2375	}
2376	tgtdev->dev_spec.sas_sata_inf.sas_address_parent = sas_address_parent;
2377
2378	parent_phy_number = tgtdev->dev_spec.sas_sata_inf.phy_id;
2379	port_id = tgtdev->io_unit_port;
2380
2381	hba_port = mpi3mr_get_hba_port_by_id(mrioc, port_id);
2382	if (!hba_port) {
2383		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2384		    __FILE__, __LINE__, __func__);
2385		return -1;
2386	}
2387	tgtdev->dev_spec.sas_sata_inf.hba_port = hba_port;
2388
2389	link_rate = mpi3mr_get_sas_negotiated_logical_linkrate(mrioc, tgtdev);
2390
2391	mpi3mr_update_links(mrioc, sas_address_parent, tgtdev->dev_handle,
2392	    parent_phy_number, link_rate, hba_port);
2393
2394	tgtdev->host_exposed = 1;
2395	if (!mpi3mr_sas_port_add(mrioc, tgtdev->dev_handle,
2396	    sas_address_parent, hba_port)) {
2397		retval = -1;
2398		} else if ((!tgtdev->starget) && (!mrioc->is_driver_loading)) {
2399			mpi3mr_sas_port_remove(mrioc, sas_address,
2400			    sas_address_parent, hba_port);
2401		retval = -1;
2402	}
2403	if (retval) {
2404		tgtdev->dev_spec.sas_sata_inf.hba_port = NULL;
2405		tgtdev->host_exposed = 0;
2406	}
2407	return retval;
2408}
2409
2410/**
2411 * mpi3mr_remove_tgtdev_from_sas_transport - remove from SAS TL
2412 * @mrioc: Adapter instance reference
2413 * @tgtdev: Target device
2414 *
2415 * This function removes the target device
2416 *
2417 * Return: None.
2418 */
2419void mpi3mr_remove_tgtdev_from_sas_transport(struct mpi3mr_ioc *mrioc,
2420	struct mpi3mr_tgt_dev *tgtdev)
2421{
2422	u64 sas_address_parent, sas_address;
2423	struct mpi3mr_hba_port *hba_port;
2424
2425	if ((tgtdev->dev_type != MPI3_DEVICE_DEVFORM_SAS_SATA) ||
2426	    !mrioc->sas_transport_enabled)
2427		return;
2428
2429	hba_port = tgtdev->dev_spec.sas_sata_inf.hba_port;
2430	sas_address = tgtdev->dev_spec.sas_sata_inf.sas_address;
2431	sas_address_parent = tgtdev->dev_spec.sas_sata_inf.sas_address_parent;
2432	mpi3mr_sas_port_remove(mrioc, sas_address, sas_address_parent,
2433	    hba_port);
2434	tgtdev->host_exposed = 0;
2435	tgtdev->dev_spec.sas_sata_inf.hba_port = NULL;
2436}
2437
2438/**
2439 * mpi3mr_get_port_id_by_sas_phy -  Get port ID of the given phy
2440 * @phy: SAS transport layer phy object
2441 *
2442 * Return: Port number for valid ID else 0xFFFF
2443 */
2444static inline u8 mpi3mr_get_port_id_by_sas_phy(struct sas_phy *phy)
2445{
2446	u8 port_id = 0xFF;
2447	struct mpi3mr_hba_port *hba_port = phy->hostdata;
2448
2449	if (hba_port)
2450		port_id = hba_port->port_id;
2451
2452	return port_id;
2453}
2454
2455/**
2456 * mpi3mr_get_port_id_by_rphy - Get Port number from SAS rphy
2457 *
2458 * @mrioc: Adapter instance reference
2459 * @rphy: SAS transport layer remote phy object
2460 *
2461 * Retrieves HBA port number in which the device pointed by the
2462 * rphy object is attached with.
2463 *
2464 * Return: Valid port number on success else OxFFFF.
2465 */
2466static u8 mpi3mr_get_port_id_by_rphy(struct mpi3mr_ioc *mrioc, struct sas_rphy *rphy)
2467{
2468	struct mpi3mr_sas_node *sas_expander;
2469	struct mpi3mr_tgt_dev *tgtdev;
2470	unsigned long flags;
2471	u8 port_id = 0xFF;
2472
2473	if (!rphy)
2474		return port_id;
2475
2476	if (rphy->identify.device_type == SAS_EDGE_EXPANDER_DEVICE ||
2477	    rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE) {
2478		spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2479		list_for_each_entry(sas_expander, &mrioc->sas_expander_list,
2480		    list) {
2481			if (sas_expander->rphy == rphy) {
2482				port_id = sas_expander->hba_port->port_id;
2483				break;
2484			}
2485		}
2486		spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2487	} else if (rphy->identify.device_type == SAS_END_DEVICE) {
2488		spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
2489
2490		tgtdev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc,
2491			    rphy->identify.sas_address, rphy);
2492		if (tgtdev && tgtdev->dev_spec.sas_sata_inf.hba_port) {
2493			port_id =
2494				tgtdev->dev_spec.sas_sata_inf.hba_port->port_id;
2495			mpi3mr_tgtdev_put(tgtdev);
2496		}
2497		spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
2498	}
2499	return port_id;
2500}
2501
2502static inline struct mpi3mr_ioc *phy_to_mrioc(struct sas_phy *phy)
2503{
2504	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
2505
2506	return shost_priv(shost);
2507}
2508
2509static inline struct mpi3mr_ioc *rphy_to_mrioc(struct sas_rphy *rphy)
2510{
2511	struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
2512
2513	return shost_priv(shost);
2514}
2515
2516/* report phy error log structure */
2517struct phy_error_log_request {
2518	u8 smp_frame_type; /* 0x40 */
2519	u8 function; /* 0x11 */
2520	u8 allocated_response_length;
2521	u8 request_length; /* 02 */
2522	u8 reserved_1[5];
2523	u8 phy_identifier;
2524	u8 reserved_2[2];
2525};
2526
2527/* report phy error log reply structure */
2528struct phy_error_log_reply {
2529	u8 smp_frame_type; /* 0x41 */
2530	u8 function; /* 0x11 */
2531	u8 function_result;
2532	u8 response_length;
2533	__be16 expander_change_count;
2534	u8 reserved_1[3];
2535	u8 phy_identifier;
2536	u8 reserved_2[2];
2537	__be32 invalid_dword;
2538	__be32 running_disparity_error;
2539	__be32 loss_of_dword_sync;
2540	__be32 phy_reset_problem;
2541};
2542
2543
2544/**
2545 * mpi3mr_get_expander_phy_error_log - return expander counters:
2546 * @mrioc: Adapter instance reference
2547 * @phy: The SAS transport layer phy object
2548 *
2549 * Return: 0 for success, non-zero for failure.
2550 *
2551 */
2552static int mpi3mr_get_expander_phy_error_log(struct mpi3mr_ioc *mrioc,
2553	struct sas_phy *phy)
2554{
2555	struct mpi3_smp_passthrough_request mpi_request;
2556	struct mpi3_smp_passthrough_reply mpi_reply;
2557	struct phy_error_log_request *phy_error_log_request;
2558	struct phy_error_log_reply *phy_error_log_reply;
2559	int rc;
2560	void *psge;
2561	void *data_out = NULL;
2562	dma_addr_t data_out_dma, data_in_dma;
2563	u32 data_out_sz, data_in_sz, sz;
2564	u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST;
2565	u16 request_sz = sizeof(struct mpi3_smp_passthrough_request);
2566	u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply);
2567	u16 ioc_status;
2568
2569	if (mrioc->reset_in_progress) {
2570		ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
2571		return -EFAULT;
2572	}
2573
2574	if (mrioc->pci_err_recovery) {
2575		ioc_err(mrioc, "%s: pci error recovery in progress!\n", __func__);
2576		return -EFAULT;
2577	}
2578
2579	data_out_sz = sizeof(struct phy_error_log_request);
2580	data_in_sz = sizeof(struct phy_error_log_reply);
2581	sz = data_out_sz + data_in_sz;
2582	data_out = dma_alloc_coherent(&mrioc->pdev->dev, sz, &data_out_dma,
2583	    GFP_KERNEL);
2584	if (!data_out) {
2585		rc = -ENOMEM;
2586		goto out;
2587	}
2588
2589	data_in_dma = data_out_dma + data_out_sz;
2590	phy_error_log_reply = data_out + data_out_sz;
2591
2592	rc = -EINVAL;
2593	memset(data_out, 0, sz);
2594	phy_error_log_request = data_out;
2595	phy_error_log_request->smp_frame_type = 0x40;
2596	phy_error_log_request->function = 0x11;
2597	phy_error_log_request->request_length = 2;
2598	phy_error_log_request->allocated_response_length = 0;
2599	phy_error_log_request->phy_identifier = phy->number;
2600
2601	memset(&mpi_request, 0, request_sz);
2602	memset(&mpi_reply, 0, reply_sz);
2603	mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
2604	mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH;
2605	mpi_request.io_unit_port = (u8) mpi3mr_get_port_id_by_sas_phy(phy);
2606	mpi_request.sas_address = cpu_to_le64(phy->identify.sas_address);
2607
2608	psge = &mpi_request.request_sge;
2609	mpi3mr_add_sg_single(psge, sgl_flags, data_out_sz, data_out_dma);
2610
2611	psge = &mpi_request.response_sge;
2612	mpi3mr_add_sg_single(psge, sgl_flags, data_in_sz, data_in_dma);
2613
2614	dprint_transport_info(mrioc,
2615	    "sending phy error log SMP request to sas_address(0x%016llx), phy_id(%d)\n",
2616	    (unsigned long long)phy->identify.sas_address, phy->number);
2617
2618	if (mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
2619	    &mpi_reply, reply_sz, MPI3MR_INTADMCMD_TIMEOUT, &ioc_status))
2620		goto out;
2621
2622	dprint_transport_info(mrioc,
2623	    "phy error log SMP request completed with ioc_status(0x%04x)\n",
2624	    ioc_status);
2625
2626	if (ioc_status == MPI3_IOCSTATUS_SUCCESS) {
2627		dprint_transport_info(mrioc,
2628		    "phy error log - reply data transfer size(%d)\n",
2629		    le16_to_cpu(mpi_reply.response_data_length));
2630
2631		if (le16_to_cpu(mpi_reply.response_data_length) !=
2632		    sizeof(struct phy_error_log_reply))
2633			goto out;
2634
2635		dprint_transport_info(mrioc,
2636		    "phy error log - function_result(%d)\n",
2637		    phy_error_log_reply->function_result);
2638
2639		phy->invalid_dword_count =
2640		    be32_to_cpu(phy_error_log_reply->invalid_dword);
2641		phy->running_disparity_error_count =
2642		    be32_to_cpu(phy_error_log_reply->running_disparity_error);
2643		phy->loss_of_dword_sync_count =
2644		    be32_to_cpu(phy_error_log_reply->loss_of_dword_sync);
2645		phy->phy_reset_problem_count =
2646		    be32_to_cpu(phy_error_log_reply->phy_reset_problem);
2647		rc = 0;
2648	}
2649
2650out:
2651	if (data_out)
2652		dma_free_coherent(&mrioc->pdev->dev, sz, data_out,
2653		    data_out_dma);
2654
2655	return rc;
2656}
2657
2658/**
2659 * mpi3mr_transport_get_linkerrors - return phy error counters
2660 * @phy: The SAS transport layer phy object
2661 *
2662 * This function retrieves the phy error log information of the
2663 * HBA or expander for which the phy belongs to
2664 *
2665 * Return: 0 for success, non-zero for failure.
2666 */
2667static int mpi3mr_transport_get_linkerrors(struct sas_phy *phy)
2668{
2669	struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy);
2670	struct mpi3_sas_phy_page1 phy_pg1;
2671	int rc = 0;
2672	u16 ioc_status;
2673
2674	rc = mpi3mr_parent_present(mrioc, phy);
2675	if (rc)
2676		return rc;
2677
2678	if (phy->identify.sas_address != mrioc->sas_hba.sas_address)
2679		return mpi3mr_get_expander_phy_error_log(mrioc, phy);
2680
2681	memset(&phy_pg1, 0, sizeof(struct mpi3_sas_phy_page1));
2682	/* get hba phy error logs */
2683	if ((mpi3mr_cfg_get_sas_phy_pg1(mrioc, &ioc_status, &phy_pg1,
2684	    sizeof(struct mpi3_sas_phy_page1),
2685	    MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, phy->number))) {
2686		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2687		    __FILE__, __LINE__, __func__);
2688		return -ENXIO;
2689	}
2690
2691	if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2692		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2693		    __FILE__, __LINE__, __func__);
2694		return -ENXIO;
2695	}
2696	phy->invalid_dword_count = le32_to_cpu(phy_pg1.invalid_dword_count);
2697	phy->running_disparity_error_count =
2698		le32_to_cpu(phy_pg1.running_disparity_error_count);
2699	phy->loss_of_dword_sync_count =
2700		le32_to_cpu(phy_pg1.loss_dword_synch_count);
2701	phy->phy_reset_problem_count =
2702		le32_to_cpu(phy_pg1.phy_reset_problem_count);
2703	return 0;
2704}
2705
2706/**
2707 * mpi3mr_transport_get_enclosure_identifier - Get Enclosure ID
2708 * @rphy: The SAS transport layer remote phy object
2709 * @identifier: Enclosure identifier to be returned
2710 *
2711 * Returns the enclosure id for the device pointed by the remote
2712 * phy object.
2713 *
2714 * Return: 0 on success or -ENXIO
2715 */
2716static int
2717mpi3mr_transport_get_enclosure_identifier(struct sas_rphy *rphy,
2718	u64 *identifier)
2719{
2720	struct mpi3mr_ioc *mrioc = rphy_to_mrioc(rphy);
2721	struct mpi3mr_tgt_dev *tgtdev = NULL;
2722	unsigned long flags;
2723	int rc;
2724
2725	spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
2726	tgtdev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc,
2727	    rphy->identify.sas_address, rphy);
2728	if (tgtdev) {
2729		*identifier =
2730			tgtdev->enclosure_logical_id;
2731		rc = 0;
2732		mpi3mr_tgtdev_put(tgtdev);
2733	} else {
2734		*identifier = 0;
2735		rc = -ENXIO;
2736	}
2737	spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
2738
2739	return rc;
2740}
2741
2742/**
2743 * mpi3mr_transport_get_bay_identifier - Get bay ID
2744 * @rphy: The SAS transport layer remote phy object
2745 *
2746 * Returns the slot id for the device pointed by the remote phy
2747 * object.
2748 *
2749 * Return: Valid slot ID on success or -ENXIO
2750 */
2751static int
2752mpi3mr_transport_get_bay_identifier(struct sas_rphy *rphy)
2753{
2754	struct mpi3mr_ioc *mrioc = rphy_to_mrioc(rphy);
2755	struct mpi3mr_tgt_dev *tgtdev = NULL;
2756	unsigned long flags;
2757	int rc;
2758
2759	spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
2760	tgtdev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc,
2761	    rphy->identify.sas_address, rphy);
2762	if (tgtdev) {
2763		rc = tgtdev->slot;
2764		mpi3mr_tgtdev_put(tgtdev);
2765	} else
2766		rc = -ENXIO;
2767	spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
2768
2769	return rc;
2770}
2771
2772/* phy control request structure */
2773struct phy_control_request {
2774	u8 smp_frame_type; /* 0x40 */
2775	u8 function; /* 0x91 */
2776	u8 allocated_response_length;
2777	u8 request_length; /* 0x09 */
2778	u16 expander_change_count;
2779	u8 reserved_1[3];
2780	u8 phy_identifier;
2781	u8 phy_operation;
2782	u8 reserved_2[13];
2783	u64 attached_device_name;
2784	u8 programmed_min_physical_link_rate;
2785	u8 programmed_max_physical_link_rate;
2786	u8 reserved_3[6];
2787};
2788
2789/* phy control reply structure */
2790struct phy_control_reply {
2791	u8 smp_frame_type; /* 0x41 */
2792	u8 function; /* 0x11 */
2793	u8 function_result;
2794	u8 response_length;
2795};
2796
2797#define SMP_PHY_CONTROL_LINK_RESET	(0x01)
2798#define SMP_PHY_CONTROL_HARD_RESET	(0x02)
2799#define SMP_PHY_CONTROL_DISABLE		(0x03)
2800
2801/**
2802 * mpi3mr_expander_phy_control - expander phy control
2803 * @mrioc: Adapter instance reference
2804 * @phy: The SAS transport layer phy object
2805 * @phy_operation: The phy operation to be executed
2806 *
2807 * Issues SMP passthru phy control request to execute a specific
2808 * phy operation for a given expander device.
2809 *
2810 * Return: 0 for success, non-zero for failure.
2811 */
2812static int
2813mpi3mr_expander_phy_control(struct mpi3mr_ioc *mrioc,
2814	struct sas_phy *phy, u8 phy_operation)
2815{
2816	struct mpi3_smp_passthrough_request mpi_request;
2817	struct mpi3_smp_passthrough_reply mpi_reply;
2818	struct phy_control_request *phy_control_request;
2819	struct phy_control_reply *phy_control_reply;
2820	int rc;
2821	void *psge;
2822	void *data_out = NULL;
2823	dma_addr_t data_out_dma;
2824	dma_addr_t data_in_dma;
2825	size_t data_in_sz;
2826	size_t data_out_sz;
2827	u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST;
2828	u16 request_sz = sizeof(struct mpi3_smp_passthrough_request);
2829	u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply);
2830	u16 ioc_status;
2831	u16 sz;
2832
2833	if (mrioc->reset_in_progress) {
2834		ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
2835		return -EFAULT;
2836	}
2837
2838	if (mrioc->pci_err_recovery) {
2839		ioc_err(mrioc, "%s: pci error recovery in progress!\n",
2840		    __func__);
2841		return -EFAULT;
2842	}
2843
2844	data_out_sz = sizeof(struct phy_control_request);
2845	data_in_sz = sizeof(struct phy_control_reply);
2846	sz = data_out_sz + data_in_sz;
2847	data_out = dma_alloc_coherent(&mrioc->pdev->dev, sz, &data_out_dma,
2848	    GFP_KERNEL);
2849	if (!data_out) {
2850		rc = -ENOMEM;
2851		goto out;
2852	}
2853
2854	data_in_dma = data_out_dma + data_out_sz;
2855	phy_control_reply = data_out + data_out_sz;
2856
2857	rc = -EINVAL;
2858	memset(data_out, 0, sz);
2859
2860	phy_control_request = data_out;
2861	phy_control_request->smp_frame_type = 0x40;
2862	phy_control_request->function = 0x91;
2863	phy_control_request->request_length = 9;
2864	phy_control_request->allocated_response_length = 0;
2865	phy_control_request->phy_identifier = phy->number;
2866	phy_control_request->phy_operation = phy_operation;
2867	phy_control_request->programmed_min_physical_link_rate =
2868	    phy->minimum_linkrate << 4;
2869	phy_control_request->programmed_max_physical_link_rate =
2870	    phy->maximum_linkrate << 4;
2871
2872	memset(&mpi_request, 0, request_sz);
2873	memset(&mpi_reply, 0, reply_sz);
2874	mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
2875	mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH;
2876	mpi_request.io_unit_port = (u8) mpi3mr_get_port_id_by_sas_phy(phy);
2877	mpi_request.sas_address = cpu_to_le64(phy->identify.sas_address);
2878
2879	psge = &mpi_request.request_sge;
2880	mpi3mr_add_sg_single(psge, sgl_flags, data_out_sz, data_out_dma);
2881
2882	psge = &mpi_request.response_sge;
2883	mpi3mr_add_sg_single(psge, sgl_flags, data_in_sz, data_in_dma);
2884
2885	dprint_transport_info(mrioc,
2886	    "sending phy control SMP request to sas_address(0x%016llx), phy_id(%d) opcode(%d)\n",
2887	    (unsigned long long)phy->identify.sas_address, phy->number,
2888	    phy_operation);
2889
2890	if (mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
2891	    &mpi_reply, reply_sz, MPI3MR_INTADMCMD_TIMEOUT, &ioc_status))
2892		goto out;
2893
2894	dprint_transport_info(mrioc,
2895	    "phy control SMP request completed with ioc_status(0x%04x)\n",
2896	    ioc_status);
2897
2898	if (ioc_status == MPI3_IOCSTATUS_SUCCESS) {
2899		dprint_transport_info(mrioc,
2900		    "phy control - reply data transfer size(%d)\n",
2901		    le16_to_cpu(mpi_reply.response_data_length));
2902
2903		if (le16_to_cpu(mpi_reply.response_data_length) !=
2904		    sizeof(struct phy_control_reply))
2905			goto out;
2906		dprint_transport_info(mrioc,
2907		    "phy control - function_result(%d)\n",
2908		    phy_control_reply->function_result);
2909		rc = 0;
2910	}
2911 out:
2912	if (data_out)
2913		dma_free_coherent(&mrioc->pdev->dev, sz, data_out,
2914		    data_out_dma);
2915
2916	return rc;
2917}
2918
2919/**
2920 * mpi3mr_transport_phy_reset - Reset a given phy
2921 * @phy: The SAS transport layer phy object
2922 * @hard_reset: Flag to indicate the type of reset
2923 *
2924 * Return: 0 for success, non-zero for failure.
2925 */
2926static int
2927mpi3mr_transport_phy_reset(struct sas_phy *phy, int hard_reset)
2928{
2929	struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy);
2930	struct mpi3_iounit_control_request mpi_request;
2931	struct mpi3_iounit_control_reply mpi_reply;
2932	u16 request_sz = sizeof(struct mpi3_iounit_control_request);
2933	u16 reply_sz = sizeof(struct mpi3_iounit_control_reply);
2934	int rc = 0;
2935	u16 ioc_status;
2936
2937	rc = mpi3mr_parent_present(mrioc, phy);
2938	if (rc)
2939		return rc;
2940
2941	/* handle expander phys */
2942	if (phy->identify.sas_address != mrioc->sas_hba.sas_address)
2943		return mpi3mr_expander_phy_control(mrioc, phy,
2944		    (hard_reset == 1) ? SMP_PHY_CONTROL_HARD_RESET :
2945		    SMP_PHY_CONTROL_LINK_RESET);
2946
2947	/* handle hba phys */
2948	memset(&mpi_request, 0, request_sz);
2949	mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
2950	mpi_request.function = MPI3_FUNCTION_IO_UNIT_CONTROL;
2951	mpi_request.operation = MPI3_CTRL_OP_SAS_PHY_CONTROL;
2952	mpi_request.param8[MPI3_CTRL_OP_SAS_PHY_CONTROL_PARAM8_ACTION_INDEX] =
2953		(hard_reset ? MPI3_CTRL_ACTION_HARD_RESET :
2954		 MPI3_CTRL_ACTION_LINK_RESET);
2955	mpi_request.param8[MPI3_CTRL_OP_SAS_PHY_CONTROL_PARAM8_PHY_INDEX] =
2956		phy->number;
2957
2958	dprint_transport_info(mrioc,
2959	    "sending phy reset request to sas_address(0x%016llx), phy_id(%d) hard_reset(%d)\n",
2960	    (unsigned long long)phy->identify.sas_address, phy->number,
2961	    hard_reset);
2962
2963	if (mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
2964	    &mpi_reply, reply_sz, MPI3MR_INTADMCMD_TIMEOUT, &ioc_status)) {
2965		rc = -EAGAIN;
2966		goto out;
2967	}
2968
2969	dprint_transport_info(mrioc,
2970	    "phy reset request completed with ioc_status(0x%04x)\n",
2971	    ioc_status);
2972out:
2973	return rc;
2974}
2975
2976/**
2977 * mpi3mr_transport_phy_enable - enable/disable phys
2978 * @phy: The SAS transport layer phy object
2979 * @enable: flag to enable/disable, enable phy when true
2980 *
2981 * This function enables/disables a given by executing required
2982 * configuration page changes or expander phy control command
2983 *
2984 * Return: 0 for success, non-zero for failure.
2985 */
2986static int
2987mpi3mr_transport_phy_enable(struct sas_phy *phy, int enable)
2988{
2989	struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy);
2990	struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL;
2991	struct mpi3_sas_io_unit_page1 *sas_io_unit_pg1 = NULL;
2992	u16 sz;
2993	int rc = 0;
2994	int i, discovery_active;
2995
2996	rc = mpi3mr_parent_present(mrioc, phy);
2997	if (rc)
2998		return rc;
2999
3000	/* handle expander phys */
3001	if (phy->identify.sas_address != mrioc->sas_hba.sas_address)
3002		return mpi3mr_expander_phy_control(mrioc, phy,
3003		    (enable == 1) ? SMP_PHY_CONTROL_LINK_RESET :
3004		    SMP_PHY_CONTROL_DISABLE);
3005
3006	/* handle hba phys */
3007	sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) +
3008		(mrioc->sas_hba.num_phys *
3009		 sizeof(struct mpi3_sas_io_unit0_phy_data));
3010	sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
3011	if (!sas_io_unit_pg0) {
3012		rc = -ENOMEM;
3013		goto out;
3014	}
3015	if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
3016		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
3017		    __FILE__, __LINE__, __func__);
3018		rc = -ENXIO;
3019		goto out;
3020	}
3021
3022	/* unable to enable/disable phys when discovery is active */
3023	for (i = 0, discovery_active = 0; i < mrioc->sas_hba.num_phys ; i++) {
3024		if (sas_io_unit_pg0->phy_data[i].port_flags &
3025		    MPI3_SASIOUNIT0_PORTFLAGS_DISC_IN_PROGRESS) {
3026			ioc_err(mrioc,
3027			    "discovery is active on port = %d, phy = %d\n"
3028			    "\tunable to enable/disable phys, try again later!\n",
3029			    sas_io_unit_pg0->phy_data[i].io_unit_port, i);
3030			discovery_active = 1;
3031		}
3032	}
3033
3034	if (discovery_active) {
3035		rc = -EAGAIN;
3036		goto out;
3037	}
3038
3039	if ((sas_io_unit_pg0->phy_data[phy->number].phy_flags &
3040	     (MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY |
3041	      MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY))) {
3042		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
3043		    __FILE__, __LINE__, __func__);
3044		rc = -ENXIO;
3045		goto out;
3046	}
3047
3048	/* read sas_iounit page 1 */
3049	sz = offsetof(struct mpi3_sas_io_unit_page1, phy_data) +
3050		(mrioc->sas_hba.num_phys *
3051		 sizeof(struct mpi3_sas_io_unit1_phy_data));
3052	sas_io_unit_pg1 = kzalloc(sz, GFP_KERNEL);
3053	if (!sas_io_unit_pg1) {
3054		rc = -ENOMEM;
3055		goto out;
3056	}
3057
3058	if (mpi3mr_cfg_get_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz)) {
3059		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
3060		    __FILE__, __LINE__, __func__);
3061		rc = -ENXIO;
3062		goto out;
3063	}
3064
3065	if (enable)
3066		sas_io_unit_pg1->phy_data[phy->number].phy_flags
3067		    &= ~MPI3_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
3068	else
3069		sas_io_unit_pg1->phy_data[phy->number].phy_flags
3070		    |= MPI3_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
3071
3072	mpi3mr_cfg_set_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz);
3073
3074	/* link reset */
3075	if (enable)
3076		mpi3mr_transport_phy_reset(phy, 0);
3077
3078 out:
3079	kfree(sas_io_unit_pg1);
3080	kfree(sas_io_unit_pg0);
3081	return rc;
3082}
3083
3084/**
3085 * mpi3mr_transport_phy_speed - set phy min/max speed
3086 * @phy: The SAS transport later phy object
3087 * @rates: Rates defined as in sas_phy_linkrates
3088 *
3089 * This function sets the link rates given in the rates
3090 * argument to the given phy by executing required configuration
3091 * page changes or expander phy control command
3092 *
3093 * Return: 0 for success, non-zero for failure.
3094 */
3095static int
3096mpi3mr_transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
3097{
3098	struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy);
3099	struct mpi3_sas_io_unit_page1 *sas_io_unit_pg1 = NULL;
3100	struct mpi3_sas_phy_page0 phy_pg0;
3101	u16 sz, ioc_status;
3102	int rc = 0;
3103
3104	rc = mpi3mr_parent_present(mrioc, phy);
3105	if (rc)
3106		return rc;
3107
3108	if (!rates->minimum_linkrate)
3109		rates->minimum_linkrate = phy->minimum_linkrate;
3110	else if (rates->minimum_linkrate < phy->minimum_linkrate_hw)
3111		rates->minimum_linkrate = phy->minimum_linkrate_hw;
3112
3113	if (!rates->maximum_linkrate)
3114		rates->maximum_linkrate = phy->maximum_linkrate;
3115	else if (rates->maximum_linkrate > phy->maximum_linkrate_hw)
3116		rates->maximum_linkrate = phy->maximum_linkrate_hw;
3117
3118	/* handle expander phys */
3119	if (phy->identify.sas_address != mrioc->sas_hba.sas_address) {
3120		phy->minimum_linkrate = rates->minimum_linkrate;
3121		phy->maximum_linkrate = rates->maximum_linkrate;
3122		return mpi3mr_expander_phy_control(mrioc, phy,
3123		    SMP_PHY_CONTROL_LINK_RESET);
3124	}
3125
3126	/* handle hba phys */
3127	sz = offsetof(struct mpi3_sas_io_unit_page1, phy_data) +
3128		(mrioc->sas_hba.num_phys *
3129		 sizeof(struct mpi3_sas_io_unit1_phy_data));
3130	sas_io_unit_pg1 = kzalloc(sz, GFP_KERNEL);
3131	if (!sas_io_unit_pg1) {
3132		rc = -ENOMEM;
3133		goto out;
3134	}
3135
3136	if (mpi3mr_cfg_get_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz)) {
3137		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
3138		    __FILE__, __LINE__, __func__);
3139		rc = -ENXIO;
3140		goto out;
3141	}
3142
3143	sas_io_unit_pg1->phy_data[phy->number].max_min_link_rate =
3144		(rates->minimum_linkrate + (rates->maximum_linkrate << 4));
3145
3146	if (mpi3mr_cfg_set_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz)) {
3147		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
3148		    __FILE__, __LINE__, __func__);
3149		rc = -ENXIO;
3150		goto out;
3151	}
3152
3153	/* link reset */
3154	mpi3mr_transport_phy_reset(phy, 0);
3155
3156	/* read phy page 0, then update the rates in the sas transport phy */
3157	if (!mpi3mr_cfg_get_sas_phy_pg0(mrioc, &ioc_status, &phy_pg0,
3158	    sizeof(struct mpi3_sas_phy_page0),
3159	    MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, phy->number) &&
3160	    (ioc_status == MPI3_IOCSTATUS_SUCCESS)) {
3161		phy->minimum_linkrate = mpi3mr_convert_phy_link_rate(
3162		    phy_pg0.programmed_link_rate &
3163		    MPI3_SAS_PRATE_MIN_RATE_MASK);
3164		phy->maximum_linkrate = mpi3mr_convert_phy_link_rate(
3165		    phy_pg0.programmed_link_rate >> 4);
3166		phy->negotiated_linkrate =
3167			mpi3mr_convert_phy_link_rate(
3168			    (phy_pg0.negotiated_link_rate &
3169			    MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK)
3170			    >> MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT);
3171	}
3172
3173out:
3174	kfree(sas_io_unit_pg1);
3175	return rc;
3176}
3177
3178/**
3179 * mpi3mr_map_smp_buffer - map BSG dma buffer
3180 * @dev: Generic device reference
3181 * @buf: BSG buffer pointer
3182 * @dma_addr: Physical address holder
3183 * @dma_len: Mapped DMA buffer length.
3184 * @p: Virtual address holder
3185 *
3186 * This function maps the DMAable buffer
3187 *
3188 * Return: 0 on success, non-zero on failure
3189 */
3190static int
3191mpi3mr_map_smp_buffer(struct device *dev, struct bsg_buffer *buf,
3192		dma_addr_t *dma_addr, size_t *dma_len, void **p)
3193{
3194	/* Check if the request is split across multiple segments */
3195	if (buf->sg_cnt > 1) {
3196		*p = dma_alloc_coherent(dev, buf->payload_len, dma_addr,
3197				GFP_KERNEL);
3198		if (!*p)
3199			return -ENOMEM;
3200		*dma_len = buf->payload_len;
3201	} else {
3202		if (!dma_map_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL))
3203			return -ENOMEM;
3204		*dma_addr = sg_dma_address(buf->sg_list);
3205		*dma_len = sg_dma_len(buf->sg_list);
3206		*p = NULL;
3207	}
3208
3209	return 0;
3210}
3211
3212/**
3213 * mpi3mr_unmap_smp_buffer - unmap BSG dma buffer
3214 * @dev: Generic device reference
3215 * @buf: BSG buffer pointer
3216 * @dma_addr: Physical address to be unmapped
3217 * @p: Virtual address
3218 *
3219 * This function unmaps the DMAable buffer
3220 */
3221static void
3222mpi3mr_unmap_smp_buffer(struct device *dev, struct bsg_buffer *buf,
3223		dma_addr_t dma_addr, void *p)
3224{
3225	if (p)
3226		dma_free_coherent(dev, buf->payload_len, p, dma_addr);
3227	else
3228		dma_unmap_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL);
3229}
3230
3231/**
3232 * mpi3mr_transport_smp_handler - handler for smp passthru
3233 * @job: BSG job reference
3234 * @shost: SCSI host object reference
3235 * @rphy: SAS transport rphy object pointing the expander
3236 *
3237 * This is used primarily by smp utils for sending the SMP
3238 * commands to the expanders attached to the controller
3239 */
3240static void
3241mpi3mr_transport_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
3242	struct sas_rphy *rphy)
3243{
3244	struct mpi3mr_ioc *mrioc = shost_priv(shost);
3245	struct mpi3_smp_passthrough_request mpi_request;
3246	struct mpi3_smp_passthrough_reply mpi_reply;
3247	int rc;
3248	void *psge;
3249	dma_addr_t dma_addr_in;
3250	dma_addr_t dma_addr_out;
3251	void *addr_in = NULL;
3252	void *addr_out = NULL;
3253	size_t dma_len_in;
3254	size_t dma_len_out;
3255	unsigned int reslen = 0;
3256	u16 request_sz = sizeof(struct mpi3_smp_passthrough_request);
3257	u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply);
3258	u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST;
3259	u16 ioc_status;
3260
3261	if (mrioc->reset_in_progress) {
3262		ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
3263		rc = -EFAULT;
3264		goto out;
3265	}
3266
3267	if (mrioc->pci_err_recovery) {
3268		ioc_err(mrioc, "%s: pci error recovery in progress!\n", __func__);
3269		rc = -EFAULT;
3270		goto out;
3271	}
3272
3273	rc = mpi3mr_map_smp_buffer(&mrioc->pdev->dev, &job->request_payload,
3274	    &dma_addr_out, &dma_len_out, &addr_out);
3275	if (rc)
3276		goto out;
3277
3278	if (addr_out)
3279		sg_copy_to_buffer(job->request_payload.sg_list,
3280		    job->request_payload.sg_cnt, addr_out,
3281		    job->request_payload.payload_len);
3282
3283	rc = mpi3mr_map_smp_buffer(&mrioc->pdev->dev, &job->reply_payload,
3284			&dma_addr_in, &dma_len_in, &addr_in);
3285	if (rc)
3286		goto unmap_out;
3287
3288	memset(&mpi_request, 0, request_sz);
3289	memset(&mpi_reply, 0, reply_sz);
3290	mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
3291	mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH;
3292	mpi_request.io_unit_port = (u8) mpi3mr_get_port_id_by_rphy(mrioc, rphy);
3293	mpi_request.sas_address = ((rphy) ?
3294	    cpu_to_le64(rphy->identify.sas_address) :
3295	    cpu_to_le64(mrioc->sas_hba.sas_address));
3296	psge = &mpi_request.request_sge;
3297	mpi3mr_add_sg_single(psge, sgl_flags, dma_len_out - 4, dma_addr_out);
3298
3299	psge = &mpi_request.response_sge;
3300	mpi3mr_add_sg_single(psge, sgl_flags, dma_len_in - 4, dma_addr_in);
3301
3302	dprint_transport_info(mrioc, "sending SMP request\n");
3303
3304	rc = mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
3305				       &mpi_reply, reply_sz,
3306				       MPI3MR_INTADMCMD_TIMEOUT, &ioc_status);
3307	if (rc)
3308		goto unmap_in;
3309
3310	dprint_transport_info(mrioc,
3311	    "SMP request completed with ioc_status(0x%04x)\n", ioc_status);
3312
3313	dprint_transport_info(mrioc,
3314		    "SMP request - reply data transfer size(%d)\n",
3315		    le16_to_cpu(mpi_reply.response_data_length));
3316
3317	memcpy(job->reply, &mpi_reply, reply_sz);
3318	job->reply_len = reply_sz;
3319	reslen = le16_to_cpu(mpi_reply.response_data_length);
3320
3321	if (addr_in)
3322		sg_copy_from_buffer(job->reply_payload.sg_list,
3323				job->reply_payload.sg_cnt, addr_in,
3324				job->reply_payload.payload_len);
3325
3326	rc = 0;
3327unmap_in:
3328	mpi3mr_unmap_smp_buffer(&mrioc->pdev->dev, &job->reply_payload,
3329			dma_addr_in, addr_in);
3330unmap_out:
3331	mpi3mr_unmap_smp_buffer(&mrioc->pdev->dev, &job->request_payload,
3332			dma_addr_out, addr_out);
3333out:
3334	bsg_job_done(job, rc, reslen);
3335}
3336
3337struct sas_function_template mpi3mr_transport_functions = {
3338	.get_linkerrors		= mpi3mr_transport_get_linkerrors,
3339	.get_enclosure_identifier = mpi3mr_transport_get_enclosure_identifier,
3340	.get_bay_identifier	= mpi3mr_transport_get_bay_identifier,
3341	.phy_reset		= mpi3mr_transport_phy_reset,
3342	.phy_enable		= mpi3mr_transport_phy_enable,
3343	.set_phy_speed		= mpi3mr_transport_phy_speed,
3344	.smp_handler		= mpi3mr_transport_smp_handler,
3345};
3346
3347struct scsi_transport_template *mpi3mr_transport_template;