1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Driver for Broadcom MPI3 Storage Controllers 4 * 5 * Copyright (C) 2017-2021 Broadcom Inc. 6 * (mailto: mpi3mr-linuxdrv.pdl@broadcom.com) 7 * 8 */ 9 10 #include "mpi3mr.h" 11 12 /* global driver scop variables */ 13 LIST_HEAD(mrioc_list); 14 DEFINE_SPINLOCK(mrioc_list_lock); 15 static int mrioc_ids; 16 static int warn_non_secure_ctlr; 17 18 MODULE_AUTHOR(MPI3MR_DRIVER_AUTHOR); 19 MODULE_DESCRIPTION(MPI3MR_DRIVER_DESC); 20 MODULE_LICENSE(MPI3MR_DRIVER_LICENSE); 21 MODULE_VERSION(MPI3MR_DRIVER_VERSION); 22 23 /* Module parameters*/ 24 int logging_level; 25 module_param(logging_level, int, 0); 26 MODULE_PARM_DESC(logging_level, 27 " bits for enabling additional logging info (default=0)"); 28 29 /** 30 * mpi3mr_map_queues - Map queues callback handler 31 * @shost: SCSI host reference 32 * 33 * Call the blk_mq_pci_map_queues with from which operational 34 * queue the mapping has to be done 35 * 36 * Return: return of blk_mq_pci_map_queues 37 */ 38 static int mpi3mr_map_queues(struct Scsi_Host *shost) 39 { 40 struct mpi3mr_ioc *mrioc = shost_priv(shost); 41 42 return blk_mq_pci_map_queues(&shost->tag_set.map[HCTX_TYPE_DEFAULT], 43 mrioc->pdev, mrioc->op_reply_q_offset); 44 } 45 46 /** 47 * mpi3mr_slave_destroy - Slave destroy callback handler 48 * @sdev: SCSI device reference 49 * 50 * Cleanup and free per device(lun) private data. 51 * 52 * Return: Nothing. 53 */ 54 static void mpi3mr_slave_destroy(struct scsi_device *sdev) 55 { 56 } 57 58 /** 59 * mpi3mr_target_destroy - Target destroy callback handler 60 * @starget: SCSI target reference 61 * 62 * Cleanup and free per target private data. 63 * 64 * Return: Nothing. 65 */ 66 static void mpi3mr_target_destroy(struct scsi_target *starget) 67 { 68 } 69 70 /** 71 * mpi3mr_slave_configure - Slave configure callback handler 72 * @sdev: SCSI device reference 73 * 74 * Configure queue depth, max hardware sectors and virt boundary 75 * as required 76 * 77 * Return: 0 always. 78 */ 79 static int mpi3mr_slave_configure(struct scsi_device *sdev) 80 { 81 int retval = 0; 82 return retval; 83 } 84 85 /** 86 * mpi3mr_slave_alloc -Slave alloc callback handler 87 * @sdev: SCSI device reference 88 * 89 * Allocate per device(lun) private data and initialize it. 90 * 91 * Return: 0 on success -ENOMEM on memory allocation failure. 92 */ 93 static int mpi3mr_slave_alloc(struct scsi_device *sdev) 94 { 95 int retval = 0; 96 return retval; 97 } 98 99 /** 100 * mpi3mr_target_alloc - Target alloc callback handler 101 * @starget: SCSI target reference 102 * 103 * Allocate per target private data and initialize it. 104 * 105 * Return: 0 on success -ENOMEM on memory allocation failure. 106 */ 107 static int mpi3mr_target_alloc(struct scsi_target *starget) 108 { 109 int retval = -ENODEV; 110 return retval; 111 } 112 113 /** 114 * mpi3mr_qcmd - I/O request despatcher 115 * @shost: SCSI Host reference 116 * @scmd: SCSI Command reference 117 * 118 * Issues the SCSI Command as an MPI3 request. 119 * 120 * Return: 0 on successful queueing of the request or if the 121 * request is completed with failure. 122 * SCSI_MLQUEUE_DEVICE_BUSY when the device is busy. 123 * SCSI_MLQUEUE_HOST_BUSY when the host queue is full. 124 */ 125 static int mpi3mr_qcmd(struct Scsi_Host *shost, 126 struct scsi_cmnd *scmd) 127 { 128 int retval = 0; 129 130 scmd->result = DID_NO_CONNECT << 16; 131 scmd->scsi_done(scmd); 132 return retval; 133 } 134 135 static struct scsi_host_template mpi3mr_driver_template = { 136 .module = THIS_MODULE, 137 .name = "MPI3 Storage Controller", 138 .proc_name = MPI3MR_DRIVER_NAME, 139 .queuecommand = mpi3mr_qcmd, 140 .target_alloc = mpi3mr_target_alloc, 141 .slave_alloc = mpi3mr_slave_alloc, 142 .slave_configure = mpi3mr_slave_configure, 143 .target_destroy = mpi3mr_target_destroy, 144 .slave_destroy = mpi3mr_slave_destroy, 145 .map_queues = mpi3mr_map_queues, 146 .no_write_same = 1, 147 .can_queue = 1, 148 .this_id = -1, 149 .sg_tablesize = MPI3MR_SG_DEPTH, 150 /* max xfer supported is 1M (2K in 512 byte sized sectors) 151 */ 152 .max_sectors = 2048, 153 .cmd_per_lun = MPI3MR_MAX_CMDS_LUN, 154 .track_queue_depth = 1, 155 .cmd_size = sizeof(struct scmd_priv), 156 }; 157 158 /** 159 * mpi3mr_init_drv_cmd - Initialize internal command tracker 160 * @cmdptr: Internal command tracker 161 * @host_tag: Host tag used for the specific command 162 * 163 * Initialize the internal command tracker structure with 164 * specified host tag. 165 * 166 * Return: Nothing. 167 */ 168 static inline void mpi3mr_init_drv_cmd(struct mpi3mr_drv_cmd *cmdptr, 169 u16 host_tag) 170 { 171 mutex_init(&cmdptr->mutex); 172 cmdptr->reply = NULL; 173 cmdptr->state = MPI3MR_CMD_NOTUSED; 174 cmdptr->dev_handle = MPI3MR_INVALID_DEV_HANDLE; 175 cmdptr->host_tag = host_tag; 176 } 177 178 /** 179 * mpi3mr_probe - PCI probe callback 180 * @pdev: PCI device instance 181 * @id: PCI device ID details 182 * 183 * controller initialization routine. Checks the security status 184 * of the controller and if it is invalid or tampered return the 185 * probe without initializing the controller. Otherwise, 186 * allocate per adapter instance through shost_priv and 187 * initialize controller specific data structures, initializae 188 * the controller hardware, add shost to the SCSI subsystem. 189 * 190 * Return: 0 on success, non-zero on failure. 191 */ 192 193 static int 194 mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id) 195 { 196 struct mpi3mr_ioc *mrioc = NULL; 197 struct Scsi_Host *shost = NULL; 198 int retval = 0; 199 200 shost = scsi_host_alloc(&mpi3mr_driver_template, 201 sizeof(struct mpi3mr_ioc)); 202 if (!shost) { 203 retval = -ENODEV; 204 goto shost_failed; 205 } 206 207 mrioc = shost_priv(shost); 208 mrioc->id = mrioc_ids++; 209 sprintf(mrioc->driver_name, "%s", MPI3MR_DRIVER_NAME); 210 sprintf(mrioc->name, "%s%d", mrioc->driver_name, mrioc->id); 211 INIT_LIST_HEAD(&mrioc->list); 212 spin_lock(&mrioc_list_lock); 213 list_add_tail(&mrioc->list, &mrioc_list); 214 spin_unlock(&mrioc_list_lock); 215 216 spin_lock_init(&mrioc->admin_req_lock); 217 spin_lock_init(&mrioc->reply_free_queue_lock); 218 spin_lock_init(&mrioc->sbq_lock); 219 220 mpi3mr_init_drv_cmd(&mrioc->init_cmds, MPI3MR_HOSTTAG_INITCMDS); 221 if (pdev->revision) 222 mrioc->enable_segqueue = true; 223 224 mrioc->logging_level = logging_level; 225 mrioc->shost = shost; 226 mrioc->pdev = pdev; 227 228 /* init shost parameters */ 229 shost->max_cmd_len = MPI3MR_MAX_CDB_LENGTH; 230 shost->max_lun = -1; 231 shost->unique_id = mrioc->id; 232 233 shost->max_channel = 1; 234 shost->max_id = 0xFFFFFFFF; 235 236 mrioc->is_driver_loading = 1; 237 if (mpi3mr_init_ioc(mrioc)) { 238 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 239 __FILE__, __LINE__, __func__); 240 retval = -ENODEV; 241 goto out_iocinit_failed; 242 } 243 244 shost->nr_hw_queues = mrioc->num_op_reply_q; 245 shost->can_queue = mrioc->max_host_ios; 246 shost->sg_tablesize = MPI3MR_SG_DEPTH; 247 shost->max_id = mrioc->facts.max_perids; 248 249 retval = scsi_add_host(shost, &pdev->dev); 250 if (retval) { 251 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 252 __FILE__, __LINE__, __func__); 253 goto addhost_failed; 254 } 255 256 scsi_scan_host(shost); 257 return retval; 258 259 addhost_failed: 260 mpi3mr_cleanup_ioc(mrioc); 261 out_iocinit_failed: 262 spin_lock(&mrioc_list_lock); 263 list_del(&mrioc->list); 264 spin_unlock(&mrioc_list_lock); 265 scsi_host_put(shost); 266 shost_failed: 267 return retval; 268 } 269 270 /** 271 * mpi3mr_remove - PCI remove callback 272 * @pdev: PCI device instance 273 * 274 * Free up all memory and resources associated with the 275 * controllerand target devices, unregister the shost. 276 * 277 * Return: Nothing. 278 */ 279 static void mpi3mr_remove(struct pci_dev *pdev) 280 { 281 struct Scsi_Host *shost = pci_get_drvdata(pdev); 282 struct mpi3mr_ioc *mrioc; 283 284 mrioc = shost_priv(shost); 285 while (mrioc->reset_in_progress || mrioc->is_driver_loading) 286 ssleep(1); 287 288 scsi_remove_host(shost); 289 290 mpi3mr_cleanup_ioc(mrioc); 291 292 spin_lock(&mrioc_list_lock); 293 list_del(&mrioc->list); 294 spin_unlock(&mrioc_list_lock); 295 296 scsi_host_put(shost); 297 } 298 299 /** 300 * mpi3mr_shutdown - PCI shutdown callback 301 * @pdev: PCI device instance 302 * 303 * Free up all memory and resources associated with the 304 * controller 305 * 306 * Return: Nothing. 307 */ 308 static void mpi3mr_shutdown(struct pci_dev *pdev) 309 { 310 struct Scsi_Host *shost = pci_get_drvdata(pdev); 311 struct mpi3mr_ioc *mrioc; 312 313 if (!shost) 314 return; 315 316 mrioc = shost_priv(shost); 317 while (mrioc->reset_in_progress || mrioc->is_driver_loading) 318 ssleep(1); 319 320 mpi3mr_cleanup_ioc(mrioc); 321 } 322 323 static const struct pci_device_id mpi3mr_pci_id_table[] = { 324 { 325 PCI_DEVICE_SUB(PCI_VENDOR_ID_LSI_LOGIC, 0x00A5, 326 PCI_ANY_ID, PCI_ANY_ID) 327 }, 328 { 0 } 329 }; 330 MODULE_DEVICE_TABLE(pci, mpi3mr_pci_id_table); 331 332 static struct pci_driver mpi3mr_pci_driver = { 333 .name = MPI3MR_DRIVER_NAME, 334 .id_table = mpi3mr_pci_id_table, 335 .probe = mpi3mr_probe, 336 .remove = mpi3mr_remove, 337 .shutdown = mpi3mr_shutdown, 338 }; 339 340 static int __init mpi3mr_init(void) 341 { 342 int ret_val; 343 344 pr_info("Loading %s version %s\n", MPI3MR_DRIVER_NAME, 345 MPI3MR_DRIVER_VERSION); 346 347 ret_val = pci_register_driver(&mpi3mr_pci_driver); 348 349 return ret_val; 350 } 351 352 static void __exit mpi3mr_exit(void) 353 { 354 if (warn_non_secure_ctlr) 355 pr_warn( 356 "Unloading %s version %s while managing a non secure controller\n", 357 MPI3MR_DRIVER_NAME, MPI3MR_DRIVER_VERSION); 358 else 359 pr_info("Unloading %s version %s\n", MPI3MR_DRIVER_NAME, 360 MPI3MR_DRIVER_VERSION); 361 362 pci_unregister_driver(&mpi3mr_pci_driver); 363 } 364 365 module_init(mpi3mr_init); 366 module_exit(mpi3mr_exit); 367