xref: /linux/drivers/scsi/leapraid/leapraid_transport.c (revision 35748ddd3b2c91555bd86b8cf88edc90e7317e57)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2026 LeapIO Tech Inc.
4  *
5  * LeapRAID storage and RAID controller driver.
6  */
7 #include <scsi/scsi_host.h>
8 
9 #include "leapraid_func.h"
10 
11 static struct leapraid_topo_node *leapraid_transport_topo_node_by_sas_addr(
12 		struct leapraid_adapter *adapter,
13 		u64 sas_addr,
14 		struct leapraid_card_port *card_port)
15 {
16 	if (adapter->dev_topo.card.sas_address == sas_addr)
17 		return &adapter->dev_topo.card;
18 
19 	return leapraid_exp_find_by_sas_address(adapter, sas_addr, card_port);
20 }
21 
22 static u8 leapraid_get_port_id_by_expander(struct leapraid_adapter *adapter,
23 					   struct sas_rphy *rphy)
24 {
25 	struct leapraid_topo_node *topo_node_exp;
26 	unsigned long flags;
27 	u8 port_id = 0xFF;
28 
29 	spin_lock_irqsave(&adapter->dev_topo.topo_node_lock, flags);
30 	list_for_each_entry(topo_node_exp, &adapter->dev_topo.exp_list, list) {
31 		if (topo_node_exp->rphy == rphy) {
32 			port_id = topo_node_exp->card_port->port_id;
33 			break;
34 		}
35 	}
36 	spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock, flags);
37 
38 	return port_id;
39 }
40 
41 static u8 leapraid_get_port_id_by_end_dev(struct leapraid_adapter *adapter,
42 					  struct sas_rphy *rphy)
43 {
44 	struct leapraid_sas_dev *sas_dev;
45 	unsigned long flags;
46 	u8 port_id = 0xFF;
47 
48 	spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
49 	sas_dev = leapraid_hold_lock_get_sas_dev_by_addr_and_rphy(
50 			adapter,
51 			rphy->identify.sas_address,
52 			rphy);
53 	if (sas_dev) {
54 		port_id = sas_dev->card_port->port_id;
55 		leapraid_sdev_put(sas_dev);
56 	}
57 	spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
58 
59 	return port_id;
60 }
61 
62 static u8 leapraid_transport_get_port_id_by_rphy(
63 		struct leapraid_adapter *adapter,
64 		struct sas_rphy *rphy)
65 {
66 	if (!rphy)
67 		return 0xFF;
68 
69 	switch (rphy->identify.device_type) {
70 	case SAS_EDGE_EXPANDER_DEVICE:
71 	case SAS_FANOUT_EXPANDER_DEVICE:
72 		return leapraid_get_port_id_by_expander(adapter, rphy);
73 	case SAS_END_DEVICE:
74 		return leapraid_get_port_id_by_end_dev(adapter, rphy);
75 	default:
76 		return 0xFF;
77 	}
78 }
79 
80 static enum sas_linkrate leapraid_transport_convert_phy_link_rate(u8 link_rate)
81 {
82 	unsigned int i;
83 
84 	#define SAS_RATE_12G SAS_LINK_RATE_12_0_GBPS
85 
86 	const struct linkrate_map {
87 		u8 in;
88 		enum sas_linkrate out;
89 	} linkrate_table[] = {
90 		{
91 			LEAPRAID_SAS_NEG_LINK_RATE_1_5,
92 			SAS_LINK_RATE_1_5_GBPS
93 		},
94 		{
95 			LEAPRAID_SAS_NEG_LINK_RATE_3_0,
96 			SAS_LINK_RATE_3_0_GBPS
97 		},
98 		{
99 			LEAPRAID_SAS_NEG_LINK_RATE_6_0,
100 			SAS_LINK_RATE_6_0_GBPS
101 		},
102 		{
103 			LEAPRAID_SAS_NEG_LINK_RATE_12_0,
104 			SAS_RATE_12G
105 		},
106 		{
107 			LEAPRAID_SAS_NEG_LINK_RATE_PHY_DISABLED,
108 			SAS_PHY_DISABLED
109 		},
110 		{
111 			LEAPRAID_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED,
112 			SAS_LINK_RATE_FAILED
113 		},
114 		{
115 			LEAPRAID_SAS_NEG_LINK_RATE_PORT_SELECTOR,
116 			SAS_SATA_PORT_SELECTOR
117 		},
118 		{
119 			LEAPRAID_SAS_NEG_LINK_RATE_SMP_RESETTING,
120 			SAS_LINK_RATE_UNKNOWN
121 		},
122 		{
123 			LEAPRAID_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE,
124 			SAS_LINK_RATE_UNKNOWN
125 		},
126 		{
127 			LEAPRAID_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE,
128 			SAS_LINK_RATE_UNKNOWN
129 		},
130 	};
131 
132 	for (i = 0; i < ARRAY_SIZE(linkrate_table); i++)
133 		if (linkrate_table[i].in == link_rate)
134 			return linkrate_table[i].out;
135 
136 	return SAS_LINK_RATE_UNKNOWN;
137 }
138 
139 static void leapraid_set_identify_protocol_flags(u32 dev_info,
140 						 struct sas_identify *identify)
141 {
142 	unsigned int i;
143 
144 	const struct protocol_mapping {
145 		u32 mask;
146 		u32 *target;
147 		u32 protocol;
148 	} mappings[] = {
149 		{
150 			LEAPRAID_DEVTYP_SSP_INIT,
151 			&identify->initiator_port_protocols,
152 			SAS_PROTOCOL_SSP
153 		},
154 		{
155 			LEAPRAID_DEVTYP_STP_INIT,
156 			&identify->initiator_port_protocols,
157 			SAS_PROTOCOL_STP
158 		},
159 		{
160 			LEAPRAID_DEVTYP_SMP_INIT,
161 			&identify->initiator_port_protocols,
162 			SAS_PROTOCOL_SMP
163 		},
164 		{
165 			LEAPRAID_DEVTYP_SATA_HOST,
166 			&identify->initiator_port_protocols,
167 			SAS_PROTOCOL_SATA
168 		},
169 		{
170 			LEAPRAID_DEVTYP_SSP_TGT,
171 			&identify->target_port_protocols,
172 			SAS_PROTOCOL_SSP
173 		},
174 		{
175 			LEAPRAID_DEVTYP_STP_TGT,
176 			&identify->target_port_protocols,
177 			SAS_PROTOCOL_STP
178 		},
179 		{
180 			LEAPRAID_DEVTYP_SMP_TGT,
181 			&identify->target_port_protocols,
182 			SAS_PROTOCOL_SMP
183 		},
184 		{
185 			LEAPRAID_DEVTYP_SATA_DEV,
186 			&identify->target_port_protocols,
187 			SAS_PROTOCOL_SATA
188 		},
189 	};
190 
191 	for (i = 0; i < ARRAY_SIZE(mappings); i++)
192 		if (dev_info & mappings[i].mask && mappings[i].target)
193 			*mappings[i].target |= mappings[i].protocol;
194 }
195 
196 static int leapraid_transport_set_identify(struct leapraid_adapter *adapter,
197 					   u16 hdl,
198 					   struct sas_identify *identify)
199 {
200 	union cfg_param_1 cfgp1 = {0};
201 	union cfg_param_2 cfgp2 = {0};
202 	struct leapraid_sas_dev_p0 sas_dev_pg0;
203 	u32 dev_info;
204 
205 	if ((adapter->access_ctrl.shost_recovering &&
206 	     !adapter->scan_dev_desc.driver_loading) ||
207 	    adapter->access_ctrl.pcie_recovering) {
208 		dev_warn(&adapter->pdev->dev,
209 			 "%s: Failed, shost_recovering=%d pcie_recovering=%d\n",
210 			 __func__,
211 			 adapter->access_ctrl.shost_recovering,
212 			 adapter->access_ctrl.pcie_recovering);
213 		return -EFAULT;
214 	}
215 
216 	cfgp1.form = LEAPRAID_SAS_DEV_CFG_PGAD_HDL;
217 	cfgp2.handle = hdl;
218 	if (leapraid_op_config_page(adapter, &sas_dev_pg0, cfgp1,
219 				    cfgp2, GET_SAS_DEVICE_PG0))
220 		return -ENXIO;
221 
222 	memset(identify, 0, sizeof(struct sas_identify));
223 	dev_info = le32_to_cpu(sas_dev_pg0.dev_info);
224 	identify->sas_address = le64_to_cpu(sas_dev_pg0.sas_address);
225 	identify->phy_identifier = sas_dev_pg0.phy_num;
226 
227 	switch (dev_info & LEAPRAID_DEVTYP_MASK_DEV_TYPE) {
228 	case LEAPRAID_DEVTYP_NO_DEV:
229 		identify->device_type = SAS_PHY_UNUSED;
230 		break;
231 	case LEAPRAID_DEVTYP_END_DEV:
232 		identify->device_type = SAS_END_DEVICE;
233 		break;
234 	case LEAPRAID_DEVTYP_EDGE_EXPANDER:
235 		identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
236 		break;
237 	case LEAPRAID_DEVTYP_FANOUT_EXPANDER:
238 		identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
239 		break;
240 	}
241 
242 	leapraid_set_identify_protocol_flags(dev_info, identify);
243 
244 	return 0;
245 }
246 
247 static void leapraid_transport_exp_set_edev(struct leapraid_adapter *adapter,
248 					    void *data_out,
249 					    struct sas_expander_device *edev)
250 {
251 	struct leapraid_smp_passthrough_rep *smp_passthrough_rep;
252 	struct leapraid_rep_manu_reply *rep_manu_reply;
253 	u8 *component_id;
254 
255 	smp_passthrough_rep =
256 		(void *)&adapter->driver_cmds.transport_cmd.reply;
257 	if (le16_to_cpu(smp_passthrough_rep->resp_data_len) !=
258 	    sizeof(struct leapraid_rep_manu_reply))
259 		return;
260 
261 	rep_manu_reply = data_out + sizeof(struct leapraid_rep_manu_request);
262 
263 	memcpy(edev->vendor_id, rep_manu_reply->vendor_identification,
264 	       SAS_EXPANDER_VENDOR_ID_LEN);
265 	edev->vendor_id[SAS_EXPANDER_VENDOR_ID_LEN] = '\0';
266 
267 	memcpy(edev->product_id, rep_manu_reply->product_identification,
268 	       SAS_EXPANDER_PRODUCT_ID_LEN);
269 	edev->product_id[SAS_EXPANDER_PRODUCT_ID_LEN] = '\0';
270 
271 	memcpy(edev->product_rev, rep_manu_reply->product_revision_level,
272 	       SAS_EXPANDER_PRODUCT_REV_LEN);
273 	edev->product_rev[SAS_EXPANDER_PRODUCT_REV_LEN] = '\0';
274 
275 	edev->level = rep_manu_reply->sas_format & 1;
276 	if (edev->level) {
277 		memcpy(edev->component_vendor_id,
278 		       rep_manu_reply->comp_vendor_identification,
279 		       SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN);
280 		edev->component_vendor_id[
281 			SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN] = '\0';
282 
283 		component_id = (u8 *)&rep_manu_reply->component_id;
284 		edev->component_id = component_id[0] << 8 | component_id[1];
285 		edev->component_revision_id =
286 			rep_manu_reply->component_revision_level;
287 	}
288 }
289 
290 static int leapraid_transport_exp_report_manu(struct leapraid_adapter *adapter,
291 					      u64 sas_address,
292 					      struct sas_expander_device *edev,
293 					      u8 port_id)
294 {
295 	struct leapraid_smp_passthrough_req *smp_passthrough_req;
296 	struct leapraid_rep_manu_request *rep_manu_request;
297 	dma_addr_t h2c_dma_addr;
298 	dma_addr_t c2h_dma_addr;
299 	bool issue_reset = false;
300 	void *data_out = NULL;
301 	u16 inter_taskid;
302 	size_t c2h_size;
303 	size_t h2c_size;
304 	void *psge;
305 	int rc;
306 
307 	if (adapter->access_ctrl.shost_recovering ||
308 	    adapter->access_ctrl.pcie_recovering) {
309 		dev_warn(&adapter->pdev->dev,
310 			 "%s: Failed, shost_recovering=%d pcie_recovering=%d\n",
311 			 __func__,
312 			 adapter->access_ctrl.shost_recovering,
313 			 adapter->access_ctrl.pcie_recovering);
314 		return -EFAULT;
315 	}
316 
317 	mutex_lock(&adapter->driver_cmds.transport_cmd.mutex);
318 	adapter->driver_cmds.transport_cmd.status = LEAPRAID_CMD_PENDING;
319 	rc = leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_SHORT,
320 					  __func__);
321 	if (rc)
322 		goto out_cleanup;
323 
324 	h2c_size = sizeof(struct leapraid_rep_manu_request);
325 	c2h_size = sizeof(struct leapraid_rep_manu_reply);
326 	data_out = dma_alloc_coherent(&adapter->pdev->dev,
327 				      h2c_size + c2h_size,
328 				      &h2c_dma_addr,
329 				      GFP_ATOMIC);
330 	if (!data_out) {
331 		rc = -ENOMEM;
332 		goto out_cleanup;
333 	}
334 
335 	rep_manu_request = data_out;
336 	rep_manu_request->smp_frame_type =
337 		SMP_REPORT_MANUFACTURER_INFORMATION_FRAME_TYPE;
338 	rep_manu_request->function = SMP_REPORT_MANUFACTURER_INFORMATION_FUNC;
339 	rep_manu_request->allocated_response_length = 0;
340 	rep_manu_request->request_length = 0;
341 
342 	inter_taskid = adapter->driver_cmds.transport_cmd.inter_taskid;
343 	smp_passthrough_req = leapraid_get_task_desc(adapter, inter_taskid);
344 	memset(smp_passthrough_req, 0,
345 	       sizeof(struct leapraid_smp_passthrough_req));
346 	smp_passthrough_req->func = LEAPRAID_FUNC_SMP_PASSTHROUGH;
347 	smp_passthrough_req->physical_port = port_id;
348 	smp_passthrough_req->sas_address = cpu_to_le64(sas_address);
349 	smp_passthrough_req->req_data_len = cpu_to_le16(h2c_size);
350 	psge = &smp_passthrough_req->sgl;
351 	c2h_dma_addr = h2c_dma_addr + sizeof(struct leapraid_rep_manu_request);
352 	leapraid_build_ieee_sg(adapter, psge, h2c_dma_addr, h2c_size,
353 			       c2h_dma_addr, c2h_size);
354 
355 	init_completion(&adapter->driver_cmds.transport_cmd.done);
356 	leapraid_fire_task(adapter, inter_taskid);
357 	wait_for_completion_timeout(&adapter->driver_cmds.transport_cmd.done,
358 				    LEAPRAID_TRANSPORT_CMD_TIMEOUT * HZ);
359 	if (!(adapter->driver_cmds.transport_cmd.status & LEAPRAID_CMD_DONE)) {
360 		rc = -ETIMEDOUT;
361 		dev_err(&adapter->pdev->dev,
362 			"%s: SMP passthrough timeout, st=0x%x\n",
363 			__func__, adapter->driver_cmds.transport_cmd.status);
364 		leapraid_log_req_context(adapter, inter_taskid,
365 					 smp_passthrough_req);
366 		if (!(adapter->driver_cmds.transport_cmd.status &
367 		      LEAPRAID_CMD_RESET))
368 			issue_reset = true;
369 
370 		goto hard_reset;
371 	}
372 
373 	if (adapter->driver_cmds.transport_cmd.status &
374 	    LEAPRAID_CMD_REPLY_VALID)
375 		leapraid_transport_exp_set_edev(adapter, data_out, edev);
376 
377 hard_reset:
378 	if (issue_reset) {
379 		dev_info(&adapter->pdev->dev, "%s:%d: call hard_reset\n",
380 			 __func__, __LINE__);
381 		rc = leapraid_hard_reset_handler(adapter, FULL_RESET);
382 	}
383 out_cleanup:
384 	adapter->driver_cmds.transport_cmd.status = LEAPRAID_CMD_NOT_USED;
385 	if (data_out)
386 		dma_free_coherent(&adapter->pdev->dev, h2c_size + c2h_size,
387 				  data_out, h2c_dma_addr);
388 
389 	mutex_unlock(&adapter->driver_cmds.transport_cmd.mutex);
390 	return rc;
391 }
392 
393 static void leapraid_transport_del_port(struct leapraid_adapter *adapter,
394 					struct leapraid_sas_port *sas_port)
395 {
396 	dev_info(&sas_port->port->dev,
397 		 "Remove port: SAS addr=0x%016llx\n",
398 		 (unsigned long long)sas_port->remote_identify.sas_address);
399 	switch (sas_port->remote_identify.device_type) {
400 	case SAS_END_DEVICE:
401 		leapraid_sas_dev_remove_by_sas_address(
402 			adapter,
403 			sas_port->remote_identify.sas_address,
404 			sas_port->card_port);
405 		break;
406 	case SAS_EDGE_EXPANDER_DEVICE:
407 	case SAS_FANOUT_EXPANDER_DEVICE:
408 		leapraid_exp_rm(adapter, sas_port->remote_identify.sas_address,
409 				sas_port->card_port);
410 		break;
411 	default:
412 		break;
413 	}
414 }
415 
416 static void leapraid_transport_del_phy(struct leapraid_adapter *adapter,
417 				       struct leapraid_sas_port *sas_port,
418 				       struct leapraid_card_phy *card_phy)
419 {
420 	dev_info(&card_phy->phy->dev,
421 		 "Remove PHY: SAS addr=0x%016llx, phy=%d\n",
422 		 (unsigned long long)sas_port->remote_identify.sas_address,
423 		 card_phy->phy_id);
424 	list_del(&card_phy->port_siblings);
425 	sas_port->phys_num--;
426 	sas_port_delete_phy(sas_port->port, card_phy->phy);
427 	card_phy->phy_is_assigned = 0;
428 }
429 
430 static void leapraid_transport_add_phy(struct leapraid_adapter *adapter,
431 				       struct leapraid_sas_port *sas_port,
432 				       struct leapraid_card_phy *card_phy)
433 {
434 	dev_info(&card_phy->phy->dev,
435 		 "Add PHY: SAS addr=0x%016llx, phy=%d\n",
436 		 (unsigned long long)sas_port->remote_identify.sas_address,
437 		 card_phy->phy_id);
438 	list_add_tail(&card_phy->port_siblings, &sas_port->phy_list);
439 	sas_port->phys_num++;
440 	sas_port_add_phy(sas_port->port, card_phy->phy);
441 	card_phy->phy_is_assigned = 1;
442 }
443 
444 void leapraid_transport_attach_phy_to_port(
445 		struct leapraid_adapter *adapter,
446 		struct leapraid_topo_node *topo_node,
447 		struct leapraid_card_phy *card_phy,
448 		u64 sas_address,
449 		struct leapraid_card_port *card_port)
450 {
451 	struct leapraid_sas_port *sas_port;
452 	struct leapraid_card_phy *card_phy_srch;
453 
454 	if (card_phy->phy_is_assigned)
455 		return;
456 
457 	if (!card_port)
458 		return;
459 
460 	list_for_each_entry(sas_port, &topo_node->sas_port_list, port_list) {
461 		if (sas_port->remote_identify.sas_address != sas_address)
462 			continue;
463 
464 		if (sas_port->card_port != card_port)
465 			continue;
466 
467 		list_for_each_entry(card_phy_srch, &sas_port->phy_list,
468 				    port_siblings) {
469 			if (card_phy_srch == card_phy)
470 				return;
471 		}
472 		leapraid_transport_add_phy(adapter, sas_port, card_phy);
473 		return;
474 	}
475 }
476 
477 void leapraid_transport_detach_phy_to_port(
478 		struct leapraid_adapter *adapter,
479 		struct leapraid_topo_node *topo_node,
480 		struct leapraid_card_phy *target_card_phy)
481 {
482 	struct leapraid_sas_port *sas_port, *sas_port_next;
483 	struct leapraid_card_phy *cur_card_phy;
484 
485 	if (!target_card_phy->phy_is_assigned)
486 		return;
487 
488 	list_for_each_entry_safe(sas_port, sas_port_next,
489 				 &topo_node->sas_port_list, port_list) {
490 		list_for_each_entry(cur_card_phy, &sas_port->phy_list,
491 				    port_siblings) {
492 			if (cur_card_phy != target_card_phy)
493 				continue;
494 
495 			if (sas_port->phys_num == 1 &&
496 			    !adapter->access_ctrl.shost_recovering)
497 				leapraid_transport_del_port(adapter, sas_port);
498 			else
499 				leapraid_transport_del_phy(adapter, sas_port,
500 							   target_card_phy);
501 			return;
502 		}
503 	}
504 }
505 
506 static void leapraid_detach_phy_from_old_port(
507 		struct leapraid_adapter *adapter,
508 		struct leapraid_topo_node *topo_node,
509 		u64 sas_address,
510 		struct leapraid_card_port *card_port)
511 {
512 	int i;
513 
514 	for (i = 0; i < topo_node->phys_num; i++) {
515 		if (topo_node->card_phy[i].remote_identify.sas_address !=
516 			sas_address ||
517 		    topo_node->card_phy[i].card_port != card_port)
518 			continue;
519 		if (topo_node->card_phy[i].phy_is_assigned)
520 			leapraid_transport_detach_phy_to_port(
521 				adapter,
522 				topo_node,
523 				&topo_node->card_phy[i]);
524 	}
525 }
526 
527 static struct leapraid_sas_port *leapraid_prepare_sas_port(
528 		struct leapraid_adapter *adapter,
529 		u16 handle, u64 sas_address,
530 		struct leapraid_card_port *card_port,
531 		struct leapraid_topo_node **out_topo_node)
532 {
533 	struct leapraid_topo_node *topo_node;
534 	struct leapraid_sas_port *sas_port;
535 	unsigned long flags;
536 
537 	sas_port = kzalloc_obj(*sas_port);
538 	if (!sas_port) {
539 		dev_warn(&adapter->pdev->dev,
540 			 "%s: Failed alloc sas_port\n", __func__);
541 		return NULL;
542 	}
543 
544 	INIT_LIST_HEAD(&sas_port->port_list);
545 	INIT_LIST_HEAD(&sas_port->phy_list);
546 
547 	spin_lock_irqsave(&adapter->dev_topo.topo_node_lock, flags);
548 	topo_node = leapraid_transport_topo_node_by_sas_addr(adapter,
549 							     sas_address,
550 							     card_port);
551 	spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock, flags);
552 
553 	if (!topo_node) {
554 		dev_err(&adapter->pdev->dev,
555 			"%s: Failed to locate parent for SAS 0x%016llx!\n",
556 			__func__, sas_address);
557 		goto out_cleanup;
558 	}
559 
560 	if (leapraid_transport_set_identify(adapter, handle,
561 					    &sas_port->remote_identify))
562 		goto out_cleanup;
563 
564 	if (sas_port->remote_identify.device_type == SAS_PHY_UNUSED) {
565 		dev_warn(&adapter->pdev->dev,
566 			 "%s: Failed, device type is SAS_PHY_UNUSED\n",
567 			 __func__);
568 		goto out_cleanup;
569 	}
570 
571 	sas_port->card_port = card_port;
572 	*out_topo_node = topo_node;
573 
574 	return sas_port;
575 
576 out_cleanup:
577 	kfree(sas_port);
578 	return NULL;
579 }
580 
581 static int leapraid_bind_phys_and_vphy(struct leapraid_adapter *adapter,
582 				       struct leapraid_sas_port *sas_port,
583 				       struct leapraid_topo_node *topo_node,
584 				       struct leapraid_card_port *card_port,
585 				       struct leapraid_vphy **out_vphy)
586 {
587 	struct leapraid_vphy *vphy = NULL;
588 	int i;
589 
590 	for (i = 0; i < topo_node->phys_num; i++) {
591 		if (topo_node->card_phy[i].remote_identify.sas_address !=
592 			sas_port->remote_identify.sas_address ||
593 		    topo_node->card_phy[i].card_port != card_port)
594 			continue;
595 
596 		list_add_tail(&topo_node->card_phy[i].port_siblings,
597 			      &sas_port->phy_list);
598 		sas_port->phys_num++;
599 
600 		if (topo_node->hdl <= adapter->dev_topo.card.phys_num) {
601 			if (!topo_node->card_phy[i].vphy) {
602 				card_port->phy_mask |= BIT(i);
603 				continue;
604 			}
605 
606 			vphy = leapraid_get_vphy_by_phy(card_port, i);
607 			if (!vphy)
608 				return LEAPRAID_OPERATION_FAILED;
609 		}
610 	}
611 
612 	*out_vphy = vphy;
613 	return sas_port->phys_num ? 0 : LEAPRAID_OPERATION_FAILED;
614 }
615 
616 static struct sas_rphy *leapraid_create_and_register_rphy(
617 		struct leapraid_adapter *adapter,
618 		struct leapraid_sas_port *sas_port,
619 		struct leapraid_topo_node *topo_node,
620 		struct leapraid_card_port *card_port,
621 		struct leapraid_vphy *vphy)
622 {
623 	struct leapraid_sas_dev *sas_dev = NULL;
624 	struct leapraid_card_phy *card_phy;
625 	struct sas_port *port;
626 	struct sas_rphy *rphy;
627 
628 	if (sas_port->remote_identify.device_type == SAS_END_DEVICE) {
629 		sas_dev = leapraid_get_sas_dev_by_addr(
630 				adapter,
631 				sas_port->remote_identify.sas_address,
632 				card_port);
633 		if (!sas_dev)
634 			return NULL;
635 		sas_dev->pend_sas_rphy_add = 1;
636 	}
637 
638 	if (!topo_node->parent_dev) {
639 		dev_warn(&adapter->pdev->dev,
640 			 "%s: topo_node parent device is NULL\n",  __func__);
641 		goto cleanup_sas_dev;
642 	}
643 
644 	port = sas_port_alloc_num(topo_node->parent_dev);
645 	if (!port) {
646 		dev_err(&adapter->pdev->dev,
647 			"%s: Failed to allocate SAS port\n", __func__);
648 		goto cleanup_sas_dev;
649 	}
650 
651 	if (sas_port_add(port)) {
652 		dev_err(&adapter->pdev->dev,
653 			"%s: Failed to add SAS port\n", __func__);
654 		goto out_delete_port;
655 	}
656 
657 	list_for_each_entry(card_phy, &sas_port->phy_list, port_siblings) {
658 		sas_port_add_phy(port, card_phy->phy);
659 		card_phy->phy_is_assigned = 1;
660 		card_phy->card_port = card_port;
661 	}
662 
663 	if (sas_dev) {
664 		rphy = sas_end_device_alloc(port);
665 		sas_dev->rphy = rphy;
666 
667 		if (topo_node->hdl <= adapter->dev_topo.card.phys_num) {
668 			if (!vphy)
669 				card_port->sas_address = sas_dev->sas_addr;
670 			else
671 				vphy->sas_address = sas_dev->sas_addr;
672 		}
673 	} else {
674 		rphy = sas_expander_alloc(
675 				port,
676 				sas_port->remote_identify.device_type);
677 		if (topo_node->hdl <= adapter->dev_topo.card.phys_num)
678 			card_port->sas_address =
679 				sas_port->remote_identify.sas_address;
680 	}
681 
682 	if (!rphy) {
683 		dev_err(&adapter->pdev->dev,
684 			"%s: Failed to allocate RPHY\n", __func__);
685 		goto cleanup_card_phy;
686 	}
687 
688 	rphy->identify = sas_port->remote_identify;
689 
690 	if (sas_rphy_add(rphy)) {
691 		dev_err(&adapter->pdev->dev,
692 			"%s: Failed to add RPHY\n", __func__);
693 		if (sas_dev)
694 			sas_dev->rphy = NULL;
695 
696 		sas_rphy_free(rphy);
697 		goto cleanup_card_phy;
698 	}
699 	sas_port->port = port;
700 
701 	if (sas_dev) {
702 		sas_dev->pend_sas_rphy_add = 0;
703 		leapraid_sdev_put(sas_dev);
704 	}
705 
706 	return rphy;
707 
708 cleanup_card_phy:
709 	if (topo_node->hdl <= adapter->dev_topo.card.phys_num) {
710 		if (!vphy)
711 			card_port->sas_address = 0;
712 		else
713 			vphy->sas_address = 0;
714 	}
715 
716 	list_for_each_entry(card_phy, &sas_port->phy_list, port_siblings) {
717 		card_phy->phy_is_assigned = 0;
718 		card_phy->card_port = NULL;
719 	}
720 
721 out_delete_port:
722 	sas_port_delete(port);
723 
724 cleanup_sas_dev:
725 	if (sas_dev) {
726 		sas_dev->pend_sas_rphy_add = 0;
727 		leapraid_sdev_put(sas_dev);
728 	}
729 	return NULL;
730 }
731 
732 struct leapraid_sas_port *leapraid_transport_port_add(
733 		struct leapraid_adapter *adapter,
734 		u16 hdl, u64 sas_address,
735 		struct leapraid_card_port *card_port)
736 {
737 	struct leapraid_card_phy *card_phy, *card_phy_next;
738 	struct leapraid_topo_node *topo_node = NULL;
739 	struct leapraid_sas_port *sas_port;
740 	struct leapraid_vphy *vphy = NULL;
741 	struct sas_rphy *rphy;
742 	unsigned long flags;
743 
744 	if (!card_port) {
745 		dev_warn(&adapter->pdev->dev,
746 			 "%s: Invalid card_port\n", __func__);
747 		return NULL;
748 	}
749 
750 	sas_port = leapraid_prepare_sas_port(adapter, hdl, sas_address,
751 					     card_port, &topo_node);
752 	if (!sas_port)
753 		return NULL;
754 
755 	leapraid_detach_phy_from_old_port(
756 		adapter,
757 		topo_node,
758 		sas_port->remote_identify.sas_address,
759 		card_port);
760 
761 	if (leapraid_bind_phys_and_vphy(adapter, sas_port, topo_node,
762 					card_port, &vphy)) {
763 		dev_err(&adapter->pdev->dev,
764 			"%s: Failed to bind phy to vphy\n", __func__);
765 		goto out_fail;
766 	}
767 
768 	rphy = leapraid_create_and_register_rphy(adapter, sas_port, topo_node,
769 						 card_port, vphy);
770 	if (!rphy) {
771 		dev_err(&adapter->pdev->dev,
772 			"%s: Failed to create rphy\n", __func__);
773 		goto out_fail;
774 	}
775 
776 	dev_info(&rphy->dev,
777 		 "%s: Added dev: hdl=0x%04x, SAS addr=0x%016llx\n",
778 		 __func__, hdl,
779 		 (unsigned long long)sas_port->remote_identify.sas_address);
780 
781 	sas_port->rphy = rphy;
782 
783 	spin_lock_irqsave(&adapter->dev_topo.topo_node_lock, flags);
784 	list_add_tail(&sas_port->port_list, &topo_node->sas_port_list);
785 	spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock, flags);
786 
787 	if (sas_port->remote_identify.device_type ==
788 	    SAS_EDGE_EXPANDER_DEVICE ||
789 	    sas_port->remote_identify.device_type ==
790 	    SAS_FANOUT_EXPANDER_DEVICE)
791 		leapraid_transport_exp_report_manu(
792 			adapter,
793 			sas_port->remote_identify.sas_address,
794 			rphy_to_expander_device(rphy),
795 			card_port->port_id);
796 
797 	return sas_port;
798 
799 out_fail:
800 	list_for_each_entry_safe(card_phy, card_phy_next,
801 				 &sas_port->phy_list, port_siblings) {
802 		if (topo_node->hdl <= adapter->dev_topo.card.phys_num &&
803 		    !card_phy->vphy)
804 			card_port->phy_mask &= ~BIT(card_phy->phy_id);
805 
806 		list_del_init(&card_phy->port_siblings);
807 	}
808 
809 	kfree(sas_port);
810 	return NULL;
811 }
812 
813 static struct leapraid_sas_port *leapraid_find_and_remove_sas_port(
814 		struct leapraid_topo_node *topo_node,
815 		u64 sas_address,
816 		struct leapraid_card_port *remove_card_port,
817 		bool *found)
818 {
819 	struct leapraid_sas_port *sas_port, *sas_port_next;
820 
821 	list_for_each_entry_safe(sas_port, sas_port_next,
822 				 &topo_node->sas_port_list, port_list) {
823 		if (sas_port->remote_identify.sas_address != sas_address)
824 			continue;
825 
826 		if (sas_port->card_port != remove_card_port)
827 			continue;
828 
829 		*found = true;
830 		list_del(&sas_port->port_list);
831 		return sas_port;
832 	}
833 	return NULL;
834 }
835 
836 static void leapraid_cleanup_card_port_and_vphys(
837 		struct leapraid_adapter *adapter,
838 		u64 sas_address,
839 		struct leapraid_card_port *remove_card_port)
840 {
841 	struct leapraid_card_port *card_port, *card_port_next;
842 	struct leapraid_vphy *vphy, *vphy_next;
843 
844 	if (remove_card_port->vphys_mask) {
845 		list_for_each_entry_safe(vphy, vphy_next,
846 					 &remove_card_port->vphys_list, list) {
847 			if (vphy->sas_address != sas_address)
848 				continue;
849 
850 			dev_dbg(&adapter->pdev->dev,
851 				"%s: Remove vphy=%p from port=%p port_id=%d\n",
852 				__func__, vphy, remove_card_port,
853 				remove_card_port->port_id);
854 
855 			remove_card_port->vphys_mask &= ~vphy->phy_mask;
856 			list_del(&vphy->list);
857 			kfree(vphy);
858 		}
859 
860 		if (!remove_card_port->vphys_mask &&
861 		    !remove_card_port->sas_address) {
862 			dev_dbg(&adapter->pdev->dev,
863 				"%s: Remove empty hba_port: %p, port_id=%d\n",
864 				__func__,
865 				remove_card_port,
866 				remove_card_port->port_id);
867 			list_del(&remove_card_port->list);
868 			kfree(remove_card_port);
869 			remove_card_port = NULL;
870 		}
871 	}
872 
873 	list_for_each_entry_safe(card_port, card_port_next,
874 				 &adapter->dev_topo.card_port_list, list) {
875 		if (card_port != remove_card_port)
876 			continue;
877 
878 		if (card_port->sas_address != sas_address)
879 			continue;
880 
881 		if (!remove_card_port->vphys_mask) {
882 			dev_dbg(&adapter->pdev->dev,
883 				"%s: Remove hba_port: %p, port_id=%d\n",
884 				__func__, card_port, card_port->port_id);
885 			list_del(&card_port->list);
886 			kfree(card_port);
887 		} else {
888 			dev_dbg(&adapter->pdev->dev,
889 				"Clear sas_address of port=%p, port_id=%d\n",
890 				card_port, card_port->port_id);
891 			remove_card_port->sas_address = 0;
892 		}
893 		break;
894 	}
895 }
896 
897 static void leapraid_clear_topo_node_phys(struct leapraid_topo_node *topo_node,
898 					  u64 sas_address)
899 {
900 	int i;
901 
902 	for (i = 0; i < topo_node->phys_num; i++)
903 		if (topo_node->card_phy[i].remote_identify.sas_address ==
904 		    sas_address) {
905 			memset(&topo_node->card_phy[i].remote_identify, 0,
906 			       sizeof(struct sas_identify));
907 			topo_node->card_phy[i].vphy = 0;
908 		}
909 }
910 
911 void leapraid_transport_port_remove(
912 		struct leapraid_adapter *adapter,
913 		u64 sas_address,
914 		u64 sas_address_parent,
915 		struct leapraid_card_port *remove_card_port)
916 {
917 	struct leapraid_card_phy *card_phy, *card_phy_next;
918 	struct leapraid_sas_port *sas_port;
919 	struct leapraid_topo_node *topo_node;
920 	unsigned long flags;
921 	bool found = false;
922 
923 	if (!remove_card_port)
924 		return;
925 
926 	spin_lock_irqsave(&adapter->dev_topo.topo_node_lock, flags);
927 
928 	topo_node = leapraid_transport_topo_node_by_sas_addr(adapter,
929 							     sas_address_parent,
930 							     remove_card_port);
931 	if (!topo_node) {
932 		spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock,
933 				       flags);
934 		return;
935 	}
936 
937 	sas_port = leapraid_find_and_remove_sas_port(topo_node, sas_address,
938 						     remove_card_port, &found);
939 
940 	if (!found) {
941 		spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock,
942 				       flags);
943 		return;
944 	}
945 
946 	if (topo_node->hdl <= adapter->dev_topo.card.phys_num &&
947 	    adapter->adapter_attr.enable_mp)
948 		leapraid_cleanup_card_port_and_vphys(adapter, sas_address,
949 						     remove_card_port);
950 
951 	leapraid_clear_topo_node_phys(topo_node, sas_address);
952 	spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock, flags);
953 
954 	list_for_each_entry_safe(card_phy, card_phy_next,
955 				 &sas_port->phy_list, port_siblings) {
956 		card_phy->phy_is_assigned = 0;
957 		if (!adapter->access_ctrl.host_removing)
958 			sas_port_delete_phy(sas_port->port, card_phy->phy);
959 
960 		list_del(&card_phy->port_siblings);
961 	}
962 
963 	if (!adapter->access_ctrl.host_removing)
964 		sas_port_delete(sas_port->port);
965 
966 	dev_dbg(&adapter->pdev->dev,
967 		"%s: Removed sas_port for SAS addr=0x%016llx\n",
968 		__func__, (unsigned long long)sas_address);
969 
970 	kfree(sas_port);
971 }
972 
973 static void leapraid_init_sas_or_exp_phy(struct leapraid_adapter *adapter,
974 					 struct leapraid_card_phy *card_phy,
975 					 struct sas_phy *phy,
976 					 struct leapraid_sas_phy_p0 *phy_pg0,
977 					 struct leapraid_exp_p1 *exp_pg1)
978 {
979 	if (exp_pg1 && phy_pg0)
980 		return;
981 
982 	if (!exp_pg1 && !phy_pg0)
983 		return;
984 
985 	phy->identify = card_phy->identify;
986 	phy->identify.phy_identifier = card_phy->phy_id;
987 	phy->negotiated_linkrate = phy_pg0 ?
988 		leapraid_transport_convert_phy_link_rate(
989 			phy_pg0->neg_link_rate &
990 			LEAPRAID_SAS_NEG_LINK_RATE_MASK_PHYSICAL) :
991 		 leapraid_transport_convert_phy_link_rate(
992 			exp_pg1->neg_link_rate &
993 			LEAPRAID_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
994 	phy->minimum_linkrate_hw = phy_pg0 ?
995 		 leapraid_transport_convert_phy_link_rate(
996 			phy_pg0->hw_link_rate &
997 			LEAPRAID_SAS_HWRATE_MIN_RATE_MASK) :
998 		 leapraid_transport_convert_phy_link_rate(
999 			exp_pg1->hw_link_rate &
1000 			LEAPRAID_SAS_HWRATE_MIN_RATE_MASK);
1001 	phy->maximum_linkrate_hw = phy_pg0 ?
1002 		 leapraid_transport_convert_phy_link_rate(
1003 			phy_pg0->hw_link_rate >>
1004 			 LEAPRAID_SAS_NEG_LINK_RATE_SHIFT) :
1005 		 leapraid_transport_convert_phy_link_rate(
1006 			exp_pg1->hw_link_rate >>
1007 			 LEAPRAID_SAS_NEG_LINK_RATE_SHIFT);
1008 	phy->minimum_linkrate = phy_pg0 ?
1009 		 leapraid_transport_convert_phy_link_rate(
1010 			phy_pg0->p_link_rate &
1011 			LEAPRAID_SAS_PRATE_MIN_RATE_MASK) :
1012 		 leapraid_transport_convert_phy_link_rate(
1013 			exp_pg1->p_link_rate &
1014 			LEAPRAID_SAS_PRATE_MIN_RATE_MASK);
1015 	phy->maximum_linkrate = phy_pg0 ?
1016 		 leapraid_transport_convert_phy_link_rate(
1017 			phy_pg0->p_link_rate >>
1018 			 LEAPRAID_SAS_NEG_LINK_RATE_SHIFT) :
1019 		 leapraid_transport_convert_phy_link_rate(
1020 			exp_pg1->p_link_rate >>
1021 			 LEAPRAID_SAS_NEG_LINK_RATE_SHIFT);
1022 	phy->hostdata = card_phy->card_port;
1023 }
1024 
1025 void leapraid_transport_add_card_phy(struct leapraid_adapter *adapter,
1026 				     struct leapraid_card_phy *card_phy,
1027 				     struct leapraid_sas_phy_p0 *phy_pg0,
1028 				     struct device *parent_dev)
1029 {
1030 	struct sas_phy *phy;
1031 	int ret;
1032 
1033 	INIT_LIST_HEAD(&card_phy->port_siblings);
1034 	phy = sas_phy_alloc(parent_dev, card_phy->phy_id);
1035 	if (!phy) {
1036 		dev_err(&adapter->pdev->dev,
1037 			"%s: sas_phy_alloc failed!\n", __func__);
1038 		return;
1039 	}
1040 
1041 	if (leapraid_transport_set_identify(adapter, card_phy->hdl,
1042 					    &card_phy->identify)) {
1043 		dev_err(&adapter->pdev->dev,
1044 			"%s: Set PHY handle identify failed!\n", __func__);
1045 		sas_phy_free(phy);
1046 		return;
1047 	}
1048 
1049 	card_phy->attached_hdl = le16_to_cpu(phy_pg0->attached_dev_hdl);
1050 	if (card_phy->attached_hdl) {
1051 		ret = leapraid_transport_set_identify(
1052 				adapter,
1053 				card_phy->attached_hdl,
1054 				&card_phy->remote_identify);
1055 		if (ret) {
1056 			dev_err(&adapter->pdev->dev,
1057 				"%s: Set PHY attached hdl identify failed!\n",
1058 				__func__);
1059 			sas_phy_free(phy);
1060 			return;
1061 		}
1062 	}
1063 
1064 	leapraid_init_sas_or_exp_phy(adapter, card_phy, phy, phy_pg0, NULL);
1065 
1066 	if (sas_phy_add(phy)) {
1067 		dev_err(&adapter->pdev->dev,
1068 			"%s: SAS PHY add failed!\n", __func__);
1069 		sas_phy_free(phy);
1070 		return;
1071 	}
1072 
1073 	card_phy->phy = phy;
1074 }
1075 
1076 int leapraid_transport_add_exp_phy(struct leapraid_adapter *adapter,
1077 				   struct leapraid_card_phy *card_phy,
1078 				   struct leapraid_exp_p1 *exp_pg1,
1079 				   struct device *parent_dev)
1080 {
1081 	struct sas_phy *phy;
1082 	int ret;
1083 
1084 	INIT_LIST_HEAD(&card_phy->port_siblings);
1085 	phy = sas_phy_alloc(parent_dev, card_phy->phy_id);
1086 	if (!phy) {
1087 		dev_err(&adapter->pdev->dev,
1088 			"%s: sas_phy_alloc failed!\n", __func__);
1089 		return -EFAULT;
1090 	}
1091 
1092 	if (leapraid_transport_set_identify(adapter, card_phy->hdl,
1093 					    &card_phy->identify)) {
1094 		dev_err(&adapter->pdev->dev,
1095 			"%s: Set PHY hdl identify failed!\n", __func__);
1096 		sas_phy_free(phy);
1097 		return -EFAULT;
1098 	}
1099 
1100 	card_phy->attached_hdl = le16_to_cpu(exp_pg1->attached_dev_hdl);
1101 	if (card_phy->attached_hdl) {
1102 		ret = leapraid_transport_set_identify(
1103 				adapter,
1104 				card_phy->attached_hdl,
1105 				&card_phy->remote_identify);
1106 		if (ret)
1107 			dev_warn(&adapter->pdev->dev,
1108 				 "%s: Set PHY attached hdl identify failed!\n",
1109 				 __func__);
1110 	}
1111 
1112 	leapraid_init_sas_or_exp_phy(adapter, card_phy, phy, NULL, exp_pg1);
1113 
1114 	if (sas_phy_add(phy)) {
1115 		dev_err(&adapter->pdev->dev,
1116 			"%s: SAS PHY add failed!\n", __func__);
1117 		sas_phy_free(phy);
1118 		return -EFAULT;
1119 	}
1120 
1121 	card_phy->phy = phy;
1122 	return 0;
1123 }
1124 
1125 void leapraid_transport_update_links(
1126 		struct leapraid_adapter *adapter,
1127 		u64 sas_address, u16 hdl, u8 phy_index,
1128 		u8 link_rate, struct leapraid_card_port *target_card_port)
1129 {
1130 	struct leapraid_topo_node *topo_node;
1131 	struct leapraid_card_phy *card_phy;
1132 	struct leapraid_card_port *card_port;
1133 	unsigned long flags;
1134 
1135 	if (adapter->access_ctrl.shost_recovering ||
1136 	    adapter->access_ctrl.pcie_recovering)
1137 		return;
1138 
1139 	spin_lock_irqsave(&adapter->dev_topo.topo_node_lock, flags);
1140 	topo_node = leapraid_transport_topo_node_by_sas_addr(adapter,
1141 							     sas_address,
1142 							     target_card_port);
1143 	if (!topo_node) {
1144 		spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock,
1145 				       flags);
1146 		return;
1147 	}
1148 
1149 	card_phy = &topo_node->card_phy[phy_index];
1150 	card_phy->attached_hdl = hdl;
1151 	spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock, flags);
1152 
1153 	if (hdl && link_rate >= LEAPRAID_SAS_NEG_LINK_RATE_1_5) {
1154 		leapraid_transport_set_identify(adapter, hdl,
1155 						&card_phy->remote_identify);
1156 		if (topo_node->hdl <= adapter->dev_topo.card.phys_num &&
1157 		    adapter->adapter_attr.enable_mp) {
1158 			list_for_each_entry(card_port,
1159 					    &adapter->dev_topo.card_port_list,
1160 					    list) {
1161 				if (card_port->sas_address == sas_address &&
1162 				    card_port == target_card_port)
1163 					card_port->phy_mask |=
1164 						BIT(card_phy->phy_id);
1165 			}
1166 		}
1167 		leapraid_transport_attach_phy_to_port(
1168 			adapter,
1169 			topo_node,
1170 			card_phy,
1171 			card_phy->remote_identify.sas_address,
1172 			target_card_port);
1173 	} else {
1174 		memset(&card_phy->remote_identify, 0,
1175 		       sizeof(struct sas_identify));
1176 	}
1177 
1178 	if (card_phy->phy)
1179 		card_phy->phy->negotiated_linkrate =
1180 			leapraid_transport_convert_phy_link_rate(link_rate);
1181 }
1182 
1183 static int leapraid_dma_map_buffer(struct device *dev, struct bsg_buffer *buf,
1184 				   dma_addr_t *dma_addr,
1185 				   size_t *dma_len, void **p)
1186 {
1187 	if (buf->sg_cnt > 1) {
1188 		*p = dma_alloc_coherent(dev, buf->payload_len, dma_addr,
1189 					GFP_KERNEL);
1190 		if (!*p)
1191 			return -ENOMEM;
1192 
1193 		*dma_len = buf->payload_len;
1194 	} else {
1195 		if (!dma_map_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL)) {
1196 			dev_err(dev,
1197 				"%s: Failed to map sg buffer for dma\n",
1198 				__func__);
1199 			return -ENOMEM;
1200 		}
1201 
1202 		*dma_addr = sg_dma_address(buf->sg_list);
1203 		*dma_len = sg_dma_len(buf->sg_list);
1204 		*p = NULL;
1205 	}
1206 	return 0;
1207 }
1208 
1209 static void leapraid_dma_unmap_buffer(struct device *dev,
1210 				      struct bsg_buffer *buf,
1211 				      dma_addr_t dma_addr,
1212 				      void *p)
1213 {
1214 	if (p)
1215 		dma_free_coherent(dev, buf->payload_len, p, dma_addr);
1216 	else
1217 		dma_unmap_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL);
1218 }
1219 
1220 static void leapraid_build_smp_task(struct leapraid_adapter *adapter,
1221 				    struct sas_rphy *rphy,
1222 				    dma_addr_t h2c_dma_addr, size_t h2c_size,
1223 				    dma_addr_t c2h_dma_addr, size_t c2h_size)
1224 {
1225 	struct leapraid_smp_passthrough_req *smp_passthrough_req;
1226 	u16 inter_taskid;
1227 	void *psge;
1228 
1229 	inter_taskid = adapter->driver_cmds.transport_cmd.inter_taskid;
1230 	smp_passthrough_req = leapraid_get_task_desc(adapter, inter_taskid);
1231 	memset(smp_passthrough_req, 0, sizeof(*smp_passthrough_req));
1232 
1233 	smp_passthrough_req->func = LEAPRAID_FUNC_SMP_PASSTHROUGH;
1234 	smp_passthrough_req->physical_port =
1235 		leapraid_transport_get_port_id_by_rphy(adapter, rphy);
1236 	smp_passthrough_req->sas_address = (rphy) ?
1237 		cpu_to_le64(rphy->identify.sas_address) :
1238 		cpu_to_le64(adapter->dev_topo.card.sas_address);
1239 	smp_passthrough_req->req_data_len =
1240 		cpu_to_le16(h2c_size - LEAPRAID_SMP_FRAME_HEADER_SIZE);
1241 	psge = &smp_passthrough_req->sgl;
1242 	leapraid_build_ieee_sg(adapter, psge, h2c_dma_addr,
1243 			       h2c_size - LEAPRAID_SMP_FRAME_HEADER_SIZE,
1244 			       c2h_dma_addr,
1245 			       c2h_size - LEAPRAID_SMP_FRAME_HEADER_SIZE);
1246 }
1247 
1248 static int leapraid_send_smp_req(struct leapraid_adapter *adapter)
1249 {
1250 	const struct leapraid_smp_passthrough_req *smp_passthrough_req;
1251 	u16 inter_taskid;
1252 
1253 	dev_dbg(&adapter->pdev->dev,
1254 		"%s: Sending smp request\n", __func__);
1255 	inter_taskid = adapter->driver_cmds.transport_cmd.inter_taskid;
1256 	smp_passthrough_req = leapraid_get_task_desc(adapter, inter_taskid);
1257 	init_completion(&adapter->driver_cmds.transport_cmd.done);
1258 	leapraid_fire_task(adapter, inter_taskid);
1259 	wait_for_completion_timeout(&adapter->driver_cmds.transport_cmd.done,
1260 				    LEAPRAID_TRANSPORT_CMD_TIMEOUT * HZ);
1261 	if (!(adapter->driver_cmds.transport_cmd.status & LEAPRAID_CMD_DONE)) {
1262 		dev_err(&adapter->pdev->dev, "%s: timeout, st=0x%x\n",
1263 			__func__, adapter->driver_cmds.transport_cmd.status);
1264 		leapraid_log_req_context(adapter, inter_taskid,
1265 					 smp_passthrough_req);
1266 		if (!(adapter->driver_cmds.transport_cmd.status &
1267 		      LEAPRAID_CMD_RESET)) {
1268 			dev_dbg(&adapter->pdev->dev,
1269 				"%s:%d: call hard_reset\n",
1270 				__func__, __LINE__);
1271 			leapraid_hard_reset_handler(adapter, FULL_RESET);
1272 			return -ETIMEDOUT;
1273 		}
1274 	}
1275 
1276 	dev_dbg(&adapter->pdev->dev, "%s: SMP request complete\n", __func__);
1277 	if (!(adapter->driver_cmds.transport_cmd.status &
1278 	      LEAPRAID_CMD_REPLY_VALID)) {
1279 		dev_err(&adapter->pdev->dev,
1280 			"%s: SMP request no reply\n", __func__);
1281 		return -ENXIO;
1282 	}
1283 
1284 	return 0;
1285 }
1286 
1287 static void leapraid_handle_smp_rep(struct leapraid_adapter *adapter,
1288 				    struct bsg_job *job, void *addr_in,
1289 				    unsigned int *reslen)
1290 {
1291 	struct leapraid_smp_passthrough_rep *smp_passthrough_rep;
1292 
1293 	smp_passthrough_rep =
1294 		(void *)&adapter->driver_cmds.transport_cmd.reply;
1295 
1296 	dev_dbg(&adapter->pdev->dev, "%s: Response data len=%d\n",
1297 		__func__, le16_to_cpu(smp_passthrough_rep->resp_data_len));
1298 
1299 	memcpy(job->reply, smp_passthrough_rep, sizeof(*smp_passthrough_rep));
1300 	job->reply_len = sizeof(*smp_passthrough_rep);
1301 	*reslen = le16_to_cpu(smp_passthrough_rep->resp_data_len);
1302 
1303 	if (addr_in)
1304 		sg_copy_from_buffer(job->reply_payload.sg_list,
1305 				    job->reply_payload.sg_cnt, addr_in,
1306 				    job->reply_payload.payload_len);
1307 }
1308 
1309 static void leapraid_transport_smp_handler(struct bsg_job *job,
1310 					   struct Scsi_Host *shost,
1311 					   struct sas_rphy *rphy)
1312 {
1313 	struct leapraid_adapter *adapter = shost_priv(shost);
1314 	dma_addr_t c2h_dma_addr;
1315 	dma_addr_t h2c_dma_addr;
1316 	void *addr_in = NULL;
1317 	void *addr_out = NULL;
1318 	size_t c2h_size;
1319 	size_t h2c_size;
1320 	int rc;
1321 	unsigned int reslen = 0;
1322 
1323 	if (adapter->access_ctrl.shost_recovering ||
1324 	    adapter->access_ctrl.pcie_recovering) {
1325 		dev_err(&adapter->pdev->dev,
1326 			"%s: Failed, shost_recovering=%d pcie_recovering=%d\n",
1327 			__func__,
1328 			adapter->access_ctrl.shost_recovering,
1329 			adapter->access_ctrl.pcie_recovering);
1330 		rc = -EFAULT;
1331 		goto exit_bsg_job;
1332 	}
1333 
1334 	rc = mutex_lock_interruptible(&adapter->driver_cmds
1335 				      .transport_cmd.mutex);
1336 	if (rc)
1337 		goto exit_bsg_job;
1338 
1339 	adapter->driver_cmds.transport_cmd.status = LEAPRAID_CMD_PENDING;
1340 	rc = leapraid_dma_map_buffer(&adapter->pdev->dev,
1341 				     &job->request_payload,
1342 				     &h2c_dma_addr, &h2c_size, &addr_out);
1343 	if (rc)
1344 		goto release_lock;
1345 
1346 	if (h2c_size < LEAPRAID_SMP_FRAME_HEADER_SIZE) {
1347 		dev_err(&adapter->pdev->dev,
1348 			"%s: Invalid SMP request payload size=%zu\n",
1349 			__func__, h2c_size);
1350 		rc = -EINVAL;
1351 		goto free_req_buf;
1352 	}
1353 
1354 	if (addr_out)
1355 		sg_copy_to_buffer(job->request_payload.sg_list,
1356 				  job->request_payload.sg_cnt, addr_out,
1357 				  job->request_payload.payload_len);
1358 
1359 	rc = leapraid_dma_map_buffer(&adapter->pdev->dev, &job->reply_payload,
1360 				     &c2h_dma_addr, &c2h_size, &addr_in);
1361 	if (rc)
1362 		goto free_req_buf;
1363 
1364 	if (c2h_size < LEAPRAID_SMP_FRAME_HEADER_SIZE) {
1365 		dev_err(&adapter->pdev->dev,
1366 			"%s: Invalid SMP reply payload size=%zu\n",
1367 			__func__, c2h_size);
1368 		rc = -EINVAL;
1369 		goto free_rep_buf;
1370 	}
1371 
1372 	rc = leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_SHORT,
1373 					  __func__);
1374 	if (rc)
1375 		goto free_rep_buf;
1376 
1377 	leapraid_build_smp_task(adapter, rphy, h2c_dma_addr,
1378 				h2c_size, c2h_dma_addr, c2h_size);
1379 
1380 	rc = leapraid_send_smp_req(adapter);
1381 	if (rc)
1382 		goto free_rep_buf;
1383 
1384 	leapraid_handle_smp_rep(adapter, job, addr_in, &reslen);
1385 
1386 free_rep_buf:
1387 	leapraid_dma_unmap_buffer(&adapter->pdev->dev, &job->reply_payload,
1388 				  c2h_dma_addr, addr_in);
1389 free_req_buf:
1390 	leapraid_dma_unmap_buffer(&adapter->pdev->dev, &job->request_payload,
1391 				  h2c_dma_addr, addr_out);
1392 release_lock:
1393 	adapter->driver_cmds.transport_cmd.status = LEAPRAID_CMD_NOT_USED;
1394 	mutex_unlock(&adapter->driver_cmds.transport_cmd.mutex);
1395 exit_bsg_job:
1396 	bsg_job_done(job, rc, reslen);
1397 }
1398 
1399 struct sas_function_template leapraid_transport_functions = {
1400 	.smp_handler = leapraid_transport_smp_handler,
1401 };
1402 
1403 struct scsi_transport_template *leapraid_transport_template;
1404