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