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