Lines Matching +full:phy +full:- +full:device

1 // SPDX-License-Identifier: GPL-2.0
3 * driver for Microsemi PQI-based storage controllers
5 * Copyright (c) 2016-2018 Microsemi Corporation
6 * Copyright (c) 2016 PMC-Sierra, Inc.
13 #include <linux/bsg-lib.h>
23 struct sas_phy *phy; in pqi_alloc_sas_phy() local
29 phy = sas_phy_alloc(pqi_sas_port->parent_node->parent_dev, in pqi_alloc_sas_phy()
30 pqi_sas_port->next_phy_index); in pqi_alloc_sas_phy()
31 if (!phy) { in pqi_alloc_sas_phy()
36 pqi_sas_port->next_phy_index++; in pqi_alloc_sas_phy()
37 pqi_sas_phy->phy = phy; in pqi_alloc_sas_phy()
38 pqi_sas_phy->parent_port = pqi_sas_port; in pqi_alloc_sas_phy()
45 struct sas_phy *phy = pqi_sas_phy->phy; in pqi_free_sas_phy() local
47 sas_port_delete_phy(pqi_sas_phy->parent_port->port, phy); in pqi_free_sas_phy()
48 sas_phy_free(phy); in pqi_free_sas_phy()
49 if (pqi_sas_phy->added_to_port) in pqi_free_sas_phy()
50 list_del(&pqi_sas_phy->phy_list_entry); in pqi_free_sas_phy()
58 struct sas_phy *phy; in pqi_sas_port_add_phy() local
61 pqi_sas_port = pqi_sas_phy->parent_port; in pqi_sas_port_add_phy()
62 phy = pqi_sas_phy->phy; in pqi_sas_port_add_phy()
64 identify = &phy->identify; in pqi_sas_port_add_phy()
66 identify->sas_address = pqi_sas_port->sas_address; in pqi_sas_port_add_phy()
67 identify->device_type = SAS_END_DEVICE; in pqi_sas_port_add_phy()
68 identify->initiator_port_protocols = SAS_PROTOCOL_STP; in pqi_sas_port_add_phy()
69 identify->target_port_protocols = SAS_PROTOCOL_STP; in pqi_sas_port_add_phy()
70 phy->minimum_linkrate_hw = SAS_LINK_RATE_UNKNOWN; in pqi_sas_port_add_phy()
71 phy->maximum_linkrate_hw = SAS_LINK_RATE_UNKNOWN; in pqi_sas_port_add_phy()
72 phy->minimum_linkrate = SAS_LINK_RATE_UNKNOWN; in pqi_sas_port_add_phy()
73 phy->maximum_linkrate = SAS_LINK_RATE_UNKNOWN; in pqi_sas_port_add_phy()
74 phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN; in pqi_sas_port_add_phy()
76 rc = sas_phy_add(pqi_sas_phy->phy); in pqi_sas_port_add_phy()
80 sas_port_add_phy(pqi_sas_port->port, pqi_sas_phy->phy); in pqi_sas_port_add_phy()
81 list_add_tail(&pqi_sas_phy->phy_list_entry, in pqi_sas_port_add_phy()
82 &pqi_sas_port->phy_list_head); in pqi_sas_port_add_phy()
83 pqi_sas_phy->added_to_port = true; in pqi_sas_port_add_phy()
93 identify = &rphy->identify; in pqi_sas_port_add_rphy()
94 identify->sas_address = pqi_sas_port->sas_address; in pqi_sas_port_add_rphy()
96 if (pqi_sas_port->device && in pqi_sas_port_add_rphy()
97 pqi_sas_port->device->is_expander_smp_device) { in pqi_sas_port_add_rphy()
98 identify->initiator_port_protocols = SAS_PROTOCOL_SMP; in pqi_sas_port_add_rphy()
99 identify->target_port_protocols = SAS_PROTOCOL_SMP; in pqi_sas_port_add_rphy()
101 identify->initiator_port_protocols = SAS_PROTOCOL_STP; in pqi_sas_port_add_rphy()
102 identify->target_port_protocols = SAS_PROTOCOL_STP; in pqi_sas_port_add_rphy()
110 if (pqi_sas_port->device && in pqi_sas_rphy_alloc()
111 pqi_sas_port->device->is_expander_smp_device) in pqi_sas_rphy_alloc()
112 return sas_expander_alloc(pqi_sas_port->port, in pqi_sas_rphy_alloc()
115 return sas_end_device_alloc(pqi_sas_port->port); in pqi_sas_rphy_alloc()
120 struct pqi_scsi_dev *device) in pqi_alloc_sas_port() argument
130 INIT_LIST_HEAD(&pqi_sas_port->phy_list_head); in pqi_alloc_sas_port()
131 pqi_sas_port->parent_node = pqi_sas_node; in pqi_alloc_sas_port()
133 port = sas_port_alloc_num(pqi_sas_node->parent_dev); in pqi_alloc_sas_port()
141 pqi_sas_port->port = port; in pqi_alloc_sas_port()
142 pqi_sas_port->sas_address = sas_address; in pqi_alloc_sas_port()
143 pqi_sas_port->device = device; in pqi_alloc_sas_port()
144 list_add_tail(&pqi_sas_port->port_list_entry, in pqi_alloc_sas_port()
145 &pqi_sas_node->port_list_head); in pqi_alloc_sas_port()
163 &pqi_sas_port->phy_list_head, phy_list_entry) in pqi_free_sas_port()
166 sas_port_delete(pqi_sas_port->port); in pqi_free_sas_port()
167 list_del(&pqi_sas_port->port_list_entry); in pqi_free_sas_port()
171 static struct pqi_sas_node *pqi_alloc_sas_node(struct device *parent_dev) in pqi_alloc_sas_node()
177 pqi_sas_node->parent_dev = parent_dev; in pqi_alloc_sas_node()
178 INIT_LIST_HEAD(&pqi_sas_node->port_list_head); in pqi_alloc_sas_node()
193 &pqi_sas_node->port_list_head, port_list_entry) in pqi_free_sas_node()
202 struct pqi_scsi_dev *device; in pqi_find_device_by_sas_rphy() local
204 list_for_each_entry(device, &ctrl_info->scsi_device_list, in pqi_find_device_by_sas_rphy()
206 if (!device->sas_port) in pqi_find_device_by_sas_rphy()
208 if (device->sas_port->rphy == rphy) in pqi_find_device_by_sas_rphy()
209 return device; in pqi_find_device_by_sas_rphy()
218 struct device *parent_dev; in pqi_add_sas_host()
223 parent_dev = &shost->shost_dev; in pqi_add_sas_host()
227 return -ENOMEM; in pqi_add_sas_host()
230 ctrl_info->sas_address, NULL); in pqi_add_sas_host()
232 rc = -ENODEV; in pqi_add_sas_host()
238 rc = -ENODEV; in pqi_add_sas_host()
246 ctrl_info->sas_host = pqi_sas_node; in pqi_add_sas_host()
262 pqi_free_sas_node(ctrl_info->sas_host); in pqi_delete_sas_host()
266 struct pqi_scsi_dev *device) in pqi_add_sas_device() argument
273 device->sas_address, device); in pqi_add_sas_device()
275 return -ENOMEM; in pqi_add_sas_device()
279 rc = -ENODEV; in pqi_add_sas_device()
283 pqi_sas_port->rphy = rphy; in pqi_add_sas_device()
284 device->sas_port = pqi_sas_port; in pqi_add_sas_device()
294 device->sas_port = NULL; in pqi_add_sas_device()
299 void pqi_remove_sas_device(struct pqi_scsi_dev *device) in pqi_remove_sas_device() argument
301 if (device->sas_port) { in pqi_remove_sas_device()
302 pqi_free_sas_port(device->sas_port); in pqi_remove_sas_device()
303 device->sas_port = NULL; in pqi_remove_sas_device()
307 static int pqi_sas_get_linkerrors(struct sas_phy *phy) in pqi_sas_get_linkerrors() argument
321 struct pqi_scsi_dev *device; in pqi_sas_get_enclosure_identifier() local
324 return -ENODEV; in pqi_sas_get_enclosure_identifier()
328 spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags); in pqi_sas_get_enclosure_identifier()
332 rc = -ENODEV; in pqi_sas_get_enclosure_identifier()
336 if (found_device->devtype == TYPE_ENCLOSURE) { in pqi_sas_get_enclosure_identifier()
337 *identifier = get_unaligned_be64(&found_device->wwid); in pqi_sas_get_enclosure_identifier()
342 if (found_device->box_index == 0xff || in pqi_sas_get_enclosure_identifier()
343 found_device->phys_box_on_bus == 0 || in pqi_sas_get_enclosure_identifier()
344 found_device->bay == 0xff) { in pqi_sas_get_enclosure_identifier()
345 rc = -EINVAL; in pqi_sas_get_enclosure_identifier()
349 list_for_each_entry(device, &ctrl_info->scsi_device_list, in pqi_sas_get_enclosure_identifier()
351 if (device->devtype == TYPE_ENCLOSURE && in pqi_sas_get_enclosure_identifier()
352 device->box_index == found_device->box_index && in pqi_sas_get_enclosure_identifier()
353 device->phys_box_on_bus == in pqi_sas_get_enclosure_identifier()
354 found_device->phys_box_on_bus && in pqi_sas_get_enclosure_identifier()
355 memcmp(device->phys_connector, in pqi_sas_get_enclosure_identifier()
356 found_device->phys_connector, 2) == 0) { in pqi_sas_get_enclosure_identifier()
358 get_unaligned_be64(&device->wwid); in pqi_sas_get_enclosure_identifier()
364 if (found_device->phy_connected_dev_type != SA_CONTROLLER_DEVICE) { in pqi_sas_get_enclosure_identifier()
365 rc = -EINVAL; in pqi_sas_get_enclosure_identifier()
369 list_for_each_entry(device, &ctrl_info->scsi_device_list, in pqi_sas_get_enclosure_identifier()
371 if (device->devtype == TYPE_ENCLOSURE && in pqi_sas_get_enclosure_identifier()
372 CISS_GET_DRIVE_NUMBER(device->scsi3addr) == in pqi_sas_get_enclosure_identifier()
374 *identifier = get_unaligned_be64(&device->wwid); in pqi_sas_get_enclosure_identifier()
380 rc = -EINVAL; in pqi_sas_get_enclosure_identifier()
382 spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags); in pqi_sas_get_enclosure_identifier()
394 struct pqi_scsi_dev *device; in pqi_sas_get_bay_identifier() local
398 return -ENODEV; in pqi_sas_get_bay_identifier()
402 spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags); in pqi_sas_get_bay_identifier()
403 device = pqi_find_device_by_sas_rphy(ctrl_info, rphy); in pqi_sas_get_bay_identifier()
405 if (!device) { in pqi_sas_get_bay_identifier()
406 rc = -ENODEV; in pqi_sas_get_bay_identifier()
410 if (device->bay == 0xff) in pqi_sas_get_bay_identifier()
411 rc = -EINVAL; in pqi_sas_get_bay_identifier()
413 rc = device->bay; in pqi_sas_get_bay_identifier()
416 spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags); in pqi_sas_get_bay_identifier()
421 static int pqi_sas_phy_reset(struct sas_phy *phy, int hard_reset) in pqi_sas_phy_reset() argument
426 static int pqi_sas_phy_enable(struct sas_phy *phy, int enable) in pqi_sas_phy_enable() argument
431 static int pqi_sas_phy_setup(struct sas_phy *phy) in pqi_sas_phy_setup() argument
436 static void pqi_sas_phy_release(struct sas_phy *phy) in pqi_sas_phy_release() argument
440 static int pqi_sas_phy_speed(struct sas_phy *phy, in pqi_sas_phy_speed() argument
443 return -EINVAL; in pqi_sas_phy_speed()
463 req_size = job->request_payload.payload_len; in pqi_build_csmi_smp_passthru_buffer()
464 resp_size = job->reply_payload.payload_len; in pqi_build_csmi_smp_passthru_buffer()
466 ioctl_header = &smp_buf->ioctl_header; in pqi_build_csmi_smp_passthru_buffer()
467 put_unaligned_le32(sizeof(smp_buf->ioctl_header), in pqi_build_csmi_smp_passthru_buffer()
468 &ioctl_header->header_length); in pqi_build_csmi_smp_passthru_buffer()
469 put_unaligned_le32(CSMI_IOCTL_TIMEOUT, &ioctl_header->timeout); in pqi_build_csmi_smp_passthru_buffer()
471 &ioctl_header->control_code); in pqi_build_csmi_smp_passthru_buffer()
472 put_unaligned_le32(sizeof(smp_buf->parameters), &ioctl_header->length); in pqi_build_csmi_smp_passthru_buffer()
474 parameters = &smp_buf->parameters; in pqi_build_csmi_smp_passthru_buffer()
475 parameters->phy_identifier = rphy->identify.phy_identifier; in pqi_build_csmi_smp_passthru_buffer()
476 parameters->port_identifier = 0; in pqi_build_csmi_smp_passthru_buffer()
477 parameters->connection_rate = 0; in pqi_build_csmi_smp_passthru_buffer()
478 put_unaligned_be64(rphy->identify.sas_address, in pqi_build_csmi_smp_passthru_buffer()
479 &parameters->destination_sas_address); in pqi_build_csmi_smp_passthru_buffer()
482 req_size -= SMP_CRC_FIELD_LENGTH; in pqi_build_csmi_smp_passthru_buffer()
484 put_unaligned_le32(req_size, &parameters->request_length); in pqi_build_csmi_smp_passthru_buffer()
486 put_unaligned_le32(resp_size, &parameters->response_length); in pqi_build_csmi_smp_passthru_buffer()
488 sg_copy_to_buffer(job->request_payload.sg_list, in pqi_build_csmi_smp_passthru_buffer()
489 job->reply_payload.sg_cnt, &parameters->request, in pqi_build_csmi_smp_passthru_buffer()
499 sg_copy_from_buffer(job->reply_payload.sg_list, in pqi_build_sas_smp_handler_reply()
500 job->reply_payload.sg_cnt, &smp_buf->parameters.response, in pqi_build_sas_smp_handler_reply()
501 le32_to_cpu(smp_buf->parameters.response_length)); in pqi_build_sas_smp_handler_reply()
503 job->reply_len = le16_to_cpu(error_info->sense_data_length); in pqi_build_sas_smp_handler_reply()
504 memcpy(job->reply, error_info->data, in pqi_build_sas_smp_handler_reply()
505 le16_to_cpu(error_info->sense_data_length)); in pqi_build_sas_smp_handler_reply()
507 return job->reply_payload.payload_len - in pqi_build_sas_smp_handler_reply()
508 get_unaligned_le32(&error_info->data_in_transferred); in pqi_build_sas_smp_handler_reply()
522 if (job->reply_payload.payload_len == 0) { in pqi_sas_smp_handler()
523 rc = -ENOMEM; in pqi_sas_smp_handler()
528 rc = -EINVAL; in pqi_sas_smp_handler()
532 if (rphy->identify.device_type != SAS_FANOUT_EXPANDER_DEVICE) { in pqi_sas_smp_handler()
533 rc = -EINVAL; in pqi_sas_smp_handler()
537 if (job->request_payload.sg_cnt > 1 || job->reply_payload.sg_cnt > 1) { in pqi_sas_smp_handler()
538 rc = -EINVAL; in pqi_sas_smp_handler()
543 rc = -ENXIO; in pqi_sas_smp_handler()
548 rc = -EBUSY; in pqi_sas_smp_handler()
554 rc = -ENOMEM; in pqi_sas_smp_handler()