1 // SPDX-License-Identifier: GPL-2.0
3 * driver for Microsemi PQI-based storage controllers
4 * Copyright (c) 2019 Microchip Technology Inc. and its subsidiaries
5 * Copyright (c) 2016-2018 Microsemi Corporation
6 * Copyright (c) 2016 PMC-Sierra, Inc.
8 * Questions/Comments/Bugfixes to storagedev@microchip.com
12 #include <linux/kernel.h>
13 #include <linux/bsg-lib.h>
14 #include <scsi/scsi_host.h>
15 #include <scsi/scsi_cmnd.h>
16 #include <scsi/scsi_transport_sas.h>
17 #include <asm/unaligned.h>
20 static struct pqi_sas_phy
*pqi_alloc_sas_phy(struct pqi_sas_port
*pqi_sas_port
)
22 struct pqi_sas_phy
*pqi_sas_phy
;
25 pqi_sas_phy
= kzalloc(sizeof(*pqi_sas_phy
), GFP_KERNEL
);
29 phy
= sas_phy_alloc(pqi_sas_port
->parent_node
->parent_dev
,
30 pqi_sas_port
->next_phy_index
);
36 pqi_sas_port
->next_phy_index
++;
37 pqi_sas_phy
->phy
= phy
;
38 pqi_sas_phy
->parent_port
= pqi_sas_port
;
43 static void pqi_free_sas_phy(struct pqi_sas_phy
*pqi_sas_phy
)
45 struct sas_phy
*phy
= pqi_sas_phy
->phy
;
47 sas_port_delete_phy(pqi_sas_phy
->parent_port
->port
, phy
);
49 if (pqi_sas_phy
->added_to_port
)
50 list_del(&pqi_sas_phy
->phy_list_entry
);
54 static int pqi_sas_port_add_phy(struct pqi_sas_phy
*pqi_sas_phy
)
57 struct pqi_sas_port
*pqi_sas_port
;
59 struct sas_identify
*identify
;
61 pqi_sas_port
= pqi_sas_phy
->parent_port
;
62 phy
= pqi_sas_phy
->phy
;
64 identify
= &phy
->identify
;
65 memset(identify
, 0, sizeof(*identify
));
66 identify
->sas_address
= pqi_sas_port
->sas_address
;
67 identify
->device_type
= SAS_END_DEVICE
;
68 identify
->initiator_port_protocols
= SAS_PROTOCOL_STP
;
69 identify
->target_port_protocols
= SAS_PROTOCOL_STP
;
70 phy
->minimum_linkrate_hw
= SAS_LINK_RATE_UNKNOWN
;
71 phy
->maximum_linkrate_hw
= SAS_LINK_RATE_UNKNOWN
;
72 phy
->minimum_linkrate
= SAS_LINK_RATE_UNKNOWN
;
73 phy
->maximum_linkrate
= SAS_LINK_RATE_UNKNOWN
;
74 phy
->negotiated_linkrate
= SAS_LINK_RATE_UNKNOWN
;
76 rc
= sas_phy_add(pqi_sas_phy
->phy
);
80 sas_port_add_phy(pqi_sas_port
->port
, pqi_sas_phy
->phy
);
81 list_add_tail(&pqi_sas_phy
->phy_list_entry
,
82 &pqi_sas_port
->phy_list_head
);
83 pqi_sas_phy
->added_to_port
= true;
88 static int pqi_sas_port_add_rphy(struct pqi_sas_port
*pqi_sas_port
,
89 struct sas_rphy
*rphy
)
91 struct sas_identify
*identify
;
93 identify
= &rphy
->identify
;
94 identify
->sas_address
= pqi_sas_port
->sas_address
;
96 if (pqi_sas_port
->device
&&
97 pqi_sas_port
->device
->is_expander_smp_device
) {
98 identify
->initiator_port_protocols
= SAS_PROTOCOL_SMP
;
99 identify
->target_port_protocols
= SAS_PROTOCOL_SMP
;
101 identify
->initiator_port_protocols
= SAS_PROTOCOL_STP
;
102 identify
->target_port_protocols
= SAS_PROTOCOL_STP
;
105 return sas_rphy_add(rphy
);
108 static struct sas_rphy
*pqi_sas_rphy_alloc(struct pqi_sas_port
*pqi_sas_port
)
110 if (pqi_sas_port
->device
&&
111 pqi_sas_port
->device
->is_expander_smp_device
)
112 return sas_expander_alloc(pqi_sas_port
->port
,
113 SAS_FANOUT_EXPANDER_DEVICE
);
115 return sas_end_device_alloc(pqi_sas_port
->port
);
118 static struct pqi_sas_port
*pqi_alloc_sas_port(
119 struct pqi_sas_node
*pqi_sas_node
, u64 sas_address
,
120 struct pqi_scsi_dev
*device
)
123 struct pqi_sas_port
*pqi_sas_port
;
124 struct sas_port
*port
;
126 pqi_sas_port
= kzalloc(sizeof(*pqi_sas_port
), GFP_KERNEL
);
130 INIT_LIST_HEAD(&pqi_sas_port
->phy_list_head
);
131 pqi_sas_port
->parent_node
= pqi_sas_node
;
133 port
= sas_port_alloc_num(pqi_sas_node
->parent_dev
);
137 rc
= sas_port_add(port
);
141 pqi_sas_port
->port
= port
;
142 pqi_sas_port
->sas_address
= sas_address
;
143 pqi_sas_port
->device
= device
;
144 list_add_tail(&pqi_sas_port
->port_list_entry
,
145 &pqi_sas_node
->port_list_head
);
157 static void pqi_free_sas_port(struct pqi_sas_port
*pqi_sas_port
)
159 struct pqi_sas_phy
*pqi_sas_phy
;
160 struct pqi_sas_phy
*next
;
162 list_for_each_entry_safe(pqi_sas_phy
, next
,
163 &pqi_sas_port
->phy_list_head
, phy_list_entry
)
164 pqi_free_sas_phy(pqi_sas_phy
);
166 sas_port_delete(pqi_sas_port
->port
);
167 list_del(&pqi_sas_port
->port_list_entry
);
171 static struct pqi_sas_node
*pqi_alloc_sas_node(struct device
*parent_dev
)
173 struct pqi_sas_node
*pqi_sas_node
;
175 pqi_sas_node
= kzalloc(sizeof(*pqi_sas_node
), GFP_KERNEL
);
177 pqi_sas_node
->parent_dev
= parent_dev
;
178 INIT_LIST_HEAD(&pqi_sas_node
->port_list_head
);
184 static void pqi_free_sas_node(struct pqi_sas_node
*pqi_sas_node
)
186 struct pqi_sas_port
*pqi_sas_port
;
187 struct pqi_sas_port
*next
;
192 list_for_each_entry_safe(pqi_sas_port
, next
,
193 &pqi_sas_node
->port_list_head
, port_list_entry
)
194 pqi_free_sas_port(pqi_sas_port
);
199 struct pqi_scsi_dev
*pqi_find_device_by_sas_rphy(
200 struct pqi_ctrl_info
*ctrl_info
, struct sas_rphy
*rphy
)
202 struct pqi_scsi_dev
*device
;
204 list_for_each_entry(device
, &ctrl_info
->scsi_device_list
,
205 scsi_device_list_entry
) {
206 if (!device
->sas_port
)
208 if (device
->sas_port
->rphy
== rphy
)
215 int pqi_add_sas_host(struct Scsi_Host
*shost
, struct pqi_ctrl_info
*ctrl_info
)
218 struct device
*parent_dev
;
219 struct pqi_sas_node
*pqi_sas_node
;
220 struct pqi_sas_port
*pqi_sas_port
;
221 struct pqi_sas_phy
*pqi_sas_phy
;
223 parent_dev
= &shost
->shost_dev
;
225 pqi_sas_node
= pqi_alloc_sas_node(parent_dev
);
229 pqi_sas_port
= pqi_alloc_sas_port(pqi_sas_node
,
230 ctrl_info
->sas_address
, NULL
);
236 pqi_sas_phy
= pqi_alloc_sas_phy(pqi_sas_port
);
242 rc
= pqi_sas_port_add_phy(pqi_sas_phy
);
246 ctrl_info
->sas_host
= pqi_sas_node
;
251 pqi_free_sas_phy(pqi_sas_phy
);
253 pqi_free_sas_port(pqi_sas_port
);
255 pqi_free_sas_node(pqi_sas_node
);
260 void pqi_delete_sas_host(struct pqi_ctrl_info
*ctrl_info
)
262 pqi_free_sas_node(ctrl_info
->sas_host
);
265 int pqi_add_sas_device(struct pqi_sas_node
*pqi_sas_node
,
266 struct pqi_scsi_dev
*device
)
269 struct pqi_sas_port
*pqi_sas_port
;
270 struct sas_rphy
*rphy
;
272 pqi_sas_port
= pqi_alloc_sas_port(pqi_sas_node
,
273 device
->sas_address
, device
);
277 rphy
= pqi_sas_rphy_alloc(pqi_sas_port
);
283 pqi_sas_port
->rphy
= rphy
;
284 device
->sas_port
= pqi_sas_port
;
286 rc
= pqi_sas_port_add_rphy(pqi_sas_port
, rphy
);
293 pqi_free_sas_port(pqi_sas_port
);
294 device
->sas_port
= NULL
;
299 void pqi_remove_sas_device(struct pqi_scsi_dev
*device
)
301 if (device
->sas_port
) {
302 pqi_free_sas_port(device
->sas_port
);
303 device
->sas_port
= NULL
;
307 static int pqi_sas_get_linkerrors(struct sas_phy
*phy
)
312 static int pqi_sas_get_enclosure_identifier(struct sas_rphy
*rphy
,
318 static int pqi_sas_get_bay_identifier(struct sas_rphy
*rphy
)
323 static int pqi_sas_phy_reset(struct sas_phy
*phy
, int hard_reset
)
328 static int pqi_sas_phy_enable(struct sas_phy
*phy
, int enable
)
333 static int pqi_sas_phy_setup(struct sas_phy
*phy
)
338 static void pqi_sas_phy_release(struct sas_phy
*phy
)
342 static int pqi_sas_phy_speed(struct sas_phy
*phy
,
343 struct sas_phy_linkrates
*rates
)
348 #define CSMI_IOCTL_TIMEOUT 60
349 #define SMP_CRC_FIELD_LENGTH 4
351 static struct bmic_csmi_smp_passthru_buffer
*
352 pqi_build_csmi_smp_passthru_buffer(struct sas_rphy
*rphy
,
355 struct bmic_csmi_smp_passthru_buffer
*smp_buf
;
356 struct bmic_csmi_ioctl_header
*ioctl_header
;
357 struct bmic_csmi_smp_passthru
*parameters
;
361 smp_buf
= kzalloc(sizeof(*smp_buf
), GFP_KERNEL
);
365 req_size
= job
->request_payload
.payload_len
;
366 resp_size
= job
->reply_payload
.payload_len
;
368 ioctl_header
= &smp_buf
->ioctl_header
;
369 put_unaligned_le32(sizeof(smp_buf
->ioctl_header
),
370 &ioctl_header
->header_length
);
371 put_unaligned_le32(CSMI_IOCTL_TIMEOUT
, &ioctl_header
->timeout
);
372 put_unaligned_le32(CSMI_CC_SAS_SMP_PASSTHRU
,
373 &ioctl_header
->control_code
);
374 put_unaligned_le32(sizeof(smp_buf
->parameters
), &ioctl_header
->length
);
376 parameters
= &smp_buf
->parameters
;
377 parameters
->phy_identifier
= rphy
->identify
.phy_identifier
;
378 parameters
->port_identifier
= 0;
379 parameters
->connection_rate
= 0;
380 put_unaligned_be64(rphy
->identify
.sas_address
,
381 ¶meters
->destination_sas_address
);
383 if (req_size
> SMP_CRC_FIELD_LENGTH
)
384 req_size
-= SMP_CRC_FIELD_LENGTH
;
386 put_unaligned_le32(req_size
, ¶meters
->request_length
);
388 put_unaligned_le32(resp_size
, ¶meters
->response_length
);
390 sg_copy_to_buffer(job
->request_payload
.sg_list
,
391 job
->reply_payload
.sg_cnt
, ¶meters
->request
,
397 static unsigned int pqi_build_sas_smp_handler_reply(
398 struct bmic_csmi_smp_passthru_buffer
*smp_buf
, struct bsg_job
*job
,
399 struct pqi_raid_error_info
*error_info
)
401 sg_copy_from_buffer(job
->reply_payload
.sg_list
,
402 job
->reply_payload
.sg_cnt
, &smp_buf
->parameters
.response
,
403 le32_to_cpu(smp_buf
->parameters
.response_length
));
405 job
->reply_len
= le16_to_cpu(error_info
->sense_data_length
);
406 memcpy(job
->reply
, error_info
->data
,
407 le16_to_cpu(error_info
->sense_data_length
));
409 return job
->reply_payload
.payload_len
-
410 get_unaligned_le32(&error_info
->data_in_transferred
);
413 void pqi_sas_smp_handler(struct bsg_job
*job
, struct Scsi_Host
*shost
,
414 struct sas_rphy
*rphy
)
417 struct pqi_ctrl_info
*ctrl_info
= shost_to_hba(shost
);
418 struct bmic_csmi_smp_passthru_buffer
*smp_buf
;
419 struct pqi_raid_error_info error_info
;
420 unsigned int reslen
= 0;
422 pqi_ctrl_busy(ctrl_info
);
424 if (job
->reply_payload
.payload_len
== 0) {
434 if (rphy
->identify
.device_type
!= SAS_FANOUT_EXPANDER_DEVICE
) {
439 if (job
->request_payload
.sg_cnt
> 1 || job
->reply_payload
.sg_cnt
> 1) {
444 if (pqi_ctrl_offline(ctrl_info
)) {
449 if (pqi_ctrl_blocked(ctrl_info
)) {
454 smp_buf
= pqi_build_csmi_smp_passthru_buffer(rphy
, job
);
460 rc
= pqi_csmi_smp_passthru(ctrl_info
, smp_buf
, sizeof(*smp_buf
),
465 reslen
= pqi_build_sas_smp_handler_reply(smp_buf
, job
, &error_info
);
467 bsg_job_done(job
, rc
, reslen
);
468 pqi_ctrl_unbusy(ctrl_info
);
470 struct sas_function_template pqi_sas_transport_functions
= {
471 .get_linkerrors
= pqi_sas_get_linkerrors
,
472 .get_enclosure_identifier
= pqi_sas_get_enclosure_identifier
,
473 .get_bay_identifier
= pqi_sas_get_bay_identifier
,
474 .phy_reset
= pqi_sas_phy_reset
,
475 .phy_enable
= pqi_sas_phy_enable
,
476 .phy_setup
= pqi_sas_phy_setup
,
477 .phy_release
= pqi_sas_phy_release
,
478 .set_phy_speed
= pqi_sas_phy_speed
,
479 .smp_handler
= pqi_sas_smp_handler
,