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