2 * driver for Microsemi PQI-based storage controllers
3 * Copyright (c) 2016-2017 Microsemi Corporation
4 * Copyright (c) 2016 PMC-Sierra, Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
13 * NON INFRINGEMENT. See the GNU General Public License for more details.
15 * Questions/Comments/Bugfixes to esc.storagedev@microsemi.com
19 #include <linux/kernel.h>
20 #include <linux/bsg-lib.h>
21 #include <scsi/scsi_host.h>
22 #include <scsi/scsi_cmnd.h>
23 #include <scsi/scsi_transport_sas.h>
24 #include <asm/unaligned.h>
27 static struct pqi_sas_phy
*pqi_alloc_sas_phy(struct pqi_sas_port
*pqi_sas_port
)
29 struct pqi_sas_phy
*pqi_sas_phy
;
32 pqi_sas_phy
= kzalloc(sizeof(*pqi_sas_phy
), GFP_KERNEL
);
36 phy
= sas_phy_alloc(pqi_sas_port
->parent_node
->parent_dev
,
37 pqi_sas_port
->next_phy_index
);
43 pqi_sas_port
->next_phy_index
++;
44 pqi_sas_phy
->phy
= phy
;
45 pqi_sas_phy
->parent_port
= pqi_sas_port
;
50 static void pqi_free_sas_phy(struct pqi_sas_phy
*pqi_sas_phy
)
52 struct sas_phy
*phy
= pqi_sas_phy
->phy
;
54 sas_port_delete_phy(pqi_sas_phy
->parent_port
->port
, phy
);
56 if (pqi_sas_phy
->added_to_port
)
57 list_del(&pqi_sas_phy
->phy_list_entry
);
61 static int pqi_sas_port_add_phy(struct pqi_sas_phy
*pqi_sas_phy
)
64 struct pqi_sas_port
*pqi_sas_port
;
66 struct sas_identify
*identify
;
68 pqi_sas_port
= pqi_sas_phy
->parent_port
;
69 phy
= pqi_sas_phy
->phy
;
71 identify
= &phy
->identify
;
72 memset(identify
, 0, sizeof(*identify
));
73 identify
->sas_address
= pqi_sas_port
->sas_address
;
74 identify
->device_type
= SAS_END_DEVICE
;
75 identify
->initiator_port_protocols
= SAS_PROTOCOL_STP
;
76 identify
->target_port_protocols
= SAS_PROTOCOL_STP
;
77 phy
->minimum_linkrate_hw
= SAS_LINK_RATE_UNKNOWN
;
78 phy
->maximum_linkrate_hw
= SAS_LINK_RATE_UNKNOWN
;
79 phy
->minimum_linkrate
= SAS_LINK_RATE_UNKNOWN
;
80 phy
->maximum_linkrate
= SAS_LINK_RATE_UNKNOWN
;
81 phy
->negotiated_linkrate
= SAS_LINK_RATE_UNKNOWN
;
83 rc
= sas_phy_add(pqi_sas_phy
->phy
);
87 sas_port_add_phy(pqi_sas_port
->port
, pqi_sas_phy
->phy
);
88 list_add_tail(&pqi_sas_phy
->phy_list_entry
,
89 &pqi_sas_port
->phy_list_head
);
90 pqi_sas_phy
->added_to_port
= true;
95 static int pqi_sas_port_add_rphy(struct pqi_sas_port
*pqi_sas_port
,
96 struct sas_rphy
*rphy
)
98 struct sas_identify
*identify
;
100 identify
= &rphy
->identify
;
101 identify
->sas_address
= pqi_sas_port
->sas_address
;
103 if (pqi_sas_port
->device
&&
104 pqi_sas_port
->device
->is_expander_smp_device
) {
105 identify
->initiator_port_protocols
= SAS_PROTOCOL_SMP
;
106 identify
->target_port_protocols
= SAS_PROTOCOL_SMP
;
108 identify
->initiator_port_protocols
= SAS_PROTOCOL_STP
;
109 identify
->target_port_protocols
= SAS_PROTOCOL_STP
;
112 return sas_rphy_add(rphy
);
115 static struct sas_rphy
*pqi_sas_rphy_alloc(struct pqi_sas_port
*pqi_sas_port
)
117 if (pqi_sas_port
->device
&&
118 pqi_sas_port
->device
->is_expander_smp_device
)
119 return sas_expander_alloc(pqi_sas_port
->port
,
120 SAS_FANOUT_EXPANDER_DEVICE
);
122 return sas_end_device_alloc(pqi_sas_port
->port
);
125 static struct pqi_sas_port
*pqi_alloc_sas_port(
126 struct pqi_sas_node
*pqi_sas_node
, u64 sas_address
,
127 struct pqi_scsi_dev
*device
)
130 struct pqi_sas_port
*pqi_sas_port
;
131 struct sas_port
*port
;
133 pqi_sas_port
= kzalloc(sizeof(*pqi_sas_port
), GFP_KERNEL
);
137 INIT_LIST_HEAD(&pqi_sas_port
->phy_list_head
);
138 pqi_sas_port
->parent_node
= pqi_sas_node
;
140 port
= sas_port_alloc_num(pqi_sas_node
->parent_dev
);
144 rc
= sas_port_add(port
);
148 pqi_sas_port
->port
= port
;
149 pqi_sas_port
->sas_address
= sas_address
;
150 pqi_sas_port
->device
= device
;
151 list_add_tail(&pqi_sas_port
->port_list_entry
,
152 &pqi_sas_node
->port_list_head
);
164 static void pqi_free_sas_port(struct pqi_sas_port
*pqi_sas_port
)
166 struct pqi_sas_phy
*pqi_sas_phy
;
167 struct pqi_sas_phy
*next
;
169 list_for_each_entry_safe(pqi_sas_phy
, next
,
170 &pqi_sas_port
->phy_list_head
, phy_list_entry
)
171 pqi_free_sas_phy(pqi_sas_phy
);
173 sas_port_delete(pqi_sas_port
->port
);
174 list_del(&pqi_sas_port
->port_list_entry
);
178 static struct pqi_sas_node
*pqi_alloc_sas_node(struct device
*parent_dev
)
180 struct pqi_sas_node
*pqi_sas_node
;
182 pqi_sas_node
= kzalloc(sizeof(*pqi_sas_node
), GFP_KERNEL
);
184 pqi_sas_node
->parent_dev
= parent_dev
;
185 INIT_LIST_HEAD(&pqi_sas_node
->port_list_head
);
191 static void pqi_free_sas_node(struct pqi_sas_node
*pqi_sas_node
)
193 struct pqi_sas_port
*pqi_sas_port
;
194 struct pqi_sas_port
*next
;
199 list_for_each_entry_safe(pqi_sas_port
, next
,
200 &pqi_sas_node
->port_list_head
, port_list_entry
)
201 pqi_free_sas_port(pqi_sas_port
);
206 struct pqi_scsi_dev
*pqi_find_device_by_sas_rphy(
207 struct pqi_ctrl_info
*ctrl_info
, struct sas_rphy
*rphy
)
209 struct pqi_scsi_dev
*device
;
211 list_for_each_entry(device
, &ctrl_info
->scsi_device_list
,
212 scsi_device_list_entry
) {
213 if (!device
->sas_port
)
215 if (device
->sas_port
->rphy
== rphy
)
222 int pqi_add_sas_host(struct Scsi_Host
*shost
, struct pqi_ctrl_info
*ctrl_info
)
225 struct device
*parent_dev
;
226 struct pqi_sas_node
*pqi_sas_node
;
227 struct pqi_sas_port
*pqi_sas_port
;
228 struct pqi_sas_phy
*pqi_sas_phy
;
230 parent_dev
= &shost
->shost_dev
;
232 pqi_sas_node
= pqi_alloc_sas_node(parent_dev
);
236 pqi_sas_port
= pqi_alloc_sas_port(pqi_sas_node
,
237 ctrl_info
->sas_address
, NULL
);
243 pqi_sas_phy
= pqi_alloc_sas_phy(pqi_sas_port
);
249 rc
= pqi_sas_port_add_phy(pqi_sas_phy
);
253 ctrl_info
->sas_host
= pqi_sas_node
;
258 pqi_free_sas_phy(pqi_sas_phy
);
260 pqi_free_sas_port(pqi_sas_port
);
262 pqi_free_sas_node(pqi_sas_node
);
267 void pqi_delete_sas_host(struct pqi_ctrl_info
*ctrl_info
)
269 pqi_free_sas_node(ctrl_info
->sas_host
);
272 int pqi_add_sas_device(struct pqi_sas_node
*pqi_sas_node
,
273 struct pqi_scsi_dev
*device
)
276 struct pqi_sas_port
*pqi_sas_port
;
277 struct sas_rphy
*rphy
;
279 pqi_sas_port
= pqi_alloc_sas_port(pqi_sas_node
,
280 device
->sas_address
, device
);
284 rphy
= pqi_sas_rphy_alloc(pqi_sas_port
);
290 pqi_sas_port
->rphy
= rphy
;
291 device
->sas_port
= pqi_sas_port
;
293 rc
= pqi_sas_port_add_rphy(pqi_sas_port
, rphy
);
300 pqi_free_sas_port(pqi_sas_port
);
301 device
->sas_port
= NULL
;
306 void pqi_remove_sas_device(struct pqi_scsi_dev
*device
)
308 if (device
->sas_port
) {
309 pqi_free_sas_port(device
->sas_port
);
310 device
->sas_port
= NULL
;
314 static int pqi_sas_get_linkerrors(struct sas_phy
*phy
)
319 static int pqi_sas_get_enclosure_identifier(struct sas_rphy
*rphy
,
325 static int pqi_sas_get_bay_identifier(struct sas_rphy
*rphy
)
330 static int pqi_sas_phy_reset(struct sas_phy
*phy
, int hard_reset
)
335 static int pqi_sas_phy_enable(struct sas_phy
*phy
, int enable
)
340 static int pqi_sas_phy_setup(struct sas_phy
*phy
)
345 static void pqi_sas_phy_release(struct sas_phy
*phy
)
349 static int pqi_sas_phy_speed(struct sas_phy
*phy
,
350 struct sas_phy_linkrates
*rates
)
355 #define CSMI_IOCTL_TIMEOUT 60
356 #define SMP_CRC_FIELD_LENGTH 4
358 static struct bmic_csmi_smp_passthru_buffer
*
359 pqi_build_csmi_smp_passthru_buffer(struct sas_rphy
*rphy
,
362 struct bmic_csmi_smp_passthru_buffer
*smp_buf
;
363 struct bmic_csmi_ioctl_header
*ioctl_header
;
364 struct bmic_csmi_smp_passthru
*parameters
;
368 smp_buf
= kzalloc(sizeof(*smp_buf
), GFP_KERNEL
);
372 req_size
= job
->request_payload
.payload_len
;
373 resp_size
= job
->reply_payload
.payload_len
;
375 ioctl_header
= &smp_buf
->ioctl_header
;
376 put_unaligned_le32(sizeof(smp_buf
->ioctl_header
),
377 &ioctl_header
->header_length
);
378 put_unaligned_le32(CSMI_IOCTL_TIMEOUT
, &ioctl_header
->timeout
);
379 put_unaligned_le32(CSMI_CC_SAS_SMP_PASSTHRU
,
380 &ioctl_header
->control_code
);
381 put_unaligned_le32(sizeof(smp_buf
->parameters
), &ioctl_header
->length
);
383 parameters
= &smp_buf
->parameters
;
384 parameters
->phy_identifier
= rphy
->identify
.phy_identifier
;
385 parameters
->port_identifier
= 0;
386 parameters
->connection_rate
= 0;
387 put_unaligned_be64(rphy
->identify
.sas_address
,
388 ¶meters
->destination_sas_address
);
390 if (req_size
> SMP_CRC_FIELD_LENGTH
)
391 req_size
-= SMP_CRC_FIELD_LENGTH
;
393 put_unaligned_le32(req_size
, ¶meters
->request_length
);
395 put_unaligned_le32(resp_size
, ¶meters
->response_length
);
397 sg_copy_to_buffer(job
->request_payload
.sg_list
,
398 job
->reply_payload
.sg_cnt
, ¶meters
->request
,
404 static unsigned int pqi_build_sas_smp_handler_reply(
405 struct bmic_csmi_smp_passthru_buffer
*smp_buf
, struct bsg_job
*job
,
406 struct pqi_raid_error_info
*error_info
)
408 sg_copy_from_buffer(job
->reply_payload
.sg_list
,
409 job
->reply_payload
.sg_cnt
, &smp_buf
->parameters
.response
,
410 le32_to_cpu(smp_buf
->parameters
.response_length
));
412 job
->reply_len
= le16_to_cpu(error_info
->sense_data_length
);
413 memcpy(job
->reply
, error_info
->data
,
414 le16_to_cpu(error_info
->sense_data_length
));
416 return job
->reply_payload
.payload_len
-
417 get_unaligned_le32(&error_info
->data_in_transferred
);
420 void pqi_sas_smp_handler(struct bsg_job
*job
, struct Scsi_Host
*shost
,
421 struct sas_rphy
*rphy
)
424 struct pqi_ctrl_info
*ctrl_info
= shost_to_hba(shost
);
425 struct bmic_csmi_smp_passthru_buffer
*smp_buf
;
426 struct pqi_raid_error_info error_info
;
427 unsigned int reslen
= 0;
429 pqi_ctrl_busy(ctrl_info
);
431 if (job
->reply_payload
.payload_len
== 0) {
441 if (rphy
->identify
.device_type
!= SAS_FANOUT_EXPANDER_DEVICE
) {
446 if (job
->request_payload
.sg_cnt
> 1 || job
->reply_payload
.sg_cnt
> 1) {
451 if (pqi_ctrl_offline(ctrl_info
)) {
456 if (pqi_ctrl_blocked(ctrl_info
)) {
461 smp_buf
= pqi_build_csmi_smp_passthru_buffer(rphy
, job
);
467 rc
= pqi_csmi_smp_passthru(ctrl_info
, smp_buf
, sizeof(*smp_buf
),
472 reslen
= pqi_build_sas_smp_handler_reply(smp_buf
, job
, &error_info
);
474 bsg_job_done(job
, rc
, reslen
);
475 pqi_ctrl_unbusy(ctrl_info
);
477 struct sas_function_template pqi_sas_transport_functions
= {
478 .get_linkerrors
= pqi_sas_get_linkerrors
,
479 .get_enclosure_identifier
= pqi_sas_get_enclosure_identifier
,
480 .get_bay_identifier
= pqi_sas_get_bay_identifier
,
481 .phy_reset
= pqi_sas_phy_reset
,
482 .phy_enable
= pqi_sas_phy_enable
,
483 .phy_setup
= pqi_sas_phy_setup
,
484 .phy_release
= pqi_sas_phy_release
,
485 .set_phy_speed
= pqi_sas_phy_speed
,
486 .smp_handler
= pqi_sas_smp_handler
,