1 /* 2 * driver for Microsemi PQI-based storage controllers 3 * Copyright (c) 2019 Microchip Technology Inc. and its subsidiaries 4 * Copyright (c) 2016-2018 Microsemi Corporation 5 * Copyright (c) 2016 PMC-Sierra, Inc. 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; version 2 of the License. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 14 * NON INFRINGEMENT. See the GNU General Public License for more details. 15 * 16 * Questions/Comments/Bugfixes to storagedev@microchip.com 17 * 18 */ 19 20 #include <linux/kernel.h> 21 #include <linux/bsg-lib.h> 22 #include <scsi/scsi_host.h> 23 #include <scsi/scsi_cmnd.h> 24 #include <scsi/scsi_transport_sas.h> 25 #include <asm/unaligned.h> 26 #include "smartpqi.h" 27 28 static struct pqi_sas_phy *pqi_alloc_sas_phy(struct pqi_sas_port *pqi_sas_port) 29 { 30 struct pqi_sas_phy *pqi_sas_phy; 31 struct sas_phy *phy; 32 33 pqi_sas_phy = kzalloc(sizeof(*pqi_sas_phy), GFP_KERNEL); 34 if (!pqi_sas_phy) 35 return NULL; 36 37 phy = sas_phy_alloc(pqi_sas_port->parent_node->parent_dev, 38 pqi_sas_port->next_phy_index); 39 if (!phy) { 40 kfree(pqi_sas_phy); 41 return NULL; 42 } 43 44 pqi_sas_port->next_phy_index++; 45 pqi_sas_phy->phy = phy; 46 pqi_sas_phy->parent_port = pqi_sas_port; 47 48 return pqi_sas_phy; 49 } 50 51 static void pqi_free_sas_phy(struct pqi_sas_phy *pqi_sas_phy) 52 { 53 struct sas_phy *phy = pqi_sas_phy->phy; 54 55 sas_port_delete_phy(pqi_sas_phy->parent_port->port, phy); 56 sas_phy_free(phy); 57 if (pqi_sas_phy->added_to_port) 58 list_del(&pqi_sas_phy->phy_list_entry); 59 kfree(pqi_sas_phy); 60 } 61 62 static int pqi_sas_port_add_phy(struct pqi_sas_phy *pqi_sas_phy) 63 { 64 int rc; 65 struct pqi_sas_port *pqi_sas_port; 66 struct sas_phy *phy; 67 struct sas_identify *identify; 68 69 pqi_sas_port = pqi_sas_phy->parent_port; 70 phy = pqi_sas_phy->phy; 71 72 identify = &phy->identify; 73 memset(identify, 0, sizeof(*identify)); 74 identify->sas_address = pqi_sas_port->sas_address; 75 identify->device_type = SAS_END_DEVICE; 76 identify->initiator_port_protocols = SAS_PROTOCOL_STP; 77 identify->target_port_protocols = SAS_PROTOCOL_STP; 78 phy->minimum_linkrate_hw = SAS_LINK_RATE_UNKNOWN; 79 phy->maximum_linkrate_hw = SAS_LINK_RATE_UNKNOWN; 80 phy->minimum_linkrate = SAS_LINK_RATE_UNKNOWN; 81 phy->maximum_linkrate = SAS_LINK_RATE_UNKNOWN; 82 phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN; 83 84 rc = sas_phy_add(pqi_sas_phy->phy); 85 if (rc) 86 return rc; 87 88 sas_port_add_phy(pqi_sas_port->port, pqi_sas_phy->phy); 89 list_add_tail(&pqi_sas_phy->phy_list_entry, 90 &pqi_sas_port->phy_list_head); 91 pqi_sas_phy->added_to_port = true; 92 93 return 0; 94 } 95 96 static int pqi_sas_port_add_rphy(struct pqi_sas_port *pqi_sas_port, 97 struct sas_rphy *rphy) 98 { 99 struct sas_identify *identify; 100 101 identify = &rphy->identify; 102 identify->sas_address = pqi_sas_port->sas_address; 103 104 if (pqi_sas_port->device && 105 pqi_sas_port->device->is_expander_smp_device) { 106 identify->initiator_port_protocols = SAS_PROTOCOL_SMP; 107 identify->target_port_protocols = SAS_PROTOCOL_SMP; 108 } else { 109 identify->initiator_port_protocols = SAS_PROTOCOL_STP; 110 identify->target_port_protocols = SAS_PROTOCOL_STP; 111 } 112 113 return sas_rphy_add(rphy); 114 } 115 116 static struct sas_rphy *pqi_sas_rphy_alloc(struct pqi_sas_port *pqi_sas_port) 117 { 118 if (pqi_sas_port->device && 119 pqi_sas_port->device->is_expander_smp_device) 120 return sas_expander_alloc(pqi_sas_port->port, 121 SAS_FANOUT_EXPANDER_DEVICE); 122 123 return sas_end_device_alloc(pqi_sas_port->port); 124 } 125 126 static struct pqi_sas_port *pqi_alloc_sas_port( 127 struct pqi_sas_node *pqi_sas_node, u64 sas_address, 128 struct pqi_scsi_dev *device) 129 { 130 int rc; 131 struct pqi_sas_port *pqi_sas_port; 132 struct sas_port *port; 133 134 pqi_sas_port = kzalloc(sizeof(*pqi_sas_port), GFP_KERNEL); 135 if (!pqi_sas_port) 136 return NULL; 137 138 INIT_LIST_HEAD(&pqi_sas_port->phy_list_head); 139 pqi_sas_port->parent_node = pqi_sas_node; 140 141 port = sas_port_alloc_num(pqi_sas_node->parent_dev); 142 if (!port) 143 goto free_pqi_port; 144 145 rc = sas_port_add(port); 146 if (rc) 147 goto free_sas_port; 148 149 pqi_sas_port->port = port; 150 pqi_sas_port->sas_address = sas_address; 151 pqi_sas_port->device = device; 152 list_add_tail(&pqi_sas_port->port_list_entry, 153 &pqi_sas_node->port_list_head); 154 155 return pqi_sas_port; 156 157 free_sas_port: 158 sas_port_free(port); 159 free_pqi_port: 160 kfree(pqi_sas_port); 161 162 return NULL; 163 } 164 165 static void pqi_free_sas_port(struct pqi_sas_port *pqi_sas_port) 166 { 167 struct pqi_sas_phy *pqi_sas_phy; 168 struct pqi_sas_phy *next; 169 170 list_for_each_entry_safe(pqi_sas_phy, next, 171 &pqi_sas_port->phy_list_head, phy_list_entry) 172 pqi_free_sas_phy(pqi_sas_phy); 173 174 sas_port_delete(pqi_sas_port->port); 175 list_del(&pqi_sas_port->port_list_entry); 176 kfree(pqi_sas_port); 177 } 178 179 static struct pqi_sas_node *pqi_alloc_sas_node(struct device *parent_dev) 180 { 181 struct pqi_sas_node *pqi_sas_node; 182 183 pqi_sas_node = kzalloc(sizeof(*pqi_sas_node), GFP_KERNEL); 184 if (pqi_sas_node) { 185 pqi_sas_node->parent_dev = parent_dev; 186 INIT_LIST_HEAD(&pqi_sas_node->port_list_head); 187 } 188 189 return pqi_sas_node; 190 } 191 192 static void pqi_free_sas_node(struct pqi_sas_node *pqi_sas_node) 193 { 194 struct pqi_sas_port *pqi_sas_port; 195 struct pqi_sas_port *next; 196 197 if (!pqi_sas_node) 198 return; 199 200 list_for_each_entry_safe(pqi_sas_port, next, 201 &pqi_sas_node->port_list_head, port_list_entry) 202 pqi_free_sas_port(pqi_sas_port); 203 204 kfree(pqi_sas_node); 205 } 206 207 struct pqi_scsi_dev *pqi_find_device_by_sas_rphy( 208 struct pqi_ctrl_info *ctrl_info, struct sas_rphy *rphy) 209 { 210 struct pqi_scsi_dev *device; 211 212 list_for_each_entry(device, &ctrl_info->scsi_device_list, 213 scsi_device_list_entry) { 214 if (!device->sas_port) 215 continue; 216 if (device->sas_port->rphy == rphy) 217 return device; 218 } 219 220 return NULL; 221 } 222 223 int pqi_add_sas_host(struct Scsi_Host *shost, struct pqi_ctrl_info *ctrl_info) 224 { 225 int rc; 226 struct device *parent_dev; 227 struct pqi_sas_node *pqi_sas_node; 228 struct pqi_sas_port *pqi_sas_port; 229 struct pqi_sas_phy *pqi_sas_phy; 230 231 parent_dev = &shost->shost_dev; 232 233 pqi_sas_node = pqi_alloc_sas_node(parent_dev); 234 if (!pqi_sas_node) 235 return -ENOMEM; 236 237 pqi_sas_port = pqi_alloc_sas_port(pqi_sas_node, 238 ctrl_info->sas_address, NULL); 239 if (!pqi_sas_port) { 240 rc = -ENODEV; 241 goto free_sas_node; 242 } 243 244 pqi_sas_phy = pqi_alloc_sas_phy(pqi_sas_port); 245 if (!pqi_sas_phy) { 246 rc = -ENODEV; 247 goto free_sas_port; 248 } 249 250 rc = pqi_sas_port_add_phy(pqi_sas_phy); 251 if (rc) 252 goto free_sas_phy; 253 254 ctrl_info->sas_host = pqi_sas_node; 255 256 return 0; 257 258 free_sas_phy: 259 pqi_free_sas_phy(pqi_sas_phy); 260 free_sas_port: 261 pqi_free_sas_port(pqi_sas_port); 262 free_sas_node: 263 pqi_free_sas_node(pqi_sas_node); 264 265 return rc; 266 } 267 268 void pqi_delete_sas_host(struct pqi_ctrl_info *ctrl_info) 269 { 270 pqi_free_sas_node(ctrl_info->sas_host); 271 } 272 273 int pqi_add_sas_device(struct pqi_sas_node *pqi_sas_node, 274 struct pqi_scsi_dev *device) 275 { 276 int rc; 277 struct pqi_sas_port *pqi_sas_port; 278 struct sas_rphy *rphy; 279 280 pqi_sas_port = pqi_alloc_sas_port(pqi_sas_node, 281 device->sas_address, device); 282 if (!pqi_sas_port) 283 return -ENOMEM; 284 285 rphy = pqi_sas_rphy_alloc(pqi_sas_port); 286 if (!rphy) { 287 rc = -ENODEV; 288 goto free_sas_port; 289 } 290 291 pqi_sas_port->rphy = rphy; 292 device->sas_port = pqi_sas_port; 293 294 rc = pqi_sas_port_add_rphy(pqi_sas_port, rphy); 295 if (rc) 296 goto free_sas_port; 297 298 return 0; 299 300 free_sas_port: 301 pqi_free_sas_port(pqi_sas_port); 302 device->sas_port = NULL; 303 304 return rc; 305 } 306 307 void pqi_remove_sas_device(struct pqi_scsi_dev *device) 308 { 309 if (device->sas_port) { 310 pqi_free_sas_port(device->sas_port); 311 device->sas_port = NULL; 312 } 313 } 314 315 static int pqi_sas_get_linkerrors(struct sas_phy *phy) 316 { 317 return 0; 318 } 319 320 static int pqi_sas_get_enclosure_identifier(struct sas_rphy *rphy, 321 u64 *identifier) 322 { 323 return 0; 324 } 325 326 static int pqi_sas_get_bay_identifier(struct sas_rphy *rphy) 327 { 328 return -ENXIO; 329 } 330 331 static int pqi_sas_phy_reset(struct sas_phy *phy, int hard_reset) 332 { 333 return 0; 334 } 335 336 static int pqi_sas_phy_enable(struct sas_phy *phy, int enable) 337 { 338 return 0; 339 } 340 341 static int pqi_sas_phy_setup(struct sas_phy *phy) 342 { 343 return 0; 344 } 345 346 static void pqi_sas_phy_release(struct sas_phy *phy) 347 { 348 } 349 350 static int pqi_sas_phy_speed(struct sas_phy *phy, 351 struct sas_phy_linkrates *rates) 352 { 353 return -EINVAL; 354 } 355 356 #define CSMI_IOCTL_TIMEOUT 60 357 #define SMP_CRC_FIELD_LENGTH 4 358 359 static struct bmic_csmi_smp_passthru_buffer * 360 pqi_build_csmi_smp_passthru_buffer(struct sas_rphy *rphy, 361 struct bsg_job *job) 362 { 363 struct bmic_csmi_smp_passthru_buffer *smp_buf; 364 struct bmic_csmi_ioctl_header *ioctl_header; 365 struct bmic_csmi_smp_passthru *parameters; 366 u32 req_size; 367 u32 resp_size; 368 369 smp_buf = kzalloc(sizeof(*smp_buf), GFP_KERNEL); 370 if (!smp_buf) 371 return NULL; 372 373 req_size = job->request_payload.payload_len; 374 resp_size = job->reply_payload.payload_len; 375 376 ioctl_header = &smp_buf->ioctl_header; 377 put_unaligned_le32(sizeof(smp_buf->ioctl_header), 378 &ioctl_header->header_length); 379 put_unaligned_le32(CSMI_IOCTL_TIMEOUT, &ioctl_header->timeout); 380 put_unaligned_le32(CSMI_CC_SAS_SMP_PASSTHRU, 381 &ioctl_header->control_code); 382 put_unaligned_le32(sizeof(smp_buf->parameters), &ioctl_header->length); 383 384 parameters = &smp_buf->parameters; 385 parameters->phy_identifier = rphy->identify.phy_identifier; 386 parameters->port_identifier = 0; 387 parameters->connection_rate = 0; 388 put_unaligned_be64(rphy->identify.sas_address, 389 ¶meters->destination_sas_address); 390 391 if (req_size > SMP_CRC_FIELD_LENGTH) 392 req_size -= SMP_CRC_FIELD_LENGTH; 393 394 put_unaligned_le32(req_size, ¶meters->request_length); 395 396 put_unaligned_le32(resp_size, ¶meters->response_length); 397 398 sg_copy_to_buffer(job->request_payload.sg_list, 399 job->reply_payload.sg_cnt, ¶meters->request, 400 req_size); 401 402 return smp_buf; 403 } 404 405 static unsigned int pqi_build_sas_smp_handler_reply( 406 struct bmic_csmi_smp_passthru_buffer *smp_buf, struct bsg_job *job, 407 struct pqi_raid_error_info *error_info) 408 { 409 sg_copy_from_buffer(job->reply_payload.sg_list, 410 job->reply_payload.sg_cnt, &smp_buf->parameters.response, 411 le32_to_cpu(smp_buf->parameters.response_length)); 412 413 job->reply_len = le16_to_cpu(error_info->sense_data_length); 414 memcpy(job->reply, error_info->data, 415 le16_to_cpu(error_info->sense_data_length)); 416 417 return job->reply_payload.payload_len - 418 get_unaligned_le32(&error_info->data_in_transferred); 419 } 420 421 void pqi_sas_smp_handler(struct bsg_job *job, struct Scsi_Host *shost, 422 struct sas_rphy *rphy) 423 { 424 int rc; 425 struct pqi_ctrl_info *ctrl_info = shost_to_hba(shost); 426 struct bmic_csmi_smp_passthru_buffer *smp_buf; 427 struct pqi_raid_error_info error_info; 428 unsigned int reslen = 0; 429 430 pqi_ctrl_busy(ctrl_info); 431 432 if (job->reply_payload.payload_len == 0) { 433 rc = -ENOMEM; 434 goto out; 435 } 436 437 if (!rphy) { 438 rc = -EINVAL; 439 goto out; 440 } 441 442 if (rphy->identify.device_type != SAS_FANOUT_EXPANDER_DEVICE) { 443 rc = -EINVAL; 444 goto out; 445 } 446 447 if (job->request_payload.sg_cnt > 1 || job->reply_payload.sg_cnt > 1) { 448 rc = -EINVAL; 449 goto out; 450 } 451 452 if (pqi_ctrl_offline(ctrl_info)) { 453 rc = -ENXIO; 454 goto out; 455 } 456 457 if (pqi_ctrl_blocked(ctrl_info)) { 458 rc = -EBUSY; 459 goto out; 460 } 461 462 smp_buf = pqi_build_csmi_smp_passthru_buffer(rphy, job); 463 if (!smp_buf) { 464 rc = -ENOMEM; 465 goto out; 466 } 467 468 rc = pqi_csmi_smp_passthru(ctrl_info, smp_buf, sizeof(*smp_buf), 469 &error_info); 470 if (rc) 471 goto out; 472 473 reslen = pqi_build_sas_smp_handler_reply(smp_buf, job, &error_info); 474 out: 475 bsg_job_done(job, rc, reslen); 476 pqi_ctrl_unbusy(ctrl_info); 477 } 478 struct sas_function_template pqi_sas_transport_functions = { 479 .get_linkerrors = pqi_sas_get_linkerrors, 480 .get_enclosure_identifier = pqi_sas_get_enclosure_identifier, 481 .get_bay_identifier = pqi_sas_get_bay_identifier, 482 .phy_reset = pqi_sas_phy_reset, 483 .phy_enable = pqi_sas_phy_enable, 484 .phy_setup = pqi_sas_phy_setup, 485 .phy_release = pqi_sas_phy_release, 486 .set_phy_speed = pqi_sas_phy_speed, 487 .smp_handler = pqi_sas_smp_handler, 488 }; 489