Linux Audio

Check our new training course

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