Pull SCSI updates from James Bottomley: "This update includes the usual round of major driver updates (ncr5380, ufs, lpfc, be2iscsi, hisi_sas, storvsc, cxlflash, aacraid, megaraid_sas, ...). There's also an assortment of minor fixes and the major update of switching a bunch of drivers to pci_alloc_irq_vectors from Christoph" * tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (188 commits) scsi: megaraid_sas: handle dma_addr_t right on 32-bit scsi: megaraid_sas: array overflow in megasas_dump_frame() scsi: snic: switch to pci_irq_alloc_vectors scsi: megaraid_sas: driver version upgrade scsi: megaraid_sas: Change RAID_1_10_RMW_CMDS to RAID_1_PEER_CMDS and set value to 2 scsi: megaraid_sas: Indentation and smatch warning fixes scsi: megaraid_sas: Cleanup VD_EXT_DEBUG and SPAN_DEBUG related debug prints scsi: megaraid_sas: Increase internal command pool scsi: megaraid_sas: Use synchronize_irq to wait for IRQs to complete scsi: megaraid_sas: Bail out the driver load if ld_list_query fails scsi: megaraid_sas: Change build_mpt_mfi_pass_thru to return void scsi: megaraid_sas: During OCR, if get_ctrl_info fails do not continue with OCR scsi: megaraid_sas: Do not set fp_possible if TM capable for non-RW syspdIO, change fp_possible to bool scsi: megaraid_sas: Remove unused pd_index from megasas_build_ld_nonrw_fusion scsi: megaraid_sas: megasas_return_cmd does not memset IO frame to zero scsi: megaraid_sas: max_fw_cmds are decremented twice, remove duplicate scsi: megaraid_sas: update can_queue only if the new value is less scsi: megaraid_sas: Change max_cmd from u32 to u16 in all functions scsi: megaraid_sas: set pd_after_lb from MR_BuildRaidContext and initialize pDevHandle to MR_DEVHANDLE_INVALID scsi: megaraid_sas: latest controller OCR capability from FW before sending shutdown DCMD ...
Unified · Split
| @@ -549,6 +549,7 @@ enum blk_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) · 548 unmodified lines | ||
| 549 | 549 | DPRINTK("EXIT, ret=%d\n", ret); |
| 550 | 550 | return ret; |
| 551 | 551 | } |
| 552 | +EXPORT_SYMBOL(ata_scsi_timed_out); | |
| 552 | 553 | |
| 553 | 554 | static void ata_eh_unload(struct ata_port *ap) |
| 554 | 555 | { |
| @@ -716,7 +716,6 @@ struct scsi_transport_template *ata_attach_transport(void) · 715 unmodified lines | ||
| 716 | 716 | return NULL; |
| 717 | 717 | |
| 718 | 718 | i->t.eh_strategy_handler = ata_scsi_error; |
| 719 | − i->t.eh_timed_out = ata_scsi_timed_out; | |
| 720 | 719 | i->t.user_scan = ata_scsi_user_scan; |
| 721 | 720 | |
| 722 | 721 | i->t.host_attrs.ac.attrs = &i->port_attrs[0]; |
| @@ -159,7 +159,6 @@ extern unsigned long ata_internal_cmd_timeout(struct ata_device *dev, u8 cmd); · 158 unmodified lines | ||
| 159 | 159 | extern void ata_internal_cmd_timed_out(struct ata_device *dev, u8 cmd); |
| 160 | 160 | extern void ata_eh_acquire(struct ata_port *ap); |
| 161 | 161 | extern void ata_eh_release(struct ata_port *ap); |
| 162 | −extern enum blk_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); | |
| 163 | 162 | extern void ata_scsi_error(struct Scsi_Host *host); |
| 164 | 163 | extern void ata_eh_fastdrain_timerfn(unsigned long arg); |
| 165 | 164 | extern void ata_qc_schedule_eh(struct ata_queued_cmd *qc); |
| @@ -400,27 +400,27 @@ static bool SA5_performant_intr_pending(ctlr_info_t *h) · 399 unmodified lines | ||
| 400 | 400 | } |
| 401 | 401 | |
| 402 | 402 | static struct access_method SA5_access = { |
| 403 | − SA5_submit_command, | |
| 404 | − SA5_intr_mask, | |
| 405 | − SA5_fifo_full, | |
| 406 | − SA5_intr_pending, | |
| 407 | − SA5_completed, | |
| 403 | + .submit_command = SA5_submit_command, | |
| 404 | + .set_intr_mask = SA5_intr_mask, | |
| 405 | + .fifo_full = SA5_fifo_full, | |
| 406 | + .intr_pending = SA5_intr_pending, | |
| 407 | + .command_completed = SA5_completed, | |
| 408 | 408 | }; |
| 409 | 409 | |
| 410 | 410 | static struct access_method SA5B_access = { |
| 411 | − SA5_submit_command, | |
| 412 | − SA5B_intr_mask, | |
| 413 | − SA5_fifo_full, | |
| 414 | − SA5B_intr_pending, | |
| 415 | − SA5_completed, | |
| 411 | + .submit_command = SA5_submit_command, | |
| 412 | + .set_intr_mask = SA5B_intr_mask, | |
| 413 | + .fifo_full = SA5_fifo_full, | |
| 414 | + .intr_pending = SA5B_intr_pending, | |
| 415 | + .command_completed = SA5_completed, | |
| 416 | 416 | }; |
| 417 | 417 | |
| 418 | 418 | static struct access_method SA5_performant_access = { |
| 419 | − SA5_submit_command, | |
| 420 | − SA5_performant_intr_mask, | |
| 421 | − SA5_fifo_full, | |
| 422 | − SA5_performant_intr_pending, | |
| 423 | − SA5_performant_completed, | |
| 419 | + .submit_command = SA5_submit_command, | |
| 420 | + .set_intr_mask = SA5_performant_intr_mask, | |
| 421 | + .fifo_full = SA5_fifo_full, | |
| 422 | + .intr_pending = SA5_performant_intr_pending, | |
| 423 | + .command_completed = SA5_performant_completed, | |
| 424 | 424 | }; |
| 425 | 425 | |
| 426 | 426 | struct board_type { |
| @@ -994,6 +994,7 @@ static struct scsi_host_template iscsi_iser_sht = { · 993 unmodified lines | ||
| 994 | 994 | .change_queue_depth = scsi_change_queue_depth, |
| 995 | 995 | .sg_tablesize = ISCSI_ISER_DEF_SG_TABLESIZE, |
| 996 | 996 | .cmd_per_lun = ISER_DEF_CMD_PER_LUN, |
| 997 | + .eh_timed_out = iscsi_eh_cmd_timed_out, | |
| 997 | 998 | .eh_abort_handler = iscsi_eh_abort, |
| 998 | 999 | .eh_device_reset_handler= iscsi_eh_device_reset, |
| 999 | 1000 | .eh_target_reset_handler = iscsi_eh_recover_target, |
| @@ -2869,6 +2869,7 @@ static struct scsi_host_template srp_template = { · 2868 unmodified lines | ||
| 2869 | 2869 | .info = srp_target_info, |
| 2870 | 2870 | .queuecommand = srp_queuecommand, |
| 2871 | 2871 | .change_queue_depth = srp_change_queue_depth, |
| 2872 | + .eh_timed_out = srp_timed_out, | |
| 2872 | 2873 | .eh_abort_handler = srp_abort, |
| 2873 | 2874 | .eh_device_reset_handler = srp_reset_device, |
| 2874 | 2875 | .eh_host_reset_handler = srp_reset_host, |
| @@ -119,6 +119,7 @@ static struct scsi_host_template mptfc_driver_template = { · 118 unmodified lines | ||
| 119 | 119 | .target_destroy = mptfc_target_destroy, |
| 120 | 120 | .slave_destroy = mptscsih_slave_destroy, |
| 121 | 121 | .change_queue_depth = mptscsih_change_queue_depth, |
| 122 | + .eh_timed_out = fc_eh_timed_out, | |
| 122 | 123 | .eh_abort_handler = mptfc_abort, |
| 123 | 124 | .eh_device_reset_handler = mptfc_dev_reset, |
| 124 | 125 | .eh_bus_reset_handler = mptfc_bus_reset, |
| @@ -65,7 +65,6 @@ · 64 unmodified lines | ||
| 65 | 65 | #include <linux/init.h> |
| 66 | 66 | #include <linux/kernel.h> |
| 67 | 67 | #include <linux/slab.h> |
| 68 | −#include <linux/miscdevice.h> | |
| 69 | 68 | #include <linux/spinlock.h> |
| 70 | 69 | #include <linux/workqueue.h> |
| 71 | 70 | #include <linux/delay.h> |
| @@ -1983,6 +1983,7 @@ static struct scsi_host_template mptsas_driver_template = { · 1982 unmodified lines | ||
| 1983 | 1983 | .target_destroy = mptsas_target_destroy, |
| 1984 | 1984 | .slave_destroy = mptscsih_slave_destroy, |
| 1985 | 1985 | .change_queue_depth = mptscsih_change_queue_depth, |
| 1986 | + .eh_timed_out = mptsas_eh_timed_out, | |
| 1986 | 1987 | .eh_abort_handler = mptscsih_abort, |
| 1987 | 1988 | .eh_device_reset_handler = mptscsih_dev_reset, |
| 1988 | 1989 | .eh_host_reset_handler = mptscsih_host_reset, |
| @@ -5398,7 +5399,6 @@ mptsas_init(void) · 3409 unmodified lines | ||
| 5398 | 5399 | sas_attach_transport(&mptsas_transport_functions); |
| 5399 | 5400 | if (!mptsas_transport_template) |
| 5400 | 5401 | return -ENODEV; |
| 5401 | − mptsas_transport_template->eh_timed_out = mptsas_eh_timed_out; | |
| 5402 | 5402 | |
| 5403 | 5403 | mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER, |
| 5404 | 5404 | "mptscsih_io_done"); |
| @@ -330,6 +330,7 @@ static struct scsi_host_template zfcp_scsi_host_template = { · 329 unmodified lines | ||
| 330 | 330 | .module = THIS_MODULE, |
| 331 | 331 | .name = "zfcp", |
| 332 | 332 | .queuecommand = zfcp_scsi_queuecommand, |
| 333 | + .eh_timed_out = fc_eh_timed_out, | |
| 333 | 334 | .eh_abort_handler = zfcp_scsi_eh_abort_handler, |
| 334 | 335 | .eh_device_reset_handler = zfcp_scsi_eh_device_reset_handler, |
| 335 | 336 | .eh_target_reset_handler = zfcp_scsi_eh_target_reset_handler, |
| @@ -96,17 +96,6 @@ · 95 unmodified lines | ||
| 96 | 96 | * of chips. To use it, you write an architecture specific functions |
| 97 | 97 | * and macros and include this file in your driver. |
| 98 | 98 | * |
| 99 | − * These macros control options : | |
| 100 | − * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically | |
| 101 | − * for commands that return with a CHECK CONDITION status. | |
| 102 | − * | |
| 103 | − * DIFFERENTIAL - if defined, NCR53c81 chips will use external differential | |
| 104 | − * transceivers. | |
| 105 | − * | |
| 106 | − * PSEUDO_DMA - if defined, PSEUDO DMA is used during the data transfer phases. | |
| 107 | − * | |
| 108 | − * REAL_DMA - if defined, REAL DMA is used during the data transfer phases. | |
| 109 | − * | |
| 110 | 99 | * These macros MUST be defined : |
| 111 | 100 | * |
| 112 | 101 | * NCR5380_read(register) - read from the specified register |
| @@ -347,7 +336,7 @@ static void NCR5380_print_phase(struct Scsi_Host *instance) · 234 unmodified lines | ||
| 347 | 336 | #endif |
| 348 | 337 | |
| 349 | 338 | /** |
| 350 | − * NCR58380_info - report driver and host information | |
| 339 | + * NCR5380_info - report driver and host information | |
| 351 | 340 | * @instance: relevant scsi host instance |
| 352 | 341 | * |
| 353 | 342 | * For use as the host template info() handler. |
| @@ -360,33 +349,6 @@ static const char *NCR5380_info(struct Scsi_Host *instance) · 6 unmodified lines | ||
| 360 | 349 | return hostdata->info; |
| 361 | 350 | } |
| 362 | 351 | |
| 363 | −static void prepare_info(struct Scsi_Host *instance) | |
| 364 | −{ | |
| 365 | − struct NCR5380_hostdata *hostdata = shost_priv(instance); | |
| 366 | − | |
| 367 | − snprintf(hostdata->info, sizeof(hostdata->info), | |
| 368 | − "%s, irq %d, " | |
| 369 | − "io_port 0x%lx, base 0x%lx, " | |
| 370 | − "can_queue %d, cmd_per_lun %d, " | |
| 371 | − "sg_tablesize %d, this_id %d, " | |
| 372 | − "flags { %s%s%s}, " | |
| 373 | − "options { %s} ", | |
| 374 | − instance->hostt->name, instance->irq, | |
| 375 | − hostdata->io_port, hostdata->base, | |
| 376 | − instance->can_queue, instance->cmd_per_lun, | |
| 377 | − instance->sg_tablesize, instance->this_id, | |
| 378 | − hostdata->flags & FLAG_DMA_FIXUP ? "DMA_FIXUP " : "", | |
| 379 | − hostdata->flags & FLAG_NO_PSEUDO_DMA ? "NO_PSEUDO_DMA " : "", | |
| 380 | − hostdata->flags & FLAG_TOSHIBA_DELAY ? "TOSHIBA_DELAY " : "", | |
| 381 | −#ifdef DIFFERENTIAL | |
| 382 | − "DIFFERENTIAL " | |
| 383 | −#endif | |
| 384 | −#ifdef PARITY | |
| 385 | − "PARITY " | |
| 386 | −#endif | |
| 387 | − ""); | |
| 388 | −} | |
| 389 | − | |
| 390 | 352 | /** |
| 391 | 353 | * NCR5380_init - initialise an NCR5380 |
| 392 | 354 | * @instance: adapter to configure |
| @@ -436,7 +398,14 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags) · 43 unmodified lines | ||
| 436 | 398 | if (!hostdata->work_q) |
| 437 | 399 | return -ENOMEM; |
| 438 | 400 | |
| 439 | − prepare_info(instance); | |
| 401 | + snprintf(hostdata->info, sizeof(hostdata->info), | |
| 402 | + "%s, irq %d, io_port 0x%lx, base 0x%lx, can_queue %d, cmd_per_lun %d, sg_tablesize %d, this_id %d, flags { %s%s%s}", | |
| 403 | + instance->hostt->name, instance->irq, hostdata->io_port, | |
| 404 | + hostdata->base, instance->can_queue, instance->cmd_per_lun, | |
| 405 | + instance->sg_tablesize, instance->this_id, | |
| 406 | + hostdata->flags & FLAG_DMA_FIXUP ? "DMA_FIXUP " : "", | |
| 407 | + hostdata->flags & FLAG_NO_PSEUDO_DMA ? "NO_PSEUDO_DMA " : "", | |
| 408 | + hostdata->flags & FLAG_TOSHIBA_DELAY ? "TOSHIBA_DELAY " : ""); | |
| 440 | 409 | |
| 441 | 410 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); |
| 442 | 411 | NCR5380_write(MODE_REG, MR_BASE); |
| @@ -622,8 +591,9 @@ static inline void maybe_release_dma_irq(struct Scsi_Host *instance) · 179 unmodified lines | ||
| 622 | 591 | list_empty(&hostdata->unissued) && |
| 623 | 592 | list_empty(&hostdata->autosense) && |
| 624 | 593 | !hostdata->connected && |
| 625 | − !hostdata->selecting) | |
| 594 | + !hostdata->selecting) { | |
| 626 | 595 | NCR5380_release_dma_irq(instance); |
| 596 | + } | |
| 627 | 597 | } |
| 628 | 598 | |
| 629 | 599 | /** |
| @@ -962,6 +932,7 @@ static irqreturn_t __maybe_unused NCR5380_intr(int irq, void *dev_id) · 332 unmodified lines | ||
| 962 | 932 | |
| 963 | 933 | static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, |
| 964 | 934 | struct scsi_cmnd *cmd) |
| 935 | + __releases(&hostdata->lock) __acquires(&hostdata->lock) | |
| 965 | 936 | { |
| 966 | 937 | struct NCR5380_hostdata *hostdata = shost_priv(instance); |
| 967 | 938 | unsigned char tmp[3], phase; |
| @@ -1194,8 +1165,16 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, · 226 unmodified lines | ||
| 1194 | 1165 | data = tmp; |
| 1195 | 1166 | phase = PHASE_MSGOUT; |
| 1196 | 1167 | NCR5380_transfer_pio(instance, &phase, &len, &data); |
| 1168 | + if (len) { | |
| 1169 | + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); | |
| 1170 | + cmd->result = DID_ERROR << 16; | |
| 1171 | + complete_cmd(instance, cmd); | |
| 1172 | + dsprintk(NDEBUG_SELECTION, instance, "IDENTIFY message transfer failed\n"); | |
| 1173 | + cmd = NULL; | |
| 1174 | + goto out; | |
| 1175 | + } | |
| 1176 | + | |
| 1197 | 1177 | dsprintk(NDEBUG_SELECTION, instance, "nexus established.\n"); |
| 1198 | − /* XXX need to handle errors here */ | |
| 1199 | 1178 | |
| 1200 | 1179 | hostdata->connected = cmd; |
| 1201 | 1180 | hostdata->busy[cmd->device->id] |= 1 << cmd->device->lun; |
| @@ -1654,6 +1633,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, · 452 unmodified lines | ||
| 1654 | 1633 | */ |
| 1655 | 1634 | |
| 1656 | 1635 | static void NCR5380_information_transfer(struct Scsi_Host *instance) |
| 1636 | + __releases(&hostdata->lock) __acquires(&hostdata->lock) | |
| 1657 | 1637 | { |
| 1658 | 1638 | struct NCR5380_hostdata *hostdata = shost_priv(instance); |
| 1659 | 1639 | unsigned char msgout = NOP; |
| @@ -81,11 +81,7 @@ · 80 unmodified lines | ||
| 81 | 81 | #define ICR_ASSERT_ATN 0x02 /* rw Set to assert ATN */ |
| 82 | 82 | #define ICR_ASSERT_DATA 0x01 /* rw SCSI_DATA_REG is asserted */ |
| 83 | 83 | |
| 84 | −#ifdef DIFFERENTIAL | |
| 85 | −#define ICR_BASE ICR_DIFF_ENABLE | |
| 86 | −#else | |
| 87 | 84 | #define ICR_BASE 0 |
| 88 | −#endif | |
| 89 | 85 | |
| 90 | 86 | #define MODE_REG 2 |
| 91 | 87 | /* |
| @@ -102,11 +98,7 @@ · 10 unmodified lines | ||
| 102 | 98 | #define MR_DMA_MODE 0x02 /* rw DMA / pseudo DMA mode */ |
| 103 | 99 | #define MR_ARBITRATE 0x01 /* rw start arbitration */ |
| 104 | 100 | |
| 105 | −#ifdef PARITY | |
| 106 | −#define MR_BASE MR_ENABLE_PAR_CHECK | |
| 107 | −#else | |
| 108 | 101 | #define MR_BASE 0 |
| 109 | −#endif | |
| 110 | 102 | |
| 111 | 103 | #define TARGET_COMMAND_REG 3 |
| 112 | 104 | #define TCR_LAST_BYTE_SENT 0x80 /* ro DMA done */ |
| @@ -174,11 +166,7 @@ · 61 unmodified lines | ||
| 174 | 166 | #define CSR_SCSI_BUF_RDY 0x02 /* ro SCSI buffer read */ |
| 175 | 167 | #define CSR_GATED_53C80_IRQ 0x01 /* ro Last block xferred */ |
| 176 | 168 | |
| 177 | −#if 0 | |
| 178 | −#define CSR_BASE CSR_SCSI_BUFF_INTR | CSR_53C80_INTR | |
| 179 | −#else | |
| 180 | 169 | #define CSR_BASE CSR_53C80_INTR |
| 181 | −#endif | |
| 182 | 170 | |
| 183 | 171 | /* Note : PHASE_* macros are based on the values of the STATUS register */ |
| 184 | 172 | #define PHASE_MASK (SR_MSG | SR_CD | SR_IO) |
| @@ -234,11 +222,9 @@ struct NCR5380_hostdata { · 49 unmodified lines | ||
| 234 | 222 | unsigned char id_higher_mask; /* All bits above id_mask */ |
| 235 | 223 | unsigned char last_message; /* Last Message Out */ |
| 236 | 224 | unsigned long region_size; /* Size of address/port range */ |
| 237 | − char info[256]; | |
| 225 | + char info[168]; /* Host banner message */ | |
| 238 | 226 | }; |
| 239 | 227 | |
| 240 | −#ifdef __KERNEL__ | |
| 241 | − | |
| 242 | 228 | struct NCR5380_cmd { |
| 243 | 229 | struct list_head list; |
| 244 | 230 | }; |
| @@ -331,5 +317,4 @@ static inline int NCR5380_dma_residual_none(struct NCR5380_hostdata *hostdata) · 86 unmodified lines | ||
| 331 | 317 | return 0; |
| 332 | 318 | } |
| 333 | 319 | |
| 334 | −#endif /* __KERNEL__ */ | |
| 335 | 320 | #endif /* NCR5380_H */ |
| @@ -6,7 +6,8 @@ · 5 unmodified lines | ||
| 6 | 6 | * Adaptec aacraid device driver for Linux. |
| 7 | 7 | * |
| 8 | 8 | * Copyright (c) 2000-2010 Adaptec, Inc. |
| 9 | − * 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | |
| 9 | + * 2010-2015 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | |
| 10 | + * 2016-2017 Microsemi Corp. (aacraid@microsemi.com) | |
| 10 | 11 | * |
| 11 | 12 | * This program is free software; you can redistribute it and/or modify |
| 12 | 13 | * it under the terms of the GNU General Public License as published by |
| @@ -22,6 +23,11 @@ · 9 unmodified lines | ||
| 22 | 23 | * along with this program; see the file COPYING. If not, write to |
| 23 | 24 | * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. |
| 24 | 25 | * |
| 26 | + * Module Name: | |
| 27 | + * aachba.c | |
| 28 | + * | |
| 29 | + * Abstract: Contains Interfaces to manage IOs. | |
| 30 | + * | |
| 25 | 31 | */ |
| 26 | 32 | |
| 27 | 33 | #include <linux/kernel.h> |
| @@ -62,6 +68,7 @@ · 34 unmodified lines | ||
| 62 | 68 | #define SENCODE_END_OF_DATA 0x00 |
| 63 | 69 | #define SENCODE_BECOMING_READY 0x04 |
| 64 | 70 | #define SENCODE_INIT_CMD_REQUIRED 0x04 |
| 71 | +#define SENCODE_UNRECOVERED_READ_ERROR 0x11 | |
| 65 | 72 | #define SENCODE_PARAM_LIST_LENGTH_ERROR 0x1A |
| 66 | 73 | #define SENCODE_INVALID_COMMAND 0x20 |
| 67 | 74 | #define SENCODE_LBA_OUT_OF_RANGE 0x21 |
| @@ -106,6 +113,8 @@ · 38 unmodified lines | ||
| 106 | 113 | #define ASENCODE_LUN_FAILED_SELF_CONFIG 0x00 |
| 107 | 114 | #define ASENCODE_OVERLAPPED_COMMAND 0x00 |
| 108 | 115 | |
| 116 | +#define AAC_STAT_GOOD (DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD) | |
| 117 | + | |
| 109 | 118 | #define BYTE0(x) (unsigned char)(x) |
| 110 | 119 | #define BYTE1(x) (unsigned char)((x) >> 8) |
| 111 | 120 | #define BYTE2(x) (unsigned char)((x) >> 16) |
| @@ -164,46 +173,56 @@ struct inquiry_data { · 52 unmodified lines | ||
| 164 | 173 | }; |
| 165 | 174 | |
| 166 | 175 | /* Added for VPD 0x83 */ |
| 167 | −typedef struct { | |
| 168 | − u8 CodeSet:4; /* VPD_CODE_SET */ | |
| 169 | − u8 Reserved:4; | |
| 170 | − u8 IdentifierType:4; /* VPD_IDENTIFIER_TYPE */ | |
| 171 | − u8 Reserved2:4; | |
| 172 | − u8 Reserved3; | |
| 173 | − u8 IdentifierLength; | |
| 174 | − u8 VendId[8]; | |
| 175 | − u8 ProductId[16]; | |
| 176 | − u8 SerialNumber[8]; /* SN in ASCII */ | |
| 177 | − | |
| 178 | −} TVPD_ID_Descriptor_Type_1; | |
| 176 | +struct tvpd_id_descriptor_type_1 { | |
| 177 | + u8 codeset:4; /* VPD_CODE_SET */ | |
| 178 | + u8 reserved:4; | |
| 179 | + u8 identifiertype:4; /* VPD_IDENTIFIER_TYPE */ | |
| 180 | + u8 reserved2:4; | |
| 181 | + u8 reserved3; | |
| 182 | + u8 identifierlength; | |
| 183 | + u8 venid[8]; | |
| 184 | + u8 productid[16]; | |
| 185 | + u8 serialnumber[8]; /* SN in ASCII */ | |
| 179 | 186 | |
| 180 | −typedef struct { | |
| 181 | − u8 CodeSet:4; /* VPD_CODE_SET */ | |
| 182 | − u8 Reserved:4; | |
| 183 | − u8 IdentifierType:4; /* VPD_IDENTIFIER_TYPE */ | |
| 184 | − u8 Reserved2:4; | |
| 185 | − u8 Reserved3; | |
| 186 | − u8 IdentifierLength; | |
| 187 | − struct TEU64Id { | |
| 187 | +}; | |
| 188 | + | |
| 189 | +struct tvpd_id_descriptor_type_2 { | |
| 190 | + u8 codeset:4; /* VPD_CODE_SET */ | |
| 191 | + u8 reserved:4; | |
| 192 | + u8 identifiertype:4; /* VPD_IDENTIFIER_TYPE */ | |
| 193 | + u8 reserved2:4; | |
| 194 | + u8 reserved3; | |
| 195 | + u8 identifierlength; | |
| 196 | + struct teu64id { | |
| 188 | 197 | u32 Serial; |
| 189 | 198 | /* The serial number supposed to be 40 bits, |
| 190 | 199 | * bit we only support 32, so make the last byte zero. */ |
| 191 | − u8 Reserved; | |
| 192 | − u8 VendId[3]; | |
| 193 | − } EU64Id; | |
| 200 | + u8 reserved; | |
| 201 | + u8 venid[3]; | |
| 202 | + } eu64id; | |
| 194 | 203 | |
| 195 | −} TVPD_ID_Descriptor_Type_2; | |
| 204 | +}; | |
| 196 | 205 | |
| 197 | −typedef struct { | |
| 206 | +struct tvpd_id_descriptor_type_3 { | |
| 207 | + u8 codeset : 4; /* VPD_CODE_SET */ | |
| 208 | + u8 reserved : 4; | |
| 209 | + u8 identifiertype : 4; /* VPD_IDENTIFIER_TYPE */ | |
| 210 | + u8 reserved2 : 4; | |
| 211 | + u8 reserved3; | |
| 212 | + u8 identifierlength; | |
| 213 | + u8 Identifier[16]; | |
| 214 | +}; | |
| 215 | + | |
| 216 | +struct tvpd_page83 { | |
| 198 | 217 | u8 DeviceType:5; |
| 199 | 218 | u8 DeviceTypeQualifier:3; |
| 200 | 219 | u8 PageCode; |
| 201 | − u8 Reserved; | |
| 220 | + u8 reserved; | |
| 202 | 221 | u8 PageLength; |
| 203 | − TVPD_ID_Descriptor_Type_1 IdDescriptorType1; | |
| 204 | − TVPD_ID_Descriptor_Type_2 IdDescriptorType2; | |
| 205 | − | |
| 206 | −} TVPD_Page83; | |
| 222 | + struct tvpd_id_descriptor_type_1 type1; | |
| 223 | + struct tvpd_id_descriptor_type_2 type2; | |
| 224 | + struct tvpd_id_descriptor_type_3 type3; | |
| 225 | +}; | |
| 207 | 226 | |
| 208 | 227 | /* |
| 209 | 228 | * M O D U L E G L O B A L S |
| @@ -214,9 +233,13 @@ static long aac_build_sg64(struct scsi_cmnd *scsicmd, struct sgmap64 *psg); · 4 unmodified lines | ||
| 214 | 233 | static long aac_build_sgraw(struct scsi_cmnd *scsicmd, struct sgmapraw *psg); |
| 215 | 234 | static long aac_build_sgraw2(struct scsi_cmnd *scsicmd, |
| 216 | 235 | struct aac_raw_io2 *rio2, int sg_max); |
| 236 | +static long aac_build_sghba(struct scsi_cmnd *scsicmd, | |
| 237 | + struct aac_hba_cmd_req *hbacmd, | |
| 238 | + int sg_max, u64 sg_address); | |
| 217 | 239 | static int aac_convert_sgraw2(struct aac_raw_io2 *rio2, |
| 218 | 240 | int pages, int nseg, int nseg_new); |
| 219 | 241 | static int aac_send_srb_fib(struct scsi_cmnd* scsicmd); |
| 242 | +static int aac_send_hba_fib(struct scsi_cmnd *scsicmd); | |
| 220 | 243 | #ifdef AAC_DETAILED_STATUS_INFO |
| 221 | 244 | static char *aac_get_status_string(u32 status); |
| 222 | 245 | #endif |
| @@ -327,7 +350,7 @@ static inline int aac_valid_context(struct scsi_cmnd *scsicmd, · 104 unmodified lines | ||
| 327 | 350 | } |
| 328 | 351 | scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; |
| 329 | 352 | device = scsicmd->device; |
| 330 | − if (unlikely(!device || !scsi_device_online(device))) { | |
| 353 | + if (unlikely(!device)) { | |
| 331 | 354 | dprintk((KERN_WARNING "aac_valid_context: scsi device corrupt\n")); |
| 332 | 355 | aac_fib_complete(fibptr); |
| 333 | 356 | return 0; |
| @@ -473,16 +496,26 @@ int aac_get_containers(struct aac_dev *dev) · 139 unmodified lines | ||
| 473 | 496 | |
| 474 | 497 | if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS) |
| 475 | 498 | maximum_num_containers = MAXIMUM_NUM_CONTAINERS; |
| 476 | − fsa_dev_ptr = kzalloc(sizeof(*fsa_dev_ptr) * maximum_num_containers, | |
| 477 | − GFP_KERNEL); | |
| 478 | − if (!fsa_dev_ptr) | |
| 479 | − return -ENOMEM; | |
| 499 | + if (dev->fsa_dev == NULL || | |
| 500 | + dev->maximum_num_containers != maximum_num_containers) { | |
| 501 | + | |
| 502 | + fsa_dev_ptr = dev->fsa_dev; | |
| 503 | + | |
| 504 | + dev->fsa_dev = kcalloc(maximum_num_containers, | |
| 505 | + sizeof(*fsa_dev_ptr), GFP_KERNEL); | |
| 506 | + | |
| 507 | + kfree(fsa_dev_ptr); | |
| 508 | + fsa_dev_ptr = NULL; | |
| 480 | 509 | |
| 481 | − dev->fsa_dev = fsa_dev_ptr; | |
| 482 | − dev->maximum_num_containers = maximum_num_containers; | |
| 483 | 510 | |
| 484 | − for (index = 0; index < dev->maximum_num_containers; ) { | |
| 485 | − fsa_dev_ptr[index].devname[0] = '\0'; | |
| 511 | + if (!dev->fsa_dev) | |
| 512 | + return -ENOMEM; | |
| 513 | + | |
| 514 | + dev->maximum_num_containers = maximum_num_containers; | |
| 515 | + } | |
| 516 | + for (index = 0; index < dev->maximum_num_containers; index++) { | |
| 517 | + dev->fsa_dev[index].devname[0] = '\0'; | |
| 518 | + dev->fsa_dev[index].valid = 0; | |
| 486 | 519 | |
| 487 | 520 | status = aac_probe_container(dev, index); |
| 488 | 521 | |
| @@ -490,12 +523,6 @@ int aac_get_containers(struct aac_dev *dev) · 1 unmodified line | ||
| 490 | 523 | printk(KERN_WARNING "aac_get_containers: SendFIB failed.\n"); |
| 491 | 524 | break; |
| 492 | 525 | } |
| 493 | − | |
| 494 | − /* | |
| 495 | − * If there are no more containers, then stop asking. | |
| 496 | − */ | |
| 497 | − if (++index >= status) | |
| 498 | − break; | |
| 499 | 526 | } |
| 500 | 527 | return status; |
| 501 | 528 | } |
| @@ -602,6 +629,7 @@ static void _aac_probe_container2(void * context, struct fib * fibptr) · 100 unmodified lines | ||
| 602 | 629 | struct fsa_dev_info *fsa_dev_ptr; |
| 603 | 630 | int (*callback)(struct scsi_cmnd *); |
| 604 | 631 | struct scsi_cmnd * scsicmd = (struct scsi_cmnd *)context; |
| 632 | + int i; | |
| 605 | 633 | |
| 606 | 634 | |
| 607 | 635 | if (!aac_valid_context(scsicmd, fibptr)) |
| @@ -624,6 +652,10 @@ static void _aac_probe_container2(void * context, struct fib * fibptr) · 16 unmodified lines | ||
| 624 | 652 | fsa_dev_ptr->block_size = |
| 625 | 653 | le32_to_cpu(dresp->mnt[0].fileinfo.bdevinfo.block_size); |
| 626 | 654 | } |
| 655 | + for (i = 0; i < 16; i++) | |
| 656 | + fsa_dev_ptr->identifier[i] = | |
| 657 | + dresp->mnt[0].fileinfo.bdevinfo | |
| 658 | + .identifier[i]; | |
| 627 | 659 | fsa_dev_ptr->valid = 1; |
| 628 | 660 | /* sense_key holds the current state of the spin-up */ |
| 629 | 661 | if (dresp->mnt[0].state & cpu_to_le32(FSCS_NOT_READY)) |
| @@ -918,6 +950,28 @@ static void setinqstr(struct aac_dev *dev, void *data, int tindex) · 288 unmodified lines | ||
| 918 | 950 | inqstrcpy ("V1.0", str->prl); |
| 919 | 951 | } |
| 920 | 952 | |
| 953 | +static void build_vpd83_type3(struct tvpd_page83 *vpdpage83data, | |
| 954 | + struct aac_dev *dev, struct scsi_cmnd *scsicmd) | |
| 955 | +{ | |
| 956 | + int container; | |
| 957 | + | |
| 958 | + vpdpage83data->type3.codeset = 1; | |
| 959 | + vpdpage83data->type3.identifiertype = 3; | |
| 960 | + vpdpage83data->type3.identifierlength = sizeof(vpdpage83data->type3) | |
| 961 | + - 4; | |
| 962 | + | |
| 963 | + for (container = 0; container < dev->maximum_num_containers; | |
| 964 | + container++) { | |
| 965 | + | |
| 966 | + if (scmd_id(scsicmd) == container) { | |
| 967 | + memcpy(vpdpage83data->type3.Identifier, | |
| 968 | + dev->fsa_dev[container].identifier, | |
| 969 | + 16); | |
| 970 | + break; | |
| 971 | + } | |
| 972 | + } | |
| 973 | +} | |
| 974 | + | |
| 921 | 975 | static void get_container_serial_callback(void *context, struct fib * fibptr) |
| 922 | 976 | { |
| 923 | 977 | struct aac_get_serial_resp * get_serial_reply; |
| @@ -935,39 +989,47 @@ static void get_container_serial_callback(void *context, struct fib * fibptr) · 11 unmodified lines | ||
| 935 | 989 | /*Check to see if it's for VPD 0x83 or 0x80 */ |
| 936 | 990 | if (scsicmd->cmnd[2] == 0x83) { |
| 937 | 991 | /* vpd page 0x83 - Device Identification Page */ |
| 992 | + struct aac_dev *dev; | |
| 938 | 993 | int i; |
| 939 | − TVPD_Page83 VPDPage83Data; | |
| 994 | + struct tvpd_page83 vpdpage83data; | |
| 995 | + | |
| 996 | + dev = (struct aac_dev *)scsicmd->device->host->hostdata; | |
| 940 | 997 | |
| 941 | − memset(((u8 *)&VPDPage83Data), 0, | |
| 942 | − sizeof(VPDPage83Data)); | |
| 998 | + memset(((u8 *)&vpdpage83data), 0, | |
| 999 | + sizeof(vpdpage83data)); | |
| 943 | 1000 | |
| 944 | 1001 | /* DIRECT_ACCESS_DEVIC */ |
| 945 | − VPDPage83Data.DeviceType = 0; | |
| 1002 | + vpdpage83data.DeviceType = 0; | |
| 946 | 1003 | /* DEVICE_CONNECTED */ |
| 947 | − VPDPage83Data.DeviceTypeQualifier = 0; | |
| 1004 | + vpdpage83data.DeviceTypeQualifier = 0; | |
| 948 | 1005 | /* VPD_DEVICE_IDENTIFIERS */ |
| 949 | − VPDPage83Data.PageCode = 0x83; | |
| 950 | − VPDPage83Data.Reserved = 0; | |
| 951 | − VPDPage83Data.PageLength = | |
| 952 | − sizeof(VPDPage83Data.IdDescriptorType1) + | |
| 953 | − sizeof(VPDPage83Data.IdDescriptorType2); | |
| 1006 | + vpdpage83data.PageCode = 0x83; | |
| 1007 | + vpdpage83data.reserved = 0; | |
| 1008 | + vpdpage83data.PageLength = | |
| 1009 | + sizeof(vpdpage83data.type1) + | |
| 1010 | + sizeof(vpdpage83data.type2); | |
| 1011 | + | |
| 1012 | + /* VPD 83 Type 3 is not supported for ARC */ | |
| 1013 | + if (dev->sa_firmware) | |
| 1014 | + vpdpage83data.PageLength += | |
| 1015 | + sizeof(vpdpage83data.type3); | |
| 954 | 1016 | |
| 955 | 1017 | /* T10 Vendor Identifier Field Format */ |
| 956 | − /* VpdCodeSetAscii */ | |
| 957 | − VPDPage83Data.IdDescriptorType1.CodeSet = 2; | |
| 1018 | + /* VpdcodesetAscii */ | |
| 1019 | + vpdpage83data.type1.codeset = 2; | |
| 958 | 1020 | /* VpdIdentifierTypeVendorId */ |
| 959 | − VPDPage83Data.IdDescriptorType1.IdentifierType = 1; | |
| 960 | − VPDPage83Data.IdDescriptorType1.IdentifierLength = | |
| 961 | − sizeof(VPDPage83Data.IdDescriptorType1) - 4; | |
| 1021 | + vpdpage83data.type1.identifiertype = 1; | |
| 1022 | + vpdpage83data.type1.identifierlength = | |
| 1023 | + sizeof(vpdpage83data.type1) - 4; | |
| 962 | 1024 | |
| 963 | 1025 | /* "ADAPTEC " for adaptec */ |
| 964 | − memcpy(VPDPage83Data.IdDescriptorType1.VendId, | |
| 1026 | + memcpy(vpdpage83data.type1.venid, | |
| 965 | 1027 | "ADAPTEC ", |
| 966 | − sizeof(VPDPage83Data.IdDescriptorType1.VendId)); | |
| 967 | − memcpy(VPDPage83Data.IdDescriptorType1.ProductId, | |
| 1028 | + sizeof(vpdpage83data.type1.venid)); | |
| 1029 | + memcpy(vpdpage83data.type1.productid, | |
| 968 | 1030 | "ARRAY ", |
| 969 | 1031 | sizeof( |
| 970 | − VPDPage83Data.IdDescriptorType1.ProductId)); | |
| 1032 | + vpdpage83data.type1.productid)); | |
| 971 | 1033 | |
| 972 | 1034 | /* Convert to ascii based serial number. |
| 973 | 1035 | * The LSB is the the end. |
| @@ -976,32 +1038,41 @@ static void get_container_serial_callback(void *context, struct fib * fibptr) · 2 unmodified lines | ||
| 976 | 1038 | u8 temp = |
| 977 | 1039 | (u8)((get_serial_reply->uid >> ((7 - i) * 4)) & 0xF); |
| 978 | 1040 | if (temp > 0x9) { |
| 979 | − VPDPage83Data.IdDescriptorType1.SerialNumber[i] = | |
| 1041 | + vpdpage83data.type1.serialnumber[i] = | |
| 980 | 1042 | 'A' + (temp - 0xA); |
| 981 | 1043 | } else { |
| 982 | − VPDPage83Data.IdDescriptorType1.SerialNumber[i] = | |
| 1044 | + vpdpage83data.type1.serialnumber[i] = | |
| 983 | 1045 | '0' + temp; |
| 984 | 1046 | } |
| 985 | 1047 | } |
| 986 | 1048 | |
| 987 | 1049 | /* VpdCodeSetBinary */ |
| 988 | − VPDPage83Data.IdDescriptorType2.CodeSet = 1; | |
| 989 | − /* VpdIdentifierTypeEUI64 */ | |
| 990 | − VPDPage83Data.IdDescriptorType2.IdentifierType = 2; | |
| 991 | − VPDPage83Data.IdDescriptorType2.IdentifierLength = | |
| 992 | − sizeof(VPDPage83Data.IdDescriptorType2) - 4; | |
| 1050 | + vpdpage83data.type2.codeset = 1; | |
| 1051 | + /* VpdidentifiertypeEUI64 */ | |
| 1052 | + vpdpage83data.type2.identifiertype = 2; | |
| 1053 | + vpdpage83data.type2.identifierlength = | |
| 1054 | + sizeof(vpdpage83data.type2) - 4; | |
| 993 | 1055 | |
| 994 | − VPDPage83Data.IdDescriptorType2.EU64Id.VendId[0] = 0xD0; | |
| 995 | − VPDPage83Data.IdDescriptorType2.EU64Id.VendId[1] = 0; | |
| 996 | − VPDPage83Data.IdDescriptorType2.EU64Id.VendId[2] = 0; | |
| 1056 | + vpdpage83data.type2.eu64id.venid[0] = 0xD0; | |
| 1057 | + vpdpage83data.type2.eu64id.venid[1] = 0; | |
| 1058 | + vpdpage83data.type2.eu64id.venid[2] = 0; | |
| 997 | 1059 | |
| 998 | − VPDPage83Data.IdDescriptorType2.EU64Id.Serial = | |
| 1060 | + vpdpage83data.type2.eu64id.Serial = | |
| 999 | 1061 | get_serial_reply->uid; |
| 1000 | − VPDPage83Data.IdDescriptorType2.EU64Id.Reserved = 0; | |
| 1062 | + vpdpage83data.type2.eu64id.reserved = 0; | |
| 1063 | + | |
| 1064 | + /* | |
| 1065 | + * VpdIdentifierTypeFCPHName | |
| 1066 | + * VPD 0x83 Type 3 not supported for ARC | |
| 1067 | + */ | |
| 1068 | + if (dev->sa_firmware) { | |
| 1069 | + build_vpd83_type3(&vpdpage83data, | |
| 1070 | + dev, scsicmd); | |
| 1071 | + } | |
| 1001 | 1072 | |
| 1002 | 1073 | /* Move the inquiry data to the response buffer. */ |
| 1003 | − scsi_sg_copy_from_buffer(scsicmd, &VPDPage83Data, | |
| 1004 | − sizeof(VPDPage83Data)); | |
| 1074 | + scsi_sg_copy_from_buffer(scsicmd, &vpdpage83data, | |
| 1075 | + sizeof(vpdpage83data)); | |
| 1005 | 1076 | } else { |
| 1006 | 1077 | /* It must be for VPD 0x80 */ |
| 1007 | 1078 | char sp[13]; |
| @@ -1144,7 +1215,9 @@ static int aac_read_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u3 · 136 unmodified lines | ||
| 1144 | 1215 | long ret; |
| 1145 | 1216 | |
| 1146 | 1217 | aac_fib_init(fib); |
| 1147 | − if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2 && !dev->sync_mode) { | |
| 1218 | + if ((dev->comm_interface == AAC_COMM_MESSAGE_TYPE2 || | |
| 1219 | + dev->comm_interface == AAC_COMM_MESSAGE_TYPE3) && | |
| 1220 | + !dev->sync_mode) { | |
| 1148 | 1221 | struct aac_raw_io2 *readcmd2; |
| 1149 | 1222 | readcmd2 = (struct aac_raw_io2 *) fib_data(fib); |
| 1150 | 1223 | memset(readcmd2, 0, sizeof(struct aac_raw_io2)); |
| @@ -1270,7 +1343,9 @@ static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u · 119 unmodified lines | ||
| 1270 | 1343 | long ret; |
| 1271 | 1344 | |
| 1272 | 1345 | aac_fib_init(fib); |
| 1273 | − if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2 && !dev->sync_mode) { | |
| 1346 | + if ((dev->comm_interface == AAC_COMM_MESSAGE_TYPE2 || | |
| 1347 | + dev->comm_interface == AAC_COMM_MESSAGE_TYPE3) && | |
| 1348 | + !dev->sync_mode) { | |
| 1274 | 1349 | struct aac_raw_io2 *writecmd2; |
| 1275 | 1350 | writecmd2 = (struct aac_raw_io2 *) fib_data(fib); |
| 1276 | 1351 | memset(writecmd2, 0, sizeof(struct aac_raw_io2)); |
| @@ -1435,6 +1510,52 @@ static struct aac_srb * aac_scsi_common(struct fib * fib, struct scsi_cmnd * cmd · 158 unmodified lines | ||
| 1435 | 1510 | return srbcmd; |
| 1436 | 1511 | } |
| 1437 | 1512 | |
| 1513 | +static struct aac_hba_cmd_req *aac_construct_hbacmd(struct fib *fib, | |
| 1514 | + struct scsi_cmnd *cmd) | |
| 1515 | +{ | |
| 1516 | + struct aac_hba_cmd_req *hbacmd; | |
| 1517 | + struct aac_dev *dev; | |
| 1518 | + int bus, target; | |
| 1519 | + u64 address; | |
| 1520 | + | |
| 1521 | + dev = (struct aac_dev *)cmd->device->host->hostdata; | |
| 1522 | + | |
| 1523 | + hbacmd = (struct aac_hba_cmd_req *)fib->hw_fib_va; | |
| 1524 | + memset(hbacmd, 0, 96); /* sizeof(*hbacmd) is not necessary */ | |
| 1525 | + /* iu_type is a parameter of aac_hba_send */ | |
| 1526 | + switch (cmd->sc_data_direction) { | |
| 1527 | + case DMA_TO_DEVICE: | |
| 1528 | + hbacmd->byte1 = 2; | |
| 1529 | + break; | |
| 1530 | + case DMA_FROM_DEVICE: | |
| 1531 | + case DMA_BIDIRECTIONAL: | |
| 1532 | + hbacmd->byte1 = 1; | |
| 1533 | + break; | |
| 1534 | + case DMA_NONE: | |
| 1535 | + default: | |
| 1536 | + break; | |
| 1537 | + } | |
| 1538 | + hbacmd->lun[1] = cpu_to_le32(cmd->device->lun); | |
| 1539 | + | |
| 1540 | + bus = aac_logical_to_phys(scmd_channel(cmd)); | |
| 1541 | + target = scmd_id(cmd); | |
| 1542 | + hbacmd->it_nexus = dev->hba_map[bus][target].rmw_nexus; | |
| 1543 | + | |
| 1544 | + /* we fill in reply_qid later in aac_src_deliver_message */ | |
| 1545 | + /* we fill in iu_type, request_id later in aac_hba_send */ | |
| 1546 | + /* we fill in emb_data_desc_count later in aac_build_sghba */ | |
| 1547 | + | |
| 1548 | + memcpy(hbacmd->cdb, cmd->cmnd, cmd->cmd_len); | |
| 1549 | + hbacmd->data_length = cpu_to_le32(scsi_bufflen(cmd)); | |
| 1550 | + | |
| 1551 | + address = (u64)fib->hw_error_pa; | |
| 1552 | + hbacmd->error_ptr_hi = cpu_to_le32((u32)(address >> 32)); | |
| 1553 | + hbacmd->error_ptr_lo = cpu_to_le32((u32)(address & 0xffffffff)); | |
| 1554 | + hbacmd->error_length = cpu_to_le32(FW_ERROR_BUFFER_SIZE); | |
| 1555 | + | |
| 1556 | + return hbacmd; | |
| 1557 | +} | |
| 1558 | + | |
| 1438 | 1559 | static void aac_srb_callback(void *context, struct fib * fibptr); |
| 1439 | 1560 | |
| 1440 | 1561 | static int aac_scsi_64(struct fib * fib, struct scsi_cmnd * cmd) |
| @@ -1505,11 +1626,243 @@ static int aac_scsi_32_64(struct fib * fib, struct scsi_cmnd * cmd) · 64 unmodified lines | ||
| 1505 | 1626 | return aac_scsi_32(fib, cmd); |
| 1506 | 1627 | } |
| 1507 | 1628 | |
| 1629 | +static int aac_adapter_hba(struct fib *fib, struct scsi_cmnd *cmd) | |
| 1630 | +{ | |
| 1631 | + struct aac_hba_cmd_req *hbacmd = aac_construct_hbacmd(fib, cmd); | |
| 1632 | + struct aac_dev *dev; | |
| 1633 | + long ret; | |
| 1634 | + | |
| 1635 | + dev = (struct aac_dev *)cmd->device->host->hostdata; | |
| 1636 | + | |
| 1637 | + ret = aac_build_sghba(cmd, hbacmd, | |
| 1638 | + dev->scsi_host_ptr->sg_tablesize, (u64)fib->hw_sgl_pa); | |
| 1639 | + if (ret < 0) | |
| 1640 | + return ret; | |
| 1641 | + | |
| 1642 | + /* | |
| 1643 | + * Now send the HBA command to the adapter | |
| 1644 | + */ | |
| 1645 | + fib->hbacmd_size = 64 + le32_to_cpu(hbacmd->emb_data_desc_count) * | |
| 1646 | + sizeof(struct aac_hba_sgl); | |
| 1647 | + | |
| 1648 | + return aac_hba_send(HBA_IU_TYPE_SCSI_CMD_REQ, fib, | |
| 1649 | + (fib_callback) aac_hba_callback, | |
| 1650 | + (void *) cmd); | |
| 1651 | +} | |
| 1652 | + | |
| 1653 | +int aac_issue_bmic_identify(struct aac_dev *dev, u32 bus, u32 target) | |
| 1654 | +{ | |
| 1655 | + struct fib *fibptr; | |
| 1656 | + struct aac_srb *srbcmd; | |
| 1657 | + struct sgmap64 *sg64; | |
| 1658 | + struct aac_ciss_identify_pd *identify_resp; | |
| 1659 | + dma_addr_t addr; | |
| 1660 | + u32 vbus, vid; | |
| 1661 | + u16 fibsize, datasize; | |
| 1662 | + int rcode = -ENOMEM; | |
| 1663 | + | |
| 1664 | + | |
| 1665 | + fibptr = aac_fib_alloc(dev); | |
| 1666 | + if (!fibptr) | |
| 1667 | + goto out; | |
| 1668 | + | |
| 1669 | + fibsize = sizeof(struct aac_srb) - | |
| 1670 | + sizeof(struct sgentry) + sizeof(struct sgentry64); | |
| 1671 | + datasize = sizeof(struct aac_ciss_identify_pd); | |
| 1672 | + | |
| 1673 | + identify_resp = pci_alloc_consistent(dev->pdev, datasize, &addr); | |
| 1674 | + | |
| 1675 | + if (!identify_resp) | |
| 1676 | + goto fib_free_ptr; | |
| 1677 | + | |
| 1678 | + vbus = (u32)le16_to_cpu(dev->supplement_adapter_info.VirtDeviceBus); | |
| 1679 | + vid = (u32)le16_to_cpu(dev->supplement_adapter_info.VirtDeviceTarget); | |
| 1680 | + | |
| 1681 | + aac_fib_init(fibptr); | |
| 1682 | + | |
| 1683 | + srbcmd = (struct aac_srb *) fib_data(fibptr); | |
| 1684 | + srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi); | |
| 1685 | + srbcmd->channel = cpu_to_le32(vbus); | |
| 1686 | + srbcmd->id = cpu_to_le32(vid); | |
| 1687 | + srbcmd->lun = 0; | |
| 1688 | + srbcmd->flags = cpu_to_le32(SRB_DataIn); | |
| 1689 | + srbcmd->timeout = cpu_to_le32(10); | |
| 1690 | + srbcmd->retry_limit = 0; | |
| 1691 | + srbcmd->cdb_size = cpu_to_le32(12); | |
| 1692 | + srbcmd->count = cpu_to_le32(datasize); | |
| 1693 | + | |
| 1694 | + memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb)); | |
| 1695 | + srbcmd->cdb[0] = 0x26; | |
| 1696 | + srbcmd->cdb[2] = (u8)((AAC_MAX_LUN + target) & 0x00FF); | |
| 1697 | + srbcmd->cdb[6] = CISS_IDENTIFY_PHYSICAL_DEVICE; | |
| 1698 | + | |
| 1699 | + sg64 = (struct sgmap64 *)&srbcmd->sg; | |
| 1700 | + sg64->count = cpu_to_le32(1); | |
| 1701 | + sg64->sg[0].addr[1] = cpu_to_le32((u32)(((addr) >> 16) >> 16)); | |
| 1702 | + sg64->sg[0].addr[0] = cpu_to_le32((u32)(addr & 0xffffffff)); | |
| 1703 | + sg64->sg[0].count = cpu_to_le32(datasize); | |
| 1704 | + | |
| 1705 | + rcode = aac_fib_send(ScsiPortCommand64, | |
| 1706 | + fibptr, fibsize, FsaNormal, 1, 1, NULL, NULL); | |
| 1707 | + | |
| 1708 | + if (identify_resp->current_queue_depth_limit <= 0 || | |
| 1709 | + identify_resp->current_queue_depth_limit > 32) | |
| 1710 | + dev->hba_map[bus][target].qd_limit = 32; | |
| 1711 | + else | |
| 1712 | + dev->hba_map[bus][target].qd_limit = | |
| 1713 | + identify_resp->current_queue_depth_limit; | |
| 1714 | + | |
| 1715 | + pci_free_consistent(dev->pdev, datasize, (void *)identify_resp, addr); | |
| 1716 | + | |
| 1717 | + aac_fib_complete(fibptr); | |
| 1718 | + | |
| 1719 | +fib_free_ptr: | |
| 1720 | + aac_fib_free(fibptr); | |
| 1721 | +out: | |
| 1722 | + return rcode; | |
| 1723 | +} | |
| 1724 | + | |
| 1725 | +/** | |
| 1726 | + * aac_update hba_map()- update current hba map with data from FW | |
| 1727 | + * @dev: aac_dev structure | |
| 1728 | + * @phys_luns: FW information from report phys luns | |
| 1729 | + * | |
| 1730 | + * Update our hba map with the information gathered from the FW | |
| 1731 | + */ | |
| 1732 | +void aac_update_hba_map(struct aac_dev *dev, | |
| 1733 | + struct aac_ciss_phys_luns_resp *phys_luns, int rescan) | |
| 1734 | +{ | |
| 1735 | + /* ok and extended reporting */ | |
| 1736 | + u32 lun_count, nexus; | |
| 1737 | + u32 i, bus, target; | |
| 1738 | + u8 expose_flag, attribs; | |
| 1739 | + u8 devtype; | |
| 1740 | + | |
| 1741 | + lun_count = ((phys_luns->list_length[0] << 24) | |
| 1742 | + + (phys_luns->list_length[1] << 16) | |
| 1743 | + + (phys_luns->list_length[2] << 8) | |
| 1744 | + + (phys_luns->list_length[3])) / 24; | |
| 1745 | + | |
| 1746 | + for (i = 0; i < lun_count; ++i) { | |
| 1747 | + | |
| 1748 | + bus = phys_luns->lun[i].level2[1] & 0x3f; | |
| 1749 | + target = phys_luns->lun[i].level2[0]; | |
| 1750 | + expose_flag = phys_luns->lun[i].bus >> 6; | |
| 1751 | + attribs = phys_luns->lun[i].node_ident[9]; | |
| 1752 | + nexus = *((u32 *) &phys_luns->lun[i].node_ident[12]); | |
| 1753 | + | |
| 1754 | + if (bus >= AAC_MAX_BUSES || target >= AAC_MAX_TARGETS) | |
| 1755 | + continue; | |
| 1756 | + | |
| 1757 | + dev->hba_map[bus][target].expose = expose_flag; | |
| 1758 | + | |
| 1759 | + if (expose_flag != 0) { | |
| 1760 | + devtype = AAC_DEVTYPE_RAID_MEMBER; | |
| 1761 | + goto update_devtype; | |
| 1762 | + } | |
| 1763 | + | |
| 1764 | + if (nexus != 0 && (attribs & 8)) { | |
| 1765 | + devtype = AAC_DEVTYPE_NATIVE_RAW; | |
| 1766 | + dev->hba_map[bus][target].rmw_nexus = | |
| 1767 | + nexus; | |
| 1768 | + } else | |
| 1769 | + devtype = AAC_DEVTYPE_ARC_RAW; | |
| 1770 | + | |
| 1771 | + if (devtype != AAC_DEVTYPE_NATIVE_RAW) | |
| 1772 | + goto update_devtype; | |
| 1773 | + | |
| 1774 | + if (aac_issue_bmic_identify(dev, bus, target) < 0) | |
| 1775 | + dev->hba_map[bus][target].qd_limit = 32; | |
| 1776 | + | |
| 1777 | +update_devtype: | |
| 1778 | + if (rescan == AAC_INIT) | |
| 1779 | + dev->hba_map[bus][target].devtype = devtype; | |
| 1780 | + else | |
| 1781 | + dev->hba_map[bus][target].new_devtype = devtype; | |
| 1782 | + } | |
| 1783 | +} | |
| 1784 | + | |
| 1785 | +/** | |
| 1786 | + * aac_report_phys_luns() Process topology change | |
| 1787 | + * @dev: aac_dev structure | |
| 1788 | + * @fibptr: fib pointer | |
| 1789 | + * | |
| 1790 | + * Execute a CISS REPORT PHYS LUNS and process the results into | |
| 1791 | + * the current hba_map. | |
| 1792 | + */ | |
| 1793 | +int aac_report_phys_luns(struct aac_dev *dev, struct fib *fibptr, int rescan) | |
| 1794 | +{ | |
| 1795 | + int fibsize, datasize; | |
| 1796 | + struct aac_ciss_phys_luns_resp *phys_luns; | |
| 1797 | + struct aac_srb *srbcmd; | |
| 1798 | + struct sgmap64 *sg64; | |
| 1799 | + dma_addr_t addr; | |
| 1800 | + u32 vbus, vid; | |
| 1801 | + int rcode = 0; | |
| 1802 | + | |
| 1803 | + /* Thor SA Firmware -> CISS_REPORT_PHYSICAL_LUNS */ | |
| 1804 | + fibsize = sizeof(struct aac_srb) - sizeof(struct sgentry) | |
| 1805 | + + sizeof(struct sgentry64); | |
| 1806 | + datasize = sizeof(struct aac_ciss_phys_luns_resp) | |
| 1807 | + + (AAC_MAX_TARGETS - 1) * sizeof(struct _ciss_lun); | |
| 1808 | + | |
| 1809 | + phys_luns = (struct aac_ciss_phys_luns_resp *) pci_alloc_consistent( | |
| 1810 | + dev->pdev, datasize, &addr); | |
| 1811 | + | |
| 1812 | + if (phys_luns == NULL) { | |
| 1813 | + rcode = -ENOMEM; | |
| 1814 | + goto err_out; | |
| 1815 | + } | |
| 1816 | + | |
| 1817 | + vbus = (u32) le16_to_cpu( | |
| 1818 | + dev->supplement_adapter_info.VirtDeviceBus); | |
| 1819 | + vid = (u32) le16_to_cpu( | |
| 1820 | + dev->supplement_adapter_info.VirtDeviceTarget); | |
| 1821 | + | |
| 1822 | + aac_fib_init(fibptr); | |
| 1823 | + | |
| 1824 | + srbcmd = (struct aac_srb *) fib_data(fibptr); | |
| 1825 | + srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi); | |
| 1826 | + srbcmd->channel = cpu_to_le32(vbus); | |
| 1827 | + srbcmd->id = cpu_to_le32(vid); | |
| 1828 | + srbcmd->lun = 0; | |
| 1829 | + srbcmd->flags = cpu_to_le32(SRB_DataIn); | |
| 1830 | + srbcmd->timeout = cpu_to_le32(10); | |
| 1831 | + srbcmd->retry_limit = 0; | |
| 1832 | + srbcmd->cdb_size = cpu_to_le32(12); | |
| 1833 | + srbcmd->count = cpu_to_le32(datasize); | |
| 1834 | + | |
| 1835 | + memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb)); | |
| 1836 | + srbcmd->cdb[0] = CISS_REPORT_PHYSICAL_LUNS; | |
| 1837 | + srbcmd->cdb[1] = 2; /* extended reporting */ | |
| 1838 | + srbcmd->cdb[8] = (u8)(datasize >> 8); | |
| 1839 | + srbcmd->cdb[9] = (u8)(datasize); | |
| 1840 | + | |
| 1841 | + sg64 = (struct sgmap64 *) &srbcmd->sg; | |
| 1842 | + sg64->count = cpu_to_le32(1); | |
| 1843 | + sg64->sg[0].addr[1] = cpu_to_le32(upper_32_bits(addr)); | |
| 1844 | + sg64->sg[0].addr[0] = cpu_to_le32(lower_32_bits(addr)); | |
| 1845 | + sg64->sg[0].count = cpu_to_le32(datasize); | |
| 1846 | + | |
| 1847 | + rcode = aac_fib_send(ScsiPortCommand64, fibptr, fibsize, | |
| 1848 | + FsaNormal, 1, 1, NULL, NULL); | |
| 1849 | + | |
| 1850 | + /* analyse data */ | |
| 1851 | + if (rcode >= 0 && phys_luns->resp_flag == 2) { | |
| 1852 | + /* ok and extended reporting */ | |
| 1853 | + aac_update_hba_map(dev, phys_luns, rescan); | |
| 1854 | + } | |
| 1855 | + | |
| 1856 | + pci_free_consistent(dev->pdev, datasize, (void *) phys_luns, addr); | |
| 1857 | +err_out: | |
| 1858 | + return rcode; | |
| 1859 | +} | |
| 1860 | + | |
| 1508 | 1861 | int aac_get_adapter_info(struct aac_dev* dev) |
| 1509 | 1862 | { |
| 1510 | 1863 | struct fib* fibptr; |
| 1511 | 1864 | int rcode; |
| 1512 | − u32 tmp; | |
| 1865 | + u32 tmp, bus, target; | |
| 1513 | 1866 | struct aac_adapter_info *info; |
| 1514 | 1867 | struct aac_bus_info *command; |
| 1515 | 1868 | struct aac_bus_info_response *bus_info; |
| @@ -1540,6 +1893,7 @@ int aac_get_adapter_info(struct aac_dev* dev) · 24 unmodified lines | ||
| 1540 | 1893 | } |
| 1541 | 1894 | memcpy(&dev->adapter_info, info, sizeof(*info)); |
| 1542 | 1895 | |
| 1896 | + dev->supplement_adapter_info.VirtDeviceBus = 0xffff; | |
| 1543 | 1897 | if (dev->adapter_info.options & AAC_OPT_SUPPLEMENT_ADAPTER_INFO) { |
| 1544 | 1898 | struct aac_supplement_adapter_info * sinfo; |
| 1545 | 1899 | |
| @@ -1567,6 +1921,13 @@ int aac_get_adapter_info(struct aac_dev* dev) · 21 unmodified lines | ||
| 1567 | 1921 | |
| 1568 | 1922 | } |
| 1569 | 1923 | |
| 1924 | + /* reset all previous mapped devices (i.e. for init. after IOP_RESET) */ | |
| 1925 | + for (bus = 0; bus < AAC_MAX_BUSES; bus++) { | |
| 1926 | + for (target = 0; target < AAC_MAX_TARGETS; target++) { | |
| 1927 | + dev->hba_map[bus][target].devtype = 0; | |
| 1928 | + dev->hba_map[bus][target].qd_limit = 0; | |
| 1929 | + } | |
| 1930 | + } | |
| 1570 | 1931 | |
| 1571 | 1932 | /* |
| 1572 | 1933 | * GetBusInfo |
| @@ -1599,6 +1960,12 @@ int aac_get_adapter_info(struct aac_dev* dev) · 26 unmodified lines | ||
| 1599 | 1960 | dev->maximum_num_channels = le32_to_cpu(bus_info->BusCount); |
| 1600 | 1961 | } |
| 1601 | 1962 | |
| 1963 | + if (!dev->sync_mode && dev->sa_firmware && | |
| 1964 | + dev->supplement_adapter_info.VirtDeviceBus != 0xffff) { | |
| 1965 | + /* Thor SA Firmware -> CISS_REPORT_PHYSICAL_LUNS */ | |
| 1966 | + rcode = aac_report_phys_luns(dev, fibptr, AAC_INIT); | |
| 1967 | + } | |
| 1968 | + | |
| 1602 | 1969 | if (!dev->in_reset) { |
| 1603 | 1970 | char buffer[16]; |
| 1604 | 1971 | tmp = le32_to_cpu(dev->adapter_info.kernelrev); |
| @@ -1765,6 +2132,11 @@ int aac_get_adapter_info(struct aac_dev* dev) · 160 unmodified lines | ||
| 1765 | 2132 | (dev->scsi_host_ptr->sg_tablesize * 8) + 112; |
| 1766 | 2133 | } |
| 1767 | 2134 | } |
| 2135 | + if (!dev->sync_mode && dev->sa_firmware && | |
| 2136 | + dev->scsi_host_ptr->sg_tablesize > HBA_MAX_SG_SEPARATE) | |
| 2137 | + dev->scsi_host_ptr->sg_tablesize = dev->sg_tablesize = | |
| 2138 | + HBA_MAX_SG_SEPARATE; | |
| 2139 | + | |
| 1768 | 2140 | /* FIB should be freed only after getting the response from the F/W */ |
| 1769 | 2141 | if (rcode != -ERESTARTSYS) { |
| 1770 | 2142 | aac_fib_complete(fibptr); |
| @@ -1845,6 +2217,15 @@ static void io_callback(void *context, struct fib * fibptr) · 74 unmodified lines | ||
| 1845 | 2217 | min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data), |
| 1846 | 2218 | SCSI_SENSE_BUFFERSIZE)); |
| 1847 | 2219 | break; |
| 2220 | + case ST_MEDERR: | |
| 2221 | + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | | |
| 2222 | + SAM_STAT_CHECK_CONDITION; | |
| 2223 | + set_sense(&dev->fsa_dev[cid].sense_data, MEDIUM_ERROR, | |
| 2224 | + SENCODE_UNRECOVERED_READ_ERROR, ASENCODE_NO_SENSE, 0, 0); | |
| 2225 | + memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, | |
| 2226 | + min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data), | |
| 2227 | + SCSI_SENSE_BUFFERSIZE)); | |
| 2228 | + break; | |
| 1848 | 2229 | default: |
| 1849 | 2230 | #ifdef AAC_DETAILED_STATUS_INFO |
| 1850 | 2231 | printk(KERN_WARNING "io_callback: io failed, status = %d\n", |
| @@ -2312,7 +2693,7 @@ static int aac_start_stop(struct scsi_cmnd *scsicmd) · 461 unmodified lines | ||
| 2312 | 2693 | |
| 2313 | 2694 | int aac_scsi_cmd(struct scsi_cmnd * scsicmd) |
| 2314 | 2695 | { |
| 2315 | − u32 cid; | |
| 2696 | + u32 cid, bus; | |
| 2316 | 2697 | struct Scsi_Host *host = scsicmd->device->host; |
| 2317 | 2698 | struct aac_dev *dev = (struct aac_dev *)host->hostdata; |
| 2318 | 2699 | struct fsa_dev_info *fsa_dev_ptr = dev->fsa_dev; |
| @@ -2330,8 +2711,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) · 11 unmodified lines | ||
| 2330 | 2711 | if((cid >= dev->maximum_num_containers) || |
| 2331 | 2712 | (scsicmd->device->lun != 0)) { |
| 2332 | 2713 | scsicmd->result = DID_NO_CONNECT << 16; |
| 2333 | − scsicmd->scsi_done(scsicmd); | |
| 2334 | − return 0; | |
| 2714 | + goto scsi_done_ret; | |
| 2335 | 2715 | } |
| 2336 | 2716 | |
| 2337 | 2717 | /* |
| @@ -2359,15 +2739,30 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) · 21 unmodified lines | ||
| 2359 | 2739 | } |
| 2360 | 2740 | } |
| 2361 | 2741 | } else { /* check for physical non-dasd devices */ |
| 2362 | − if (dev->nondasd_support || expose_physicals || | |
| 2363 | − dev->jbod) { | |
| 2742 | + bus = aac_logical_to_phys(scmd_channel(scsicmd)); | |
| 2743 | + if (bus < AAC_MAX_BUSES && cid < AAC_MAX_TARGETS && | |
| 2744 | + (dev->hba_map[bus][cid].expose | |
| 2745 | + == AAC_HIDE_DISK)){ | |
| 2746 | + if (scsicmd->cmnd[0] == INQUIRY) { | |
| 2747 | + scsicmd->result = DID_NO_CONNECT << 16; | |
| 2748 | + goto scsi_done_ret; | |
| 2749 | + } | |
| 2750 | + } | |
| 2751 | + | |
| 2752 | + if (bus < AAC_MAX_BUSES && cid < AAC_MAX_TARGETS && | |
| 2753 | + dev->hba_map[bus][cid].devtype | |
| 2754 | + == AAC_DEVTYPE_NATIVE_RAW) { | |
| 2755 | + if (dev->in_reset) | |
| 2756 | + return -1; | |
| 2757 | + return aac_send_hba_fib(scsicmd); | |
| 2758 | + } else if (dev->nondasd_support || expose_physicals || | |
| 2759 | + dev->jbod) { | |
| 2364 | 2760 | if (dev->in_reset) |
| 2365 | 2761 | return -1; |
| 2366 | 2762 | return aac_send_srb_fib(scsicmd); |
| 2367 | 2763 | } else { |
| 2368 | 2764 | scsicmd->result = DID_NO_CONNECT << 16; |
| 2369 | − scsicmd->scsi_done(scsicmd); | |
| 2370 | − return 0; | |
| 2765 | + goto scsi_done_ret; | |
| 2371 | 2766 | } |
| 2372 | 2767 | } |
| 2373 | 2768 | } |
| @@ -2385,13 +2780,34 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) · 11 unmodified lines | ||
| 2385 | 2780 | memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, |
| 2386 | 2781 | min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data), |
| 2387 | 2782 | SCSI_SENSE_BUFFERSIZE)); |
| 2388 | − scsicmd->scsi_done(scsicmd); | |
| 2389 | − return 0; | |
| 2783 | + goto scsi_done_ret; | |
| 2390 | 2784 | } |
| 2391 | 2785 | |
| 2392 | − | |
| 2393 | − /* Handle commands here that don't really require going out to the adapter */ | |
| 2394 | 2786 | switch (scsicmd->cmnd[0]) { |
| 2787 | + case READ_6: | |
| 2788 | + case READ_10: | |
| 2789 | + case READ_12: | |
| 2790 | + case READ_16: | |
| 2791 | + if (dev->in_reset) | |
| 2792 | + return -1; | |
| 2793 | + return aac_read(scsicmd); | |
| 2794 | + | |
| 2795 | + case WRITE_6: | |
| 2796 | + case WRITE_10: | |
| 2797 | + case WRITE_12: | |
| 2798 | + case WRITE_16: | |
| 2799 | + if (dev->in_reset) | |
| 2800 | + return -1; | |
| 2801 | + return aac_write(scsicmd); | |
| 2802 | + | |
| 2803 | + case SYNCHRONIZE_CACHE: | |
| 2804 | + if (((aac_cache & 6) == 6) && dev->cache_protected) { | |
| 2805 | + scsicmd->result = AAC_STAT_GOOD; | |
| 2806 | + break; | |
| 2807 | + } | |
| 2808 | + /* Issue FIB to tell Firmware to flush it's cache */ | |
| 2809 | + if ((aac_cache & 6) != 2) | |
| 2810 | + return aac_synchronize(scsicmd); | |
| 2395 | 2811 | case INQUIRY: |
| 2396 | 2812 | { |
| 2397 | 2813 | struct inquiry_data inq_data; |
| @@ -2414,8 +2830,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) · 16 unmodified lines | ||
| 2414 | 2830 | arr[1] = scsicmd->cmnd[2]; |
| 2415 | 2831 | scsi_sg_copy_from_buffer(scsicmd, &inq_data, |
| 2416 | 2832 | sizeof(inq_data)); |
| 2417 | − scsicmd->result = DID_OK << 16 | | |
| 2418 | − COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | |
| 2833 | + scsicmd->result = AAC_STAT_GOOD; | |
| 2419 | 2834 | } else if (scsicmd->cmnd[2] == 0x80) { |
| 2420 | 2835 | /* unit serial number page */ |
| 2421 | 2836 | arr[3] = setinqserial(dev, &arr[4], |
| @@ -2426,8 +2841,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) · 4 unmodified lines | ||
| 2426 | 2841 | if (aac_wwn != 2) |
| 2427 | 2842 | return aac_get_container_serial( |
| 2428 | 2843 | scsicmd); |
| 2429 | − scsicmd->result = DID_OK << 16 | | |
| 2430 | − COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | |
| 2844 | + scsicmd->result = AAC_STAT_GOOD; | |
| 2431 | 2845 | } else if (scsicmd->cmnd[2] == 0x83) { |
| 2432 | 2846 | /* vpd page 0x83 - Device Identification Page */ |
| 2433 | 2847 | char *sno = (char *)&inq_data; |
| @@ -2436,8 +2850,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) · 2 unmodified lines | ||
| 2436 | 2850 | if (aac_wwn != 2) |
| 2437 | 2851 | return aac_get_container_serial( |
| 2438 | 2852 | scsicmd); |
| 2439 | − scsicmd->result = DID_OK << 16 | | |
| 2440 | − COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | |
| 2853 | + scsicmd->result = AAC_STAT_GOOD; | |
| 2441 | 2854 | } else { |
| 2442 | 2855 | /* vpd page not implemented */ |
| 2443 | 2856 | scsicmd->result = DID_OK << 16 | |
| @@ -2452,8 +2865,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) · 8 unmodified lines | ||
| 2452 | 2865 | sizeof(dev->fsa_dev[cid].sense_data), |
| 2453 | 2866 | SCSI_SENSE_BUFFERSIZE)); |
| 2454 | 2867 | } |
| 2455 | − scsicmd->scsi_done(scsicmd); | |
| 2456 | − return 0; | |
| 2868 | + break; | |
| 2457 | 2869 | } |
| 2458 | 2870 | inq_data.inqd_ver = 2; /* claim compliance to SCSI-2 */ |
| 2459 | 2871 | inq_data.inqd_rdf = 2; /* A response data format value of two indicates that the data shall be in the format specified in SCSI-2 */ |
| @@ -2469,9 +2881,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) · 9 unmodified lines | ||
| 2469 | 2881 | inq_data.inqd_pdt = INQD_PDT_PROC; /* Processor device */ |
| 2470 | 2882 | scsi_sg_copy_from_buffer(scsicmd, &inq_data, |
| 2471 | 2883 | sizeof(inq_data)); |
| 2472 | − scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | |
| 2473 | − scsicmd->scsi_done(scsicmd); | |
| 2474 | − return 0; | |
| 2884 | + scsicmd->result = AAC_STAT_GOOD; | |
| 2885 | + break; | |
| 2475 | 2886 | } |
| 2476 | 2887 | if (dev->in_reset) |
| 2477 | 2888 | return -1; |
| @@ -2519,10 +2930,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) · 41 unmodified lines | ||
| 2519 | 2930 | /* Do not cache partition table for arrays */ |
| 2520 | 2931 | scsicmd->device->removable = 1; |
| 2521 | 2932 | |
| 2522 | − scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | |
| 2523 | − scsicmd->scsi_done(scsicmd); | |
| 2524 | − | |
| 2525 | − return 0; | |
| 2933 | + scsicmd->result = AAC_STAT_GOOD; | |
| 2934 | + break; | |
| 2526 | 2935 | } |
| 2527 | 2936 | |
| 2528 | 2937 | case READ_CAPACITY: |
| @@ -2547,11 +2956,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) · 18 unmodified lines | ||
| 2547 | 2956 | scsi_sg_copy_from_buffer(scsicmd, cp, sizeof(cp)); |
| 2548 | 2957 | /* Do not cache partition table for arrays */ |
| 2549 | 2958 | scsicmd->device->removable = 1; |
| 2550 | − scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | | |
| 2551 | − SAM_STAT_GOOD; | |
| 2552 | − scsicmd->scsi_done(scsicmd); | |
| 2553 | − | |
| 2554 | − return 0; | |
| 2959 | + scsicmd->result = AAC_STAT_GOOD; | |
| 2960 | + break; | |
| 2555 | 2961 | } |
| 2556 | 2962 | |
| 2557 | 2963 | case MODE_SENSE: |
| @@ -2629,10 +3035,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) · 71 unmodified lines | ||
| 2629 | 3035 | scsi_sg_copy_from_buffer(scsicmd, |
| 2630 | 3036 | (char *)&mpd, |
| 2631 | 3037 | mode_buf_length); |
| 2632 | − scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | |
| 2633 | − scsicmd->scsi_done(scsicmd); | |
| 2634 | − | |
| 2635 | − return 0; | |
| 3038 | + scsicmd->result = AAC_STAT_GOOD; | |
| 3039 | + break; | |
| 2636 | 3040 | } |
| 2637 | 3041 | case MODE_SENSE_10: |
| 2638 | 3042 | { |
| @@ -2708,18 +3112,17 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) · 69 unmodified lines | ||
| 2708 | 3112 | (char *)&mpd10, |
| 2709 | 3113 | mode_buf_length); |
| 2710 | 3114 | |
| 2711 | − scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | |
| 2712 | − scsicmd->scsi_done(scsicmd); | |
| 2713 | − | |
| 2714 | − return 0; | |
| 3115 | + scsicmd->result = AAC_STAT_GOOD; | |
| 3116 | + break; | |
| 2715 | 3117 | } |
| 2716 | 3118 | case REQUEST_SENSE: |
| 2717 | 3119 | dprintk((KERN_DEBUG "REQUEST SENSE command.\n")); |
| 2718 | − memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, sizeof (struct sense_data)); | |
| 2719 | − memset(&dev->fsa_dev[cid].sense_data, 0, sizeof (struct sense_data)); | |
| 2720 | − scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | |
| 2721 | − scsicmd->scsi_done(scsicmd); | |
| 2722 | − return 0; | |
| 3120 | + memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, | |
| 3121 | + sizeof(struct sense_data)); | |
| 3122 | + memset(&dev->fsa_dev[cid].sense_data, 0, | |
| 3123 | + sizeof(struct sense_data)); | |
| 3124 | + scsicmd->result = AAC_STAT_GOOD; | |
| 3125 | + break; | |
| 2723 | 3126 | |
| 2724 | 3127 | case ALLOW_MEDIUM_REMOVAL: |
| 2725 | 3128 | dprintk((KERN_DEBUG "LOCK command.\n")); |
| @@ -2728,9 +3131,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) · 2 unmodified lines | ||
| 2728 | 3131 | else |
| 2729 | 3132 | fsa_dev_ptr[cid].locked = 0; |
| 2730 | 3133 | |
| 2731 | − scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | |
| 2732 | − scsicmd->scsi_done(scsicmd); | |
| 2733 | − return 0; | |
| 3134 | + scsicmd->result = AAC_STAT_GOOD; | |
| 3135 | + break; | |
| 2734 | 3136 | /* |
| 2735 | 3137 | * These commands are all No-Ops |
| 2736 | 3138 | */ |
| @@ -2746,80 +3148,41 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) · 9 unmodified lines | ||
| 2746 | 3148 | min_t(size_t, |
| 2747 | 3149 | sizeof(dev->fsa_dev[cid].sense_data), |
| 2748 | 3150 | SCSI_SENSE_BUFFERSIZE)); |
| 2749 | − scsicmd->scsi_done(scsicmd); | |
| 2750 | − return 0; | |
| 3151 | + break; | |
| 2751 | 3152 | } |
| 2752 | − /* FALLTHRU */ | |
| 2753 | 3153 | case RESERVE: |
| 2754 | 3154 | case RELEASE: |
| 2755 | 3155 | case REZERO_UNIT: |
| 2756 | 3156 | case REASSIGN_BLOCKS: |
| 2757 | 3157 | case SEEK_10: |
| 2758 | − scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | |
| 2759 | − scsicmd->scsi_done(scsicmd); | |
| 2760 | − return 0; | |
| 3158 | + scsicmd->result = AAC_STAT_GOOD; | |
| 3159 | + break; | |
| 2761 | 3160 | |
| 2762 | 3161 | case START_STOP: |
| 2763 | 3162 | return aac_start_stop(scsicmd); |
| 2764 | − } | |
| 2765 | − | |
| 2766 | − switch (scsicmd->cmnd[0]) | |
| 2767 | − { | |
| 2768 | − case READ_6: | |
| 2769 | − case READ_10: | |
| 2770 | − case READ_12: | |
| 2771 | − case READ_16: | |
| 2772 | − if (dev->in_reset) | |
| 2773 | − return -1; | |
| 2774 | − /* | |
| 2775 | − * Hack to keep track of ordinal number of the device that | |
| 2776 | − * corresponds to a container. Needed to convert | |
| 2777 | − * containers to /dev/sd device names | |
| 2778 | − */ | |
| 2779 | − | |
| 2780 | − if (scsicmd->request->rq_disk) | |
| 2781 | − strlcpy(fsa_dev_ptr[cid].devname, | |
| 2782 | − scsicmd->request->rq_disk->disk_name, | |
| 2783 | − min(sizeof(fsa_dev_ptr[cid].devname), | |
| 2784 | − sizeof(scsicmd->request->rq_disk->disk_name) + 1)); | |
| 2785 | − | |
| 2786 | − return aac_read(scsicmd); | |
| 2787 | 3163 | |
| 2788 | − case WRITE_6: | |
| 2789 | − case WRITE_10: | |
| 2790 | − case WRITE_12: | |
| 2791 | − case WRITE_16: | |
| 2792 | − if (dev->in_reset) | |
| 2793 | − return -1; | |
| 2794 | − return aac_write(scsicmd); | |
| 2795 | − | |
| 2796 | − case SYNCHRONIZE_CACHE: | |
| 2797 | − if (((aac_cache & 6) == 6) && dev->cache_protected) { | |
| 2798 | − scsicmd->result = DID_OK << 16 | | |
| 2799 | − COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | |
| 2800 | − scsicmd->scsi_done(scsicmd); | |
| 2801 | − return 0; | |
| 2802 | − } | |
| 2803 | − /* Issue FIB to tell Firmware to flush it's cache */ | |
| 2804 | − if ((aac_cache & 6) != 2) | |
| 2805 | − return aac_synchronize(scsicmd); | |
| 2806 | − /* FALLTHRU */ | |
| 2807 | − default: | |
| 2808 | − /* | |
| 2809 | − * Unhandled commands | |
| 2810 | − */ | |
| 2811 | − dprintk((KERN_WARNING "Unhandled SCSI Command: 0x%x.\n", scsicmd->cmnd[0])); | |
| 2812 | − scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION; | |
| 2813 | − set_sense(&dev->fsa_dev[cid].sense_data, | |
| 3164 | + /* FALLTHRU */ | |
| 3165 | + default: | |
| 3166 | + /* | |
| 3167 | + * Unhandled commands | |
| 3168 | + */ | |
| 3169 | + dprintk((KERN_WARNING "Unhandled SCSI Command: 0x%x.\n", | |
| 3170 | + scsicmd->cmnd[0])); | |
| 3171 | + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | | |
| 3172 | + SAM_STAT_CHECK_CONDITION; | |
| 3173 | + set_sense(&dev->fsa_dev[cid].sense_data, | |
| 2814 | 3174 | ILLEGAL_REQUEST, SENCODE_INVALID_COMMAND, |
| 2815 | 3175 | ASENCODE_INVALID_COMMAND, 0, 0); |
| 2816 | − memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, | |
| 3176 | + memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, | |
| 2817 | 3177 | min_t(size_t, |
| 2818 | 3178 | sizeof(dev->fsa_dev[cid].sense_data), |
| 2819 | 3179 | SCSI_SENSE_BUFFERSIZE)); |
| 2820 | − scsicmd->scsi_done(scsicmd); | |
| 2821 | − return 0; | |
| 2822 | 3180 | } |
| 3181 | + | |
| 3182 | +scsi_done_ret: | |
| 3183 | + | |
| 3184 | + scsicmd->scsi_done(scsicmd); | |
| 3185 | + return 0; | |
| 2823 | 3186 | } |
| 2824 | 3187 | |
| 2825 | 3188 | static int query_disk(struct aac_dev *dev, void __user *arg) |
| @@ -2954,16 +3317,11 @@ static void aac_srb_callback(void *context, struct fib * fibptr) · 128 unmodified lines | ||
| 2954 | 3317 | return; |
| 2955 | 3318 | |
| 2956 | 3319 | BUG_ON(fibptr == NULL); |
| 2957 | − dev = fibptr->dev; | |
| 2958 | 3320 | |
| 2959 | − scsi_dma_unmap(scsicmd); | |
| 2960 | − | |
| 2961 | − /* expose physical device if expose_physicald flag is on */ | |
| 2962 | − if (scsicmd->cmnd[0] == INQUIRY && !(scsicmd->cmnd[1] & 0x01) | |
| 2963 | − && expose_physicals > 0) | |
| 2964 | − aac_expose_phy_device(scsicmd); | |
| 3321 | + dev = fibptr->dev; | |
| 2965 | 3322 | |
| 2966 | 3323 | srbreply = (struct aac_srb_reply *) fib_data(fibptr); |
| 3324 | + | |
| 2967 | 3325 | scsicmd->sense_buffer[0] = '\0'; /* Initialize sense valid flag to false */ |
| 2968 | 3326 | |
| 2969 | 3327 | if (fibptr->flags & FIB_CONTEXT_FLAG_FASTRESP) { |
| @@ -2976,158 +3334,176 @@ static void aac_srb_callback(void *context, struct fib * fibptr) · 6 unmodified lines | ||
| 2976 | 3334 | */ |
| 2977 | 3335 | scsi_set_resid(scsicmd, scsi_bufflen(scsicmd) |
| 2978 | 3336 | - le32_to_cpu(srbreply->data_xfer_length)); |
| 2979 | − /* | |
| 2980 | − * First check the fib status | |
| 2981 | − */ | |
| 3337 | + } | |
| 2982 | 3338 | |
| 2983 | − if (le32_to_cpu(srbreply->status) != ST_OK) { | |
| 2984 | − int len; | |
| 2985 | 3339 | |
| 2986 | − printk(KERN_WARNING "aac_srb_callback: srb failed, status = %d\n", le32_to_cpu(srbreply->status)); | |
| 2987 | − len = min_t(u32, le32_to_cpu(srbreply->sense_data_size), | |
| 2988 | − SCSI_SENSE_BUFFERSIZE); | |
| 2989 | − scsicmd->result = DID_ERROR << 16 | |
| 2990 | − | COMMAND_COMPLETE << 8 | |
| 2991 | − | SAM_STAT_CHECK_CONDITION; | |
| 2992 | − memcpy(scsicmd->sense_buffer, | |
| 2993 | − srbreply->sense_data, len); | |
| 2994 | − } | |
| 3340 | + scsi_dma_unmap(scsicmd); | |
| 2995 | 3341 | |
| 2996 | − /* | |
| 2997 | − * Next check the srb status | |
| 2998 | − */ | |
| 2999 | − switch ((le32_to_cpu(srbreply->srb_status))&0x3f) { | |
| 3000 | − case SRB_STATUS_ERROR_RECOVERY: | |
| 3001 | − case SRB_STATUS_PENDING: | |
| 3002 | − case SRB_STATUS_SUCCESS: | |
| 3003 | − scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; | |
| 3004 | − break; | |
| 3005 | − case SRB_STATUS_DATA_OVERRUN: | |
| 3006 | − switch (scsicmd->cmnd[0]) { | |
| 3007 | − case READ_6: | |
| 3008 | − case WRITE_6: | |
| 3009 | − case READ_10: | |
| 3010 | − case WRITE_10: | |
| 3011 | − case READ_12: | |
| 3012 | − case WRITE_12: | |
| 3013 | − case READ_16: | |
| 3014 | − case WRITE_16: | |
| 3015 | − if (le32_to_cpu(srbreply->data_xfer_length) | |
| 3016 | − < scsicmd->underflow) | |
| 3017 | − printk(KERN_WARNING"aacraid: SCSI CMD underflow\n"); | |
| 3018 | − else | |
| 3019 | − printk(KERN_WARNING"aacraid: SCSI CMD Data Overrun\n"); | |
| 3020 | − scsicmd->result = DID_ERROR << 16 | |
| 3021 | − | COMMAND_COMPLETE << 8; | |
| 3022 | − break; | |
| 3023 | − case INQUIRY: { | |
| 3024 | − scsicmd->result = DID_OK << 16 | |
| 3025 | − | COMMAND_COMPLETE << 8; | |
| 3026 | − break; | |
| 3027 | − } | |
| 3028 | − default: | |
| 3029 | − scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; | |
| 3030 | − break; | |
| 3031 | − } | |
| 3032 | − break; | |
| 3033 | − case SRB_STATUS_ABORTED: | |
| 3034 | − scsicmd->result = DID_ABORT << 16 | ABORT << 8; | |
| 3035 | − break; | |
| 3036 | − case SRB_STATUS_ABORT_FAILED: | |
| 3037 | − /* | |
| 3038 | − * Not sure about this one - but assuming the | |
| 3039 | − * hba was trying to abort for some reason | |
| 3040 | − */ | |
| 3041 | − scsicmd->result = DID_ERROR << 16 | ABORT << 8; | |
| 3342 | + /* expose physical device if expose_physicald flag is on */ | |
| 3343 | + if (scsicmd->cmnd[0] == INQUIRY && !(scsicmd->cmnd[1] & 0x01) | |
| 3344 | + && expose_physicals > 0) | |
| 3345 | + aac_expose_phy_device(scsicmd); | |
| 3346 | + | |
| 3347 | + /* | |
| 3348 | + * First check the fib status | |
| 3349 | + */ | |
| 3350 | + | |
| 3351 | + if (le32_to_cpu(srbreply->status) != ST_OK) { | |
| 3352 | + int len; | |
| 3353 | + | |
| 3354 | + pr_warn("aac_srb_callback: srb failed, status = %d\n", | |
| 3355 | + le32_to_cpu(srbreply->status)); | |
| 3356 | + len = min_t(u32, le32_to_cpu(srbreply->sense_data_size), | |
| 3357 | + SCSI_SENSE_BUFFERSIZE); | |
| 3358 | + scsicmd->result = DID_ERROR << 16 | |
| 3359 | + | COMMAND_COMPLETE << 8 | |
| 3360 | + | SAM_STAT_CHECK_CONDITION; | |
| 3361 | + memcpy(scsicmd->sense_buffer, | |
| 3362 | + srbreply->sense_data, len); | |
| 3363 | + } | |
| 3364 | + | |
| 3365 | + /* | |
| 3366 | + * Next check the srb status | |
| 3367 | + */ | |
| 3368 | + switch ((le32_to_cpu(srbreply->srb_status))&0x3f) { | |
| 3369 | + case SRB_STATUS_ERROR_RECOVERY: | |
| 3370 | + case SRB_STATUS_PENDING: | |
| 3371 | + case SRB_STATUS_SUCCESS: | |
| 3372 | + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; | |
| 3373 | + break; | |
| 3374 | + case SRB_STATUS_DATA_OVERRUN: | |
| 3375 | + switch (scsicmd->cmnd[0]) { | |
| 3376 | + case READ_6: | |
| 3377 | + case WRITE_6: | |
| 3378 | + case READ_10: | |
| 3379 | + case WRITE_10: | |
| 3380 | + case READ_12: | |
| 3381 | + case WRITE_12: | |
| 3382 | + case READ_16: | |
| 3383 | + case WRITE_16: | |
| 3384 | + if (le32_to_cpu(srbreply->data_xfer_length) | |
| 3385 | + < scsicmd->underflow) | |
| 3386 | + pr_warn("aacraid: SCSI CMD underflow\n"); | |
| 3387 | + else | |
| 3388 | + pr_warn("aacraid: SCSI CMD Data Overrun\n"); | |
| 3389 | + scsicmd->result = DID_ERROR << 16 | |
| 3390 | + | COMMAND_COMPLETE << 8; | |
| 3042 | 3391 | break; |
| 3043 | − case SRB_STATUS_PARITY_ERROR: | |
| 3044 | − scsicmd->result = DID_PARITY << 16 | |
| 3045 | − | MSG_PARITY_ERROR << 8; | |
| 3392 | + case INQUIRY: | |
| 3393 | + scsicmd->result = DID_OK << 16 | |
| 3394 | + | COMMAND_COMPLETE << 8; | |
| 3046 | 3395 | break; |
| 3047 | − case SRB_STATUS_NO_DEVICE: | |
| 3048 | − case SRB_STATUS_INVALID_PATH_ID: | |
| 3049 | − case SRB_STATUS_INVALID_TARGET_ID: | |
| 3050 | − case SRB_STATUS_INVALID_LUN: | |
| 3051 | − case SRB_STATUS_SELECTION_TIMEOUT: | |
| 3052 | − scsicmd->result = DID_NO_CONNECT << 16 | |
| 3053 | − | COMMAND_COMPLETE << 8; | |
| 3396 | + default: | |
| 3397 | + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; | |
| 3054 | 3398 | break; |
| 3399 | + } | |
| 3400 | + break; | |
| 3401 | + case SRB_STATUS_ABORTED: | |
| 3402 | + scsicmd->result = DID_ABORT << 16 | ABORT << 8; | |
| 3403 | + break; | |
| 3404 | + case SRB_STATUS_ABORT_FAILED: | |
| 3405 | + /* | |
| 3406 | + * Not sure about this one - but assuming the | |
| 3407 | + * hba was trying to abort for some reason | |
| 3408 | + */ | |
| 3409 | + scsicmd->result = DID_ERROR << 16 | ABORT << 8; | |
| 3410 | + break; | |
| 3411 | + case SRB_STATUS_PARITY_ERROR: | |
| 3412 | + scsicmd->result = DID_PARITY << 16 | |
| 3413 | + | MSG_PARITY_ERROR << 8; | |
| 3414 | + break; | |
| 3415 | + case SRB_STATUS_NO_DEVICE: | |
| 3416 | + case SRB_STATUS_INVALID_PATH_ID: | |
| 3417 | + case SRB_STATUS_INVALID_TARGET_ID: | |
| 3418 | + case SRB_STATUS_INVALID_LUN: | |
| 3419 | + case SRB_STATUS_SELECTION_TIMEOUT: | |
| 3420 | + scsicmd->result = DID_NO_CONNECT << 16 | |
| 3421 | + | COMMAND_COMPLETE << 8; | |
| 3422 | + break; | |
| 3055 | 3423 | |
| 3056 | − case SRB_STATUS_COMMAND_TIMEOUT: | |
| 3057 | − case SRB_STATUS_TIMEOUT: | |
| 3058 | − scsicmd->result = DID_TIME_OUT << 16 | |
| 3059 | − | COMMAND_COMPLETE << 8; | |
| 3060 | − break; | |
| 3424 | + case SRB_STATUS_COMMAND_TIMEOUT: | |
| 3425 | + case SRB_STATUS_TIMEOUT: | |
| 3426 | + scsicmd->result = DID_TIME_OUT << 16 | |
| 3427 | + | COMMAND_COMPLETE << 8; | |
| 3428 | + break; | |
| 3061 | 3429 | |
| 3062 | − case SRB_STATUS_BUSY: | |
| 3063 | − scsicmd->result = DID_BUS_BUSY << 16 | |
| 3064 | − | COMMAND_COMPLETE << 8; | |
| 3065 | − break; | |
| 3430 | + case SRB_STATUS_BUSY: | |
| 3431 | + scsicmd->result = DID_BUS_BUSY << 16 | |
| 3432 | + | COMMAND_COMPLETE << 8; | |
| 3433 | + break; | |
| 3066 | 3434 | |
| 3067 | − case SRB_STATUS_BUS_RESET: | |
| 3068 | − scsicmd->result = DID_RESET << 16 | |
| 3069 | − | COMMAND_COMPLETE << 8; | |
| 3070 | − break; | |
| 3435 | + case SRB_STATUS_BUS_RESET: | |
| 3436 | + scsicmd->result = DID_RESET << 16 | |
| 3437 | + | COMMAND_COMPLETE << 8; | |
| 3438 | + break; | |
| 3071 | 3439 | |
| 3072 | − case SRB_STATUS_MESSAGE_REJECTED: | |
| 3073 | − scsicmd->result = DID_ERROR << 16 | |
| 3074 | − | MESSAGE_REJECT << 8; | |
| 3075 | − break; | |
| 3076 | − case SRB_STATUS_REQUEST_FLUSHED: | |
| 3077 | − case SRB_STATUS_ERROR: | |
| 3078 | − case SRB_STATUS_INVALID_REQUEST: | |
| 3079 | − case SRB_STATUS_REQUEST_SENSE_FAILED: | |
| 3080 | − case SRB_STATUS_NO_HBA: | |
| 3081 | − case SRB_STATUS_UNEXPECTED_BUS_FREE: | |
| 3082 | − case SRB_STATUS_PHASE_SEQUENCE_FAILURE: | |
| 3083 | − case SRB_STATUS_BAD_SRB_BLOCK_LENGTH: | |
| 3084 | − case SRB_STATUS_DELAYED_RETRY: | |
| 3085 | − case SRB_STATUS_BAD_FUNCTION: | |
| 3086 | − case SRB_STATUS_NOT_STARTED: | |
| 3087 | − case SRB_STATUS_NOT_IN_USE: | |
| 3088 | − case SRB_STATUS_FORCE_ABORT: | |
| 3089 | − case SRB_STATUS_DOMAIN_VALIDATION_FAIL: | |
| 3090 | − default: | |
| 3440 | + case SRB_STATUS_MESSAGE_REJECTED: | |
| 3441 | + scsicmd->result = DID_ERROR << 16 | |
| 3442 | + | MESSAGE_REJECT << 8; | |
| 3443 | + break; | |
| 3444 | + case SRB_STATUS_REQUEST_FLUSHED: | |
| 3445 | + case SRB_STATUS_ERROR: | |
| 3446 | + case SRB_STATUS_INVALID_REQUEST: | |
| 3447 | + case SRB_STATUS_REQUEST_SENSE_FAILED: | |
| 3448 | + case SRB_STATUS_NO_HBA: | |
| 3449 | + case SRB_STATUS_UNEXPECTED_BUS_FREE: | |
| 3450 | + case SRB_STATUS_PHASE_SEQUENCE_FAILURE: | |
| 3451 | + case SRB_STATUS_BAD_SRB_BLOCK_LENGTH: | |
| 3452 | + case SRB_STATUS_DELAYED_RETRY: | |
| 3453 | + case SRB_STATUS_BAD_FUNCTION: | |
| 3454 | + case SRB_STATUS_NOT_STARTED: | |
| 3455 | + case SRB_STATUS_NOT_IN_USE: | |
| 3456 | + case SRB_STATUS_FORCE_ABORT: | |
| 3457 | + case SRB_STATUS_DOMAIN_VALIDATION_FAIL: | |
| 3458 | + default: | |
| 3091 | 3459 | #ifdef AAC_DETAILED_STATUS_INFO |
| 3092 | − printk(KERN_INFO "aacraid: SRB ERROR(%u) %s scsi cmd 0x%x - scsi status 0x%x\n", | |
| 3093 | − le32_to_cpu(srbreply->srb_status) & 0x3F, | |
| 3094 | − aac_get_status_string( | |
| 3095 | − le32_to_cpu(srbreply->srb_status) & 0x3F), | |
| 3096 | − scsicmd->cmnd[0], | |
| 3097 | − le32_to_cpu(srbreply->scsi_status)); | |
| 3460 | + pr_info("aacraid: SRB ERROR(%u) %s scsi cmd 0x%x -scsi status 0x%x\n", | |
| 3461 | + le32_to_cpu(srbreply->srb_status) & 0x3F, | |
| 3462 | + aac_get_status_string( | |
| 3463 | + le32_to_cpu(srbreply->srb_status) & 0x3F), | |
| 3464 | + scsicmd->cmnd[0], | |
| 3465 | + le32_to_cpu(srbreply->scsi_status)); | |
| 3098 | 3466 | #endif |
| 3099 | − if ((scsicmd->cmnd[0] == ATA_12) | |
| 3100 | − || (scsicmd->cmnd[0] == ATA_16)) { | |
| 3101 | − if (scsicmd->cmnd[2] & (0x01 << 5)) { | |
| 3102 | − scsicmd->result = DID_OK << 16 | |
| 3103 | − | COMMAND_COMPLETE << 8; | |
| 3104 | − break; | |
| 3105 | − } else { | |
| 3106 | − scsicmd->result = DID_ERROR << 16 | |
| 3107 | − | COMMAND_COMPLETE << 8; | |
| 3108 | − break; | |
| 3109 | − } | |
| 3467 | + /* | |
| 3468 | + * When the CC bit is SET by the host in ATA pass thru CDB, | |
| 3469 | + * driver is supposed to return DID_OK | |
| 3470 | + * | |
| 3471 | + * When the CC bit is RESET by the host, driver should | |
| 3472 | + * return DID_ERROR | |
| 3473 | + */ | |
| 3474 | + if ((scsicmd->cmnd[0] == ATA_12) | |
| 3475 | + || (scsicmd->cmnd[0] == ATA_16)) { | |
| 3476 | + | |
| 3477 | + if (scsicmd->cmnd[2] & (0x01 << 5)) { | |
| 3478 | + scsicmd->result = DID_OK << 16 | |
| 3479 | + | COMMAND_COMPLETE << 8; | |
| 3480 | + break; | |
| 3110 | 3481 | } else { |
| 3111 | 3482 | scsicmd->result = DID_ERROR << 16 |
| 3112 | 3483 | | COMMAND_COMPLETE << 8; |
| 3113 | − break; | |
| 3484 | + break; | |
| 3114 | 3485 | } |
| 3486 | + } else { | |
| 3487 | + scsicmd->result = DID_ERROR << 16 | |
| 3488 | + | COMMAND_COMPLETE << 8; | |
| 3489 | + break; | |
| 3115 | 3490 | } |
| 3116 | − if (le32_to_cpu(srbreply->scsi_status) | |
| 3117 | − == SAM_STAT_CHECK_CONDITION) { | |
| 3118 | − int len; | |
| 3491 | + } | |
| 3492 | + if (le32_to_cpu(srbreply->scsi_status) | |
| 3493 | + == SAM_STAT_CHECK_CONDITION) { | |
| 3494 | + int len; | |
| 3119 | 3495 | |
| 3120 | − scsicmd->result |= SAM_STAT_CHECK_CONDITION; | |
| 3121 | − len = min_t(u32, le32_to_cpu(srbreply->sense_data_size), | |
| 3122 | − SCSI_SENSE_BUFFERSIZE); | |
| 3496 | + scsicmd->result |= SAM_STAT_CHECK_CONDITION; | |
| 3497 | + len = min_t(u32, le32_to_cpu(srbreply->sense_data_size), | |
| 3498 | + SCSI_SENSE_BUFFERSIZE); | |
| 3123 | 3499 | #ifdef AAC_DETAILED_STATUS_INFO |
| 3124 | − printk(KERN_WARNING "aac_srb_callback: check condition, status = %d len=%d\n", | |
| 3125 | − le32_to_cpu(srbreply->status), len); | |
| 3500 | + pr_warn("aac_srb_callback: check condition, status = %d len=%d\n", | |
| 3501 | + le32_to_cpu(srbreply->status), len); | |
| 3126 | 3502 | #endif |
| 3127 | − memcpy(scsicmd->sense_buffer, | |
| 3128 | − srbreply->sense_data, len); | |
| 3129 | − } | |
| 3503 | + memcpy(scsicmd->sense_buffer, | |
| 3504 | + srbreply->sense_data, len); | |
| 3130 | 3505 | } |
| 3506 | + | |
| 3131 | 3507 | /* |
| 3132 | 3508 | * OR in the scsi status (already shifted up a bit) |
| 3133 | 3509 | */ |
| @@ -3137,9 +3513,152 @@ static void aac_srb_callback(void *context, struct fib * fibptr) · 3 unmodified lines | ||
| 3137 | 3513 | scsicmd->scsi_done(scsicmd); |
| 3138 | 3514 | } |
| 3139 | 3515 | |
| 3516 | +static void hba_resp_task_complete(struct aac_dev *dev, | |
| 3517 | + struct scsi_cmnd *scsicmd, | |
| 3518 | + struct aac_hba_resp *err) { | |
| 3519 | + | |
| 3520 | + scsicmd->result = err->status; | |
| 3521 | + /* set residual count */ | |
| 3522 | + scsi_set_resid(scsicmd, le32_to_cpu(err->residual_count)); | |
| 3523 | + | |
| 3524 | + switch (err->status) { | |
| 3525 | + case SAM_STAT_GOOD: | |
| 3526 | + scsicmd->result |= DID_OK << 16 | COMMAND_COMPLETE << 8; | |
| 3527 | + break; | |
| 3528 | + case SAM_STAT_CHECK_CONDITION: | |
| 3529 | + { | |
| 3530 | + int len; | |
| 3531 | + | |
| 3532 | + len = min_t(u8, err->sense_response_data_len, | |
| 3533 | + SCSI_SENSE_BUFFERSIZE); | |
| 3534 | + if (len) | |
| 3535 | + memcpy(scsicmd->sense_buffer, | |
| 3536 | + err->sense_response_buf, len); | |
| 3537 | + scsicmd->result |= DID_OK << 16 | COMMAND_COMPLETE << 8; | |
| 3538 | + break; | |
| 3539 | + } | |
| 3540 | + case SAM_STAT_BUSY: | |
| 3541 | + scsicmd->result |= DID_BUS_BUSY << 16 | COMMAND_COMPLETE << 8; | |
| 3542 | + break; | |
| 3543 | + case SAM_STAT_TASK_ABORTED: | |
| 3544 | + scsicmd->result |= DID_ABORT << 16 | ABORT << 8; | |
| 3545 | + break; | |
| 3546 | + case SAM_STAT_RESERVATION_CONFLICT: | |
| 3547 | + case SAM_STAT_TASK_SET_FULL: | |
| 3548 | + default: | |
| 3549 | + scsicmd->result |= DID_ERROR << 16 | COMMAND_COMPLETE << 8; | |
| 3550 | + break; | |
| 3551 | + } | |
| 3552 | +} | |
| 3553 | + | |
| 3554 | +static void hba_resp_task_failure(struct aac_dev *dev, | |
| 3555 | + struct scsi_cmnd *scsicmd, | |
| 3556 | + struct aac_hba_resp *err) | |
| 3557 | +{ | |
| 3558 | + switch (err->status) { | |
| 3559 | + case HBA_RESP_STAT_HBAMODE_DISABLED: | |
| 3560 | + { | |
| 3561 | + u32 bus, cid; | |
| 3562 | + | |
| 3563 | + bus = aac_logical_to_phys(scmd_channel(scsicmd)); | |
| 3564 | + cid = scmd_id(scsicmd); | |
| 3565 | + if (dev->hba_map[bus][cid].devtype == AAC_DEVTYPE_NATIVE_RAW) { | |
| 3566 | + dev->hba_map[bus][cid].devtype = AAC_DEVTYPE_ARC_RAW; | |
| 3567 | + dev->hba_map[bus][cid].rmw_nexus = 0xffffffff; | |
| 3568 | + } | |
| 3569 | + scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8; | |
| 3570 | + break; | |
| 3571 | + } | |
| 3572 | + case HBA_RESP_STAT_IO_ERROR: | |
| 3573 | + case HBA_RESP_STAT_NO_PATH_TO_DEVICE: | |
| 3574 | + scsicmd->result = DID_OK << 16 | | |
| 3575 | + COMMAND_COMPLETE << 8 | SAM_STAT_BUSY; | |
| 3576 | + break; | |
| 3577 | + case HBA_RESP_STAT_IO_ABORTED: | |
| 3578 | + scsicmd->result = DID_ABORT << 16 | ABORT << 8; | |
| 3579 | + break; | |
| 3580 | + case HBA_RESP_STAT_INVALID_DEVICE: | |
| 3581 | + scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8; | |
| 3582 | + break; | |
| 3583 | + case HBA_RESP_STAT_UNDERRUN: | |
| 3584 | + /* UNDERRUN is OK */ | |
| 3585 | + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; | |
| 3586 | + break; | |
| 3587 | + case HBA_RESP_STAT_OVERRUN: | |
| 3588 | + default: | |
| 3589 | + scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8; | |
| 3590 | + break; | |
| 3591 | + } | |
| 3592 | +} | |
| 3593 | + | |
| 3594 | +/** | |
| 3595 | + * | |
| 3596 | + * aac_hba_callback | |
| 3597 | + * @context: the context set in the fib - here it is scsi cmd | |
| 3598 | + * @fibptr: pointer to the fib | |
| 3599 | + * | |
| 3600 | + * Handles the completion of a native HBA scsi command | |
| 3601 | + * | |
| 3602 | + */ | |
| 3603 | +void aac_hba_callback(void *context, struct fib *fibptr) | |
| 3604 | +{ | |
| 3605 | + struct aac_dev *dev; | |
| 3606 | + struct scsi_cmnd *scsicmd; | |
| 3607 | + | |
| 3608 | + struct aac_hba_resp *err = | |
| 3609 | + &((struct aac_native_hba *)fibptr->hw_fib_va)->resp.err; | |
| 3610 | + | |
| 3611 | + scsicmd = (struct scsi_cmnd *) context; | |
| 3612 | + | |
| 3613 | + if (!aac_valid_context(scsicmd, fibptr)) | |
| 3614 | + return; | |
| 3615 | + | |
| 3616 | + WARN_ON(fibptr == NULL); | |
| 3617 | + dev = fibptr->dev; | |
| 3618 | + | |
| 3619 | + if (!(fibptr->flags & FIB_CONTEXT_FLAG_NATIVE_HBA_TMF)) | |
| 3620 | + scsi_dma_unmap(scsicmd); | |
| 3621 | + | |
| 3622 | + if (fibptr->flags & FIB_CONTEXT_FLAG_FASTRESP) { | |
| 3623 | + /* fast response */ | |
| 3624 | + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; | |
| 3625 | + goto out; | |
| 3626 | + } | |
| 3627 | + | |
| 3628 | + switch (err->service_response) { | |
| 3629 | + case HBA_RESP_SVCRES_TASK_COMPLETE: | |
| 3630 | + hba_resp_task_complete(dev, scsicmd, err); | |
| 3631 | + break; | |
| 3632 | + case HBA_RESP_SVCRES_FAILURE: | |
| 3633 | + hba_resp_task_failure(dev, scsicmd, err); | |
| 3634 | + break; | |
| 3635 | + case HBA_RESP_SVCRES_TMF_REJECTED: | |
| 3636 | + scsicmd->result = DID_ERROR << 16 | MESSAGE_REJECT << 8; | |
| 3637 | + break; | |
| 3638 | + case HBA_RESP_SVCRES_TMF_LUN_INVALID: | |
| 3639 | + scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8; | |
| 3640 | + break; | |
| 3641 | + case HBA_RESP_SVCRES_TMF_COMPLETE: | |
| 3642 | + case HBA_RESP_SVCRES_TMF_SUCCEEDED: | |
| 3643 | + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; | |
| 3644 | + break; | |
| 3645 | + default: | |
| 3646 | + scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8; | |
| 3647 | + break; | |
| 3648 | + } | |
| 3649 | + | |
| 3650 | +out: | |
| 3651 | + aac_fib_complete(fibptr); | |
| 3652 | + | |
| 3653 | + if (fibptr->flags & FIB_CONTEXT_FLAG_NATIVE_HBA_TMF) | |
| 3654 | + scsicmd->SCp.sent_command = 1; | |
| 3655 | + else | |
| 3656 | + scsicmd->scsi_done(scsicmd); | |
| 3657 | +} | |
| 3658 | + | |
| 3140 | 3659 | /** |
| 3141 | 3660 | * |
| 3142 | − * aac_send_scb_fib | |
| 3661 | + * aac_send_srb_fib | |
| 3143 | 3662 | * @scsicmd: the scsi command block |
| 3144 | 3663 | * |
| 3145 | 3664 | * This routine will form a FIB and fill in the aac_srb from the |
| @@ -3182,6 +3701,54 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd) · 36 unmodified lines | ||
| 3182 | 3701 | return -1; |
| 3183 | 3702 | } |
| 3184 | 3703 | |
| 3704 | +/** | |
| 3705 | + * | |
| 3706 | + * aac_send_hba_fib | |
| 3707 | + * @scsicmd: the scsi command block | |
| 3708 | + * | |
| 3709 | + * This routine will form a FIB and fill in the aac_hba_cmd_req from the | |
| 3710 | + * scsicmd passed in. | |
| 3711 | + */ | |
| 3712 | +static int aac_send_hba_fib(struct scsi_cmnd *scsicmd) | |
| 3713 | +{ | |
| 3714 | + struct fib *cmd_fibcontext; | |
| 3715 | + struct aac_dev *dev; | |
| 3716 | + int status; | |
| 3717 | + | |
| 3718 | + dev = shost_priv(scsicmd->device->host); | |
| 3719 | + if (scmd_id(scsicmd) >= dev->maximum_num_physicals || | |
| 3720 | + scsicmd->device->lun > AAC_MAX_LUN - 1) { | |
| 3721 | + scsicmd->result = DID_NO_CONNECT << 16; | |
| 3722 | + scsicmd->scsi_done(scsicmd); | |
| 3723 | + return 0; | |
| 3724 | + } | |
| 3725 | + | |
| 3726 | + /* | |
| 3727 | + * Allocate and initialize a Fib then setup a BlockWrite command | |
| 3728 | + */ | |
| 3729 | + cmd_fibcontext = aac_fib_alloc_tag(dev, scsicmd); | |
| 3730 | + if (!cmd_fibcontext) | |
| 3731 | + return -1; | |
| 3732 | + | |
| 3733 | + status = aac_adapter_hba(cmd_fibcontext, scsicmd); | |
| 3734 | + | |
| 3735 | + /* | |
| 3736 | + * Check that the command queued to the controller | |
| 3737 | + */ | |
| 3738 | + if (status == -EINPROGRESS) { | |
| 3739 | + scsicmd->SCp.phase = AAC_OWNER_FIRMWARE; | |
| 3740 | + return 0; | |
| 3741 | + } | |
| 3742 | + | |
| 3743 | + pr_warn("aac_hba_cmd_req: aac_fib_send failed with status: %d\n", | |
| 3744 | + status); | |
| 3745 | + aac_fib_complete(cmd_fibcontext); | |
| 3746 | + aac_fib_free(cmd_fibcontext); | |
| 3747 | + | |
| 3748 | + return -1; | |
| 3749 | +} | |
| 3750 | + | |
| 3751 | + | |
| 3185 | 3752 | static long aac_build_sg(struct scsi_cmnd *scsicmd, struct sgmap *psg) |
| 3186 | 3753 | { |
| 3187 | 3754 | struct aac_dev *dev; |
| @@ -3434,6 +4001,75 @@ static int aac_convert_sgraw2(struct aac_raw_io2 *rio2, int pages, int nseg, int · 246 unmodified lines | ||
| 3434 | 4001 | return 0; |
| 3435 | 4002 | } |
| 3436 | 4003 | |
| 4004 | +static long aac_build_sghba(struct scsi_cmnd *scsicmd, | |
| 4005 | + struct aac_hba_cmd_req *hbacmd, | |
| 4006 | + int sg_max, | |
| 4007 | + u64 sg_address) | |
| 4008 | +{ | |
| 4009 | + unsigned long byte_count = 0; | |
| 4010 | + int nseg; | |
| 4011 | + struct scatterlist *sg; | |
| 4012 | + int i; | |
| 4013 | + u32 cur_size; | |
| 4014 | + struct aac_hba_sgl *sge; | |
| 4015 | + | |
| 4016 | + nseg = scsi_dma_map(scsicmd); | |
| 4017 | + if (nseg <= 0) { | |
| 4018 | + byte_count = nseg; | |
| 4019 | + goto out; | |
| 4020 | + } | |
| 4021 | + | |
| 4022 | + if (nseg > HBA_MAX_SG_EMBEDDED) | |
| 4023 | + sge = &hbacmd->sge[2]; | |
| 4024 | + else | |
| 4025 | + sge = &hbacmd->sge[0]; | |
| 4026 | + | |
| 4027 | + scsi_for_each_sg(scsicmd, sg, nseg, i) { | |
| 4028 | + int count = sg_dma_len(sg); | |
| 4029 | + u64 addr = sg_dma_address(sg); | |
| 4030 | + | |
| 4031 | + WARN_ON(i >= sg_max); | |
| 4032 | + sge->addr_hi = cpu_to_le32((u32)(addr>>32)); | |
| 4033 | + sge->addr_lo = cpu_to_le32((u32)(addr & 0xffffffff)); | |
| 4034 | + cur_size = cpu_to_le32(count); | |
| 4035 | + sge->len = cur_size; | |
| 4036 | + sge->flags = 0; | |
| 4037 | + byte_count += count; | |
| 4038 | + sge++; | |
| 4039 | + } | |
| 4040 | + | |
| 4041 | + sge--; | |
| 4042 | + /* hba wants the size to be exact */ | |
| 4043 | + if (byte_count > scsi_bufflen(scsicmd)) { | |
| 4044 | + u32 temp; | |
| 4045 | + | |
| 4046 | + temp = le32_to_cpu(sge->len) - byte_count | |
| 4047 | + - scsi_bufflen(scsicmd); | |
| 4048 | + sge->len = cpu_to_le32(temp); | |
| 4049 | + byte_count = scsi_bufflen(scsicmd); | |
| 4050 | + } | |
| 4051 | + | |
| 4052 | + if (nseg <= HBA_MAX_SG_EMBEDDED) { | |
| 4053 | + hbacmd->emb_data_desc_count = cpu_to_le32(nseg); | |
| 4054 | + sge->flags = cpu_to_le32(0x40000000); | |
| 4055 | + } else { | |
| 4056 | + /* not embedded */ | |
| 4057 | + hbacmd->sge[0].flags = cpu_to_le32(0x80000000); | |
| 4058 | + hbacmd->emb_data_desc_count = (u8)cpu_to_le32(1); | |
| 4059 | + hbacmd->sge[0].addr_hi = (u32)cpu_to_le32(sg_address >> 32); | |
| 4060 | + hbacmd->sge[0].addr_lo = | |
| 4061 | + cpu_to_le32((u32)(sg_address & 0xffffffff)); | |
| 4062 | + } | |
| 4063 | + | |
| 4064 | + /* Check for command underflow */ | |
| 4065 | + if (scsicmd->underflow && (byte_count < scsicmd->underflow)) { | |
| 4066 | + pr_warn("aacraid: cmd len %08lX cmd underflow %08X\n", | |
| 4067 | + byte_count, scsicmd->underflow); | |
| 4068 | + } | |
| 4069 | +out: | |
| 4070 | + return byte_count; | |
| 4071 | +} | |
| 4072 | + | |
| 3437 | 4073 | #ifdef AAC_DETAILED_STATUS_INFO |
| 3438 | 4074 | |
| 3439 | 4075 | struct aac_srb_status_info { |
| @@ -1,3 +1,37 @@ | ||
| 1 | +/* | |
| 2 | + * Adaptec AAC series RAID controller driver | |
| 3 | + * (c) Copyright 2001 Red Hat Inc. <alan@redhat.com> | |
| 4 | + * | |
| 5 | + * based on the old aacraid driver that is.. | |
| 6 | + * Adaptec aacraid device driver for Linux. | |
| 7 | + * | |
| 8 | + * Copyright (c) 2000-2010 Adaptec, Inc. | |
| 9 | + * 2010-2015 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | |
| 10 | + * 2016-2017 Microsemi Corp. (aacraid@microsemi.com) | |
| 11 | + * | |
| 12 | + * This program is free software; you can redistribute it and/or modify | |
| 13 | + * it under the terms of the GNU General Public License as published by | |
| 14 | + * the Free Software Foundation; either version 2, or (at your option) | |
| 15 | + * any later version. | |
| 16 | + * | |
| 17 | + * This program is distributed in the hope that it will be useful, | |
| 18 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 19 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 20 | + * GNU General Public License for more details. | |
| 21 | + * | |
| 22 | + * You should have received a copy of the GNU General Public License | |
| 23 | + * along with this program; see the file COPYING. If not, write to | |
| 24 | + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | |
| 25 | + * | |
| 26 | + * Module Name: | |
| 27 | + * aacraid.h | |
| 28 | + * | |
| 29 | + * Abstract: Contains all routines for control of the aacraid driver | |
| 30 | + * | |
| 31 | + */ | |
| 32 | + | |
| 33 | +#ifndef _AACRAID_H_ | |
| 34 | +#define _AACRAID_H_ | |
| 1 | 35 | #ifndef dprintk |
| 2 | 36 | # define dprintk(x) |
| 3 | 37 | #endif |
| @@ -63,8 +97,8 @@ enum { · 59 unmodified lines | ||
| 63 | 97 | #define PMC_GLOBAL_INT_BIT0 0x00000001 |
| 64 | 98 | |
| 65 | 99 | #ifndef AAC_DRIVER_BUILD |
| 66 | −# define AAC_DRIVER_BUILD 41066 | |
| 67 | −# define AAC_DRIVER_BRANCH "-ms" | |
| 100 | +# define AAC_DRIVER_BUILD 50740 | |
| 101 | +# define AAC_DRIVER_BRANCH "-custom" | |
| 68 | 102 | #endif |
| 69 | 103 | #define MAXIMUM_NUM_CONTAINERS 32 |
| 70 | 104 | |
| @@ -72,13 +106,311 @@ enum { · 1 unmodified line | ||
| 72 | 106 | #define AAC_NUM_IO_FIB (1024 - AAC_NUM_MGT_FIB) |
| 73 | 107 | #define AAC_NUM_FIB (AAC_NUM_IO_FIB + AAC_NUM_MGT_FIB) |
| 74 | 108 | |
| 75 | −#define AAC_MAX_LUN (8) | |
| 109 | +#define AAC_MAX_LUN 256 | |
| 76 | 110 | |
| 77 | 111 | #define AAC_MAX_HOSTPHYSMEMPAGES (0xfffff) |
| 78 | 112 | #define AAC_MAX_32BIT_SGBCOUNT ((unsigned short)256) |
| 79 | 113 | |
| 80 | 114 | #define AAC_DEBUG_INSTRUMENT_AIF_DELETE |
| 81 | 115 | |
| 116 | +#define AAC_MAX_NATIVE_TARGETS 1024 | |
| 117 | +/* Thor: 5 phys. buses: #0: empty, 1-4: 256 targets each */ | |
| 118 | +#define AAC_MAX_BUSES 5 | |
| 119 | +#define AAC_MAX_TARGETS 256 | |
| 120 | +#define AAC_MAX_NATIVE_SIZE 2048 | |
| 121 | +#define FW_ERROR_BUFFER_SIZE 512 | |
| 122 | + | |
| 123 | +/* Thor AIF events */ | |
| 124 | +#define SA_AIF_HOTPLUG (1<<1) | |
| 125 | +#define SA_AIF_HARDWARE (1<<2) | |
| 126 | +#define SA_AIF_PDEV_CHANGE (1<<4) | |
| 127 | +#define SA_AIF_LDEV_CHANGE (1<<5) | |
| 128 | +#define SA_AIF_BPSTAT_CHANGE (1<<30) | |
| 129 | +#define SA_AIF_BPCFG_CHANGE (1<<31) | |
| 130 | + | |
| 131 | +#define HBA_MAX_SG_EMBEDDED 28 | |
| 132 | +#define HBA_MAX_SG_SEPARATE 90 | |
| 133 | +#define HBA_SENSE_DATA_LEN_MAX 32 | |
| 134 | +#define HBA_REQUEST_TAG_ERROR_FLAG 0x00000002 | |
| 135 | +#define HBA_SGL_FLAGS_EXT 0x80000000UL | |
| 136 | + | |
| 137 | +struct aac_hba_sgl { | |
| 138 | + u32 addr_lo; /* Lower 32-bits of SGL element address */ | |
| 139 | + u32 addr_hi; /* Upper 32-bits of SGL element address */ | |
| 140 | + u32 len; /* Length of SGL element in bytes */ | |
| 141 | + u32 flags; /* SGL element flags */ | |
| 142 | +}; | |
| 143 | + | |
| 144 | +enum { | |
| 145 | + HBA_IU_TYPE_SCSI_CMD_REQ = 0x40, | |
| 146 | + HBA_IU_TYPE_SCSI_TM_REQ = 0x41, | |
| 147 | + HBA_IU_TYPE_SATA_REQ = 0x42, | |
| 148 | + HBA_IU_TYPE_RESP = 0x60, | |
| 149 | + HBA_IU_TYPE_COALESCED_RESP = 0x61, | |
| 150 | + HBA_IU_TYPE_INT_COALESCING_CFG_REQ = 0x70 | |
| 151 | +}; | |
| 152 | + | |
| 153 | +enum { | |
| 154 | + HBA_CMD_BYTE1_DATA_DIR_IN = 0x1, | |
| 155 | + HBA_CMD_BYTE1_DATA_DIR_OUT = 0x2, | |
| 156 | + HBA_CMD_BYTE1_DATA_TYPE_DDR = 0x4, | |
| 157 | + HBA_CMD_BYTE1_CRYPTO_ENABLE = 0x8 | |
| 158 | +}; | |
| 159 | + | |
| 160 | +enum { | |
| 161 | + HBA_CMD_BYTE1_BITOFF_DATA_DIR_IN = 0x0, | |
| 162 | + HBA_CMD_BYTE1_BITOFF_DATA_DIR_OUT, | |
| 163 | + HBA_CMD_BYTE1_BITOFF_DATA_TYPE_DDR, | |
| 164 | + HBA_CMD_BYTE1_BITOFF_CRYPTO_ENABLE | |
| 165 | +}; | |
| 166 | + | |
| 167 | +enum { | |
| 168 | + HBA_RESP_DATAPRES_NO_DATA = 0x0, | |
| 169 | + HBA_RESP_DATAPRES_RESPONSE_DATA, | |
| 170 | + HBA_RESP_DATAPRES_SENSE_DATA | |
| 171 | +}; | |
| 172 | + | |
| 173 | +enum { | |
| 174 | + HBA_RESP_SVCRES_TASK_COMPLETE = 0x0, | |
| 175 | + HBA_RESP_SVCRES_FAILURE, | |
| 176 | + HBA_RESP_SVCRES_TMF_COMPLETE, | |
| 177 | + HBA_RESP_SVCRES_TMF_SUCCEEDED, | |
| 178 | + HBA_RESP_SVCRES_TMF_REJECTED, | |
| 179 | + HBA_RESP_SVCRES_TMF_LUN_INVALID | |
| 180 | +}; | |
| 181 | + | |
| 182 | +enum { | |
| 183 | + HBA_RESP_STAT_IO_ERROR = 0x1, | |
| 184 | + HBA_RESP_STAT_IO_ABORTED, | |
| 185 | + HBA_RESP_STAT_NO_PATH_TO_DEVICE, | |
| 186 | + HBA_RESP_STAT_INVALID_DEVICE, | |
| 187 | + HBA_RESP_STAT_HBAMODE_DISABLED = 0xE, | |
| 188 | + HBA_RESP_STAT_UNDERRUN = 0x51, | |
| 189 | + HBA_RESP_STAT_OVERRUN = 0x75 | |
| 190 | +}; | |
| 191 | + | |
| 192 | +struct aac_hba_cmd_req { | |
| 193 | + u8 iu_type; /* HBA information unit type */ | |
| 194 | + /* | |
| 195 | + * byte1: | |
| 196 | + * [1:0] DIR - 0=No data, 0x1 = IN, 0x2 = OUT | |
| 197 | + * [2] TYPE - 0=PCI, 1=DDR | |
| 198 | + * [3] CRYPTO_ENABLE - 0=Crypto disabled, 1=Crypto enabled | |
| 199 | + */ | |
| 200 | + u8 byte1; | |
| 201 | + u8 reply_qid; /* Host reply queue to post response to */ | |
| 202 | + u8 reserved1; | |
| 203 | + __le32 it_nexus; /* Device handle for the request */ | |
| 204 | + __le32 request_id; /* Sender context */ | |
| 205 | + /* Lower 32-bits of tweak value for crypto enabled IOs */ | |
| 206 | + __le32 tweak_value_lo; | |
| 207 | + u8 cdb[16]; /* SCSI CDB of the command */ | |
| 208 | + u8 lun[8]; /* SCSI LUN of the command */ | |
| 209 | + | |
| 210 | + /* Total data length in bytes to be read/written (if any) */ | |
| 211 | + __le32 data_length; | |
| 212 | + | |
| 213 | + /* [2:0] Task Attribute, [6:3] Command Priority */ | |
| 214 | + u8 attr_prio; | |
| 215 | + | |
| 216 | + /* Number of SGL elements embedded in the HBA req */ | |
| 217 | + u8 emb_data_desc_count; | |
| 218 | + | |
| 219 | + __le16 dek_index; /* DEK index for crypto enabled IOs */ | |
| 220 | + | |
| 221 | + /* Lower 32-bits of reserved error data target location on the host */ | |
| 222 | + __le32 error_ptr_lo; | |
| 223 | + | |
| 224 | + /* Upper 32-bits of reserved error data target location on the host */ | |
| 225 | + __le32 error_ptr_hi; | |
| 226 | + | |
| 227 | + /* Length of reserved error data area on the host in bytes */ | |
| 228 | + __le32 error_length; | |
| 229 | + | |
| 230 | + /* Upper 32-bits of tweak value for crypto enabled IOs */ | |
| 231 | + __le32 tweak_value_hi; | |
| 232 | + | |
| 233 | + struct aac_hba_sgl sge[HBA_MAX_SG_SEPARATE+2]; /* SG list space */ | |
| 234 | + | |
| 235 | + /* | |
| 236 | + * structure must not exceed | |
| 237 | + * AAC_MAX_NATIVE_SIZE-FW_ERROR_BUFFER_SIZE | |
| 238 | + */ | |
| 239 | +}; | |
| 240 | + | |
| 241 | +/* Task Management Functions (TMF) */ | |
| 242 | +#define HBA_TMF_ABORT_TASK 0x01 | |
| 243 | +#define HBA_TMF_LUN_RESET 0x08 | |
| 244 | + | |
| 245 | +struct aac_hba_tm_req { | |
| 246 | + u8 iu_type; /* HBA information unit type */ | |
| 247 | + u8 reply_qid; /* Host reply queue to post response to */ | |
| 248 | + u8 tmf; /* Task management function */ | |
| 249 | + u8 reserved1; | |
| 250 | + | |
| 251 | + __le32 it_nexus; /* Device handle for the command */ | |
| 252 | + | |
| 253 | + u8 lun[8]; /* SCSI LUN */ | |
| 254 | + | |
| 255 | + /* Used to hold sender context. */ | |
| 256 | + __le32 request_id; /* Sender context */ | |
| 257 | + __le32 reserved2; | |
| 258 | + | |
| 259 | + /* Request identifier of managed task */ | |
| 260 | + __le32 managed_request_id; /* Sender context being managed */ | |
| 261 | + __le32 reserved3; | |
| 262 | + | |
| 263 | + /* Lower 32-bits of reserved error data target location on the host */ | |
| 264 | + __le32 error_ptr_lo; | |
| 265 | + /* Upper 32-bits of reserved error data target location on the host */ | |
| 266 | + __le32 error_ptr_hi; | |
| 267 | + /* Length of reserved error data area on the host in bytes */ | |
| 268 | + __le32 error_length; | |
| 269 | +}; | |
| 270 | + | |
| 271 | +struct aac_hba_reset_req { | |
| 272 | + u8 iu_type; /* HBA information unit type */ | |
| 273 | + /* 0 - reset specified device, 1 - reset all devices */ | |
| 274 | + u8 reset_type; | |
| 275 | + u8 reply_qid; /* Host reply queue to post response to */ | |
| 276 | + u8 reserved1; | |
| 277 | + | |
| 278 | + __le32 it_nexus; /* Device handle for the command */ | |
| 279 | + __le32 request_id; /* Sender context */ | |
| 280 | + /* Lower 32-bits of reserved error data target location on the host */ | |
| 281 | + __le32 error_ptr_lo; | |
| 282 | + /* Upper 32-bits of reserved error data target location on the host */ | |
| 283 | + __le32 error_ptr_hi; | |
| 284 | + /* Length of reserved error data area on the host in bytes */ | |
| 285 | + __le32 error_length; | |
| 286 | +}; | |
| 287 | + | |
| 288 | +struct aac_hba_resp { | |
| 289 | + u8 iu_type; /* HBA information unit type */ | |
| 290 | + u8 reserved1[3]; | |
| 291 | + __le32 request_identifier; /* sender context */ | |
| 292 | + __le32 reserved2; | |
| 293 | + u8 service_response; /* SCSI service response */ | |
| 294 | + u8 status; /* SCSI status */ | |
| 295 | + u8 datapres; /* [1:0] - data present, [7:2] - reserved */ | |
| 296 | + u8 sense_response_data_len; /* Sense/response data length */ | |
| 297 | + __le32 residual_count; /* Residual data length in bytes */ | |
| 298 | + /* Sense/response data */ | |
| 299 | + u8 sense_response_buf[HBA_SENSE_DATA_LEN_MAX]; | |
| 300 | +}; | |
| 301 | + | |
| 302 | +struct aac_native_hba { | |
| 303 | + union { | |
| 304 | + struct aac_hba_cmd_req cmd; | |
| 305 | + struct aac_hba_tm_req tmr; | |
| 306 | + u8 cmd_bytes[AAC_MAX_NATIVE_SIZE-FW_ERROR_BUFFER_SIZE]; | |
| 307 | + } cmd; | |
| 308 | + union { | |
| 309 | + struct aac_hba_resp err; | |
| 310 | + u8 resp_bytes[FW_ERROR_BUFFER_SIZE]; | |
| 311 | + } resp; | |
| 312 | +}; | |
| 313 | + | |
| 314 | +#define CISS_REPORT_PHYSICAL_LUNS 0xc3 | |
| 315 | +#define WRITE_HOST_WELLNESS 0xa5 | |
| 316 | +#define CISS_IDENTIFY_PHYSICAL_DEVICE 0x15 | |
| 317 | +#define BMIC_IN 0x26 | |
| 318 | +#define BMIC_OUT 0x27 | |
| 319 | + | |
| 320 | +struct aac_ciss_phys_luns_resp { | |
| 321 | + u8 list_length[4]; /* LUN list length (N-7, big endian) */ | |
| 322 | + u8 resp_flag; /* extended response_flag */ | |
| 323 | + u8 reserved[3]; | |
| 324 | + struct _ciss_lun { | |
| 325 | + u8 tid[3]; /* Target ID */ | |
| 326 | + u8 bus; /* Bus, flag (bits 6,7) */ | |
| 327 | + u8 level3[2]; | |
| 328 | + u8 level2[2]; | |
| 329 | + u8 node_ident[16]; /* phys. node identifier */ | |
| 330 | + } lun[1]; /* List of phys. devices */ | |
| 331 | +}; | |
| 332 | + | |
| 333 | +/* | |
| 334 | + * Interrupts | |
| 335 | + */ | |
| 336 | +#define AAC_MAX_HRRQ 64 | |
| 337 | + | |
| 338 | +struct aac_ciss_identify_pd { | |
| 339 | + u8 scsi_bus; /* SCSI Bus number on controller */ | |
| 340 | + u8 scsi_id; /* SCSI ID on this bus */ | |
| 341 | + u16 block_size; /* sector size in bytes */ | |
| 342 | + u32 total_blocks; /* number for sectors on drive */ | |
| 343 | + u32 reserved_blocks; /* controller reserved (RIS) */ | |
| 344 | + u8 model[40]; /* Physical Drive Model */ | |
| 345 | + u8 serial_number[40]; /* Drive Serial Number */ | |
| 346 | + u8 firmware_revision[8]; /* drive firmware revision */ | |
| 347 | + u8 scsi_inquiry_bits; /* inquiry byte 7 bits */ | |
| 348 | + u8 compaq_drive_stamp; /* 0 means drive not stamped */ | |
| 349 | + u8 last_failure_reason; | |
| 350 | + | |
| 351 | + u8 flags; | |
| 352 | + u8 more_flags; | |
| 353 | + u8 scsi_lun; /* SCSI LUN for phys drive */ | |
| 354 | + u8 yet_more_flags; | |
| 355 | + u8 even_more_flags; | |
| 356 | + u32 spi_speed_rules; /* SPI Speed :Ultra disable diagnose */ | |
| 357 | + u8 phys_connector[2]; /* connector number on controller */ | |
| 358 | + u8 phys_box_on_bus; /* phys enclosure this drive resides */ | |
| 359 | + u8 phys_bay_in_box; /* phys drv bay this drive resides */ | |
| 360 | + u32 rpm; /* Drive rotational speed in rpm */ | |
| 361 | + u8 device_type; /* type of drive */ | |
| 362 | + u8 sata_version; /* only valid when drive_type is SATA */ | |
| 363 | + u64 big_total_block_count; | |
| 364 | + u64 ris_starting_lba; | |
| 365 | + u32 ris_size; | |
| 366 | + u8 wwid[20]; | |
| 367 | + u8 controller_phy_map[32]; | |
| 368 | + u16 phy_count; | |
| 369 | + u8 phy_connected_dev_type[256]; | |
| 370 | + u8 phy_to_drive_bay_num[256]; | |
| 371 | + u16 phy_to_attached_dev_index[256]; | |
| 372 | + u8 box_index; | |
| 373 | + u8 spitfire_support; | |
| 374 | + u16 extra_physical_drive_flags; | |
| 375 | + u8 negotiated_link_rate[256]; | |
| 376 | + u8 phy_to_phy_map[256]; | |
| 377 | + u8 redundant_path_present_map; | |
| 378 | + u8 redundant_path_failure_map; | |
| 379 | + u8 active_path_number; | |
| 380 | + u16 alternate_paths_phys_connector[8]; | |
| 381 | + u8 alternate_paths_phys_box_on_port[8]; | |
| 382 | + u8 multi_lun_device_lun_count; | |
| 383 | + u8 minimum_good_fw_revision[8]; | |
| 384 | + u8 unique_inquiry_bytes[20]; | |
| 385 | + u8 current_temperature_degreesC; | |
| 386 | + u8 temperature_threshold_degreesC; | |
| 387 | + u8 max_temperature_degreesC; | |
| 388 | + u8 logical_blocks_per_phys_block_exp; /* phyblocksize = 512 * 2^exp */ | |
| 389 | + u16 current_queue_depth_limit; | |
| 390 | + u8 switch_name[10]; | |
| 391 | + u16 switch_port; | |
| 392 | + u8 alternate_paths_switch_name[40]; | |
| 393 | + u8 alternate_paths_switch_port[8]; | |
| 394 | + u16 power_on_hours; /* valid only if gas gauge supported */ | |
| 395 | + u16 percent_endurance_used; /* valid only if gas gauge supported. */ | |
| 396 | + u8 drive_authentication; | |
| 397 | + u8 smart_carrier_authentication; | |
| 398 | + u8 smart_carrier_app_fw_version; | |
| 399 | + u8 smart_carrier_bootloader_fw_version; | |
| 400 | + u8 SanitizeSecureEraseSupport; | |
| 401 | + u8 DriveKeyFlags; | |
| 402 | + u8 encryption_key_name[64]; | |
| 403 | + u32 misc_drive_flags; | |
| 404 | + u16 dek_index; | |
| 405 | + u16 drive_encryption_flags; | |
| 406 | + u8 sanitize_maximum_time[6]; | |
| 407 | + u8 connector_info_mode; | |
| 408 | + u8 connector_info_number[4]; | |
| 409 | + u8 long_connector_name[64]; | |
| 410 | + u8 device_unique_identifier[16]; | |
| 411 | + u8 padto_2K[17]; | |
| 412 | +} __packed; | |
| 413 | + | |
| 82 | 414 | /* |
| 83 | 415 | * These macros convert from physical channels to virtual channels |
| 84 | 416 | */ |
| @@ -86,6 +418,7 @@ enum { · 1 unmodified line | ||
| 86 | 418 | #define CONTAINER_TO_CHANNEL(cont) (CONTAINER_CHANNEL) |
| 87 | 419 | #define CONTAINER_TO_ID(cont) (cont) |
| 88 | 420 | #define CONTAINER_TO_LUN(cont) (0) |
| 421 | +#define ENCLOSURE_CHANNEL (3) | |
| 89 | 422 | |
| 90 | 423 | #define PMC_DEVICE_S6 0x28b |
| 91 | 424 | #define PMC_DEVICE_S7 0x28c |
| @@ -351,10 +684,10 @@ enum aac_queue_types { · 259 unmodified lines | ||
| 351 | 684 | |
| 352 | 685 | /* transport FIB header (PMC) */ |
| 353 | 686 | struct aac_fib_xporthdr { |
| 354 | − u64 HostAddress; /* FIB host address w/o xport header */ | |
| 355 | − u32 Size; /* FIB size excluding xport header */ | |
| 356 | − u32 Handle; /* driver handle to reference the FIB */ | |
| 357 | − u64 Reserved[2]; | |
| 687 | + __le64 HostAddress; /* FIB host address w/o xport header */ | |
| 688 | + __le32 Size; /* FIB size excluding xport header */ | |
| 689 | + __le32 Handle; /* driver handle to reference the FIB */ | |
| 690 | + __le64 Reserved[2]; | |
| 358 | 691 | }; |
| 359 | 692 | |
| 360 | 693 | #define ALIGN32 32 |
| @@ -379,7 +712,7 @@ struct aac_fibhdr { · 18 unmodified lines | ||
| 379 | 712 | __le32 SenderFibAddressHigh;/* upper 32bit of phys. FIB address */ |
| 380 | 713 | __le32 TimeStamp; /* otherwise timestamp for FW internal use */ |
| 381 | 714 | } u; |
| 382 | − u32 Handle; /* FIB handle used for MSGU commnunication */ | |
| 715 | + __le32 Handle; /* FIB handle used for MSGU commnunication */ | |
| 383 | 716 | u32 Previous; /* FW internal use */ |
| 384 | 717 | u32 Next; /* FW internal use */ |
| 385 | 718 | }; |
| @@ -489,41 +822,64 @@ enum fib_xfer_state { · 103 unmodified lines | ||
| 489 | 822 | #define ADAPTER_INIT_STRUCT_REVISION_4 4 // rocket science |
| 490 | 823 | #define ADAPTER_INIT_STRUCT_REVISION_6 6 /* PMC src */ |
| 491 | 824 | #define ADAPTER_INIT_STRUCT_REVISION_7 7 /* Denali */ |
| 825 | +#define ADAPTER_INIT_STRUCT_REVISION_8 8 // Thor | |
| 492 | 826 | |
| 493 | −struct aac_init | |
| 827 | +union aac_init | |
| 494 | 828 | { |
| 495 | − __le32 InitStructRevision; | |
| 496 | − __le32 Sa_MSIXVectors; | |
| 497 | − __le32 fsrev; | |
| 498 | − __le32 CommHeaderAddress; | |
| 499 | − __le32 FastIoCommAreaAddress; | |
| 500 | − __le32 AdapterFibsPhysicalAddress; | |
| 501 | − __le32 AdapterFibsVirtualAddress; | |
| 502 | − __le32 AdapterFibsSize; | |
| 503 | − __le32 AdapterFibAlign; | |
| 504 | − __le32 printfbuf; | |
| 505 | − __le32 printfbufsiz; | |
| 506 | − __le32 HostPhysMemPages; /* number of 4k pages of host | |
| 507 | − physical memory */ | |
| 508 | − __le32 HostElapsedSeconds; /* number of seconds since 1970. */ | |
| 509 | − /* | |
| 510 | − * ADAPTER_INIT_STRUCT_REVISION_4 begins here | |
| 511 | − */ | |
| 512 | − __le32 InitFlags; /* flags for supported features */ | |
| 829 | + struct _r7 { | |
| 830 | + __le32 init_struct_revision; | |
| 831 | + __le32 no_of_msix_vectors; | |
| 832 | + __le32 fsrev; | |
| 833 | + __le32 comm_header_address; | |
| 834 | + __le32 fast_io_comm_area_address; | |
| 835 | + __le32 adapter_fibs_physical_address; | |
| 836 | + __le32 adapter_fibs_virtual_address; | |
| 837 | + __le32 adapter_fibs_size; | |
| 838 | + __le32 adapter_fib_align; | |
| 839 | + __le32 printfbuf; | |
| 840 | + __le32 printfbufsiz; | |
| 841 | + /* number of 4k pages of host phys. mem. */ | |
| 842 | + __le32 host_phys_mem_pages; | |
| 843 | + /* number of seconds since 1970. */ | |
| 844 | + __le32 host_elapsed_seconds; | |
| 845 | + /* ADAPTER_INIT_STRUCT_REVISION_4 begins here */ | |
| 846 | + __le32 init_flags; /* flags for supported features */ | |
| 513 | 847 | #define INITFLAGS_NEW_COMM_SUPPORTED 0x00000001 |
| 514 | 848 | #define INITFLAGS_DRIVER_USES_UTC_TIME 0x00000010 |
| 515 | 849 | #define INITFLAGS_DRIVER_SUPPORTS_PM 0x00000020 |
| 516 | 850 | #define INITFLAGS_NEW_COMM_TYPE1_SUPPORTED 0x00000040 |
| 517 | 851 | #define INITFLAGS_FAST_JBOD_SUPPORTED 0x00000080 |
| 518 | 852 | #define INITFLAGS_NEW_COMM_TYPE2_SUPPORTED 0x00000100 |
| 519 | − __le32 MaxIoCommands; /* max outstanding commands */ | |
| 520 | − __le32 MaxIoSize; /* largest I/O command */ | |
| 521 | − __le32 MaxFibSize; /* largest FIB to adapter */ | |
| 522 | − /* ADAPTER_INIT_STRUCT_REVISION_5 begins here */ | |
| 523 | − __le32 MaxNumAif; /* max number of aif */ | |
| 524 | − /* ADAPTER_INIT_STRUCT_REVISION_6 begins here */ | |
| 525 | − __le32 HostRRQ_AddrLow; | |
| 526 | − __le32 HostRRQ_AddrHigh; /* Host RRQ (response queue) for SRC */ | |
| 853 | +#define INITFLAGS_DRIVER_SUPPORTS_HBA_MODE 0x00000400 | |
| 854 | + __le32 max_io_commands; /* max outstanding commands */ | |
| 855 | + __le32 max_io_size; /* largest I/O command */ | |
| 856 | + __le32 max_fib_size; /* largest FIB to adapter */ | |
| 857 | + /* ADAPTER_INIT_STRUCT_REVISION_5 begins here */ | |
| 858 | + __le32 max_num_aif; /* max number of aif */ | |
| 859 | + /* ADAPTER_INIT_STRUCT_REVISION_6 begins here */ | |
| 860 | + /* Host RRQ (response queue) for SRC */ | |
| 861 | + __le32 host_rrq_addr_low; | |
| 862 | + __le32 host_rrq_addr_high; | |
| 863 | + } r7; | |
| 864 | + struct _r8 { | |
| 865 | + /* ADAPTER_INIT_STRUCT_REVISION_8 */ | |
| 866 | + __le32 init_struct_revision; | |
| 867 | + __le32 rr_queue_count; | |
| 868 | + __le32 host_elapsed_seconds; /* number of secs since 1970. */ | |
| 869 | + __le32 init_flags; | |
| 870 | + __le32 max_io_size; /* largest I/O command */ | |
| 871 | + __le32 max_num_aif; /* max number of aif */ | |
| 872 | + __le32 reserved1; | |
| 873 | + __le32 reserved2; | |
| 874 | + struct _rrq { | |
| 875 | + __le32 host_addr_low; | |
| 876 | + __le32 host_addr_high; | |
| 877 | + __le16 msix_id; | |
| 878 | + __le16 element_count; | |
| 879 | + __le16 comp_thresh; | |
| 880 | + __le16 unused; | |
| 881 | + } rrq[1]; /* up to 64 RRQ addresses */ | |
| 882 | + } r8; | |
| 527 | 883 | }; |
| 528 | 884 | |
| 529 | 885 | enum aac_log_level { |
| @@ -554,7 +910,7 @@ struct adapter_ops · 24 unmodified lines | ||
| 554 | 910 | void (*adapter_enable_int)(struct aac_dev *dev); |
| 555 | 911 | int (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4); |
| 556 | 912 | int (*adapter_check_health)(struct aac_dev *dev); |
| 557 | − int (*adapter_restart)(struct aac_dev *dev, int bled); | |
| 913 | + int (*adapter_restart)(struct aac_dev *dev, int bled, u8 reset_type); | |
| 558 | 914 | void (*adapter_start)(struct aac_dev *dev); |
| 559 | 915 | /* Transport operations */ |
| 560 | 916 | int (*adapter_ioremap)(struct aac_dev * dev, u32 size); |
| @@ -727,6 +1083,7 @@ struct sa_registers { · 166 unmodified lines | ||
| 727 | 1083 | |
| 728 | 1084 | |
| 729 | 1085 | #define SA_INIT_NUM_MSIXVECTORS 1 |
| 1086 | +#define SA_MINIPORT_REVISION SA_INIT_NUM_MSIXVECTORS | |
| 730 | 1087 | |
| 731 | 1088 | #define sa_readw(AEP, CSR) readl(&((AEP)->regs.sa->CSR)) |
| 732 | 1089 | #define sa_readl(AEP, CSR) readl(&((AEP)->regs.sa->CSR)) |
| @@ -820,32 +1177,37 @@ struct rkt_registers { · 87 unmodified lines | ||
| 820 | 1177 | #define src_inbound rx_inbound |
| 821 | 1178 | |
| 822 | 1179 | struct src_mu_registers { |
| 823 | − /* PCI*| Name */ | |
| 824 | − __le32 reserved0[6]; /* 00h | Reserved */ | |
| 825 | − __le32 IOAR[2]; /* 18h | IOA->host interrupt register */ | |
| 826 | − __le32 IDR; /* 20h | Inbound Doorbell Register */ | |
| 827 | − __le32 IISR; /* 24h | Inbound Int. Status Register */ | |
| 828 | − __le32 reserved1[3]; /* 28h | Reserved */ | |
| 829 | − __le32 OIMR; /* 34h | Outbound Int. Mask Register */ | |
| 830 | − __le32 reserved2[25]; /* 38h | Reserved */ | |
| 831 | − __le32 ODR_R; /* 9ch | Outbound Doorbell Read */ | |
| 832 | − __le32 ODR_C; /* a0h | Outbound Doorbell Clear */ | |
| 833 | − __le32 reserved3[6]; /* a4h | Reserved */ | |
| 834 | − __le32 OMR; /* bch | Outbound Message Register */ | |
| 1180 | + /* PCI*| Name */ | |
| 1181 | + __le32 reserved0[6]; /* 00h | Reserved */ | |
| 1182 | + __le32 IOAR[2]; /* 18h | IOA->host interrupt register */ | |
| 1183 | + __le32 IDR; /* 20h | Inbound Doorbell Register */ | |
| 1184 | + __le32 IISR; /* 24h | Inbound Int. Status Register */ | |
| 1185 | + __le32 reserved1[3]; /* 28h | Reserved */ | |
| 1186 | + __le32 OIMR; /* 34h | Outbound Int. Mask Register */ | |
| 1187 | + __le32 reserved2[25]; /* 38h | Reserved */ | |
| 1188 | + __le32 ODR_R; /* 9ch | Outbound Doorbell Read */ | |
| 1189 | + __le32 ODR_C; /* a0h | Outbound Doorbell Clear */ | |
| 1190 | + __le32 reserved3[3]; /* a4h | Reserved */ | |
| 1191 | + __le32 SCR0; /* b0h | Scratchpad 0 */ | |
| 1192 | + __le32 reserved4[2]; /* b4h | Reserved */ | |
| 1193 | + __le32 OMR; /* bch | Outbound Message Register */ | |
| 835 | 1194 | __le32 IQ_L; /* c0h | Inbound Queue (Low address) */ |
| 836 | 1195 | __le32 IQ_H; /* c4h | Inbound Queue (High address) */ |
| 837 | 1196 | __le32 ODR_MSI; /* c8h | MSI register for sync./AIF */ |
| 1197 | + __le32 reserved5; /* cch | Reserved */ | |
| 1198 | + __le32 IQN_L; /* d0h | Inbound (native cmd) low */ | |
| 1199 | + __le32 IQN_H; /* d4h | Inbound (native cmd) high */ | |
| 838 | 1200 | }; |
| 839 | 1201 | |
| 840 | 1202 | struct src_registers { |
| 841 | 1203 | struct src_mu_registers MUnit; /* 00h - cbh */ |
| 842 | 1204 | union { |
| 843 | 1205 | struct { |
| 844 | − __le32 reserved1[130789]; /* cch - 7fc5fh */ | |
| 1206 | + __le32 reserved1[130786]; /* d8h - 7fc5fh */ | |
| 845 | 1207 | struct src_inbound IndexRegs; /* 7fc60h */ |
| 846 | 1208 | } tupelo; |
| 847 | 1209 | struct { |
| 848 | − __le32 reserved1[973]; /* cch - fffh */ | |
| 1210 | + __le32 reserved1[970]; /* d8h - fffh */ | |
| 849 | 1211 | struct src_inbound IndexRegs; /* 1000h */ |
| 850 | 1212 | } denali; |
| 851 | 1213 | } u; |
| @@ -930,6 +1292,7 @@ struct fsa_dev_info { · 78 unmodified lines | ||
| 930 | 1292 | char devname[8]; |
| 931 | 1293 | struct sense_data sense_data; |
| 932 | 1294 | u32 block_size; |
| 1295 | + u8 identifier[16]; | |
| 933 | 1296 | }; |
| 934 | 1297 | |
| 935 | 1298 | struct fib { |
| @@ -958,8 +1321,30 @@ struct fib { · 22 unmodified lines | ||
| 958 | 1321 | struct list_head fiblink; |
| 959 | 1322 | void *data; |
| 960 | 1323 | u32 vector_no; |
| 961 | − struct hw_fib *hw_fib_va; /* Actual shared object */ | |
| 962 | − dma_addr_t hw_fib_pa; /* physical address of hw_fib*/ | |
| 1324 | + struct hw_fib *hw_fib_va; /* also used for native */ | |
| 1325 | + dma_addr_t hw_fib_pa; /* physical address of hw_fib*/ | |
| 1326 | + dma_addr_t hw_sgl_pa; /* extra sgl for native */ | |
| 1327 | + dma_addr_t hw_error_pa; /* error buffer for native */ | |
| 1328 | + u32 hbacmd_size; /* cmd size for native */ | |
| 1329 | +}; | |
| 1330 | + | |
| 1331 | +#define AAC_INIT 0 | |
| 1332 | +#define AAC_RESCAN 1 | |
| 1333 | + | |
| 1334 | +#define AAC_DEVTYPE_RAID_MEMBER 1 | |
| 1335 | +#define AAC_DEVTYPE_ARC_RAW 2 | |
| 1336 | +#define AAC_DEVTYPE_NATIVE_RAW 3 | |
| 1337 | +#define AAC_EXPOSE_DISK 0 | |
| 1338 | +#define AAC_HIDE_DISK 3 | |
| 1339 | + | |
| 1340 | +struct aac_hba_map_info { | |
| 1341 | + __le32 rmw_nexus; /* nexus for native HBA devices */ | |
| 1342 | + u8 devtype; /* device type */ | |
| 1343 | + u8 new_devtype; | |
| 1344 | + u8 reset_state; /* 0 - no reset, 1..x - */ | |
| 1345 | + /* after xth TM LUN reset */ | |
| 1346 | + u16 qd_limit; | |
| 1347 | + u8 expose; /*checks if to expose or not*/ | |
| 963 | 1348 | }; |
| 964 | 1349 | |
| 965 | 1350 | /* |
| @@ -1025,7 +1410,28 @@ struct aac_supplement_adapter_info · 59 unmodified lines | ||
| 1025 | 1410 | /* StructExpansion == 1 */ |
| 1026 | 1411 | __le32 FeatureBits3; |
| 1027 | 1412 | __le32 SupportedPerformanceModes; |
| 1028 | − __le32 ReservedForFutureGrowth[80]; | |
| 1413 | + u8 HostBusType; /* uses HOST_BUS_TYPE_xxx defines */ | |
| 1414 | + u8 HostBusWidth; /* actual width in bits or links */ | |
| 1415 | + u16 HostBusSpeed; /* actual bus speed/link rate in MHz */ | |
| 1416 | + u8 MaxRRCDrives; /* max. number of ITP-RRC drives/pool */ | |
| 1417 | + u8 MaxDiskXtasks; /* max. possible num of DiskX Tasks */ | |
| 1418 | + | |
| 1419 | + u8 CpldVerLoaded; | |
| 1420 | + u8 CpldVerInFlash; | |
| 1421 | + | |
| 1422 | + __le64 MaxRRCCapacity; | |
| 1423 | + __le32 CompiledMaxHistLogLevel; | |
| 1424 | + u8 CustomBoardName[12]; | |
| 1425 | + u16 SupportedCntlrMode; /* identify supported controller mode */ | |
| 1426 | + u16 ReservedForFuture16; | |
| 1427 | + __le32 SupportedOptions3; /* reserved for future options */ | |
| 1428 | + | |
| 1429 | + __le16 VirtDeviceBus; /* virt. SCSI device for Thor */ | |
| 1430 | + __le16 VirtDeviceTarget; | |
| 1431 | + __le16 VirtDeviceLUN; | |
| 1432 | + __le16 Unused; | |
| 1433 | + __le32 ReservedForFutureGrowth[68]; | |
| 1434 | + | |
| 1029 | 1435 | }; |
| 1030 | 1436 | #define AAC_FEATURE_FALCON cpu_to_le32(0x00000010) |
| 1031 | 1437 | #define AAC_FEATURE_JBOD cpu_to_le32(0x08000000) |
| @@ -1099,11 +1505,21 @@ struct aac_bus_info_response { · 67 unmodified lines | ||
| 1099 | 1505 | #define AAC_OPT_SUPPLEMENT_ADAPTER_INFO cpu_to_le32(1<<16) |
| 1100 | 1506 | #define AAC_OPT_NEW_COMM cpu_to_le32(1<<17) |
| 1101 | 1507 | #define AAC_OPT_NEW_COMM_64 cpu_to_le32(1<<18) |
| 1508 | +#define AAC_OPT_EXTENDED cpu_to_le32(1<<23) | |
| 1509 | +#define AAC_OPT_NATIVE_HBA cpu_to_le32(1<<25) | |
| 1102 | 1510 | #define AAC_OPT_NEW_COMM_TYPE1 cpu_to_le32(1<<28) |
| 1103 | 1511 | #define AAC_OPT_NEW_COMM_TYPE2 cpu_to_le32(1<<29) |
| 1104 | 1512 | #define AAC_OPT_NEW_COMM_TYPE3 cpu_to_le32(1<<30) |
| 1105 | 1513 | #define AAC_OPT_NEW_COMM_TYPE4 cpu_to_le32(1<<31) |
| 1106 | 1514 | |
| 1515 | +#define AAC_COMM_PRODUCER 0 | |
| 1516 | +#define AAC_COMM_MESSAGE 1 | |
| 1517 | +#define AAC_COMM_MESSAGE_TYPE1 3 | |
| 1518 | +#define AAC_COMM_MESSAGE_TYPE2 4 | |
| 1519 | +#define AAC_COMM_MESSAGE_TYPE3 5 | |
| 1520 | + | |
| 1521 | +#define AAC_EXTOPT_SA_FIRMWARE cpu_to_le32(1<<1) | |
| 1522 | + | |
| 1107 | 1523 | /* MSIX context */ |
| 1108 | 1524 | struct aac_msix_ctx { |
| 1109 | 1525 | int vector_no; |
| @@ -1119,15 +1535,17 @@ struct aac_dev · 9 unmodified lines | ||
| 1119 | 1535 | /* |
| 1120 | 1536 | * negotiated FIB settings |
| 1121 | 1537 | */ |
| 1122 | − unsigned max_fib_size; | |
| 1123 | − unsigned sg_tablesize; | |
| 1124 | − unsigned max_num_aif; | |
| 1538 | + unsigned int max_fib_size; | |
| 1539 | + unsigned int sg_tablesize; | |
| 1540 | + unsigned int max_num_aif; | |
| 1541 | + | |
| 1542 | + unsigned int max_cmd_size; /* max_fib_size or MAX_NATIVE */ | |
| 1125 | 1543 | |
| 1126 | 1544 | /* |
| 1127 | 1545 | * Map for 128 fib objects (64k) |
| 1128 | 1546 | */ |
| 1129 | − dma_addr_t hw_fib_pa; | |
| 1130 | − struct hw_fib *hw_fib_va; | |
| 1547 | + dma_addr_t hw_fib_pa; /* also used for native cmd */ | |
| 1548 | + struct hw_fib *hw_fib_va; /* also used for native cmd */ | |
| 1131 | 1549 | struct hw_fib *aif_base_va; |
| 1132 | 1550 | /* |
| 1133 | 1551 | * Fib Headers |
| @@ -1157,21 +1575,23 @@ struct aac_dev · 23 unmodified lines | ||
| 1157 | 1575 | |
| 1158 | 1576 | resource_size_t base_size, dbg_size; /* Size of |
| 1159 | 1577 | * mapped in region */ |
| 1160 | − | |
| 1161 | − struct aac_init *init; /* Holds initialization info to communicate with adapter */ | |
| 1578 | + /* | |
| 1579 | + * Holds initialization info | |
| 1580 | + * to communicate with adapter | |
| 1581 | + */ | |
| 1582 | + union aac_init *init; | |
| 1162 | 1583 | dma_addr_t init_pa; /* Holds physical address of the init struct */ |
| 1163 | − | |
| 1164 | − u32 *host_rrq; /* response queue | |
| 1165 | − * if AAC_COMM_MESSAGE_TYPE1 */ | |
| 1166 | − | |
| 1584 | + /* response queue (if AAC_COMM_MESSAGE_TYPE1) */ | |
| 1585 | + __le32 *host_rrq; | |
| 1167 | 1586 | dma_addr_t host_rrq_pa; /* phys. address */ |
| 1168 | 1587 | /* index into rrq buffer */ |
| 1169 | 1588 | u32 host_rrq_idx[AAC_MAX_MSIX]; |
| 1170 | 1589 | atomic_t rrq_outstanding[AAC_MAX_MSIX]; |
| 1171 | 1590 | u32 fibs_pushed_no; |
| 1172 | 1591 | struct pci_dev *pdev; /* Our PCI interface */ |
| 1173 | − void * printfbuf; /* pointer to buffer used for printf's from the adapter */ | |
| 1174 | − void * comm_addr; /* Base address of Comm area */ | |
| 1592 | + /* pointer to buffer used for printf's from the adapter */ | |
| 1593 | + void *printfbuf; | |
| 1594 | + void *comm_addr; /* Base address of Comm area */ | |
| 1175 | 1595 | dma_addr_t comm_phys; /* Physical Address of Comm area */ |
| 1176 | 1596 | size_t comm_size; |
| 1177 | 1597 | |
| @@ -1227,15 +1647,12 @@ struct aac_dev · 49 unmodified lines | ||
| 1227 | 1647 | u8 needs_dac; |
| 1228 | 1648 | u8 raid_scsi_mode; |
| 1229 | 1649 | u8 comm_interface; |
| 1230 | −# define AAC_COMM_PRODUCER 0 | |
| 1231 | −# define AAC_COMM_MESSAGE 1 | |
| 1232 | −# define AAC_COMM_MESSAGE_TYPE1 3 | |
| 1233 | −# define AAC_COMM_MESSAGE_TYPE2 4 | |
| 1234 | 1650 | u8 raw_io_interface; |
| 1235 | 1651 | u8 raw_io_64; |
| 1236 | 1652 | u8 printf_enabled; |
| 1237 | 1653 | u8 in_reset; |
| 1238 | 1654 | u8 msi; |
| 1655 | + u8 sa_firmware; | |
| 1239 | 1656 | int management_fib_count; |
| 1240 | 1657 | spinlock_t manage_lock; |
| 1241 | 1658 | spinlock_t sync_lock; |
| @@ -1246,7 +1663,10 @@ struct aac_dev · 4 unmodified lines | ||
| 1246 | 1663 | u32 max_msix; /* max. MSI-X vectors */ |
| 1247 | 1664 | u32 vector_cap; /* MSI-X vector capab.*/ |
| 1248 | 1665 | int msi_enabled; /* MSI/MSI-X enabled */ |
| 1666 | + atomic_t msix_counter; | |
| 1667 | + struct msix_entry msixentry[AAC_MAX_MSIX]; | |
| 1249 | 1668 | struct aac_msix_ctx aac_msix[AAC_MAX_MSIX]; /* context */ |
| 1669 | + struct aac_hba_map_info hba_map[AAC_MAX_BUSES][AAC_MAX_TARGETS]; | |
| 1250 | 1670 | u8 adapter_shutdown; |
| 1251 | 1671 | u32 handle_pci_error; |
| 1252 | 1672 | }; |
| @@ -1269,8 +1689,8 @@ struct aac_dev · 16 unmodified lines | ||
| 1269 | 1689 | #define aac_adapter_check_health(dev) \ |
| 1270 | 1690 | (dev)->a_ops.adapter_check_health(dev) |
| 1271 | 1691 | |
| 1272 | −#define aac_adapter_restart(dev,bled) \ | |
| 1273 | − (dev)->a_ops.adapter_restart(dev,bled) | |
| 1692 | +#define aac_adapter_restart(dev, bled, reset_type) \ | |
| 1693 | + ((dev)->a_ops.adapter_restart(dev, bled, reset_type)) | |
| 1274 | 1694 | |
| 1275 | 1695 | #define aac_adapter_start(dev) \ |
| 1276 | 1696 | ((dev)->a_ops.adapter_start(dev)) |
| @@ -1300,6 +1720,8 @@ struct aac_dev · 23 unmodified lines | ||
| 1300 | 1720 | #define FIB_CONTEXT_FLAG (0x00000002) |
| 1301 | 1721 | #define FIB_CONTEXT_FLAG_WAIT (0x00000004) |
| 1302 | 1722 | #define FIB_CONTEXT_FLAG_FASTRESP (0x00000008) |
| 1723 | +#define FIB_CONTEXT_FLAG_NATIVE_HBA (0x00000010) | |
| 1724 | +#define FIB_CONTEXT_FLAG_NATIVE_HBA_TMF (0x00000020) | |
| 1303 | 1725 | |
| 1304 | 1726 | /* |
| 1305 | 1727 | * Define the command values |
| @@ -1358,6 +1780,7 @@ struct aac_dev · 52 unmodified lines | ||
| 1358 | 1780 | #define ST_IO 5 |
| 1359 | 1781 | #define ST_NXIO 6 |
| 1360 | 1782 | #define ST_E2BIG 7 |
| 1783 | +#define ST_MEDERR 8 | |
| 1361 | 1784 | #define ST_ACCES 13 |
| 1362 | 1785 | #define ST_EXIST 17 |
| 1363 | 1786 | #define ST_XDEV 18 |
| @@ -1715,6 +2138,8 @@ struct aac_fsinfo { · 351 unmodified lines | ||
| 1715 | 2138 | |
| 1716 | 2139 | struct aac_blockdevinfo { |
| 1717 | 2140 | __le32 block_size; |
| 2141 | + __le32 logical_phys_map; | |
| 2142 | + u8 identifier[16]; | |
| 1718 | 2143 | }; |
| 1719 | 2144 | |
| 1720 | 2145 | union aac_contentinfo { |
| @@ -1940,6 +2365,15 @@ struct revision · 219 unmodified lines | ||
| 1940 | 2365 | #define FSACTL_FORCE_DELETE_DISK CTL_CODE(2120, METHOD_NEITHER) |
| 1941 | 2366 | #define FSACTL_GET_CONTAINERS 2131 |
| 1942 | 2367 | #define FSACTL_SEND_LARGE_FIB CTL_CODE(2138, METHOD_BUFFERED) |
| 2368 | +#define FSACTL_RESET_IOP CTL_CODE(2140, METHOD_BUFFERED) | |
| 2369 | +#define FSACTL_GET_HBA_INFO CTL_CODE(2150, METHOD_BUFFERED) | |
| 2370 | +/* flags defined for IOP & HW SOFT RESET */ | |
| 2371 | +#define HW_IOP_RESET 0x01 | |
| 2372 | +#define HW_SOFT_RESET 0x02 | |
| 2373 | +#define IOP_HWSOFT_RESET (HW_IOP_RESET | HW_SOFT_RESET) | |
| 2374 | +/* HW Soft Reset register offset */ | |
| 2375 | +#define IBW_SWR_OFFSET 0x4000 | |
| 2376 | +#define SOFT_RESET_TIME 60 | |
| 1943 | 2377 | |
| 1944 | 2378 | |
| 1945 | 2379 | struct aac_common |
| @@ -1958,6 +2392,8 @@ struct aac_common · 12 unmodified lines | ||
| 1958 | 2392 | #ifdef DBG |
| 1959 | 2393 | u32 FibsSent; |
| 1960 | 2394 | u32 FibRecved; |
| 2395 | + u32 NativeSent; | |
| 2396 | + u32 NativeRecved; | |
| 1961 | 2397 | u32 NoResponseSent; |
| 1962 | 2398 | u32 NoResponseRecved; |
| 1963 | 2399 | u32 AsyncSent; |
| @@ -1969,6 +2405,56 @@ struct aac_common · 5 unmodified lines | ||
| 1969 | 2405 | |
| 1970 | 2406 | extern struct aac_common aac_config; |
| 1971 | 2407 | |
| 2408 | +/* | |
| 2409 | + * This is for management ioctl purpose only. | |
| 2410 | + */ | |
| 2411 | +struct aac_hba_info { | |
| 2412 | + | |
| 2413 | + u8 driver_name[50]; | |
| 2414 | + u8 adapter_number; | |
| 2415 | + u8 system_io_bus_number; | |
| 2416 | + u8 device_number; | |
| 2417 | + u32 function_number; | |
| 2418 | + u32 vendor_id; | |
| 2419 | + u32 device_id; | |
| 2420 | + u32 sub_vendor_id; | |
| 2421 | + u32 sub_system_id; | |
| 2422 | + u32 mapped_base_address_size; | |
| 2423 | + u32 base_physical_address_high_part; | |
| 2424 | + u32 base_physical_address_low_part; | |
| 2425 | + | |
| 2426 | + u32 max_command_size; | |
| 2427 | + u32 max_fib_size; | |
| 2428 | + u32 max_scatter_gather_from_os; | |
| 2429 | + u32 max_scatter_gather_to_fw; | |
| 2430 | + u32 max_outstanding_fibs; | |
| 2431 | + | |
| 2432 | + u32 queue_start_threshold; | |
| 2433 | + u32 queue_dump_threshold; | |
| 2434 | + u32 max_io_size_queued; | |
| 2435 | + u32 outstanding_io; | |
| 2436 | + | |
| 2437 | + u32 firmware_build_number; | |
| 2438 | + u32 bios_build_number; | |
| 2439 | + u32 driver_build_number; | |
| 2440 | + u32 serial_number_high_part; | |
| 2441 | + u32 serial_number_low_part; | |
| 2442 | + u32 supported_options; | |
| 2443 | + u32 feature_bits; | |
| 2444 | + u32 currentnumber_ports; | |
| 2445 | + | |
| 2446 | + u8 new_comm_interface:1; | |
| 2447 | + u8 new_commands_supported:1; | |
| 2448 | + u8 disable_passthrough:1; | |
| 2449 | + u8 expose_non_dasd:1; | |
| 2450 | + u8 queue_allowed:1; | |
| 2451 | + u8 bled_check_enabled:1; | |
| 2452 | + u8 reserved1:1; | |
| 2453 | + u8 reserted2:1; | |
| 2454 | + | |
| 2455 | + u32 reserved3[10]; | |
| 2456 | + | |
| 2457 | +}; | |
| 1972 | 2458 | |
| 1973 | 2459 | /* |
| 1974 | 2460 | * The following macro is used when sending and receiving FIBs. It is |
| @@ -2096,9 +2582,10 @@ extern struct aac_common aac_config; · 121 unmodified lines | ||
| 2096 | 2582 | |
| 2097 | 2583 | /* PMC NEW COMM: Request the event data */ |
| 2098 | 2584 | #define AifReqEvent 200 |
| 2585 | +#define AifRawDeviceRemove 203 /* RAW device deleted */ | |
| 2586 | +#define AifNativeDeviceAdd 204 /* native HBA device added */ | |
| 2587 | +#define AifNativeDeviceRemove 205 /* native HBA device removed */ | |
| 2099 | 2588 | |
| 2100 | −/* RAW device deleted */ | |
| 2101 | −#define AifRawDeviceRemove 203 | |
| 2102 | 2589 | |
| 2103 | 2590 | /* |
| 2104 | 2591 | * Adapter Initiated FIB command structures. Start with the adapter |
| @@ -2131,6 +2618,8 @@ static inline unsigned int cap_to_cyls(sector_t capacity, unsigned divisor) · 26 unmodified lines | ||
| 2131 | 2618 | |
| 2132 | 2619 | int aac_acquire_irq(struct aac_dev *dev); |
| 2133 | 2620 | void aac_free_irq(struct aac_dev *dev); |
| 2621 | +int aac_report_phys_luns(struct aac_dev *dev, struct fib *fibptr, int rescan); | |
| 2622 | +int aac_issue_bmic_identify(struct aac_dev *dev, u32 bus, u32 target); | |
| 2134 | 2623 | const char *aac_driverinfo(struct Scsi_Host *); |
| 2135 | 2624 | void aac_fib_vector_assign(struct aac_dev *dev); |
| 2136 | 2625 | struct fib *aac_fib_alloc(struct aac_dev *dev); |
| @@ -2141,9 +2630,12 @@ void aac_fib_free(struct fib * context); · 4 unmodified lines | ||
| 2141 | 2630 | void aac_fib_init(struct fib * context); |
| 2142 | 2631 | void aac_printf(struct aac_dev *dev, u32 val); |
| 2143 | 2632 | int aac_fib_send(u16 command, struct fib * context, unsigned long size, int priority, int wait, int reply, fib_callback callback, void *ctxt); |
| 2633 | +int aac_hba_send(u8 command, struct fib *context, | |
| 2634 | + fib_callback callback, void *ctxt); | |
| 2144 | 2635 | int aac_consumer_get(struct aac_dev * dev, struct aac_queue * q, struct aac_entry **entry); |
| 2145 | 2636 | void aac_consumer_free(struct aac_dev * dev, struct aac_queue * q, u32 qnum); |
| 2146 | 2637 | int aac_fib_complete(struct fib * context); |
| 2638 | +void aac_hba_callback(void *context, struct fib *fibptr); | |
| 2147 | 2639 | #define fib_data(fibctx) ((void *)(fibctx)->hw_fib_va->data) |
| 2148 | 2640 | struct aac_dev *aac_init_adapter(struct aac_dev *dev); |
| 2149 | 2641 | void aac_src_access_devreg(struct aac_dev *dev, int mode); |
| @@ -2169,7 +2661,7 @@ unsigned int aac_command_normal(struct aac_queue * q); · 19 unmodified lines | ||
| 2169 | 2661 | unsigned int aac_intr_normal(struct aac_dev *dev, u32 Index, |
| 2170 | 2662 | int isAif, int isFastResponse, |
| 2171 | 2663 | struct hw_fib *aif_fib); |
| 2172 | −int aac_reset_adapter(struct aac_dev * dev, int forced); | |
| 2664 | +int aac_reset_adapter(struct aac_dev *dev, int forced, u8 reset_type); | |
| 2173 | 2665 | int aac_check_health(struct aac_dev * dev); |
| 2174 | 2666 | int aac_command_thread(void *data); |
| 2175 | 2667 | int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context *fibctx); |
| @@ -2183,7 +2675,6 @@ int aac_rx_select_comm(struct aac_dev *dev, int comm); · 7 unmodified lines | ||
| 2183 | 2675 | int aac_rx_deliver_producer(struct fib * fib); |
| 2184 | 2676 | char * get_container_type(unsigned type); |
| 2185 | 2677 | extern int numacb; |
| 2186 | −extern int acbsize; | |
| 2187 | 2678 | extern char aac_driver_version[]; |
| 2188 | 2679 | extern int startup_timeout; |
| 2189 | 2680 | extern int aif_timeout; |
| @@ -2194,3 +2685,4 @@ extern int aac_commit; · 4 unmodified lines | ||
| 2194 | 2685 | extern int update_interval; |
| 2195 | 2686 | extern int check_interval; |
| 2196 | 2687 | extern int aac_check_reset; |
| 2688 | +#endif | |
| @@ -6,7 +6,8 @@ · 5 unmodified lines | ||
| 6 | 6 | * Adaptec aacraid device driver for Linux. |
| 7 | 7 | * |
| 8 | 8 | * Copyright (c) 2000-2010 Adaptec, Inc. |
| 9 | − * 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | |
| 9 | + * 2010-2015 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | |
| 10 | + * 2016-2017 Microsemi Corp. (aacraid@microsemi.com) | |
| 10 | 11 | * |
| 11 | 12 | * This program is free software; you can redistribute it and/or modify |
| 12 | 13 | * it under the terms of the GNU General Public License as published by |
| @@ -477,20 +478,24 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) · 464 unmodified lines | ||
| 477 | 478 | struct fib* srbfib; |
| 478 | 479 | int status; |
| 479 | 480 | struct aac_srb *srbcmd = NULL; |
| 481 | + struct aac_hba_cmd_req *hbacmd = NULL; | |
| 480 | 482 | struct user_aac_srb *user_srbcmd = NULL; |
| 481 | 483 | struct user_aac_srb __user *user_srb = arg; |
| 482 | 484 | struct aac_srb_reply __user *user_reply; |
| 483 | − struct aac_srb_reply* reply; | |
| 485 | + u32 chn; | |
| 484 | 486 | u32 fibsize = 0; |
| 485 | 487 | u32 flags = 0; |
| 486 | 488 | s32 rcode = 0; |
| 487 | 489 | u32 data_dir; |
| 488 | − void __user *sg_user[32]; | |
| 489 | − void *sg_list[32]; | |
| 490 | + void __user *sg_user[HBA_MAX_SG_EMBEDDED]; | |
| 491 | + void *sg_list[HBA_MAX_SG_EMBEDDED]; | |
| 492 | + u32 sg_count[HBA_MAX_SG_EMBEDDED]; | |
| 490 | 493 | u32 sg_indx = 0; |
| 491 | 494 | u32 byte_count = 0; |
| 492 | 495 | u32 actual_fibsize64, actual_fibsize = 0; |
| 493 | 496 | int i; |
| 497 | + int is_native_device; | |
| 498 | + u64 address; | |
| 494 | 499 | |
| 495 | 500 | |
| 496 | 501 | if (dev->in_reset) { |
| @@ -507,11 +512,6 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) · 10 unmodified lines | ||
| 507 | 512 | if (!(srbfib = aac_fib_alloc(dev))) { |
| 508 | 513 | return -ENOMEM; |
| 509 | 514 | } |
| 510 | − aac_fib_init(srbfib); | |
| 511 | − /* raw_srb FIB is not FastResponseCapable */ | |
| 512 | − srbfib->hw_fib_va->header.XferState &= ~cpu_to_le32(FastResponseCapable); | |
| 513 | − | |
| 514 | − srbcmd = (struct aac_srb*) fib_data(srbfib); | |
| 515 | 515 | |
| 516 | 516 | memset(sg_list, 0, sizeof(sg_list)); /* cleanup may take issue */ |
| 517 | 517 | if(copy_from_user(&fibsize, &user_srb->count,sizeof(u32))){ |
| @@ -538,21 +538,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) · 20 unmodified lines | ||
| 538 | 538 | goto cleanup; |
| 539 | 539 | } |
| 540 | 540 | |
| 541 | − user_reply = arg+fibsize; | |
| 542 | − | |
| 543 | 541 | flags = user_srbcmd->flags; /* from user in cpu order */ |
| 544 | − // Fix up srb for endian and force some values | |
| 545 | − | |
| 546 | − srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi); // Force this | |
| 547 | − srbcmd->channel = cpu_to_le32(user_srbcmd->channel); | |
| 548 | − srbcmd->id = cpu_to_le32(user_srbcmd->id); | |
| 549 | − srbcmd->lun = cpu_to_le32(user_srbcmd->lun); | |
| 550 | − srbcmd->timeout = cpu_to_le32(user_srbcmd->timeout); | |
| 551 | − srbcmd->flags = cpu_to_le32(flags); | |
| 552 | − srbcmd->retry_limit = 0; // Obsolete parameter | |
| 553 | − srbcmd->cdb_size = cpu_to_le32(user_srbcmd->cdb_size); | |
| 554 | − memcpy(srbcmd->cdb, user_srbcmd->cdb, sizeof(srbcmd->cdb)); | |
| 555 | − | |
| 556 | 542 | switch (flags & (SRB_DataIn | SRB_DataOut)) { |
| 557 | 543 | case SRB_DataOut: |
| 558 | 544 | data_dir = DMA_TO_DEVICE; |
| @@ -568,7 +554,12 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) · 9 unmodified lines | ||
| 568 | 554 | } |
| 569 | 555 | if (user_srbcmd->sg.count > ARRAY_SIZE(sg_list)) { |
| 570 | 556 | dprintk((KERN_DEBUG"aacraid: too many sg entries %d\n", |
| 571 | − le32_to_cpu(srbcmd->sg.count))); | |
| 557 | + user_srbcmd->sg.count)); | |
| 558 | + rcode = -EINVAL; | |
| 559 | + goto cleanup; | |
| 560 | + } | |
| 561 | + if ((data_dir == DMA_NONE) && user_srbcmd->sg.count) { | |
| 562 | + dprintk((KERN_DEBUG"aacraid:SG with no direction specified\n")); | |
| 572 | 563 | rcode = -EINVAL; |
| 573 | 564 | goto cleanup; |
| 574 | 565 | } |
| @@ -588,13 +579,136 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) · 13 unmodified lines | ||
| 588 | 579 | rcode = -EINVAL; |
| 589 | 580 | goto cleanup; |
| 590 | 581 | } |
| 591 | − if ((data_dir == DMA_NONE) && user_srbcmd->sg.count) { | |
| 592 | − dprintk((KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n")); | |
| 593 | − rcode = -EINVAL; | |
| 594 | − goto cleanup; | |
| 582 | + | |
| 583 | + chn = aac_logical_to_phys(user_srbcmd->channel); | |
| 584 | + if (chn < AAC_MAX_BUSES && user_srbcmd->id < AAC_MAX_TARGETS && | |
| 585 | + dev->hba_map[chn][user_srbcmd->id].devtype == | |
| 586 | + AAC_DEVTYPE_NATIVE_RAW) { | |
| 587 | + is_native_device = 1; | |
| 588 | + hbacmd = (struct aac_hba_cmd_req *)srbfib->hw_fib_va; | |
| 589 | + memset(hbacmd, 0, 96); /* sizeof(*hbacmd) is not necessary */ | |
| 590 | + | |
| 591 | + /* iu_type is a parameter of aac_hba_send */ | |
| 592 | + switch (data_dir) { | |
| 593 | + case DMA_TO_DEVICE: | |
| 594 | + hbacmd->byte1 = 2; | |
| 595 | + break; | |
| 596 | + case DMA_FROM_DEVICE: | |
| 597 | + case DMA_BIDIRECTIONAL: | |
| 598 | + hbacmd->byte1 = 1; | |
| 599 | + break; | |
| 600 | + case DMA_NONE: | |
| 601 | + default: | |
| 602 | + break; | |
| 603 | + } | |
| 604 | + hbacmd->lun[1] = cpu_to_le32(user_srbcmd->lun); | |
| 605 | + hbacmd->it_nexus = dev->hba_map[chn][user_srbcmd->id].rmw_nexus; | |
| 606 | + | |
| 607 | + /* | |
| 608 | + * we fill in reply_qid later in aac_src_deliver_message | |
| 609 | + * we fill in iu_type, request_id later in aac_hba_send | |
| 610 | + * we fill in emb_data_desc_count, data_length later | |
| 611 | + * in sg list build | |
| 612 | + */ | |
| 613 | + | |
| 614 | + memcpy(hbacmd->cdb, user_srbcmd->cdb, sizeof(hbacmd->cdb)); | |
| 615 | + | |
| 616 | + address = (u64)srbfib->hw_error_pa; | |
| 617 | + hbacmd->error_ptr_hi = cpu_to_le32((u32)(address >> 32)); | |
| 618 | + hbacmd->error_ptr_lo = cpu_to_le32((u32)(address & 0xffffffff)); | |
| 619 | + hbacmd->error_length = cpu_to_le32(FW_ERROR_BUFFER_SIZE); | |
| 620 | + hbacmd->emb_data_desc_count = | |
| 621 | + cpu_to_le32(user_srbcmd->sg.count); | |
| 622 | + srbfib->hbacmd_size = 64 + | |
| 623 | + user_srbcmd->sg.count * sizeof(struct aac_hba_sgl); | |
| 624 | + | |
| 625 | + } else { | |
| 626 | + is_native_device = 0; | |
| 627 | + aac_fib_init(srbfib); | |
| 628 | + | |
| 629 | + /* raw_srb FIB is not FastResponseCapable */ | |
| 630 | + srbfib->hw_fib_va->header.XferState &= | |
| 631 | + ~cpu_to_le32(FastResponseCapable); | |
| 632 | + | |
| 633 | + srbcmd = (struct aac_srb *) fib_data(srbfib); | |
| 634 | + | |
| 635 | + // Fix up srb for endian and force some values | |
| 636 | + | |
| 637 | + srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi); // Force this | |
| 638 | + srbcmd->channel = cpu_to_le32(user_srbcmd->channel); | |
| 639 | + srbcmd->id = cpu_to_le32(user_srbcmd->id); | |
| 640 | + srbcmd->lun = cpu_to_le32(user_srbcmd->lun); | |
| 641 | + srbcmd->timeout = cpu_to_le32(user_srbcmd->timeout); | |
| 642 | + srbcmd->flags = cpu_to_le32(flags); | |
| 643 | + srbcmd->retry_limit = 0; // Obsolete parameter | |
| 644 | + srbcmd->cdb_size = cpu_to_le32(user_srbcmd->cdb_size); | |
| 645 | + memcpy(srbcmd->cdb, user_srbcmd->cdb, sizeof(srbcmd->cdb)); | |
| 595 | 646 | } |
| 647 | + | |
| 596 | 648 | byte_count = 0; |
| 597 | − if (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64) { | |
| 649 | + if (is_native_device) { | |
| 650 | + struct user_sgmap *usg32 = &user_srbcmd->sg; | |
| 651 | + struct user_sgmap64 *usg64 = | |
| 652 | + (struct user_sgmap64 *)&user_srbcmd->sg; | |
| 653 | + | |
| 654 | + for (i = 0; i < usg32->count; i++) { | |
| 655 | + void *p; | |
| 656 | + u64 addr; | |
| 657 | + | |
| 658 | + sg_count[i] = (actual_fibsize64 == fibsize) ? | |
| 659 | + usg64->sg[i].count : usg32->sg[i].count; | |
| 660 | + if (sg_count[i] > | |
| 661 | + (dev->scsi_host_ptr->max_sectors << 9)) { | |
| 662 | + pr_err("aacraid: upsg->sg[%d].count=%u>%u\n", | |
| 663 | + i, sg_count[i], | |
| 664 | + dev->scsi_host_ptr->max_sectors << 9); | |
| 665 | + rcode = -EINVAL; | |
| 666 | + goto cleanup; | |
| 667 | + } | |
| 668 | + | |
| 669 | + p = kmalloc(sg_count[i], GFP_KERNEL|__GFP_DMA); | |
| 670 | + if (!p) { | |
| 671 | + rcode = -ENOMEM; | |
| 672 | + goto cleanup; | |
| 673 | + } | |
| 674 | + | |
| 675 | + if (actual_fibsize64 == fibsize) { | |
| 676 | + addr = (u64)usg64->sg[i].addr[0]; | |
| 677 | + addr += ((u64)usg64->sg[i].addr[1]) << 32; | |
| 678 | + } else { | |
| 679 | + addr = (u64)usg32->sg[i].addr; | |
| 680 | + } | |
| 681 | + | |
| 682 | + sg_user[i] = (void __user *)(uintptr_t)addr; | |
| 683 | + sg_list[i] = p; // save so we can clean up later | |
| 684 | + sg_indx = i; | |
| 685 | + | |
| 686 | + if (flags & SRB_DataOut) { | |
| 687 | + if (copy_from_user(p, sg_user[i], | |
| 688 | + sg_count[i])) { | |
| 689 | + rcode = -EFAULT; | |
| 690 | + goto cleanup; | |
| 691 | + } | |
| 692 | + } | |
| 693 | + addr = pci_map_single(dev->pdev, p, sg_count[i], | |
| 694 | + data_dir); | |
| 695 | + hbacmd->sge[i].addr_hi = cpu_to_le32((u32)(addr>>32)); | |
| 696 | + hbacmd->sge[i].addr_lo = cpu_to_le32( | |
| 697 | + (u32)(addr & 0xffffffff)); | |
| 698 | + hbacmd->sge[i].len = cpu_to_le32(sg_count[i]); | |
| 699 | + hbacmd->sge[i].flags = 0; | |
| 700 | + byte_count += sg_count[i]; | |
| 701 | + } | |
| 702 | + | |
| 703 | + if (usg32->count > 0) /* embedded sglist */ | |
| 704 | + hbacmd->sge[usg32->count-1].flags = | |
| 705 | + cpu_to_le32(0x40000000); | |
| 706 | + hbacmd->data_length = cpu_to_le32(byte_count); | |
| 707 | + | |
| 708 | + status = aac_hba_send(HBA_IU_TYPE_SCSI_CMD_REQ, srbfib, | |
| 709 | + NULL, NULL); | |
| 710 | + | |
| 711 | + } else if (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64) { | |
| 598 | 712 | struct user_sgmap64* upsg = (struct user_sgmap64*)&user_srbcmd->sg; |
| 599 | 713 | struct sgmap64* psg = (struct sgmap64*)&srbcmd->sg; |
| 600 | 714 | |
| @@ -606,7 +720,9 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) · 5 unmodified lines | ||
| 606 | 720 | for (i = 0; i < upsg->count; i++) { |
| 607 | 721 | u64 addr; |
| 608 | 722 | void* p; |
| 609 | − if (upsg->sg[i].count > | |
| 723 | + | |
| 724 | + sg_count[i] = upsg->sg[i].count; | |
| 725 | + if (sg_count[i] > | |
| 610 | 726 | ((dev->adapter_info.options & |
| 611 | 727 | AAC_OPT_NEW_COMM) ? |
| 612 | 728 | (dev->scsi_host_ptr->max_sectors << 9) : |
| @@ -615,10 +731,10 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) · 2 unmodified lines | ||
| 615 | 731 | goto cleanup; |
| 616 | 732 | } |
| 617 | 733 | /* Does this really need to be GFP_DMA? */ |
| 618 | − p = kmalloc(upsg->sg[i].count,GFP_KERNEL|__GFP_DMA); | |
| 734 | + p = kmalloc(sg_count[i], GFP_KERNEL|__GFP_DMA); | |
| 619 | 735 | if(!p) { |
| 620 | 736 | dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n", |
| 621 | − upsg->sg[i].count,i,upsg->count)); | |
| 737 | + sg_count[i], i, upsg->count)); | |
| 622 | 738 | rcode = -ENOMEM; |
| 623 | 739 | goto cleanup; |
| 624 | 740 | } |
| @@ -629,18 +745,20 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) · 4 unmodified lines | ||
| 629 | 745 | sg_indx = i; |
| 630 | 746 | |
| 631 | 747 | if (flags & SRB_DataOut) { |
| 632 | − if(copy_from_user(p,sg_user[i],upsg->sg[i].count)){ | |
| 748 | + if (copy_from_user(p, sg_user[i], | |
| 749 | + sg_count[i])){ | |
| 633 | 750 | dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n")); |
| 634 | 751 | rcode = -EFAULT; |
| 635 | 752 | goto cleanup; |
| 636 | 753 | } |
| 637 | 754 | } |
| 638 | − addr = pci_map_single(dev->pdev, p, upsg->sg[i].count, data_dir); | |
| 755 | + addr = pci_map_single(dev->pdev, p, | |
| 756 | + sg_count[i], data_dir); | |
| 639 | 757 | |
| 640 | 758 | psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff); |
| 641 | 759 | psg->sg[i].addr[1] = cpu_to_le32(addr>>32); |
| 642 | − byte_count += upsg->sg[i].count; | |
| 643 | − psg->sg[i].count = cpu_to_le32(upsg->sg[i].count); | |
| 760 | + byte_count += sg_count[i]; | |
| 761 | + psg->sg[i].count = cpu_to_le32(sg_count[i]); | |
| 644 | 762 | } |
| 645 | 763 | } else { |
| 646 | 764 | struct user_sgmap* usg; |
| @@ -657,7 +775,9 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) · 10 unmodified lines | ||
| 657 | 775 | for (i = 0; i < usg->count; i++) { |
| 658 | 776 | u64 addr; |
| 659 | 777 | void* p; |
| 660 | − if (usg->sg[i].count > | |
| 778 | + | |
| 779 | + sg_count[i] = usg->sg[i].count; | |
| 780 | + if (sg_count[i] > | |
| 661 | 781 | ((dev->adapter_info.options & |
| 662 | 782 | AAC_OPT_NEW_COMM) ? |
| 663 | 783 | (dev->scsi_host_ptr->max_sectors << 9) : |
| @@ -667,10 +787,10 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) · 3 unmodified lines | ||
| 667 | 787 | goto cleanup; |
| 668 | 788 | } |
| 669 | 789 | /* Does this really need to be GFP_DMA? */ |
| 670 | − p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA); | |
| 790 | + p = kmalloc(sg_count[i], GFP_KERNEL|__GFP_DMA); | |
| 671 | 791 | if(!p) { |
| 672 | 792 | dprintk((KERN_DEBUG "aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n", |
| 673 | − usg->sg[i].count,i,usg->count)); | |
| 793 | + sg_count[i], i, usg->count)); | |
| 674 | 794 | kfree(usg); |
| 675 | 795 | rcode = -ENOMEM; |
| 676 | 796 | goto cleanup; |
| @@ -680,19 +800,21 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) · 3 unmodified lines | ||
| 680 | 800 | sg_indx = i; |
| 681 | 801 | |
| 682 | 802 | if (flags & SRB_DataOut) { |
| 683 | − if(copy_from_user(p,sg_user[i],upsg->sg[i].count)){ | |
| 803 | + if (copy_from_user(p, sg_user[i], | |
| 804 | + sg_count[i])) { | |
| 684 | 805 | kfree (usg); |
| 685 | 806 | dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n")); |
| 686 | 807 | rcode = -EFAULT; |
| 687 | 808 | goto cleanup; |
| 688 | 809 | } |
| 689 | 810 | } |
| 690 | − addr = pci_map_single(dev->pdev, p, usg->sg[i].count, data_dir); | |
| 811 | + addr = pci_map_single(dev->pdev, p, | |
| 812 | + sg_count[i], data_dir); | |
| 691 | 813 | |
| 692 | 814 | psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff); |
| 693 | 815 | psg->sg[i].addr[1] = cpu_to_le32(addr>>32); |
| 694 | − byte_count += usg->sg[i].count; | |
| 695 | − psg->sg[i].count = cpu_to_le32(usg->sg[i].count); | |
| 816 | + byte_count += sg_count[i]; | |
| 817 | + psg->sg[i].count = cpu_to_le32(sg_count[i]); | |
| 696 | 818 | } |
| 697 | 819 | kfree (usg); |
| 698 | 820 | } |
| @@ -711,7 +833,9 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) · 12 unmodified lines | ||
| 711 | 833 | for (i = 0; i < upsg->count; i++) { |
| 712 | 834 | uintptr_t addr; |
| 713 | 835 | void* p; |
| 714 | − if (usg->sg[i].count > | |
| 836 | + | |
| 837 | + sg_count[i] = usg->sg[i].count; | |
| 838 | + if (sg_count[i] > | |
| 715 | 839 | ((dev->adapter_info.options & |
| 716 | 840 | AAC_OPT_NEW_COMM) ? |
| 717 | 841 | (dev->scsi_host_ptr->max_sectors << 9) : |
| @@ -720,10 +844,10 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) · 2 unmodified lines | ||
| 720 | 844 | goto cleanup; |
| 721 | 845 | } |
| 722 | 846 | /* Does this really need to be GFP_DMA? */ |
| 723 | − p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA); | |
| 724 | − if(!p) { | |
| 847 | + p = kmalloc(sg_count[i], GFP_KERNEL|__GFP_DMA); | |
| 848 | + if (!p) { | |
| 725 | 849 | dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n", |
| 726 | − usg->sg[i].count,i,usg->count)); | |
| 850 | + sg_count[i], i, usg->count)); | |
| 727 | 851 | rcode = -ENOMEM; |
| 728 | 852 | goto cleanup; |
| 729 | 853 | } |
| @@ -734,7 +858,8 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) · 4 unmodified lines | ||
| 734 | 858 | sg_indx = i; |
| 735 | 859 | |
| 736 | 860 | if (flags & SRB_DataOut) { |
| 737 | − if(copy_from_user(p,sg_user[i],usg->sg[i].count)){ | |
| 861 | + if (copy_from_user(p, sg_user[i], | |
| 862 | + sg_count[i])){ | |
| 738 | 863 | dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n")); |
| 739 | 864 | rcode = -EFAULT; |
| 740 | 865 | goto cleanup; |
| @@ -744,13 +869,15 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) · 3 unmodified lines | ||
| 744 | 869 | |
| 745 | 870 | psg->sg[i].addr = cpu_to_le32(addr & 0xffffffff); |
| 746 | 871 | byte_count += usg->sg[i].count; |
| 747 | − psg->sg[i].count = cpu_to_le32(usg->sg[i].count); | |
| 872 | + psg->sg[i].count = cpu_to_le32(sg_count[i]); | |
| 748 | 873 | } |
| 749 | 874 | } else { |
| 750 | 875 | for (i = 0; i < upsg->count; i++) { |
| 751 | 876 | dma_addr_t addr; |
| 752 | 877 | void* p; |
| 753 | − if (upsg->sg[i].count > | |
| 878 | + | |
| 879 | + sg_count[i] = upsg->sg[i].count; | |
| 880 | + if (sg_count[i] > | |
| 754 | 881 | ((dev->adapter_info.options & |
| 755 | 882 | AAC_OPT_NEW_COMM) ? |
| 756 | 883 | (dev->scsi_host_ptr->max_sectors << 9) : |
| @@ -758,10 +885,10 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) · 1 unmodified line | ||
| 758 | 885 | rcode = -EINVAL; |
| 759 | 886 | goto cleanup; |
| 760 | 887 | } |
| 761 | − p = kmalloc(upsg->sg[i].count, GFP_KERNEL); | |
| 888 | + p = kmalloc(sg_count[i], GFP_KERNEL); | |
| 762 | 889 | if (!p) { |
| 763 | 890 | dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n", |
| 764 | − upsg->sg[i].count, i, upsg->count)); | |
| 891 | + sg_count[i], i, upsg->count)); | |
| 765 | 892 | rcode = -ENOMEM; |
| 766 | 893 | goto cleanup; |
| 767 | 894 | } |
| @@ -770,19 +897,19 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) · 2 unmodified lines | ||
| 770 | 897 | sg_indx = i; |
| 771 | 898 | |
| 772 | 899 | if (flags & SRB_DataOut) { |
| 773 | − if(copy_from_user(p, sg_user[i], | |
| 774 | − upsg->sg[i].count)) { | |
| 900 | + if (copy_from_user(p, sg_user[i], | |
| 901 | + sg_count[i])) { | |
| 775 | 902 | dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n")); |
| 776 | 903 | rcode = -EFAULT; |
| 777 | 904 | goto cleanup; |
| 778 | 905 | } |
| 779 | 906 | } |
| 780 | 907 | addr = pci_map_single(dev->pdev, p, |
| 781 | − upsg->sg[i].count, data_dir); | |
| 908 | + sg_count[i], data_dir); | |
| 782 | 909 | |
| 783 | 910 | psg->sg[i].addr = cpu_to_le32(addr); |
| 784 | − byte_count += upsg->sg[i].count; | |
| 785 | − psg->sg[i].count = cpu_to_le32(upsg->sg[i].count); | |
| 911 | + byte_count += sg_count[i]; | |
| 912 | + psg->sg[i].count = cpu_to_le32(sg_count[i]); | |
| 786 | 913 | } |
| 787 | 914 | } |
| 788 | 915 | srbcmd->count = cpu_to_le32(byte_count); |
| @@ -792,12 +919,13 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) · 3 unmodified lines | ||
| 792 | 919 | psg->count = 0; |
| 793 | 920 | status = aac_fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL); |
| 794 | 921 | } |
| 922 | + | |
| 795 | 923 | if (status == -ERESTARTSYS) { |
| 796 | 924 | rcode = -ERESTARTSYS; |
| 797 | 925 | goto cleanup; |
| 798 | 926 | } |
| 799 | 927 | |
| 800 | − if (status != 0){ | |
| 928 | + if (status != 0) { | |
| 801 | 929 | dprintk((KERN_DEBUG"aacraid: Could not send raw srb fib to hba\n")); |
| 802 | 930 | rcode = -ENXIO; |
| 803 | 931 | goto cleanup; |
| @@ -805,11 +933,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) · 1 unmodified line | ||
| 805 | 933 | |
| 806 | 934 | if (flags & SRB_DataIn) { |
| 807 | 935 | for(i = 0 ; i <= sg_indx; i++){ |
| 808 | − byte_count = le32_to_cpu( | |
| 809 | − (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64) | |
| 810 | − ? ((struct sgmap64*)&srbcmd->sg)->sg[i].count | |
| 811 | − : srbcmd->sg.sg[i].count); | |
| 812 | − if(copy_to_user(sg_user[i], sg_list[i], byte_count)){ | |
| 936 | + if (copy_to_user(sg_user[i], sg_list[i], sg_count[i])) { | |
| 813 | 937 | dprintk((KERN_DEBUG"aacraid: Could not copy sg data to user\n")); |
| 814 | 938 | rcode = -EFAULT; |
| 815 | 939 | goto cleanup; |
| @@ -818,19 +942,50 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) · 2 unmodified lines | ||
| 818 | 942 | } |
| 819 | 943 | } |
| 820 | 944 | |
| 821 | − reply = (struct aac_srb_reply *) fib_data(srbfib); | |
| 822 | − if(copy_to_user(user_reply,reply,sizeof(struct aac_srb_reply))){ | |
| 823 | − dprintk((KERN_DEBUG"aacraid: Could not copy reply to user\n")); | |
| 824 | − rcode = -EFAULT; | |
| 825 | − goto cleanup; | |
| 945 | + user_reply = arg + fibsize; | |
| 946 | + if (is_native_device) { | |
| 947 | + struct aac_hba_resp *err = | |
| 948 | + &((struct aac_native_hba *)srbfib->hw_fib_va)->resp.err; | |
| 949 | + struct aac_srb_reply reply; | |
| 950 | + | |
| 951 | + reply.status = ST_OK; | |
| 952 | + if (srbfib->flags & FIB_CONTEXT_FLAG_FASTRESP) { | |
| 953 | + /* fast response */ | |
| 954 | + reply.srb_status = SRB_STATUS_SUCCESS; | |
| 955 | + reply.scsi_status = 0; | |
| 956 | + reply.data_xfer_length = byte_count; | |
| 957 | + } else { | |
| 958 | + reply.srb_status = err->service_response; | |
| 959 | + reply.scsi_status = err->status; | |
| 960 | + reply.data_xfer_length = byte_count - | |
| 961 | + le32_to_cpu(err->residual_count); | |
| 962 | + reply.sense_data_size = err->sense_response_data_len; | |
| 963 | + memcpy(reply.sense_data, err->sense_response_buf, | |
| 964 | + AAC_SENSE_BUFFERSIZE); | |
| 965 | + } | |
| 966 | + if (copy_to_user(user_reply, &reply, | |
| 967 | + sizeof(struct aac_srb_reply))) { | |
| 968 | + dprintk((KERN_DEBUG"aacraid: Copy to user failed\n")); | |
| 969 | + rcode = -EFAULT; | |
| 970 | + goto cleanup; | |
| 971 | + } | |
| 972 | + } else { | |
| 973 | + struct aac_srb_reply *reply; | |
| 974 | + | |
| 975 | + reply = (struct aac_srb_reply *) fib_data(srbfib); | |
| 976 | + if (copy_to_user(user_reply, reply, | |
| 977 | + sizeof(struct aac_srb_reply))) { | |
| 978 | + dprintk((KERN_DEBUG"aacraid: Copy to user failed\n")); | |
| 979 | + rcode = -EFAULT; | |
| 980 | + goto cleanup; | |
| 981 | + } | |
| 826 | 982 | } |
| 827 | 983 | |
| 828 | 984 | cleanup: |
| 829 | 985 | kfree(user_srbcmd); |
| 830 | − for(i=0; i <= sg_indx; i++){ | |
| 831 | − kfree(sg_list[i]); | |
| 832 | − } | |
| 833 | 986 | if (rcode != -ERESTARTSYS) { |
| 987 | + for (i = 0; i <= sg_indx; i++) | |
| 988 | + kfree(sg_list[i]); | |
| 834 | 989 | aac_fib_complete(srbfib); |
| 835 | 990 | aac_fib_free(srbfib); |
| 836 | 991 | } |
| @@ -858,6 +1013,44 @@ static int aac_get_pci_info(struct aac_dev* dev, void __user *arg) · 21 unmodified lines | ||
| 858 | 1013 | return 0; |
| 859 | 1014 | } |
| 860 | 1015 | |
| 1016 | +static int aac_get_hba_info(struct aac_dev *dev, void __user *arg) | |
| 1017 | +{ | |
| 1018 | + struct aac_hba_info hbainfo; | |
| 1019 | + | |
| 1020 | + hbainfo.adapter_number = (u8) dev->id; | |
| 1021 | + hbainfo.system_io_bus_number = dev->pdev->bus->number; | |
| 1022 | + hbainfo.device_number = (dev->pdev->devfn >> 3); | |
| 1023 | + hbainfo.function_number = (dev->pdev->devfn & 0x0007); | |
| 1024 | + | |
| 1025 | + hbainfo.vendor_id = dev->pdev->vendor; | |
| 1026 | + hbainfo.device_id = dev->pdev->device; | |
| 1027 | + hbainfo.sub_vendor_id = dev->pdev->subsystem_vendor; | |
| 1028 | + hbainfo.sub_system_id = dev->pdev->subsystem_device; | |
| 1029 | + | |
| 1030 | + if (copy_to_user(arg, &hbainfo, sizeof(struct aac_hba_info))) { | |
| 1031 | + dprintk((KERN_DEBUG "aacraid: Could not copy hba info\n")); | |
| 1032 | + return -EFAULT; | |
| 1033 | + } | |
| 1034 | + | |
| 1035 | + return 0; | |
| 1036 | +} | |
| 1037 | + | |
| 1038 | +struct aac_reset_iop { | |
| 1039 | + u8 reset_type; | |
| 1040 | +}; | |
| 1041 | + | |
| 1042 | +static int aac_send_reset_adapter(struct aac_dev *dev, void __user *arg) | |
| 1043 | +{ | |
| 1044 | + struct aac_reset_iop reset; | |
| 1045 | + int retval; | |
| 1046 | + | |
| 1047 | + if (copy_from_user((void *)&reset, arg, sizeof(struct aac_reset_iop))) | |
| 1048 | + return -EFAULT; | |
| 1049 | + | |
| 1050 | + retval = aac_reset_adapter(dev, 0, reset.reset_type); | |
| 1051 | + return retval; | |
| 1052 | + | |
| 1053 | +} | |
| 861 | 1054 | |
| 862 | 1055 | int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg) |
| 863 | 1056 | { |
| @@ -901,6 +1094,13 @@ int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg) · 37 unmodified lines | ||
| 901 | 1094 | case FSACTL_GET_PCI_INFO: |
| 902 | 1095 | status = aac_get_pci_info(dev,arg); |
| 903 | 1096 | break; |
| 1097 | + case FSACTL_GET_HBA_INFO: | |
| 1098 | + status = aac_get_hba_info(dev, arg); | |
| 1099 | + break; | |
| 1100 | + case FSACTL_RESET_IOP: | |
| 1101 | + status = aac_send_reset_adapter(dev, arg); | |
| 1102 | + break; | |
| 1103 | + | |
| 904 | 1104 | default: |
| 905 | 1105 | status = -ENOTTY; |
| 906 | 1106 | break; |
| @@ -6,7 +6,8 @@ · 5 unmodified lines | ||
| 6 | 6 | * Adaptec aacraid device driver for Linux. |
| 7 | 7 | * |
| 8 | 8 | * Copyright (c) 2000-2010 Adaptec, Inc. |
| 9 | − * 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | |
| 9 | + * 2010-2015 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | |
| 10 | + * 2016-2017 Microsemi Corp. (aacraid@microsemi.com) | |
| 10 | 11 | * |
| 11 | 12 | * This program is free software; you can redistribute it and/or modify |
| 12 | 13 | * it under the terms of the GNU General Public License as published by |
| @@ -72,104 +73,175 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co · 59 unmodified lines | ||
| 72 | 73 | unsigned long size, align; |
| 73 | 74 | const unsigned long fibsize = dev->max_fib_size; |
| 74 | 75 | const unsigned long printfbufsiz = 256; |
| 75 | − unsigned long host_rrq_size = 0; | |
| 76 | − struct aac_init *init; | |
| 76 | + unsigned long host_rrq_size, aac_init_size; | |
| 77 | + union aac_init *init; | |
| 77 | 78 | dma_addr_t phys; |
| 78 | 79 | unsigned long aac_max_hostphysmempages; |
| 79 | 80 | |
| 80 | − if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1 || | |
| 81 | − dev->comm_interface == AAC_COMM_MESSAGE_TYPE2) | |
| 81 | + if ((dev->comm_interface == AAC_COMM_MESSAGE_TYPE1) || | |
| 82 | + (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2) || | |
| 83 | + (dev->comm_interface == AAC_COMM_MESSAGE_TYPE3 && | |
| 84 | + !dev->sa_firmware)) { | |
| 85 | + host_rrq_size = | |
| 86 | + (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB) | |
| 87 | + * sizeof(u32); | |
| 88 | + aac_init_size = sizeof(union aac_init); | |
| 89 | + } else if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE3 && | |
| 90 | + dev->sa_firmware) { | |
| 82 | 91 | host_rrq_size = (dev->scsi_host_ptr->can_queue |
| 83 | − + AAC_NUM_MGT_FIB) * sizeof(u32); | |
| 84 | − size = fibsize + sizeof(struct aac_init) + commsize + | |
| 85 | − commalign + printfbufsiz + host_rrq_size; | |
| 86 | − | |
| 92 | + + AAC_NUM_MGT_FIB) * sizeof(u32) * AAC_MAX_MSIX; | |
| 93 | + aac_init_size = sizeof(union aac_init) + | |
| 94 | + (AAC_MAX_HRRQ - 1) * sizeof(struct _rrq); | |
| 95 | + } else { | |
| 96 | + host_rrq_size = 0; | |
| 97 | + aac_init_size = sizeof(union aac_init); | |
| 98 | + } | |
| 99 | + size = fibsize + aac_init_size + commsize + commalign + | |
| 100 | + printfbufsiz + host_rrq_size; | |
| 101 | + | |
| 87 | 102 | base = pci_alloc_consistent(dev->pdev, size, &phys); |
| 88 | 103 | |
| 89 | − if(base == NULL) | |
| 90 | − { | |
| 104 | + if (base == NULL) { | |
| 91 | 105 | printk(KERN_ERR "aacraid: unable to create mapping.\n"); |
| 92 | 106 | return 0; |
| 93 | 107 | } |
| 108 | + | |
| 94 | 109 | dev->comm_addr = (void *)base; |
| 95 | 110 | dev->comm_phys = phys; |
| 96 | 111 | dev->comm_size = size; |
| 97 | − | |
| 98 | − if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1 || | |
| 99 | − dev->comm_interface == AAC_COMM_MESSAGE_TYPE2) { | |
| 112 | + | |
| 113 | + if ((dev->comm_interface == AAC_COMM_MESSAGE_TYPE1) || | |
| 114 | + (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2) || | |
| 115 | + (dev->comm_interface == AAC_COMM_MESSAGE_TYPE3)) { | |
| 100 | 116 | dev->host_rrq = (u32 *)(base + fibsize); |
| 101 | 117 | dev->host_rrq_pa = phys + fibsize; |
| 102 | 118 | memset(dev->host_rrq, 0, host_rrq_size); |
| 103 | 119 | } |
| 104 | 120 | |
| 105 | − dev->init = (struct aac_init *)(base + fibsize + host_rrq_size); | |
| 121 | + dev->init = (union aac_init *)(base + fibsize + host_rrq_size); | |
| 106 | 122 | dev->init_pa = phys + fibsize + host_rrq_size; |
| 107 | 123 | |
| 108 | 124 | init = dev->init; |
| 109 | 125 | |
| 110 | − init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION); | |
| 111 | − if (dev->max_fib_size != sizeof(struct hw_fib)) | |
| 112 | − init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4); | |
| 113 | − init->Sa_MSIXVectors = cpu_to_le32(SA_INIT_NUM_MSIXVECTORS); | |
| 114 | − init->fsrev = cpu_to_le32(dev->fsrev); | |
| 126 | + if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE3) { | |
| 127 | + int i; | |
| 128 | + u64 addr; | |
| 129 | + | |
| 130 | + init->r8.init_struct_revision = | |
| 131 | + cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_8); | |
| 132 | + init->r8.init_flags = cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED | | |
| 133 | + INITFLAGS_DRIVER_USES_UTC_TIME | | |
| 134 | + INITFLAGS_DRIVER_SUPPORTS_PM); | |
| 135 | + init->r8.init_flags |= | |
| 136 | + cpu_to_le32(INITFLAGS_DRIVER_SUPPORTS_HBA_MODE); | |
| 137 | + init->r8.rr_queue_count = cpu_to_le32(dev->max_msix); | |
| 138 | + init->r8.max_io_size = | |
| 139 | + cpu_to_le32(dev->scsi_host_ptr->max_sectors << 9); | |
| 140 | + init->r8.max_num_aif = init->r8.reserved1 = | |
| 141 | + init->r8.reserved2 = 0; | |
| 142 | + | |
| 143 | + for (i = 0; i < dev->max_msix; i++) { | |
| 144 | + addr = (u64)dev->host_rrq_pa + dev->vector_cap * i * | |
| 145 | + sizeof(u32); | |
| 146 | + init->r8.rrq[i].host_addr_high = cpu_to_le32( | |
| 147 | + upper_32_bits(addr)); | |
| 148 | + init->r8.rrq[i].host_addr_low = cpu_to_le32( | |
| 149 | + lower_32_bits(addr)); | |
| 150 | + init->r8.rrq[i].msix_id = i; | |
| 151 | + init->r8.rrq[i].element_count = cpu_to_le16( | |
| 152 | + (u16)dev->vector_cap); | |
| 153 | + init->r8.rrq[i].comp_thresh = | |
| 154 | + init->r8.rrq[i].unused = 0; | |
| 155 | + } | |
| 115 | 156 | |
| 116 | − /* | |
| 117 | − * Adapter Fibs are the first thing allocated so that they | |
| 118 | − * start page aligned | |
| 119 | − */ | |
| 120 | − dev->aif_base_va = (struct hw_fib *)base; | |
| 121 | − | |
| 122 | − init->AdapterFibsVirtualAddress = 0; | |
| 123 | − init->AdapterFibsPhysicalAddress = cpu_to_le32((u32)phys); | |
| 124 | − init->AdapterFibsSize = cpu_to_le32(fibsize); | |
| 125 | − init->AdapterFibAlign = cpu_to_le32(sizeof(struct hw_fib)); | |
| 126 | − /* | |
| 127 | − * number of 4k pages of host physical memory. The aacraid fw needs | |
| 128 | − * this number to be less than 4gb worth of pages. New firmware doesn't | |
| 129 | − * have any issues with the mapping system, but older Firmware did, and | |
| 130 | − * had *troubles* dealing with the math overloading past 32 bits, thus | |
| 131 | − * we must limit this field. | |
| 132 | − */ | |
| 133 | − aac_max_hostphysmempages = dma_get_required_mask(&dev->pdev->dev) >> 12; | |
| 134 | − if (aac_max_hostphysmempages < AAC_MAX_HOSTPHYSMEMPAGES) | |
| 135 | − init->HostPhysMemPages = cpu_to_le32(aac_max_hostphysmempages); | |
| 136 | − else | |
| 137 | − init->HostPhysMemPages = cpu_to_le32(AAC_MAX_HOSTPHYSMEMPAGES); | |
| 138 | − | |
| 139 | − init->InitFlags = cpu_to_le32(INITFLAGS_DRIVER_USES_UTC_TIME | | |
| 140 | − INITFLAGS_DRIVER_SUPPORTS_PM); | |
| 141 | − init->MaxIoCommands = cpu_to_le32(dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); | |
| 142 | − init->MaxIoSize = cpu_to_le32(dev->scsi_host_ptr->max_sectors << 9); | |
| 143 | − init->MaxFibSize = cpu_to_le32(dev->max_fib_size); | |
| 144 | − init->MaxNumAif = cpu_to_le32(dev->max_num_aif); | |
| 145 | − | |
| 146 | − if (dev->comm_interface == AAC_COMM_MESSAGE) { | |
| 147 | − init->InitFlags |= cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED); | |
| 148 | − dprintk((KERN_WARNING"aacraid: New Comm Interface enabled\n")); | |
| 149 | − } else if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1) { | |
| 150 | − init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_6); | |
| 151 | − init->InitFlags |= cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED | | |
| 152 | − INITFLAGS_NEW_COMM_TYPE1_SUPPORTED | INITFLAGS_FAST_JBOD_SUPPORTED); | |
| 153 | − init->HostRRQ_AddrHigh = cpu_to_le32((u32)((u64)dev->host_rrq_pa >> 32)); | |
| 154 | − init->HostRRQ_AddrLow = cpu_to_le32((u32)(dev->host_rrq_pa & 0xffffffff)); | |
| 155 | − dprintk((KERN_WARNING"aacraid: New Comm Interface type1 enabled\n")); | |
| 156 | − } else if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2) { | |
| 157 | − init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_7); | |
| 158 | − init->InitFlags |= cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED | | |
| 159 | − INITFLAGS_NEW_COMM_TYPE2_SUPPORTED | INITFLAGS_FAST_JBOD_SUPPORTED); | |
| 160 | − init->HostRRQ_AddrHigh = cpu_to_le32((u32)((u64)dev->host_rrq_pa >> 32)); | |
| 161 | − init->HostRRQ_AddrLow = cpu_to_le32((u32)(dev->host_rrq_pa & 0xffffffff)); | |
| 162 | − /* number of MSI-X */ | |
| 163 | − init->Sa_MSIXVectors = cpu_to_le32(dev->max_msix); | |
| 164 | − dprintk((KERN_WARNING"aacraid: New Comm Interface type2 enabled\n")); | |
| 157 | + pr_warn("aacraid: Comm Interface type3 enabled\n"); | |
| 158 | + } else { | |
| 159 | + init->r7.init_struct_revision = | |
| 160 | + cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION); | |
| 161 | + if (dev->max_fib_size != sizeof(struct hw_fib)) | |
| 162 | + init->r7.init_struct_revision = | |
| 163 | + cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4); | |
| 164 | + init->r7.no_of_msix_vectors = cpu_to_le32(SA_MINIPORT_REVISION); | |
| 165 | + init->r7.fsrev = cpu_to_le32(dev->fsrev); | |
| 166 | + | |
| 167 | + /* | |
| 168 | + * Adapter Fibs are the first thing allocated so that they | |
| 169 | + * start page aligned | |
| 170 | + */ | |
| 171 | + dev->aif_base_va = (struct hw_fib *)base; | |
| 172 | + | |
| 173 | + init->r7.adapter_fibs_virtual_address = 0; | |
| 174 | + init->r7.adapter_fibs_physical_address = cpu_to_le32((u32)phys); | |
| 175 | + init->r7.adapter_fibs_size = cpu_to_le32(fibsize); | |
| 176 | + init->r7.adapter_fib_align = cpu_to_le32(sizeof(struct hw_fib)); | |
| 177 | + | |
| 178 | + /* | |
| 179 | + * number of 4k pages of host physical memory. The aacraid fw | |
| 180 | + * needs this number to be less than 4gb worth of pages. New | |
| 181 | + * firmware doesn't have any issues with the mapping system, but | |
| 182 | + * older Firmware did, and had *troubles* dealing with the math | |
| 183 | + * overloading past 32 bits, thus we must limit this field. | |
| 184 | + */ | |
| 185 | + aac_max_hostphysmempages = | |
| 186 | + dma_get_required_mask(&dev->pdev->dev) >> 12; | |
| 187 | + if (aac_max_hostphysmempages < AAC_MAX_HOSTPHYSMEMPAGES) | |
| 188 | + init->r7.host_phys_mem_pages = | |
| 189 | + cpu_to_le32(aac_max_hostphysmempages); | |
| 190 | + else | |
| 191 | + init->r7.host_phys_mem_pages = | |
| 192 | + cpu_to_le32(AAC_MAX_HOSTPHYSMEMPAGES); | |
| 193 | + | |
| 194 | + init->r7.init_flags = | |
| 195 | + cpu_to_le32(INITFLAGS_DRIVER_USES_UTC_TIME | | |
| 196 | + INITFLAGS_DRIVER_SUPPORTS_PM); | |
| 197 | + init->r7.max_io_commands = | |
| 198 | + cpu_to_le32(dev->scsi_host_ptr->can_queue + | |
| 199 | + AAC_NUM_MGT_FIB); | |
| 200 | + init->r7.max_io_size = | |
| 201 | + cpu_to_le32(dev->scsi_host_ptr->max_sectors << 9); | |
| 202 | + init->r7.max_fib_size = cpu_to_le32(dev->max_fib_size); | |
| 203 | + init->r7.max_num_aif = cpu_to_le32(dev->max_num_aif); | |
| 204 | + | |
| 205 | + if (dev->comm_interface == AAC_COMM_MESSAGE) { | |
| 206 | + init->r7.init_flags |= | |
| 207 | + cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED); | |
| 208 | + pr_warn("aacraid: Comm Interface enabled\n"); | |
| 209 | + } else if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1) { | |
| 210 | + init->r7.init_struct_revision = | |
| 211 | + cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_6); | |
| 212 | + init->r7.init_flags |= | |
| 213 | + cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED | | |
| 214 | + INITFLAGS_NEW_COMM_TYPE1_SUPPORTED | | |
| 215 | + INITFLAGS_FAST_JBOD_SUPPORTED); | |
| 216 | + init->r7.host_rrq_addr_high = | |
| 217 | + cpu_to_le32(upper_32_bits(dev->host_rrq_pa)); | |
| 218 | + init->r7.host_rrq_addr_low = | |
| 219 | + cpu_to_le32(lower_32_bits(dev->host_rrq_pa)); | |
| 220 | + pr_warn("aacraid: Comm Interface type1 enabled\n"); | |
| 221 | + } else if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2) { | |
| 222 | + init->r7.init_struct_revision = | |
| 223 | + cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_7); | |
| 224 | + init->r7.init_flags |= | |
| 225 | + cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED | | |
| 226 | + INITFLAGS_NEW_COMM_TYPE2_SUPPORTED | | |
| 227 | + INITFLAGS_FAST_JBOD_SUPPORTED); | |
| 228 | + init->r7.host_rrq_addr_high = | |
| 229 | + cpu_to_le32(upper_32_bits(dev->host_rrq_pa)); | |
| 230 | + init->r7.host_rrq_addr_low = | |
| 231 | + cpu_to_le32(lower_32_bits(dev->host_rrq_pa)); | |
| 232 | + init->r7.no_of_msix_vectors = | |
| 233 | + cpu_to_le32(dev->max_msix); | |
| 234 | + /* must be the COMM_PREFERRED_SETTINGS values */ | |
| 235 | + pr_warn("aacraid: Comm Interface type2 enabled\n"); | |
| 236 | + } | |
| 165 | 237 | } |
| 166 | 238 | |
| 167 | 239 | /* |
| 168 | 240 | * Increment the base address by the amount already used |
| 169 | 241 | */ |
| 170 | − base = base + fibsize + host_rrq_size + sizeof(struct aac_init); | |
| 242 | + base = base + fibsize + host_rrq_size + aac_init_size; | |
| 171 | 243 | phys = (dma_addr_t)((ulong)phys + fibsize + host_rrq_size + |
| 172 | − sizeof(struct aac_init)); | |
| 244 | + aac_init_size); | |
| 173 | 245 | |
| 174 | 246 | /* |
| 175 | 247 | * Align the beginning of Headers to commalign |
| @@ -181,7 +253,8 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co · 5 unmodified lines | ||
| 181 | 253 | * Fill in addresses of the Comm Area Headers and Queues |
| 182 | 254 | */ |
| 183 | 255 | *commaddr = base; |
| 184 | − init->CommHeaderAddress = cpu_to_le32((u32)phys); | |
| 256 | + if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE3) | |
| 257 | + init->r7.comm_header_address = cpu_to_le32((u32)phys); | |
| 185 | 258 | /* |
| 186 | 259 | * Increment the base address by the size of the CommArea |
| 187 | 260 | */ |
| @@ -191,12 +264,14 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co · 3 unmodified lines | ||
| 191 | 264 | * Place the Printf buffer area after the Fast I/O comm area. |
| 192 | 265 | */ |
| 193 | 266 | dev->printfbuf = (void *)base; |
| 194 | − init->printfbuf = cpu_to_le32(phys); | |
| 195 | − init->printfbufsiz = cpu_to_le32(printfbufsiz); | |
| 267 | + if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE3) { | |
| 268 | + init->r7.printfbuf = cpu_to_le32(phys); | |
| 269 | + init->r7.printfbufsiz = cpu_to_le32(printfbufsiz); | |
| 270 | + } | |
| 196 | 271 | memset(base, 0, printfbufsiz); |
| 197 | 272 | return 1; |
| 198 | 273 | } |
| 199 | − | |
| 274 | + | |
| 200 | 275 | static void aac_queue_init(struct aac_dev * dev, struct aac_queue * q, u32 *mem, int qsize) |
| 201 | 276 | { |
| 202 | 277 | atomic_set(&q->numpending, 0); |
| @@ -404,9 +479,13 @@ void aac_define_int_mode(struct aac_dev *dev) · 201 unmodified lines | ||
| 404 | 479 | if (dev->max_msix > msi_count) |
| 405 | 480 | dev->max_msix = msi_count; |
| 406 | 481 | } |
| 407 | − dev->vector_cap = | |
| 408 | − (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB) / | |
| 409 | − msi_count; | |
| 482 | + if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE3 && dev->sa_firmware) | |
| 483 | + dev->vector_cap = dev->scsi_host_ptr->can_queue + | |
| 484 | + AAC_NUM_MGT_FIB; | |
| 485 | + else | |
| 486 | + dev->vector_cap = (dev->scsi_host_ptr->can_queue + | |
| 487 | + AAC_NUM_MGT_FIB) / msi_count; | |
| 488 | + | |
| 410 | 489 | } |
| 411 | 490 | struct aac_dev *aac_init_adapter(struct aac_dev *dev) |
| 412 | 491 | { |
| @@ -440,30 +519,37 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) · 27 unmodified lines | ||
| 440 | 519 | |
| 441 | 520 | if ((!aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES, |
| 442 | 521 | 0, 0, 0, 0, 0, 0, |
| 443 | − status+0, status+1, status+2, status+3, NULL)) && | |
| 444 | − (status[0] == 0x00000001)) { | |
| 522 | + status+0, status+1, status+2, status+3, status+4)) && | |
| 523 | + (status[0] == 0x00000001)) { | |
| 445 | 524 | dev->doorbell_mask = status[3]; |
| 446 | − if (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_64)) | |
| 525 | + if (status[1] & AAC_OPT_NEW_COMM_64) | |
| 447 | 526 | dev->raw_io_64 = 1; |
| 448 | 527 | dev->sync_mode = aac_sync_mode; |
| 449 | 528 | if (dev->a_ops.adapter_comm && |
| 450 | − (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM))) { | |
| 529 | + (status[1] & AAC_OPT_NEW_COMM)) { | |
| 451 | 530 | dev->comm_interface = AAC_COMM_MESSAGE; |
| 452 | 531 | dev->raw_io_interface = 1; |
| 453 | − if ((status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE1))) { | |
| 532 | + if ((status[1] & AAC_OPT_NEW_COMM_TYPE1)) { | |
| 454 | 533 | /* driver supports TYPE1 (Tupelo) */ |
| 455 | 534 | dev->comm_interface = AAC_COMM_MESSAGE_TYPE1; |
| 456 | − } else if ((status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE2))) { | |
| 457 | − /* driver supports TYPE2 (Denali) */ | |
| 535 | + } else if (status[1] & AAC_OPT_NEW_COMM_TYPE2) { | |
| 536 | + /* driver supports TYPE2 (Denali, Yosemite) */ | |
| 458 | 537 | dev->comm_interface = AAC_COMM_MESSAGE_TYPE2; |
| 459 | − } else if ((status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE4)) || | |
| 460 | − (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE3))) { | |
| 461 | − /* driver doesn't TYPE3 and TYPE4 */ | |
| 462 | − /* switch to sync. mode */ | |
| 538 | + } else if (status[1] & AAC_OPT_NEW_COMM_TYPE3) { | |
| 539 | + /* driver supports TYPE3 (Yosemite, Thor) */ | |
| 540 | + dev->comm_interface = AAC_COMM_MESSAGE_TYPE3; | |
| 541 | + } else if (status[1] & AAC_OPT_NEW_COMM_TYPE4) { | |
| 542 | + /* not supported TYPE - switch to sync. mode */ | |
| 463 | 543 | dev->comm_interface = AAC_COMM_MESSAGE_TYPE2; |
| 464 | 544 | dev->sync_mode = 1; |
| 465 | 545 | } |
| 466 | 546 | } |
| 547 | + if ((status[1] & le32_to_cpu(AAC_OPT_EXTENDED)) && | |
| 548 | + (status[4] & le32_to_cpu(AAC_EXTOPT_SA_FIRMWARE))) | |
| 549 | + dev->sa_firmware = 1; | |
| 550 | + else | |
| 551 | + dev->sa_firmware = 0; | |
| 552 | + | |
| 467 | 553 | if ((dev->comm_interface == AAC_COMM_MESSAGE) && |
| 468 | 554 | (status[2] > dev->base_size)) { |
| 469 | 555 | aac_adapter_ioremap(dev, 0); |
| @@ -500,61 +586,25 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) · 30 unmodified lines | ||
| 500 | 586 | dev->sg_tablesize = status[2] & 0xFFFF; |
| 501 | 587 | if (dev->pdev->device == PMC_DEVICE_S7 || |
| 502 | 588 | dev->pdev->device == PMC_DEVICE_S8 || |
| 503 | − dev->pdev->device == PMC_DEVICE_S9) | |
| 504 | − host->can_queue = ((status[3] >> 16) ? (status[3] >> 16) : | |
| 505 | − (status[3] & 0xFFFF)) - AAC_NUM_MGT_FIB; | |
| 506 | − else | |
| 507 | − host->can_queue = (status[3] & 0xFFFF) - AAC_NUM_MGT_FIB; | |
| 589 | + dev->pdev->device == PMC_DEVICE_S9) { | |
| 590 | + if (host->can_queue > (status[3] >> 16) - | |
| 591 | + AAC_NUM_MGT_FIB) | |
| 592 | + host->can_queue = (status[3] >> 16) - | |
| 593 | + AAC_NUM_MGT_FIB; | |
| 594 | + } else if (host->can_queue > (status[3] & 0xFFFF) - | |
| 595 | + AAC_NUM_MGT_FIB) | |
| 596 | + host->can_queue = (status[3] & 0xFFFF) - | |
| 597 | + AAC_NUM_MGT_FIB; | |
| 598 | + | |
| 508 | 599 | dev->max_num_aif = status[4] & 0xFFFF; |
| 509 | − /* | |
| 510 | − * NOTE: | |
| 511 | − * All these overrides are based on a fixed internal | |
| 512 | − * knowledge and understanding of existing adapters, | |
| 513 | − * acbsize should be set with caution. | |
| 514 | − */ | |
| 515 | − if (acbsize == 512) { | |
| 516 | − host->max_sectors = AAC_MAX_32BIT_SGBCOUNT; | |
| 517 | − dev->max_fib_size = 512; | |
| 518 | − dev->sg_tablesize = host->sg_tablesize | |
| 519 | − = (512 - sizeof(struct aac_fibhdr) | |
| 520 | − - sizeof(struct aac_write) + sizeof(struct sgentry)) | |
| 521 | − / sizeof(struct sgentry); | |
| 522 | − host->can_queue = AAC_NUM_IO_FIB; | |
| 523 | − } else if (acbsize == 2048) { | |
| 524 | − host->max_sectors = 512; | |
| 525 | − dev->max_fib_size = 2048; | |
| 526 | − host->sg_tablesize = 65; | |
| 527 | − dev->sg_tablesize = 81; | |
| 528 | − host->can_queue = 512 - AAC_NUM_MGT_FIB; | |
| 529 | − } else if (acbsize == 4096) { | |
| 530 | − host->max_sectors = 1024; | |
| 531 | − dev->max_fib_size = 4096; | |
| 532 | − host->sg_tablesize = 129; | |
| 533 | − dev->sg_tablesize = 166; | |
| 534 | − host->can_queue = 256 - AAC_NUM_MGT_FIB; | |
| 535 | − } else if (acbsize == 8192) { | |
| 536 | − host->max_sectors = 2048; | |
| 537 | − dev->max_fib_size = 8192; | |
| 538 | − host->sg_tablesize = 257; | |
| 539 | − dev->sg_tablesize = 337; | |
| 540 | − host->can_queue = 128 - AAC_NUM_MGT_FIB; | |
| 541 | − } else if (acbsize > 0) { | |
| 542 | − printk("Illegal acbsize=%d ignored\n", acbsize); | |
| 543 | − } | |
| 544 | 600 | } |
| 545 | − { | |
| 546 | − | |
| 547 | − if (numacb > 0) { | |
| 548 | − if (numacb < host->can_queue) | |
| 549 | − host->can_queue = numacb; | |
| 550 | − else | |
| 551 | − printk("numacb=%d ignored\n", numacb); | |
| 552 | − } | |
| 601 | + if (numacb > 0) { | |
| 602 | + if (numacb < host->can_queue) | |
| 603 | + host->can_queue = numacb; | |
| 604 | + else | |
| 605 | + pr_warn("numacb=%d ignored\n", numacb); | |
| 553 | 606 | } |
| 554 | 607 | |
| 555 | − if (host->can_queue > AAC_NUM_IO_FIB) | |
| 556 | − host->can_queue = AAC_NUM_IO_FIB; | |
| 557 | − | |
| 558 | 608 | if (dev->pdev->device == PMC_DEVICE_S6 || |
| 559 | 609 | dev->pdev->device == PMC_DEVICE_S7 || |
| 560 | 610 | dev->pdev->device == PMC_DEVICE_S8 || |
| @@ -6,7 +6,8 @@ · 5 unmodified lines | ||
| 6 | 6 | * Adaptec aacraid device driver for Linux. |
| 7 | 7 | * |
| 8 | 8 | * Copyright (c) 2000-2010 Adaptec, Inc. |
| 9 | − * 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | |
| 9 | + * 2010-2015 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | |
| 10 | + * 2016-2017 Microsemi Corp. (aacraid@microsemi.com) | |
| 10 | 11 | * |
| 11 | 12 | * This program is free software; you can redistribute it and/or modify |
| 12 | 13 | * it under the terms of the GNU General Public License as published by |
| @@ -43,6 +44,7 @@ · 30 unmodified lines | ||
| 43 | 44 | #include <linux/kthread.h> |
| 44 | 45 | #include <linux/interrupt.h> |
| 45 | 46 | #include <linux/semaphore.h> |
| 47 | +#include <linux/bcd.h> | |
| 46 | 48 | #include <scsi/scsi.h> |
| 47 | 49 | #include <scsi/scsi_host.h> |
| 48 | 50 | #include <scsi/scsi_device.h> |
| @@ -60,12 +62,22 @@ · 11 unmodified lines | ||
| 60 | 62 | |
| 61 | 63 | static int fib_map_alloc(struct aac_dev *dev) |
| 62 | 64 | { |
| 65 | + if (dev->max_fib_size > AAC_MAX_NATIVE_SIZE) | |
| 66 | + dev->max_cmd_size = AAC_MAX_NATIVE_SIZE; | |
| 67 | + else | |
| 68 | + dev->max_cmd_size = dev->max_fib_size; | |
| 69 | + if (dev->max_fib_size < AAC_MAX_NATIVE_SIZE) { | |
| 70 | + dev->max_cmd_size = AAC_MAX_NATIVE_SIZE; | |
| 71 | + } else { | |
| 72 | + dev->max_cmd_size = dev->max_fib_size; | |
| 73 | + } | |
| 74 | + | |
| 63 | 75 | dprintk((KERN_INFO |
| 64 | 76 | "allocate hardware fibs pci_alloc_consistent(%p, %d * (%d + %d), %p)\n", |
| 65 | − dev->pdev, dev->max_fib_size, dev->scsi_host_ptr->can_queue, | |
| 77 | + dev->pdev, dev->max_cmd_size, dev->scsi_host_ptr->can_queue, | |
| 66 | 78 | AAC_NUM_MGT_FIB, &dev->hw_fib_pa)); |
| 67 | 79 | dev->hw_fib_va = pci_alloc_consistent(dev->pdev, |
| 68 | − (dev->max_fib_size + sizeof(struct aac_fib_xporthdr)) | |
| 80 | + (dev->max_cmd_size + sizeof(struct aac_fib_xporthdr)) | |
| 69 | 81 | * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB) + (ALIGN32 - 1), |
| 70 | 82 | &dev->hw_fib_pa); |
| 71 | 83 | if (dev->hw_fib_va == NULL) |
| @@ -83,9 +95,9 @@ static int fib_map_alloc(struct aac_dev *dev) · 11 unmodified lines | ||
| 83 | 95 | |
| 84 | 96 | void aac_fib_map_free(struct aac_dev *dev) |
| 85 | 97 | { |
| 86 | − if (dev->hw_fib_va && dev->max_fib_size) { | |
| 98 | + if (dev->hw_fib_va && dev->max_cmd_size) { | |
| 87 | 99 | pci_free_consistent(dev->pdev, |
| 88 | − (dev->max_fib_size * | |
| 100 | + (dev->max_cmd_size * | |
| 89 | 101 | (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB)), |
| 90 | 102 | dev->hw_fib_va, dev->hw_fib_pa); |
| 91 | 103 | } |
| @@ -129,11 +141,14 @@ int aac_fib_setup(struct aac_dev * dev) · 37 unmodified lines | ||
| 129 | 141 | struct hw_fib *hw_fib; |
| 130 | 142 | dma_addr_t hw_fib_pa; |
| 131 | 143 | int i; |
| 144 | + u32 max_cmds; | |
| 132 | 145 | |
| 133 | 146 | while (((i = fib_map_alloc(dev)) == -ENOMEM) |
| 134 | 147 | && (dev->scsi_host_ptr->can_queue > (64 - AAC_NUM_MGT_FIB))) { |
| 135 | − dev->init->MaxIoCommands = cpu_to_le32((dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB) >> 1); | |
| 136 | − dev->scsi_host_ptr->can_queue = le32_to_cpu(dev->init->MaxIoCommands) - AAC_NUM_MGT_FIB; | |
| 148 | + max_cmds = (dev->scsi_host_ptr->can_queue+AAC_NUM_MGT_FIB) >> 1; | |
| 149 | + dev->scsi_host_ptr->can_queue = max_cmds - AAC_NUM_MGT_FIB; | |
| 150 | + if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE3) | |
| 151 | + dev->init->r7.max_io_commands = cpu_to_le32(max_cmds); | |
| 137 | 152 | } |
| 138 | 153 | if (i<0) |
| 139 | 154 | return -ENOMEM; |
| @@ -144,7 +159,7 @@ int aac_fib_setup(struct aac_dev * dev) · 4 unmodified lines | ||
| 144 | 159 | (hw_fib_pa - dev->hw_fib_pa)); |
| 145 | 160 | dev->hw_fib_pa = hw_fib_pa; |
| 146 | 161 | memset(dev->hw_fib_va, 0, |
| 147 | − (dev->max_fib_size + sizeof(struct aac_fib_xporthdr)) * | |
| 162 | + (dev->max_cmd_size + sizeof(struct aac_fib_xporthdr)) * | |
| 148 | 163 | (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB)); |
| 149 | 164 | |
| 150 | 165 | /* add Xport header */ |
| @@ -170,12 +185,22 @@ int aac_fib_setup(struct aac_dev * dev) · 19 unmodified lines | ||
| 170 | 185 | sema_init(&fibptr->event_wait, 0); |
| 171 | 186 | spin_lock_init(&fibptr->event_lock); |
| 172 | 187 | hw_fib->header.XferState = cpu_to_le32(0xffffffff); |
| 173 | − hw_fib->header.SenderSize = cpu_to_le16(dev->max_fib_size); | |
| 188 | + hw_fib->header.SenderSize = | |
| 189 | + cpu_to_le16(dev->max_fib_size); /* ?? max_cmd_size */ | |
| 174 | 190 | fibptr->hw_fib_pa = hw_fib_pa; |
| 191 | + fibptr->hw_sgl_pa = hw_fib_pa + | |
| 192 | + offsetof(struct aac_hba_cmd_req, sge[2]); | |
| 193 | + /* | |
| 194 | + * one element is for the ptr to the separate sg list, | |
| 195 | + * second element for 32 byte alignment | |
| 196 | + */ | |
| 197 | + fibptr->hw_error_pa = hw_fib_pa + | |
| 198 | + offsetof(struct aac_native_hba, resp.resp_bytes[0]); | |
| 199 | + | |
| 175 | 200 | hw_fib = (struct hw_fib *)((unsigned char *)hw_fib + |
| 176 | − dev->max_fib_size + sizeof(struct aac_fib_xporthdr)); | |
| 201 | + dev->max_cmd_size + sizeof(struct aac_fib_xporthdr)); | |
| 177 | 202 | hw_fib_pa = hw_fib_pa + |
| 178 | − dev->max_fib_size + sizeof(struct aac_fib_xporthdr); | |
| 203 | + dev->max_cmd_size + sizeof(struct aac_fib_xporthdr); | |
| 179 | 204 | } |
| 180 | 205 | |
| 181 | 206 | /* |
| @@ -273,7 +298,8 @@ void aac_fib_free(struct fib *fibptr) · 91 unmodified lines | ||
| 273 | 298 | spin_lock_irqsave(&fibptr->dev->fib_lock, flags); |
| 274 | 299 | if (unlikely(fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) |
| 275 | 300 | aac_config.fib_timeouts++; |
| 276 | − if (fibptr->hw_fib_va->header.XferState != 0) { | |
| 301 | + if (!(fibptr->flags & FIB_CONTEXT_FLAG_NATIVE_HBA) && | |
| 302 | + fibptr->hw_fib_va->header.XferState != 0) { | |
| 277 | 303 | printk(KERN_WARNING "aac_fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n", |
| 278 | 304 | (void*)fibptr, |
| 279 | 305 | le32_to_cpu(fibptr->hw_fib_va->header.XferState)); |
| @@ -501,8 +527,15 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, · 221 unmodified lines | ||
| 501 | 527 | * Map the fib into 32bits by using the fib number |
| 502 | 528 | */ |
| 503 | 529 | |
| 504 | − hw_fib->header.SenderFibAddress = cpu_to_le32(((u32)(fibptr - dev->fibs)) << 2); | |
| 505 | − hw_fib->header.Handle = (u32)(fibptr - dev->fibs) + 1; | |
| 530 | + hw_fib->header.SenderFibAddress = | |
| 531 | + cpu_to_le32(((u32)(fibptr - dev->fibs)) << 2); | |
| 532 | + | |
| 533 | + /* use the same shifted value for handle to be compatible | |
| 534 | + * with the new native hba command handle | |
| 535 | + */ | |
| 536 | + hw_fib->header.Handle = | |
| 537 | + cpu_to_le32((((u32)(fibptr - dev->fibs)) << 2) + 1); | |
| 538 | + | |
| 506 | 539 | /* |
| 507 | 540 | * Set FIB state to indicate where it came from and if we want a |
| 508 | 541 | * response from the adapter. Also load the command from the |
| @@ -670,6 +703,82 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, · 161 unmodified lines | ||
| 670 | 703 | return 0; |
| 671 | 704 | } |
| 672 | 705 | |
| 706 | +int aac_hba_send(u8 command, struct fib *fibptr, fib_callback callback, | |
| 707 | + void *callback_data) | |
| 708 | +{ | |
| 709 | + struct aac_dev *dev = fibptr->dev; | |
| 710 | + int wait; | |
| 711 | + unsigned long flags = 0; | |
| 712 | + unsigned long mflags = 0; | |
| 713 | + | |
| 714 | + fibptr->flags = (FIB_CONTEXT_FLAG | FIB_CONTEXT_FLAG_NATIVE_HBA); | |
| 715 | + if (callback) { | |
| 716 | + wait = 0; | |
| 717 | + fibptr->callback = callback; | |
| 718 | + fibptr->callback_data = callback_data; | |
| 719 | + } else | |
| 720 | + wait = 1; | |
| 721 | + | |
| 722 | + | |
| 723 | + if (command == HBA_IU_TYPE_SCSI_CMD_REQ) { | |
| 724 | + struct aac_hba_cmd_req *hbacmd = | |
| 725 | + (struct aac_hba_cmd_req *)fibptr->hw_fib_va; | |
| 726 | + | |
| 727 | + hbacmd->iu_type = command; | |
| 728 | + /* bit1 of request_id must be 0 */ | |
| 729 | + hbacmd->request_id = | |
| 730 | + cpu_to_le32((((u32)(fibptr - dev->fibs)) << 2) + 1); | |
| 731 | + } else | |
| 732 | + return -EINVAL; | |
| 733 | + | |
| 734 | + | |
| 735 | + if (wait) { | |
| 736 | + spin_lock_irqsave(&dev->manage_lock, mflags); | |
| 737 | + if (dev->management_fib_count >= AAC_NUM_MGT_FIB) { | |
| 738 | + spin_unlock_irqrestore(&dev->manage_lock, mflags); | |
| 739 | + return -EBUSY; | |
| 740 | + } | |
| 741 | + dev->management_fib_count++; | |
| 742 | + spin_unlock_irqrestore(&dev->manage_lock, mflags); | |
| 743 | + spin_lock_irqsave(&fibptr->event_lock, flags); | |
| 744 | + } | |
| 745 | + | |
| 746 | + if (aac_adapter_deliver(fibptr) != 0) { | |
| 747 | + if (wait) { | |
| 748 | + spin_unlock_irqrestore(&fibptr->event_lock, flags); | |
| 749 | + spin_lock_irqsave(&dev->manage_lock, mflags); | |
| 750 | + dev->management_fib_count--; | |
| 751 | + spin_unlock_irqrestore(&dev->manage_lock, mflags); | |
| 752 | + } | |
| 753 | + return -EBUSY; | |
| 754 | + } | |
| 755 | + FIB_COUNTER_INCREMENT(aac_config.NativeSent); | |
| 756 | + | |
| 757 | + if (wait) { | |
| 758 | + spin_unlock_irqrestore(&fibptr->event_lock, flags); | |
| 759 | + /* Only set for first known interruptable command */ | |
| 760 | + if (down_interruptible(&fibptr->event_wait)) { | |
| 761 | + fibptr->done = 2; | |
| 762 | + up(&fibptr->event_wait); | |
| 763 | + } | |
| 764 | + spin_lock_irqsave(&fibptr->event_lock, flags); | |
| 765 | + if ((fibptr->done == 0) || (fibptr->done == 2)) { | |
| 766 | + fibptr->done = 2; /* Tell interrupt we aborted */ | |
| 767 | + spin_unlock_irqrestore(&fibptr->event_lock, flags); | |
| 768 | + return -ERESTARTSYS; | |
| 769 | + } | |
| 770 | + spin_unlock_irqrestore(&fibptr->event_lock, flags); | |
| 771 | + WARN_ON(fibptr->done == 0); | |
| 772 | + | |
| 773 | + if (unlikely(fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) | |
| 774 | + return -ETIMEDOUT; | |
| 775 | + | |
| 776 | + return 0; | |
| 777 | + } | |
| 778 | + | |
| 779 | + return -EINPROGRESS; | |
| 780 | +} | |
| 781 | + | |
| 673 | 782 | /** |
| 674 | 783 | * aac_consumer_get - get the top of the queue |
| 675 | 784 | * @dev: Adapter |
| @@ -761,7 +870,8 @@ int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size) · 85 unmodified lines | ||
| 761 | 870 | unsigned long qflags; |
| 762 | 871 | |
| 763 | 872 | if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1 || |
| 764 | − dev->comm_interface == AAC_COMM_MESSAGE_TYPE2) { | |
| 873 | + dev->comm_interface == AAC_COMM_MESSAGE_TYPE2 || | |
| 874 | + dev->comm_interface == AAC_COMM_MESSAGE_TYPE3) { | |
| 765 | 875 | kfree(hw_fib); |
| 766 | 876 | return 0; |
| 767 | 877 | } |
| @@ -827,11 +937,17 @@ int aac_fib_complete(struct fib *fibptr) · 59 unmodified lines | ||
| 827 | 937 | { |
| 828 | 938 | struct hw_fib * hw_fib = fibptr->hw_fib_va; |
| 829 | 939 | |
| 940 | + if (fibptr->flags & FIB_CONTEXT_FLAG_NATIVE_HBA) { | |
| 941 | + fib_dealloc(fibptr); | |
| 942 | + return 0; | |
| 943 | + } | |
| 944 | + | |
| 830 | 945 | /* |
| 831 | − * Check for a fib which has already been completed | |
| 946 | + * Check for a fib which has already been completed or with a | |
| 947 | + * status wait timeout | |
| 832 | 948 | */ |
| 833 | 949 | |
| 834 | − if (hw_fib->header.XferState == 0) | |
| 950 | + if (hw_fib->header.XferState == 0 || fibptr->done == 2) | |
| 835 | 951 | return 0; |
| 836 | 952 | /* |
| 837 | 953 | * If we plan to do anything check the structure type first. |
| @@ -984,20 +1100,9 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) · 146 unmodified lines | ||
| 984 | 1100 | lun = (container >> 16) & 0xFF; |
| 985 | 1101 | container = (u32)-1; |
| 986 | 1102 | channel = aac_phys_to_logical(channel); |
| 987 | − device_config_needed = | |
| 988 | − (((__le32 *)aifcmd->data)[0] == | |
| 989 | − cpu_to_le32(AifRawDeviceRemove)) ? DELETE : ADD; | |
| 990 | − | |
| 991 | − if (device_config_needed == ADD) { | |
| 992 | − device = scsi_device_lookup( | |
| 993 | − dev->scsi_host_ptr, | |
| 994 | − channel, id, lun); | |
| 995 | − if (device) { | |
| 996 | − scsi_remove_device(device); | |
| 997 | − scsi_device_put(device); | |
| 998 | − } | |
| 999 | − } | |
| 1103 | + device_config_needed = DELETE; | |
| 1000 | 1104 | break; |
| 1105 | + | |
| 1001 | 1106 | /* |
| 1002 | 1107 | * Morph or Expand complete |
| 1003 | 1108 | */ |
| @@ -1351,7 +1456,7 @@ retry_next: · 347 unmodified lines | ||
| 1351 | 1456 | } |
| 1352 | 1457 | } |
| 1353 | 1458 | |
| 1354 | −static int _aac_reset_adapter(struct aac_dev *aac, int forced) | |
| 1459 | +static int _aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type) | |
| 1355 | 1460 | { |
| 1356 | 1461 | int index, quirks; |
| 1357 | 1462 | int retval; |
| @@ -1360,6 +1465,7 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced) · 2 unmodified lines | ||
| 1360 | 1465 | struct scsi_cmnd *command; |
| 1361 | 1466 | struct scsi_cmnd *command_list; |
| 1362 | 1467 | int jafo = 0; |
| 1468 | + int bled; | |
| 1363 | 1469 | |
| 1364 | 1470 | /* |
| 1365 | 1471 | * Assumptions: |
| @@ -1384,7 +1490,8 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced) · 18 unmodified lines | ||
| 1384 | 1490 | * If a positive health, means in a known DEAD PANIC |
| 1385 | 1491 | * state and the adapter could be reset to `try again'. |
| 1386 | 1492 | */ |
| 1387 | − retval = aac_adapter_restart(aac, forced ? 0 : aac_adapter_check_health(aac)); | |
| 1493 | + bled = forced ? 0 : aac_adapter_check_health(aac); | |
| 1494 | + retval = aac_adapter_restart(aac, bled, reset_type); | |
| 1388 | 1495 | |
| 1389 | 1496 | if (retval) |
| 1390 | 1497 | goto out; |
| @@ -1494,11 +1601,12 @@ out: · 103 unmodified lines | ||
| 1494 | 1601 | return retval; |
| 1495 | 1602 | } |
| 1496 | 1603 | |
| 1497 | −int aac_reset_adapter(struct aac_dev * aac, int forced) | |
| 1604 | +int aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type) | |
| 1498 | 1605 | { |
| 1499 | 1606 | unsigned long flagv = 0; |
| 1500 | 1607 | int retval; |
| 1501 | 1608 | struct Scsi_Host * host; |
| 1609 | + int bled; | |
| 1502 | 1610 | |
| 1503 | 1611 | if (spin_trylock_irqsave(&aac->fib_lock, flagv) == 0) |
| 1504 | 1612 | return -EBUSY; |
| @@ -1547,7 +1655,9 @@ int aac_reset_adapter(struct aac_dev * aac, int forced) · 42 unmodified lines | ||
| 1547 | 1655 | if (forced < 2) |
| 1548 | 1656 | aac_send_shutdown(aac); |
| 1549 | 1657 | spin_lock_irqsave(host->host_lock, flagv); |
| 1550 | − retval = _aac_reset_adapter(aac, forced ? forced : ((aac_check_reset != 0) && (aac_check_reset != 1))); | |
| 1658 | + bled = forced ? forced : | |
| 1659 | + (aac_check_reset != 0 && aac_check_reset != 1); | |
| 1660 | + retval = _aac_reset_adapter(aac, bled, reset_type); | |
| 1551 | 1661 | spin_unlock_irqrestore(host->host_lock, flagv); |
| 1552 | 1662 | |
| 1553 | 1663 | if ((forced < 2) && (retval == -ENODEV)) { |
| @@ -1593,6 +1703,7 @@ int aac_check_health(struct aac_dev * aac) · 39 unmodified lines | ||
| 1593 | 1703 | unsigned long time_now, flagv = 0; |
| 1594 | 1704 | struct list_head * entry; |
| 1595 | 1705 | struct Scsi_Host * host; |
| 1706 | + int bled; | |
| 1596 | 1707 | |
| 1597 | 1708 | /* Extending the scope of fib_lock slightly to protect aac->in_reset */ |
| 1598 | 1709 | if (spin_trylock_irqsave(&aac->fib_lock, flagv) == 0) |
| @@ -1710,7 +1821,8 @@ int aac_check_health(struct aac_dev * aac) · 111 unmodified lines | ||
| 1710 | 1821 | host = aac->scsi_host_ptr; |
| 1711 | 1822 | if (aac->thread->pid != current->pid) |
| 1712 | 1823 | spin_lock_irqsave(host->host_lock, flagv); |
| 1713 | − BlinkLED = _aac_reset_adapter(aac, aac_check_reset != 1); | |
| 1824 | + bled = aac_check_reset != 1 ? 1 : 0; | |
| 1825 | + _aac_reset_adapter(aac, bled, IOP_HWSOFT_RESET); | |
| 1714 | 1826 | if (aac->thread->pid != current->pid) |
| 1715 | 1827 | spin_unlock_irqrestore(host->host_lock, flagv); |
| 1716 | 1828 | return BlinkLED; |
| @@ -1721,6 +1833,552 @@ out: · 4 unmodified lines | ||
| 1721 | 1833 | } |
| 1722 | 1834 | |
| 1723 | 1835 | |
| 1836 | +static void aac_resolve_luns(struct aac_dev *dev) | |
| 1837 | +{ | |
| 1838 | + int bus, target, channel; | |
| 1839 | + struct scsi_device *sdev; | |
| 1840 | + u8 devtype; | |
| 1841 | + u8 new_devtype; | |
| 1842 | + | |
| 1843 | + for (bus = 0; bus < AAC_MAX_BUSES; bus++) { | |
| 1844 | + for (target = 0; target < AAC_MAX_TARGETS; target++) { | |
| 1845 | + | |
| 1846 | + if (aac_phys_to_logical(bus) == ENCLOSURE_CHANNEL) | |
| 1847 | + continue; | |
| 1848 | + | |
| 1849 | + if (bus == CONTAINER_CHANNEL) | |
| 1850 | + channel = CONTAINER_CHANNEL; | |
| 1851 | + else | |
| 1852 | + channel = aac_phys_to_logical(bus); | |
| 1853 | + | |
| 1854 | + devtype = dev->hba_map[bus][target].devtype; | |
| 1855 | + new_devtype = dev->hba_map[bus][target].new_devtype; | |
| 1856 | + | |
| 1857 | + sdev = scsi_device_lookup(dev->scsi_host_ptr, channel, | |
| 1858 | + target, 0); | |
| 1859 | + | |
| 1860 | + if (!sdev && devtype) | |
| 1861 | + scsi_add_device(dev->scsi_host_ptr, channel, | |
| 1862 | + target, 0); | |
| 1863 | + else if (sdev && new_devtype != devtype) | |
| 1864 | + scsi_remove_device(sdev); | |
| 1865 | + else if (sdev && new_devtype == devtype) | |
| 1866 | + scsi_rescan_device(&sdev->sdev_gendev); | |
| 1867 | + | |
| 1868 | + if (sdev) | |
| 1869 | + scsi_device_put(sdev); | |
| 1870 | + | |
| 1871 | + dev->hba_map[bus][target].devtype = new_devtype; | |
| 1872 | + } | |
| 1873 | + } | |
| 1874 | +} | |
| 1875 | + | |
| 1876 | +/** | |
| 1877 | + * aac_handle_sa_aif Handle a message from the firmware | |
| 1878 | + * @dev: Which adapter this fib is from | |
| 1879 | + * @fibptr: Pointer to fibptr from adapter | |
| 1880 | + * | |
| 1881 | + * This routine handles a driver notify fib from the adapter and | |
| 1882 | + * dispatches it to the appropriate routine for handling. | |
| 1883 | + */ | |
| 1884 | +static void aac_handle_sa_aif(struct aac_dev *dev, struct fib *fibptr) | |
| 1885 | +{ | |
| 1886 | + int i, bus, target, container, rcode = 0; | |
| 1887 | + u32 events = 0; | |
| 1888 | + struct fib *fib; | |
| 1889 | + struct scsi_device *sdev; | |
| 1890 | + | |
| 1891 | + if (fibptr->hbacmd_size & SA_AIF_HOTPLUG) | |
| 1892 | + events = SA_AIF_HOTPLUG; | |
| 1893 | + else if (fibptr->hbacmd_size & SA_AIF_HARDWARE) | |
| 1894 | + events = SA_AIF_HARDWARE; | |
| 1895 | + else if (fibptr->hbacmd_size & SA_AIF_PDEV_CHANGE) | |
| 1896 | + events = SA_AIF_PDEV_CHANGE; | |
| 1897 | + else if (fibptr->hbacmd_size & SA_AIF_LDEV_CHANGE) | |
| 1898 | + events = SA_AIF_LDEV_CHANGE; | |
| 1899 | + else if (fibptr->hbacmd_size & SA_AIF_BPSTAT_CHANGE) | |
| 1900 | + events = SA_AIF_BPSTAT_CHANGE; | |
| 1901 | + else if (fibptr->hbacmd_size & SA_AIF_BPCFG_CHANGE) | |
| 1902 | + events = SA_AIF_BPCFG_CHANGE; | |
| 1903 | + | |
| 1904 | + switch (events) { | |
| 1905 | + case SA_AIF_HOTPLUG: | |
| 1906 | + case SA_AIF_HARDWARE: | |
| 1907 | + case SA_AIF_PDEV_CHANGE: | |
| 1908 | + case SA_AIF_LDEV_CHANGE: | |
| 1909 | + case SA_AIF_BPCFG_CHANGE: | |
| 1910 | + | |
| 1911 | + fib = aac_fib_alloc(dev); | |
| 1912 | + if (!fib) { | |
| 1913 | + pr_err("aac_handle_sa_aif: out of memory\n"); | |
| 1914 | + return; | |
| 1915 | + } | |
| 1916 | + for (bus = 0; bus < AAC_MAX_BUSES; bus++) | |
| 1917 | + for (target = 0; target < AAC_MAX_TARGETS; target++) | |
| 1918 | + dev->hba_map[bus][target].new_devtype = 0; | |
| 1919 | + | |
| 1920 | + rcode = aac_report_phys_luns(dev, fib, AAC_RESCAN); | |
| 1921 | + | |
| 1922 | + if (rcode != -ERESTARTSYS) | |
| 1923 | + aac_fib_free(fib); | |
| 1924 | + | |
| 1925 | + aac_resolve_luns(dev); | |
| 1926 | + | |
| 1927 | + if (events == SA_AIF_LDEV_CHANGE || | |
| 1928 | + events == SA_AIF_BPCFG_CHANGE) { | |
| 1929 | + aac_get_containers(dev); | |
| 1930 | + for (container = 0; container < | |
| 1931 | + dev->maximum_num_containers; ++container) { | |
| 1932 | + sdev = scsi_device_lookup(dev->scsi_host_ptr, | |
| 1933 | + CONTAINER_CHANNEL, | |
| 1934 | + container, 0); | |
| 1935 | + if (dev->fsa_dev[container].valid && !sdev) { | |
| 1936 | + scsi_add_device(dev->scsi_host_ptr, | |
| 1937 | + CONTAINER_CHANNEL, | |
| 1938 | + container, 0); | |
| 1939 | + } else if (!dev->fsa_dev[container].valid && | |
| 1940 | + sdev) { | |
| 1941 | + scsi_remove_device(sdev); | |
| 1942 | + scsi_device_put(sdev); | |
| 1943 | + } else if (sdev) { | |
| 1944 | + scsi_rescan_device(&sdev->sdev_gendev); | |
| 1945 | + scsi_device_put(sdev); | |
| 1946 | + } | |
| 1947 | + } | |
| 1948 | + } | |
| 1949 | + break; | |
| 1950 | + | |
| 1951 | + case SA_AIF_BPSTAT_CHANGE: | |
| 1952 | + /* currently do nothing */ | |
| 1953 | + break; | |
| 1954 | + } | |
| 1955 | + | |
| 1956 | + for (i = 1; i <= 10; ++i) { | |
| 1957 | + events = src_readl(dev, MUnit.IDR); | |
| 1958 | + if (events & (1<<23)) { | |
| 1959 | + pr_warn(" AIF not cleared by firmware - %d/%d)\n", | |
| 1960 | + i, 10); | |
| 1961 | + ssleep(1); | |
| 1962 | + } | |
| 1963 | + } | |
| 1964 | +} | |
| 1965 | + | |
| 1966 | +static int get_fib_count(struct aac_dev *dev) | |
| 1967 | +{ | |
| 1968 | + unsigned int num = 0; | |
| 1969 | + struct list_head *entry; | |
| 1970 | + unsigned long flagv; | |
| 1971 | + | |
| 1972 | + /* | |
| 1973 | + * Warning: no sleep allowed while | |
| 1974 | + * holding spinlock. We take the estimate | |
| 1975 | + * and pre-allocate a set of fibs outside the | |
| 1976 | + * lock. | |
| 1977 | + */ | |
| 1978 | + num = le32_to_cpu(dev->init->r7.adapter_fibs_size) | |
| 1979 | + / sizeof(struct hw_fib); /* some extra */ | |
| 1980 | + spin_lock_irqsave(&dev->fib_lock, flagv); | |
| 1981 | + entry = dev->fib_list.next; | |
| 1982 | + while (entry != &dev->fib_list) { | |
| 1983 | + entry = entry->next; | |
| 1984 | + ++num; | |
| 1985 | + } | |
| 1986 | + spin_unlock_irqrestore(&dev->fib_lock, flagv); | |
| 1987 | + | |
| 1988 | + return num; | |
| 1989 | +} | |
| 1990 | + | |
| 1991 | +static int fillup_pools(struct aac_dev *dev, struct hw_fib **hw_fib_pool, | |
| 1992 | + struct fib **fib_pool, | |
| 1993 | + unsigned int num) | |
| 1994 | +{ | |
| 1995 | + struct hw_fib **hw_fib_p; | |
| 1996 | + struct fib **fib_p; | |
| 1997 | + int rcode = 1; | |
| 1998 | + | |
| 1999 | + hw_fib_p = hw_fib_pool; | |
| 2000 | + fib_p = fib_pool; | |
| 2001 | + while (hw_fib_p < &hw_fib_pool[num]) { | |
| 2002 | + *(hw_fib_p) = kmalloc(sizeof(struct hw_fib), GFP_KERNEL); | |
| 2003 | + if (!(*(hw_fib_p++))) { | |
| 2004 | + --hw_fib_p; | |
| 2005 | + break; | |
| 2006 | + } | |
| 2007 | + | |
| 2008 | + *(fib_p) = kmalloc(sizeof(struct fib), GFP_KERNEL); | |
| 2009 | + if (!(*(fib_p++))) { | |
| 2010 | + kfree(*(--hw_fib_p)); | |
| 2011 | + break; | |
| 2012 | + } | |
| 2013 | + } | |
| 2014 | + | |
| 2015 | + num = hw_fib_p - hw_fib_pool; | |
| 2016 | + if (!num) | |
| 2017 | + rcode = 0; | |
| 2018 | + | |
| 2019 | + return rcode; | |
| 2020 | +} | |
| 2021 | + | |
| 2022 | +static void wakeup_fibctx_threads(struct aac_dev *dev, | |
| 2023 | + struct hw_fib **hw_fib_pool, | |
| 2024 | + struct fib **fib_pool, | |
| 2025 | + struct fib *fib, | |
| 2026 | + struct hw_fib *hw_fib, | |
| 2027 | + unsigned int num) | |
| 2028 | +{ | |
| 2029 | + unsigned long flagv; | |
| 2030 | + struct list_head *entry; | |
| 2031 | + struct hw_fib **hw_fib_p; | |
| 2032 | + struct fib **fib_p; | |
| 2033 | + u32 time_now, time_last; | |
| 2034 | + struct hw_fib *hw_newfib; | |
| 2035 | + struct fib *newfib; | |
| 2036 | + struct aac_fib_context *fibctx; | |
| 2037 | + | |
| 2038 | + time_now = jiffies/HZ; | |
| 2039 | + spin_lock_irqsave(&dev->fib_lock, flagv); | |
| 2040 | + entry = dev->fib_list.next; | |
| 2041 | + /* | |
| 2042 | + * For each Context that is on the | |
| 2043 | + * fibctxList, make a copy of the | |
| 2044 | + * fib, and then set the event to wake up the | |
| 2045 | + * thread that is waiting for it. | |
| 2046 | + */ | |
| 2047 | + | |
| 2048 | + hw_fib_p = hw_fib_pool; | |
| 2049 | + fib_p = fib_pool; | |
| 2050 | + while (entry != &dev->fib_list) { | |
| 2051 | + /* | |
| 2052 | + * Extract the fibctx | |
| 2053 | + */ | |
| 2054 | + fibctx = list_entry(entry, struct aac_fib_context, | |
| 2055 | + next); | |
| 2056 | + /* | |
| 2057 | + * Check if the queue is getting | |
| 2058 | + * backlogged | |
| 2059 | + */ | |
| 2060 | + if (fibctx->count > 20) { | |
| 2061 | + /* | |
| 2062 | + * It's *not* jiffies folks, | |
| 2063 | + * but jiffies / HZ so do not | |
| 2064 | + * panic ... | |
| 2065 | + */ | |
| 2066 | + time_last = fibctx->jiffies; | |
| 2067 | + /* | |
| 2068 | + * Has it been > 2 minutes | |
| 2069 | + * since the last read off | |
| 2070 | + * the queue? | |
| 2071 | + */ | |
| 2072 | + if ((time_now - time_last) > aif_timeout) { | |
| 2073 | + entry = entry->next; | |
| 2074 | + aac_close_fib_context(dev, fibctx); | |
| 2075 | + continue; | |
| 2076 | + } | |
| 2077 | + } | |
| 2078 | + /* | |
| 2079 | + * Warning: no sleep allowed while | |
| 2080 | + * holding spinlock | |
| 2081 | + */ | |
| 2082 | + if (hw_fib_p >= &hw_fib_pool[num]) { | |
| 2083 | + pr_warn("aifd: didn't allocate NewFib\n"); | |
| 2084 | + entry = entry->next; | |
| 2085 | + continue; | |
| 2086 | + } | |
| 2087 | + | |
| 2088 | + hw_newfib = *hw_fib_p; | |
| 2089 | + *(hw_fib_p++) = NULL; | |
| 2090 | + newfib = *fib_p; | |
| 2091 | + *(fib_p++) = NULL; | |
| 2092 | + /* | |
| 2093 | + * Make the copy of the FIB | |
| 2094 | + */ | |
| 2095 | + memcpy(hw_newfib, hw_fib, sizeof(struct hw_fib)); | |
| 2096 | + memcpy(newfib, fib, sizeof(struct fib)); | |
| 2097 | + newfib->hw_fib_va = hw_newfib; | |
| 2098 | + /* | |
| 2099 | + * Put the FIB onto the | |
| 2100 | + * fibctx's fibs | |
| 2101 | + */ | |
| 2102 | + list_add_tail(&newfib->fiblink, &fibctx->fib_list); | |
| 2103 | + fibctx->count++; | |
| 2104 | + /* | |
| 2105 | + * Set the event to wake up the | |
| 2106 | + * thread that is waiting. | |
| 2107 | + */ | |
| 2108 | + up(&fibctx->wait_sem); | |
| 2109 | + | |
| 2110 | + entry = entry->next; | |
| 2111 | + } | |
| 2112 | + /* | |
| 2113 | + * Set the status of this FIB | |
| 2114 | + */ | |
| 2115 | + *(__le32 *)hw_fib->data = cpu_to_le32(ST_OK); | |
| 2116 | + aac_fib_adapter_complete(fib, sizeof(u32)); | |
| 2117 | + spin_unlock_irqrestore(&dev->fib_lock, flagv); | |
| 2118 | + | |
| 2119 | +} | |
| 2120 | + | |
| 2121 | +static void aac_process_events(struct aac_dev *dev) | |
| 2122 | +{ | |
| 2123 | + struct hw_fib *hw_fib; | |
| 2124 | + struct fib *fib; | |
| 2125 | + unsigned long flags; | |
| 2126 | + spinlock_t *t_lock; | |
| 2127 | + unsigned int rcode; | |
| 2128 | + | |
| 2129 | + t_lock = dev->queues->queue[HostNormCmdQueue].lock; | |
| 2130 | + spin_lock_irqsave(t_lock, flags); | |
| 2131 | + | |
| 2132 | + while (!list_empty(&(dev->queues->queue[HostNormCmdQueue].cmdq))) { | |
| 2133 | + struct list_head *entry; | |
| 2134 | + struct aac_aifcmd *aifcmd; | |
| 2135 | + unsigned int num; | |
| 2136 | + struct hw_fib **hw_fib_pool, **hw_fib_p; | |
| 2137 | + struct fib **fib_pool, **fib_p; | |
| 2138 | + | |
| 2139 | + set_current_state(TASK_RUNNING); | |
| 2140 | + | |
| 2141 | + entry = dev->queues->queue[HostNormCmdQueue].cmdq.next; | |
| 2142 | + list_del(entry); | |
| 2143 | + | |
| 2144 | + t_lock = dev->queues->queue[HostNormCmdQueue].lock; | |
| 2145 | + spin_unlock_irqrestore(t_lock, flags); | |
| 2146 | + | |
| 2147 | + fib = list_entry(entry, struct fib, fiblink); | |
| 2148 | + hw_fib = fib->hw_fib_va; | |
| 2149 | + if (dev->sa_firmware) { | |
| 2150 | + /* Thor AIF */ | |
| 2151 | + aac_handle_sa_aif(dev, fib); | |
| 2152 | + aac_fib_adapter_complete(fib, (u16)sizeof(u32)); | |
| 2153 | + continue; | |
| 2154 | + } | |
| 2155 | + /* | |
| 2156 | + * We will process the FIB here or pass it to a | |
| 2157 | + * worker thread that is TBD. We Really can't | |
| 2158 | + * do anything at this point since we don't have | |
| 2159 | + * anything defined for this thread to do. | |
| 2160 | + */ | |
| 2161 | + memset(fib, 0, sizeof(struct fib)); | |
| 2162 | + fib->type = FSAFS_NTC_FIB_CONTEXT; | |
| 2163 | + fib->size = sizeof(struct fib); | |
| 2164 | + fib->hw_fib_va = hw_fib; | |
| 2165 | + fib->data = hw_fib->data; | |
| 2166 | + fib->dev = dev; | |
| 2167 | + /* | |
| 2168 | + * We only handle AifRequest fibs from the adapter. | |
| 2169 | + */ | |
| 2170 | + | |
| 2171 | + aifcmd = (struct aac_aifcmd *) hw_fib->data; | |
| 2172 | + if (aifcmd->command == cpu_to_le32(AifCmdDriverNotify)) { | |
| 2173 | + /* Handle Driver Notify Events */ | |
| 2174 | + aac_handle_aif(dev, fib); | |
| 2175 | + *(__le32 *)hw_fib->data = cpu_to_le32(ST_OK); | |
| 2176 | + aac_fib_adapter_complete(fib, (u16)sizeof(u32)); | |
| 2177 | + goto free_fib; | |
| 2178 | + } | |
| 2179 | + /* | |
| 2180 | + * The u32 here is important and intended. We are using | |
| 2181 | + * 32bit wrapping time to fit the adapter field | |
| 2182 | + */ | |
| 2183 | + | |
| 2184 | + /* Sniff events */ | |
| 2185 | + if (aifcmd->command == cpu_to_le32(AifCmdEventNotify) | |
| 2186 | + || aifcmd->command == cpu_to_le32(AifCmdJobProgress)) { | |
| 2187 | + aac_handle_aif(dev, fib); | |
| 2188 | + } | |
| 2189 | + | |
| 2190 | + /* | |
| 2191 | + * get number of fibs to process | |
| 2192 | + */ | |
| 2193 | + num = get_fib_count(dev); | |
| 2194 | + if (!num) | |
| 2195 | + goto free_fib; | |
| 2196 | + | |
| 2197 | + hw_fib_pool = kmalloc_array(num, sizeof(struct hw_fib *), | |
| 2198 | + GFP_KERNEL); | |
| 2199 | + if (!hw_fib_pool) | |
| 2200 | + goto free_fib; | |
| 2201 | + | |
| 2202 | + fib_pool = kmalloc_array(num, sizeof(struct fib *), GFP_KERNEL); | |
| 2203 | + if (!fib_pool) | |
| 2204 | + goto free_hw_fib_pool; | |
| 2205 | + | |
| 2206 | + /* | |
| 2207 | + * Fill up fib pointer pools with actual fibs | |
| 2208 | + * and hw_fibs | |
| 2209 | + */ | |
| 2210 | + rcode = fillup_pools(dev, hw_fib_pool, fib_pool, num); | |
| 2211 | + if (!rcode) | |
| 2212 | + goto free_mem; | |
| 2213 | + | |
| 2214 | + /* | |
| 2215 | + * wakeup the thread that is waiting for | |
| 2216 | + * the response from fw (ioctl) | |
| 2217 | + */ | |
| 2218 | + wakeup_fibctx_threads(dev, hw_fib_pool, fib_pool, | |
| 2219 | + fib, hw_fib, num); | |
| 2220 | + | |
| 2221 | +free_mem: | |
| 2222 | + /* Free up the remaining resources */ | |
| 2223 | + hw_fib_p = hw_fib_pool; | |
| 2224 | + fib_p = fib_pool; | |
| 2225 | + while (hw_fib_p < &hw_fib_pool[num]) { | |
| 2226 | + kfree(*hw_fib_p); | |
| 2227 | + kfree(*fib_p); | |
| 2228 | + ++fib_p; | |
| 2229 | + ++hw_fib_p; | |
| 2230 | + } | |
| 2231 | + kfree(fib_pool); | |
| 2232 | +free_hw_fib_pool: | |
| 2233 | + kfree(hw_fib_pool); | |
| 2234 | +free_fib: | |
| 2235 | + kfree(fib); | |
| 2236 | + t_lock = dev->queues->queue[HostNormCmdQueue].lock; | |
| 2237 | + spin_lock_irqsave(t_lock, flags); | |
| 2238 | + } | |
| 2239 | + /* | |
| 2240 | + * There are no more AIF's | |
| 2241 | + */ | |
| 2242 | + t_lock = dev->queues->queue[HostNormCmdQueue].lock; | |
| 2243 | + spin_unlock_irqrestore(t_lock, flags); | |
| 2244 | +} | |
| 2245 | + | |
| 2246 | +static int aac_send_wellness_command(struct aac_dev *dev, char *wellness_str, | |
| 2247 | + u32 datasize) | |
| 2248 | +{ | |
| 2249 | + struct aac_srb *srbcmd; | |
| 2250 | + struct sgmap64 *sg64; | |
| 2251 | + dma_addr_t addr; | |
| 2252 | + char *dma_buf; | |
| 2253 | + struct fib *fibptr; | |
| 2254 | + int ret = -ENOMEM; | |
| 2255 | + u32 vbus, vid; | |
| 2256 | + | |
| 2257 | + fibptr = aac_fib_alloc(dev); | |
| 2258 | + if (!fibptr) | |
| 2259 | + goto out; | |
| 2260 | + | |
| 2261 | + dma_buf = pci_alloc_consistent(dev->pdev, datasize, &addr); | |
| 2262 | + if (!dma_buf) | |
| 2263 | + goto fib_free_out; | |
| 2264 | + | |
| 2265 | + aac_fib_init(fibptr); | |
| 2266 | + | |
| 2267 | + vbus = (u32)le16_to_cpu(dev->supplement_adapter_info.VirtDeviceBus); | |
| 2268 | + vid = (u32)le16_to_cpu(dev->supplement_adapter_info.VirtDeviceTarget); | |
| 2269 | + | |
| 2270 | + srbcmd = (struct aac_srb *)fib_data(fibptr); | |
| 2271 | + | |
| 2272 | + srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi); | |
| 2273 | + srbcmd->channel = cpu_to_le32(vbus); | |
| 2274 | + srbcmd->id = cpu_to_le32(vid); | |
| 2275 | + srbcmd->lun = 0; | |
| 2276 | + srbcmd->flags = cpu_to_le32(SRB_DataOut); | |
| 2277 | + srbcmd->timeout = cpu_to_le32(10); | |
| 2278 | + srbcmd->retry_limit = 0; | |
| 2279 | + srbcmd->cdb_size = cpu_to_le32(12); | |
| 2280 | + srbcmd->count = cpu_to_le32(datasize); | |
| 2281 | + | |
| 2282 | + memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb)); | |
| 2283 | + srbcmd->cdb[0] = BMIC_OUT; | |
| 2284 | + srbcmd->cdb[6] = WRITE_HOST_WELLNESS; | |
| 2285 | + memcpy(dma_buf, (char *)wellness_str, datasize); | |
| 2286 | + | |
| 2287 | + sg64 = (struct sgmap64 *)&srbcmd->sg; | |
| 2288 | + sg64->count = cpu_to_le32(1); | |
| 2289 | + sg64->sg[0].addr[1] = cpu_to_le32((u32)(((addr) >> 16) >> 16)); | |
| 2290 | + sg64->sg[0].addr[0] = cpu_to_le32((u32)(addr & 0xffffffff)); | |
| 2291 | + sg64->sg[0].count = cpu_to_le32(datasize); | |
| 2292 | + | |
| 2293 | + ret = aac_fib_send(ScsiPortCommand64, fibptr, sizeof(struct aac_srb), | |
| 2294 | + FsaNormal, 1, 1, NULL, NULL); | |
| 2295 | + | |
| 2296 | + pci_free_consistent(dev->pdev, datasize, (void *)dma_buf, addr); | |
| 2297 | + | |
| 2298 | + /* | |
| 2299 | + * Do not set XferState to zero unless | |
| 2300 | + * receives a response from F/W | |
| 2301 | + */ | |
| 2302 | + if (ret >= 0) | |
| 2303 | + aac_fib_complete(fibptr); | |
| 2304 | + | |
| 2305 | + /* | |
| 2306 | + * FIB should be freed only after | |
| 2307 | + * getting the response from the F/W | |
| 2308 | + */ | |
| 2309 | + if (ret != -ERESTARTSYS) | |
| 2310 | + goto fib_free_out; | |
| 2311 | + | |
| 2312 | +out: | |
| 2313 | + return ret; | |
| 2314 | +fib_free_out: | |
| 2315 | + aac_fib_free(fibptr); | |
| 2316 | + goto out; | |
| 2317 | +} | |
| 2318 | + | |
| 2319 | +int aac_send_safw_hostttime(struct aac_dev *dev, struct timeval *now) | |
| 2320 | +{ | |
| 2321 | + struct tm cur_tm; | |
| 2322 | + char wellness_str[] = "<HW>TD\010\0\0\0\0\0\0\0\0\0DW\0\0ZZ"; | |
| 2323 | + u32 datasize = sizeof(wellness_str); | |
| 2324 | + unsigned long local_time; | |
| 2325 | + int ret = -ENODEV; | |
| 2326 | + | |
| 2327 | + if (!dev->sa_firmware) | |
| 2328 | + goto out; | |
| 2329 | + | |
| 2330 | + local_time = (u32)(now->tv_sec - (sys_tz.tz_minuteswest * 60)); | |
| 2331 | + time_to_tm(local_time, 0, &cur_tm); | |
| 2332 | + cur_tm.tm_mon += 1; | |
| 2333 | + cur_tm.tm_year += 1900; | |
| 2334 | + wellness_str[8] = bin2bcd(cur_tm.tm_hour); | |
| 2335 | + wellness_str[9] = bin2bcd(cur_tm.tm_min); | |
| 2336 | + wellness_str[10] = bin2bcd(cur_tm.tm_sec); | |
| 2337 | + wellness_str[12] = bin2bcd(cur_tm.tm_mon); | |
| 2338 | + wellness_str[13] = bin2bcd(cur_tm.tm_mday); | |
| 2339 | + wellness_str[14] = bin2bcd(cur_tm.tm_year / 100); | |
| 2340 | + wellness_str[15] = bin2bcd(cur_tm.tm_year % 100); | |
| 2341 | + | |
| 2342 | + ret = aac_send_wellness_command(dev, wellness_str, datasize); | |
| 2343 | + | |
| 2344 | +out: | |
| 2345 | + return ret; | |
| 2346 | +} | |
| 2347 | + | |
| 2348 | +int aac_send_hosttime(struct aac_dev *dev, struct timeval *now) | |
| 2349 | +{ | |
| 2350 | + int ret = -ENOMEM; | |
| 2351 | + struct fib *fibptr; | |
| 2352 | + __le32 *info; | |
| 2353 | + | |
| 2354 | + fibptr = aac_fib_alloc(dev); | |
| 2355 | + if (!fibptr) | |
| 2356 | + goto out; | |
| 2357 | + | |
| 2358 | + aac_fib_init(fibptr); | |
| 2359 | + info = (__le32 *)fib_data(fibptr); | |
| 2360 | + *info = cpu_to_le32(now->tv_sec); | |
| 2361 | + ret = aac_fib_send(SendHostTime, fibptr, sizeof(*info), FsaNormal, | |
| 2362 | + 1, 1, NULL, NULL); | |
| 2363 | + | |
| 2364 | + /* | |
| 2365 | + * Do not set XferState to zero unless | |
| 2366 | + * receives a response from F/W | |
| 2367 | + */ | |
| 2368 | + if (ret >= 0) | |
| 2369 | + aac_fib_complete(fibptr); | |
| 2370 | + | |
| 2371 | + /* | |
| 2372 | + * FIB should be freed only after | |
| 2373 | + * getting the response from the F/W | |
| 2374 | + */ | |
| 2375 | + if (ret != -ERESTARTSYS) | |
| 2376 | + aac_fib_free(fibptr); | |
| 2377 | + | |
| 2378 | +out: | |
| 2379 | + return ret; | |
| 2380 | +} | |
| 2381 | + | |
| 1724 | 2382 | /** |
| 1725 | 2383 | * aac_command_thread - command processing thread |
| 1726 | 2384 | * @dev: Adapter to monitor |
| @@ -1734,10 +2392,6 @@ out: · 7 unmodified lines | ||
| 1734 | 2392 | int aac_command_thread(void *data) |
| 1735 | 2393 | { |
| 1736 | 2394 | struct aac_dev *dev = data; |
| 1737 | − struct hw_fib *hw_fib, *hw_newfib; | |
| 1738 | − struct fib *fib, *newfib; | |
| 1739 | − struct aac_fib_context *fibctx; | |
| 1740 | − unsigned long flags; | |
| 1741 | 2395 | DECLARE_WAITQUEUE(wait, current); |
| 1742 | 2396 | unsigned long next_jiffies = jiffies + HZ; |
| 1743 | 2397 | unsigned long next_check_jiffies = next_jiffies; |
| @@ -1757,196 +2411,8 @@ int aac_command_thread(void *data) · 13 unmodified lines | ||
| 1757 | 2411 | set_current_state(TASK_INTERRUPTIBLE); |
| 1758 | 2412 | dprintk ((KERN_INFO "aac_command_thread start\n")); |
| 1759 | 2413 | while (1) { |
| 1760 | − spin_lock_irqsave(dev->queues->queue[HostNormCmdQueue].lock, flags); | |
| 1761 | − while(!list_empty(&(dev->queues->queue[HostNormCmdQueue].cmdq))) { | |
| 1762 | − struct list_head *entry; | |
| 1763 | − struct aac_aifcmd * aifcmd; | |
| 1764 | − | |
| 1765 | − set_current_state(TASK_RUNNING); | |
| 1766 | 2414 | |
| 1767 | − entry = dev->queues->queue[HostNormCmdQueue].cmdq.next; | |
| 1768 | − list_del(entry); | |
| 1769 | − | |
| 1770 | − spin_unlock_irqrestore(dev->queues->queue[HostNormCmdQueue].lock, flags); | |
| 1771 | − fib = list_entry(entry, struct fib, fiblink); | |
| 1772 | − /* | |
| 1773 | − * We will process the FIB here or pass it to a | |
| 1774 | − * worker thread that is TBD. We Really can't | |
| 1775 | − * do anything at this point since we don't have | |
| 1776 | − * anything defined for this thread to do. | |
| 1777 | − */ | |
| 1778 | − hw_fib = fib->hw_fib_va; | |
| 1779 | − memset(fib, 0, sizeof(struct fib)); | |
| 1780 | − fib->type = FSAFS_NTC_FIB_CONTEXT; | |
| 1781 | − fib->size = sizeof(struct fib); | |
| 1782 | − fib->hw_fib_va = hw_fib; | |
| 1783 | − fib->data = hw_fib->data; | |
| 1784 | − fib->dev = dev; | |
| 1785 | − /* | |
| 1786 | − * We only handle AifRequest fibs from the adapter. | |
| 1787 | − */ | |
| 1788 | − aifcmd = (struct aac_aifcmd *) hw_fib->data; | |
| 1789 | − if (aifcmd->command == cpu_to_le32(AifCmdDriverNotify)) { | |
| 1790 | − /* Handle Driver Notify Events */ | |
| 1791 | − aac_handle_aif(dev, fib); | |
| 1792 | − *(__le32 *)hw_fib->data = cpu_to_le32(ST_OK); | |
| 1793 | − aac_fib_adapter_complete(fib, (u16)sizeof(u32)); | |
| 1794 | − } else { | |
| 1795 | − /* The u32 here is important and intended. We are using | |
| 1796 | − 32bit wrapping time to fit the adapter field */ | |
| 1797 | − | |
| 1798 | − u32 time_now, time_last; | |
| 1799 | − unsigned long flagv; | |
| 1800 | − unsigned num; | |
| 1801 | − struct hw_fib ** hw_fib_pool, ** hw_fib_p; | |
| 1802 | − struct fib ** fib_pool, ** fib_p; | |
| 1803 | − | |
| 1804 | − /* Sniff events */ | |
| 1805 | − if ((aifcmd->command == | |
| 1806 | − cpu_to_le32(AifCmdEventNotify)) || | |
| 1807 | − (aifcmd->command == | |
| 1808 | − cpu_to_le32(AifCmdJobProgress))) { | |
| 1809 | − aac_handle_aif(dev, fib); | |
| 1810 | − } | |
| 1811 | − | |
| 1812 | − time_now = jiffies/HZ; | |
| 1813 | − | |
| 1814 | − /* | |
| 1815 | − * Warning: no sleep allowed while | |
| 1816 | − * holding spinlock. We take the estimate | |
| 1817 | − * and pre-allocate a set of fibs outside the | |
| 1818 | − * lock. | |
| 1819 | − */ | |
| 1820 | − num = le32_to_cpu(dev->init->AdapterFibsSize) | |
| 1821 | − / sizeof(struct hw_fib); /* some extra */ | |
| 1822 | − spin_lock_irqsave(&dev->fib_lock, flagv); | |
| 1823 | − entry = dev->fib_list.next; | |
| 1824 | − while (entry != &dev->fib_list) { | |
| 1825 | − entry = entry->next; | |
| 1826 | − ++num; | |
| 1827 | − } | |
| 1828 | − spin_unlock_irqrestore(&dev->fib_lock, flagv); | |
| 1829 | − hw_fib_pool = NULL; | |
| 1830 | − fib_pool = NULL; | |
| 1831 | − if (num | |
| 1832 | − && ((hw_fib_pool = kmalloc(sizeof(struct hw_fib *) * num, GFP_KERNEL))) | |
| 1833 | − && ((fib_pool = kmalloc(sizeof(struct fib *) * num, GFP_KERNEL)))) { | |
| 1834 | − hw_fib_p = hw_fib_pool; | |
| 1835 | − fib_p = fib_pool; | |
| 1836 | − while (hw_fib_p < &hw_fib_pool[num]) { | |
| 1837 | − if (!(*(hw_fib_p++) = kmalloc(sizeof(struct hw_fib), GFP_KERNEL))) { | |
| 1838 | − --hw_fib_p; | |
| 1839 | − break; | |
| 1840 | − } | |
| 1841 | − if (!(*(fib_p++) = kmalloc(sizeof(struct fib), GFP_KERNEL))) { | |
| 1842 | − kfree(*(--hw_fib_p)); | |
| 1843 | − break; | |
| 1844 | − } | |
| 1845 | − } | |
| 1846 | − if ((num = hw_fib_p - hw_fib_pool) == 0) { | |
| 1847 | − kfree(fib_pool); | |
| 1848 | − fib_pool = NULL; | |
| 1849 | − kfree(hw_fib_pool); | |
| 1850 | − hw_fib_pool = NULL; | |
| 1851 | − } | |
| 1852 | − } else { | |
| 1853 | − kfree(hw_fib_pool); | |
| 1854 | − hw_fib_pool = NULL; | |
| 1855 | − } | |
| 1856 | − spin_lock_irqsave(&dev->fib_lock, flagv); | |
| 1857 | − entry = dev->fib_list.next; | |
| 1858 | − /* | |
| 1859 | − * For each Context that is on the | |
| 1860 | − * fibctxList, make a copy of the | |
| 1861 | − * fib, and then set the event to wake up the | |
| 1862 | − * thread that is waiting for it. | |
| 1863 | − */ | |
| 1864 | − hw_fib_p = hw_fib_pool; | |
| 1865 | − fib_p = fib_pool; | |
| 1866 | − while (entry != &dev->fib_list) { | |
| 1867 | − /* | |
| 1868 | − * Extract the fibctx | |
| 1869 | − */ | |
| 1870 | − fibctx = list_entry(entry, struct aac_fib_context, next); | |
| 1871 | − /* | |
| 1872 | − * Check if the queue is getting | |
| 1873 | − * backlogged | |
| 1874 | − */ | |
| 1875 | − if (fibctx->count > 20) | |
| 1876 | − { | |
| 1877 | − /* | |
| 1878 | − * It's *not* jiffies folks, | |
| 1879 | − * but jiffies / HZ so do not | |
| 1880 | − * panic ... | |
| 1881 | − */ | |
| 1882 | − time_last = fibctx->jiffies; | |
| 1883 | − /* | |
| 1884 | − * Has it been > 2 minutes | |
| 1885 | − * since the last read off | |
| 1886 | − * the queue? | |
| 1887 | − */ | |
| 1888 | − if ((time_now - time_last) > aif_timeout) { | |
| 1889 | − entry = entry->next; | |
| 1890 | − aac_close_fib_context(dev, fibctx); | |
| 1891 | − continue; | |
| 1892 | − } | |
| 1893 | − } | |
| 1894 | − /* | |
| 1895 | − * Warning: no sleep allowed while | |
| 1896 | − * holding spinlock | |
| 1897 | − */ | |
| 1898 | − if (hw_fib_p < &hw_fib_pool[num]) { | |
| 1899 | − hw_newfib = *hw_fib_p; | |
| 1900 | − *(hw_fib_p++) = NULL; | |
| 1901 | − newfib = *fib_p; | |
| 1902 | − *(fib_p++) = NULL; | |
| 1903 | − /* | |
| 1904 | − * Make the copy of the FIB | |
| 1905 | − */ | |
| 1906 | − memcpy(hw_newfib, hw_fib, sizeof(struct hw_fib)); | |
| 1907 | − memcpy(newfib, fib, sizeof(struct fib)); | |
| 1908 | − newfib->hw_fib_va = hw_newfib; | |
| 1909 | − /* | |
| 1910 | − * Put the FIB onto the | |
| 1911 | − * fibctx's fibs | |
| 1912 | − */ | |
| 1913 | − list_add_tail(&newfib->fiblink, &fibctx->fib_list); | |
| 1914 | − fibctx->count++; | |
| 1915 | − /* | |
| 1916 | − * Set the event to wake up the | |
| 1917 | − * thread that is waiting. | |
| 1918 | − */ | |
| 1919 | − up(&fibctx->wait_sem); | |
| 1920 | − } else { | |
| 1921 | − printk(KERN_WARNING "aifd: didn't allocate NewFib.\n"); | |
| 1922 | − } | |
| 1923 | − entry = entry->next; | |
| 1924 | − } | |
| 1925 | − /* | |
| 1926 | − * Set the status of this FIB | |
| 1927 | − */ | |
| 1928 | − *(__le32 *)hw_fib->data = cpu_to_le32(ST_OK); | |
| 1929 | − aac_fib_adapter_complete(fib, sizeof(u32)); | |
| 1930 | − spin_unlock_irqrestore(&dev->fib_lock, flagv); | |
| 1931 | − /* Free up the remaining resources */ | |
| 1932 | − hw_fib_p = hw_fib_pool; | |
| 1933 | − fib_p = fib_pool; | |
| 1934 | − while (hw_fib_p < &hw_fib_pool[num]) { | |
| 1935 | − kfree(*hw_fib_p); | |
| 1936 | − kfree(*fib_p); | |
| 1937 | − ++fib_p; | |
| 1938 | − ++hw_fib_p; | |
| 1939 | − } | |
| 1940 | − kfree(hw_fib_pool); | |
| 1941 | − kfree(fib_pool); | |
| 1942 | − } | |
| 1943 | − kfree(fib); | |
| 1944 | − spin_lock_irqsave(dev->queues->queue[HostNormCmdQueue].lock, flags); | |
| 1945 | − } | |
| 1946 | − /* | |
| 1947 | − * There are no more AIF's | |
| 1948 | − */ | |
| 1949 | − spin_unlock_irqrestore(dev->queues->queue[HostNormCmdQueue].lock, flags); | |
| 2415 | + aac_process_events(dev); | |
| 1950 | 2416 | |
| 1951 | 2417 | /* |
| 1952 | 2418 | * Background activity |
| @@ -1968,7 +2434,7 @@ int aac_command_thread(void *data) · 15 unmodified lines | ||
| 1968 | 2434 | |
| 1969 | 2435 | /* Don't even try to talk to adapter if its sick */ |
| 1970 | 2436 | ret = aac_check_health(dev); |
| 1971 | − if (!ret && !dev->queues) | |
| 2437 | + if (!dev->queues) | |
| 1972 | 2438 | break; |
| 1973 | 2439 | next_check_jiffies = jiffies |
| 1974 | 2440 | + ((long)(unsigned)check_interval) |
| @@ -1981,36 +2447,16 @@ int aac_command_thread(void *data) · 6 unmodified lines | ||
| 1981 | 2447 | difference = (((1000000 - now.tv_usec) * HZ) |
| 1982 | 2448 | + 500000) / 1000000; |
| 1983 | 2449 | else if (ret == 0) { |
| 1984 | − struct fib *fibptr; | |
| 1985 | − | |
| 1986 | − if ((fibptr = aac_fib_alloc(dev))) { | |
| 1987 | − int status; | |
| 1988 | − __le32 *info; | |
| 1989 | − | |
| 1990 | − aac_fib_init(fibptr); | |
| 1991 | − | |
| 1992 | − info = (__le32 *) fib_data(fibptr); | |
| 1993 | − if (now.tv_usec > 500000) | |
| 1994 | − ++now.tv_sec; | |
| 1995 | − | |
| 1996 | − *info = cpu_to_le32(now.tv_sec); | |
| 1997 | − | |
| 1998 | − status = aac_fib_send(SendHostTime, | |
| 1999 | − fibptr, | |
| 2000 | − sizeof(*info), | |
| 2001 | − FsaNormal, | |
| 2002 | − 1, 1, | |
| 2003 | − NULL, | |
| 2004 | − NULL); | |
| 2005 | − /* Do not set XferState to zero unless | |
| 2006 | − * receives a response from F/W */ | |
| 2007 | − if (status >= 0) | |
| 2008 | − aac_fib_complete(fibptr); | |
| 2009 | − /* FIB should be freed only after | |
| 2010 | − * getting the response from the F/W */ | |
| 2011 | − if (status != -ERESTARTSYS) | |
| 2012 | − aac_fib_free(fibptr); | |
| 2013 | − } | |
| 2450 | + | |
| 2451 | + if (now.tv_usec > 500000) | |
| 2452 | + ++now.tv_sec; | |
| 2453 | + | |
| 2454 | + if (dev->sa_firmware) | |
| 2455 | + ret = | |
| 2456 | + aac_send_safw_hostttime(dev, &now); | |
| 2457 | + else | |
| 2458 | + ret = aac_send_hosttime(dev, &now); | |
| 2459 | + | |
| 2014 | 2460 | difference = (long)(unsigned)update_interval*HZ; |
| 2015 | 2461 | } else { |
| 2016 | 2462 | /* retry shortly */ |
| @@ -6,7 +6,8 @@ · 5 unmodified lines | ||
| 6 | 6 | * Adaptec aacraid device driver for Linux. |
| 7 | 7 | * |
| 8 | 8 | * Copyright (c) 2000-2010 Adaptec, Inc. |
| 9 | − * 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | |
| 9 | + * 2010-2015 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | |
| 10 | + * 2016-2017 Microsemi Corp. (aacraid@microsemi.com) | |
| 10 | 11 | * |
| 11 | 12 | * This program is free software; you can redistribute it and/or modify |
| 12 | 13 | * it under the terms of the GNU General Public License as published by |
| @@ -122,7 +123,6 @@ unsigned int aac_response_normal(struct aac_queue * q) · 109 unmodified lines | ||
| 122 | 123 | * NOTE: we cannot touch the fib after this |
| 123 | 124 | * call, because it may have been deallocated. |
| 124 | 125 | */ |
| 125 | − fib->flags &= FIB_CONTEXT_FLAG_FASTRESP; | |
| 126 | 126 | fib->callback(fib->callback_data, fib); |
| 127 | 127 | } else { |
| 128 | 128 | unsigned long flagv; |
| @@ -251,8 +251,9 @@ static void aac_aif_callback(void *context, struct fib * fibptr) · 122 unmodified lines | ||
| 251 | 251 | BUG_ON(fibptr == NULL); |
| 252 | 252 | dev = fibptr->dev; |
| 253 | 253 | |
| 254 | − if (fibptr->hw_fib_va->header.XferState & | |
| 255 | − cpu_to_le32(NoMoreAifDataAvailable)) { | |
| 254 | + if ((fibptr->hw_fib_va->header.XferState & | |
| 255 | + cpu_to_le32(NoMoreAifDataAvailable)) || | |
| 256 | + dev->sa_firmware) { | |
| 256 | 257 | aac_fib_complete(fibptr); |
| 257 | 258 | aac_fib_free(fibptr); |
| 258 | 259 | return; |
| @@ -282,8 +283,8 @@ static void aac_aif_callback(void *context, struct fib * fibptr) · 23 unmodified lines | ||
| 282 | 283 | * know there is a response on our normal priority queue. We will pull off |
| 283 | 284 | * all QE there are and wake up all the waiters before exiting. |
| 284 | 285 | */ |
| 285 | −unsigned int aac_intr_normal(struct aac_dev *dev, u32 index, | |
| 286 | − int isAif, int isFastResponse, struct hw_fib *aif_fib) | |
| 286 | +unsigned int aac_intr_normal(struct aac_dev *dev, u32 index, int isAif, | |
| 287 | + int isFastResponse, struct hw_fib *aif_fib) | |
| 287 | 288 | { |
| 288 | 289 | unsigned long mflags; |
| 289 | 290 | dprintk((KERN_INFO "aac_intr_normal(%p,%x)\n", dev, index)); |
| @@ -305,12 +306,14 @@ unsigned int aac_intr_normal(struct aac_dev *dev, u32 index, · 15 unmodified lines | ||
| 305 | 306 | kfree (fib); |
| 306 | 307 | return 1; |
| 307 | 308 | } |
| 308 | − if (aif_fib != NULL) { | |
| 309 | + if (dev->sa_firmware) { | |
| 310 | + fib->hbacmd_size = index; /* store event type */ | |
| 311 | + } else if (aif_fib != NULL) { | |
| 309 | 312 | memcpy(hw_fib, aif_fib, sizeof(struct hw_fib)); |
| 310 | 313 | } else { |
| 311 | − memcpy(hw_fib, | |
| 312 | − (struct hw_fib *)(((uintptr_t)(dev->regs.sa)) + | |
| 313 | − index), sizeof(struct hw_fib)); | |
| 314 | + memcpy(hw_fib, (struct hw_fib *) | |
| 315 | + (((uintptr_t)(dev->regs.sa)) + index), | |
| 316 | + sizeof(struct hw_fib)); | |
| 314 | 317 | } |
| 315 | 318 | INIT_LIST_HEAD(&fib->fiblink); |
| 316 | 319 | fib->type = FSAFS_NTC_FIB_CONTEXT; |
| @@ -344,7 +347,7 @@ unsigned int aac_intr_normal(struct aac_dev *dev, u32 index, · 27 unmodified lines | ||
| 344 | 347 | (fib_callback)aac_aif_callback, fibctx); |
| 345 | 348 | } else { |
| 346 | 349 | struct fib *fib = &dev->fibs[index]; |
| 347 | − struct hw_fib * hwfib = fib->hw_fib_va; | |
| 350 | + int start_callback = 0; | |
| 348 | 351 | |
| 349 | 352 | /* |
| 350 | 353 | * Remove this fib from the Outstanding I/O queue. |
| @@ -362,60 +365,104 @@ unsigned int aac_intr_normal(struct aac_dev *dev, u32 index, · 11 unmodified lines | ||
| 362 | 365 | return 0; |
| 363 | 366 | } |
| 364 | 367 | |
| 365 | − if (isFastResponse) { | |
| 366 | − /* | |
| 367 | − * Doctor the fib | |
| 368 | − */ | |
| 369 | − *(__le32 *)hwfib->data = cpu_to_le32(ST_OK); | |
| 370 | − hwfib->header.XferState |= cpu_to_le32(AdapterProcessed); | |
| 371 | − fib->flags |= FIB_CONTEXT_FLAG_FASTRESP; | |
| 372 | − } | |
| 373 | − | |
| 374 | 368 | FIB_COUNTER_INCREMENT(aac_config.FibRecved); |
| 375 | 369 | |
| 376 | − if (hwfib->header.Command == cpu_to_le16(NuFileSystem)) | |
| 377 | − { | |
| 378 | − __le32 *pstatus = (__le32 *)hwfib->data; | |
| 379 | − if (*pstatus & cpu_to_le32(0xffff0000)) | |
| 380 | − *pstatus = cpu_to_le32(ST_OK); | |
| 381 | − } | |
| 382 | − if (hwfib->header.XferState & cpu_to_le32(NoResponseExpected | Async)) | |
| 383 | − { | |
| 384 | − if (hwfib->header.XferState & cpu_to_le32(NoResponseExpected)) | |
| 385 | − FIB_COUNTER_INCREMENT(aac_config.NoResponseRecved); | |
| 386 | − else | |
| 387 | − FIB_COUNTER_INCREMENT(aac_config.AsyncRecved); | |
| 388 | − /* | |
| 389 | − * NOTE: we cannot touch the fib after this | |
| 390 | − * call, because it may have been deallocated. | |
| 391 | − */ | |
| 392 | − if (likely(fib->callback && fib->callback_data)) { | |
| 393 | − fib->flags &= FIB_CONTEXT_FLAG_FASTRESP; | |
| 394 | − fib->callback(fib->callback_data, fib); | |
| 395 | − } else | |
| 396 | − dev_info(&dev->pdev->dev, | |
| 397 | − "Invalid callback_fib[%d] (*%p)(%p)\n", | |
| 398 | − index, fib->callback, fib->callback_data); | |
| 370 | + if (fib->flags & FIB_CONTEXT_FLAG_NATIVE_HBA) { | |
| 371 | + | |
| 372 | + if (isFastResponse) | |
| 373 | + fib->flags |= FIB_CONTEXT_FLAG_FASTRESP; | |
| 374 | + | |
| 375 | + if (fib->callback) { | |
| 376 | + start_callback = 1; | |
| 377 | + } else { | |
| 378 | + unsigned long flagv; | |
| 379 | + int complete = 0; | |
| 380 | + | |
| 381 | + dprintk((KERN_INFO "event_wait up\n")); | |
| 382 | + spin_lock_irqsave(&fib->event_lock, flagv); | |
| 383 | + if (fib->done == 2) { | |
| 384 | + fib->done = 1; | |
| 385 | + complete = 1; | |
| 386 | + } else { | |
| 387 | + fib->done = 1; | |
| 388 | + up(&fib->event_wait); | |
| 389 | + } | |
| 390 | + spin_unlock_irqrestore(&fib->event_lock, flagv); | |
| 391 | + | |
| 392 | + spin_lock_irqsave(&dev->manage_lock, mflags); | |
| 393 | + dev->management_fib_count--; | |
| 394 | + spin_unlock_irqrestore(&dev->manage_lock, | |
| 395 | + mflags); | |
| 396 | + | |
| 397 | + FIB_COUNTER_INCREMENT(aac_config.NativeRecved); | |
| 398 | + if (complete) | |
| 399 | + aac_fib_complete(fib); | |
| 400 | + } | |
| 399 | 401 | } else { |
| 400 | − unsigned long flagv; | |
| 401 | − dprintk((KERN_INFO "event_wait up\n")); | |
| 402 | − spin_lock_irqsave(&fib->event_lock, flagv); | |
| 403 | − if (!fib->done) { | |
| 404 | − fib->done = 1; | |
| 405 | − up(&fib->event_wait); | |
| 402 | + struct hw_fib *hwfib = fib->hw_fib_va; | |
| 403 | + | |
| 404 | + if (isFastResponse) { | |
| 405 | + /* Doctor the fib */ | |
| 406 | + *(__le32 *)hwfib->data = cpu_to_le32(ST_OK); | |
| 407 | + hwfib->header.XferState |= | |
| 408 | + cpu_to_le32(AdapterProcessed); | |
| 409 | + fib->flags |= FIB_CONTEXT_FLAG_FASTRESP; | |
| 406 | 410 | } |
| 407 | − spin_unlock_irqrestore(&fib->event_lock, flagv); | |
| 408 | 411 | |
| 409 | − spin_lock_irqsave(&dev->manage_lock, mflags); | |
| 410 | − dev->management_fib_count--; | |
| 411 | − spin_unlock_irqrestore(&dev->manage_lock, mflags); | |
| 412 | + if (hwfib->header.Command == | |
| 413 | + cpu_to_le16(NuFileSystem)) { | |
| 414 | + __le32 *pstatus = (__le32 *)hwfib->data; | |
| 412 | 415 | |
| 413 | − FIB_COUNTER_INCREMENT(aac_config.NormalRecved); | |
| 414 | − if (fib->done == 2) { | |
| 416 | + if (*pstatus & cpu_to_le32(0xffff0000)) | |
| 417 | + *pstatus = cpu_to_le32(ST_OK); | |
| 418 | + } | |
| 419 | + if (hwfib->header.XferState & | |
| 420 | + cpu_to_le32(NoResponseExpected | Async)) { | |
| 421 | + if (hwfib->header.XferState & cpu_to_le32( | |
| 422 | + NoResponseExpected)) | |
| 423 | + FIB_COUNTER_INCREMENT( | |
| 424 | + aac_config.NoResponseRecved); | |
| 425 | + else | |
| 426 | + FIB_COUNTER_INCREMENT( | |
| 427 | + aac_config.AsyncRecved); | |
| 428 | + start_callback = 1; | |
| 429 | + } else { | |
| 430 | + unsigned long flagv; | |
| 431 | + int complete = 0; | |
| 432 | + | |
| 433 | + dprintk((KERN_INFO "event_wait up\n")); | |
| 415 | 434 | spin_lock_irqsave(&fib->event_lock, flagv); |
| 416 | − fib->done = 0; | |
| 435 | + if (fib->done == 2) { | |
| 436 | + fib->done = 1; | |
| 437 | + complete = 1; | |
| 438 | + } else { | |
| 439 | + fib->done = 1; | |
| 440 | + up(&fib->event_wait); | |
| 441 | + } | |
| 417 | 442 | spin_unlock_irqrestore(&fib->event_lock, flagv); |
| 443 | + | |
| 444 | + spin_lock_irqsave(&dev->manage_lock, mflags); | |
| 445 | + dev->management_fib_count--; | |
| 446 | + spin_unlock_irqrestore(&dev->manage_lock, | |
| 447 | + mflags); | |
| 448 | + | |
| 449 | + FIB_COUNTER_INCREMENT(aac_config.NormalRecved); | |
| 450 | + if (complete) | |
| 451 | + aac_fib_complete(fib); | |
| 452 | + } | |
| 453 | + } | |
| 454 | + | |
| 455 | + | |
| 456 | + if (start_callback) { | |
| 457 | + /* | |
| 458 | + * NOTE: we cannot touch the fib after this | |
| 459 | + * call, because it may have been deallocated. | |
| 460 | + */ | |
| 461 | + if (likely(fib->callback && fib->callback_data)) { | |
| 462 | + fib->callback(fib->callback_data, fib); | |
| 463 | + } else { | |
| 418 | 464 | aac_fib_complete(fib); |
| 465 | + aac_fib_free(fib); | |
| 419 | 466 | } |
| 420 | 467 | |
| 421 | 468 | } |
| @@ -6,7 +6,8 @@ · 5 unmodified lines | ||
| 6 | 6 | * Adaptec aacraid device driver for Linux. |
| 7 | 7 | * |
| 8 | 8 | * Copyright (c) 2000-2010 Adaptec, Inc. |
| 9 | − * 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | |
| 9 | + * 2010-2015 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | |
| 10 | + * 2016-2017 Microsemi Corp. (aacraid@microsemi.com) | |
| 10 | 11 | * |
| 11 | 12 | * This program is free software; you can redistribute it and/or modify |
| 12 | 13 | * it under the terms of the GNU General Public License as published by |
| @@ -57,7 +58,7 @@ · 44 unmodified lines | ||
| 57 | 58 | |
| 58 | 59 | #include "aacraid.h" |
| 59 | 60 | |
| 60 | −#define AAC_DRIVER_VERSION "1.2-1" | |
| 61 | +#define AAC_DRIVER_VERSION "1.2.1" | |
| 61 | 62 | #ifndef AAC_DRIVER_BRANCH |
| 62 | 63 | #define AAC_DRIVER_BRANCH "" |
| 63 | 64 | #endif |
| @@ -401,61 +402,89 @@ static int aac_biosparm(struct scsi_device *sdev, struct block_device *bdev, · 337 unmodified lines | ||
| 401 | 402 | static int aac_slave_configure(struct scsi_device *sdev) |
| 402 | 403 | { |
| 403 | 404 | struct aac_dev *aac = (struct aac_dev *)sdev->host->hostdata; |
| 405 | + int chn, tid; | |
| 406 | + unsigned int depth = 0; | |
| 407 | + unsigned int set_timeout = 0; | |
| 408 | + | |
| 409 | + chn = aac_logical_to_phys(sdev_channel(sdev)); | |
| 410 | + tid = sdev_id(sdev); | |
| 411 | + if (chn < AAC_MAX_BUSES && tid < AAC_MAX_TARGETS && | |
| 412 | + aac->hba_map[chn][tid].devtype == AAC_DEVTYPE_NATIVE_RAW) { | |
| 413 | + depth = aac->hba_map[chn][tid].qd_limit; | |
| 414 | + set_timeout = 1; | |
| 415 | + goto common_config; | |
| 416 | + } | |
| 417 | + | |
| 418 | + | |
| 404 | 419 | if (aac->jbod && (sdev->type == TYPE_DISK)) |
| 405 | 420 | sdev->removable = 1; |
| 406 | − if ((sdev->type == TYPE_DISK) && | |
| 407 | − (sdev_channel(sdev) != CONTAINER_CHANNEL) && | |
| 408 | − (!aac->jbod || sdev->inq_periph_qual) && | |
| 409 | − (!aac->raid_scsi_mode || (sdev_channel(sdev) != 2))) { | |
| 421 | + | |
| 422 | + if (sdev->type == TYPE_DISK | |
| 423 | + && sdev_channel(sdev) != CONTAINER_CHANNEL | |
| 424 | + && (!aac->jbod || sdev->inq_periph_qual) | |
| 425 | + && (!aac->raid_scsi_mode || (sdev_channel(sdev) != 2))) { | |
| 426 | + | |
| 410 | 427 | if (expose_physicals == 0) |
| 411 | 428 | return -ENXIO; |
| 429 | + | |
| 412 | 430 | if (expose_physicals < 0) |
| 413 | 431 | sdev->no_uld_attach = 1; |
| 414 | 432 | } |
| 415 | − if (sdev->tagged_supported && (sdev->type == TYPE_DISK) && | |
| 416 | − (!aac->raid_scsi_mode || (sdev_channel(sdev) != 2)) && | |
| 417 | − !sdev->no_uld_attach) { | |
| 433 | + | |
| 434 | + if (sdev->tagged_supported | |
| 435 | + && sdev->type == TYPE_DISK | |
| 436 | + && (!aac->raid_scsi_mode || (sdev_channel(sdev) != 2)) | |
| 437 | + && !sdev->no_uld_attach) { | |
| 438 | + | |
| 418 | 439 | struct scsi_device * dev; |
| 419 | 440 | struct Scsi_Host *host = sdev->host; |
| 420 | 441 | unsigned num_lsu = 0; |
| 421 | 442 | unsigned num_one = 0; |
| 422 | − unsigned depth; | |
| 423 | 443 | unsigned cid; |
| 424 | 444 | |
| 425 | − /* | |
| 426 | − * Firmware has an individual device recovery time typically | |
| 427 | − * of 35 seconds, give us a margin. | |
| 428 | − */ | |
| 429 | − if (sdev->request_queue->rq_timeout < (45 * HZ)) | |
| 430 | − blk_queue_rq_timeout(sdev->request_queue, 45*HZ); | |
| 445 | + set_timeout = 1; | |
| 446 | + | |
| 431 | 447 | for (cid = 0; cid < aac->maximum_num_containers; ++cid) |
| 432 | 448 | if (aac->fsa_dev[cid].valid) |
| 433 | 449 | ++num_lsu; |
| 450 | + | |
| 434 | 451 | __shost_for_each_device(dev, host) { |
| 435 | − if (dev->tagged_supported && (dev->type == TYPE_DISK) && | |
| 436 | − (!aac->raid_scsi_mode || | |
| 437 | − (sdev_channel(sdev) != 2)) && | |
| 438 | − !dev->no_uld_attach) { | |
| 452 | + if (dev->tagged_supported | |
| 453 | + && dev->type == TYPE_DISK | |
| 454 | + && (!aac->raid_scsi_mode || (sdev_channel(sdev) != 2)) | |
| 455 | + && !dev->no_uld_attach) { | |
| 439 | 456 | if ((sdev_channel(dev) != CONTAINER_CHANNEL) |
| 440 | − || !aac->fsa_dev[sdev_id(dev)].valid) | |
| 457 | + || !aac->fsa_dev[sdev_id(dev)].valid) { | |
| 441 | 458 | ++num_lsu; |
| 442 | − } else | |
| 459 | + } | |
| 460 | + } else { | |
| 443 | 461 | ++num_one; |
| 462 | + } | |
| 444 | 463 | } |
| 464 | + | |
| 445 | 465 | if (num_lsu == 0) |
| 446 | 466 | ++num_lsu; |
| 447 | − depth = (host->can_queue - num_one) / num_lsu; | |
| 448 | − if (depth > 256) | |
| 449 | − depth = 256; | |
| 450 | − else if (depth < 2) | |
| 451 | − depth = 2; | |
| 452 | − scsi_change_queue_depth(sdev, depth); | |
| 453 | − } else { | |
| 454 | − scsi_change_queue_depth(sdev, 1); | |
| 455 | 467 | |
| 456 | − sdev->tagged_supported = 1; | |
| 468 | + depth = (host->can_queue - num_one) / num_lsu; | |
| 457 | 469 | } |
| 458 | 470 | |
| 471 | +common_config: | |
| 472 | + /* | |
| 473 | + * Firmware has an individual device recovery time typically | |
| 474 | + * of 35 seconds, give us a margin. | |
| 475 | + */ | |
| 476 | + if (set_timeout && sdev->request_queue->rq_timeout < (45 * HZ)) | |
| 477 | + blk_queue_rq_timeout(sdev->request_queue, 45*HZ); | |
| 478 | + | |
| 479 | + if (depth > 256) | |
| 480 | + depth = 256; | |
| 481 | + else if (depth < 1) | |
| 482 | + depth = 1; | |
| 483 | + | |
| 484 | + scsi_change_queue_depth(sdev, depth); | |
| 485 | + | |
| 486 | + sdev->tagged_supported = 1; | |
| 487 | + | |
| 459 | 488 | return 0; |
| 460 | 489 | } |
| 461 | 490 | |
| @@ -470,6 +499,15 @@ static int aac_slave_configure(struct scsi_device *sdev) · 8 unmodified lines | ||
| 470 | 499 | |
| 471 | 500 | static int aac_change_queue_depth(struct scsi_device *sdev, int depth) |
| 472 | 501 | { |
| 502 | + struct aac_dev *aac = (struct aac_dev *)(sdev->host->hostdata); | |
| 503 | + int chn, tid, is_native_device = 0; | |
| 504 | + | |
| 505 | + chn = aac_logical_to_phys(sdev_channel(sdev)); | |
| 506 | + tid = sdev_id(sdev); | |
| 507 | + if (chn < AAC_MAX_BUSES && tid < AAC_MAX_TARGETS && | |
| 508 | + aac->hba_map[chn][tid].devtype == AAC_DEVTYPE_NATIVE_RAW) | |
| 509 | + is_native_device = 1; | |
| 510 | + | |
| 473 | 511 | if (sdev->tagged_supported && (sdev->type == TYPE_DISK) && |
| 474 | 512 | (sdev_channel(sdev) == CONTAINER_CHANNEL)) { |
| 475 | 513 | struct scsi_device * dev; |
| @@ -491,9 +529,12 @@ static int aac_change_queue_depth(struct scsi_device *sdev, int depth) · 15 unmodified lines | ||
| 491 | 529 | else if (depth < 2) |
| 492 | 530 | depth = 2; |
| 493 | 531 | return scsi_change_queue_depth(sdev, depth); |
| 532 | + } else if (is_native_device) { | |
| 533 | + scsi_change_queue_depth(sdev, aac->hba_map[chn][tid].qd_limit); | |
| 534 | + } else { | |
| 535 | + scsi_change_queue_depth(sdev, 1); | |
| 494 | 536 | } |
| 495 | − | |
| 496 | − return scsi_change_queue_depth(sdev, 1); | |
| 537 | + return sdev->queue_depth; | |
| 497 | 538 | } |
| 498 | 539 | |
| 499 | 540 | static ssize_t aac_show_raid_level(struct device *dev, struct device_attribute *attr, char *buf) |
| @@ -516,8 +557,39 @@ static struct device_attribute aac_raid_level_attr = { · 16 unmodified lines | ||
| 516 | 557 | .show = aac_show_raid_level |
| 517 | 558 | }; |
| 518 | 559 | |
| 560 | +static ssize_t aac_show_unique_id(struct device *dev, | |
| 561 | + struct device_attribute *attr, char *buf) | |
| 562 | +{ | |
| 563 | + struct scsi_device *sdev = to_scsi_device(dev); | |
| 564 | + struct aac_dev *aac = (struct aac_dev *)(sdev->host->hostdata); | |
| 565 | + unsigned char sn[16]; | |
| 566 | + | |
| 567 | + memset(sn, 0, sizeof(sn)); | |
| 568 | + | |
| 569 | + if (sdev_channel(sdev) == CONTAINER_CHANNEL) | |
| 570 | + memcpy(sn, aac->fsa_dev[sdev_id(sdev)].identifier, sizeof(sn)); | |
| 571 | + | |
| 572 | + return snprintf(buf, 16 * 2 + 2, | |
| 573 | + "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n", | |
| 574 | + sn[0], sn[1], sn[2], sn[3], | |
| 575 | + sn[4], sn[5], sn[6], sn[7], | |
| 576 | + sn[8], sn[9], sn[10], sn[11], | |
| 577 | + sn[12], sn[13], sn[14], sn[15]); | |
| 578 | +} | |
| 579 | + | |
| 580 | +static struct device_attribute aac_unique_id_attr = { | |
| 581 | + .attr = { | |
| 582 | + .name = "unique_id", | |
| 583 | + .mode = 0444, | |
| 584 | + }, | |
| 585 | + .show = aac_show_unique_id | |
| 586 | +}; | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
| 519 | 590 | static struct device_attribute *aac_dev_attrs[] = { |
| 520 | 591 | &aac_raid_level_attr, |
| 592 | + &aac_unique_id_attr, | |
| 521 | 593 | NULL, |
| 522 | 594 | }; |
| 523 | 595 | |
| @@ -534,46 +606,136 @@ static int aac_eh_abort(struct scsi_cmnd* cmd) · 10 unmodified lines | ||
| 534 | 606 | struct scsi_device * dev = cmd->device; |
| 535 | 607 | struct Scsi_Host * host = dev->host; |
| 536 | 608 | struct aac_dev * aac = (struct aac_dev *)host->hostdata; |
| 537 | − int count; | |
| 609 | + int count, found; | |
| 610 | + u32 bus, cid; | |
| 538 | 611 | int ret = FAILED; |
| 539 | 612 | |
| 540 | − printk(KERN_ERR "%s: Host adapter abort request (%d,%d,%d,%llu)\n", | |
| 541 | − AAC_DRIVERNAME, | |
| 542 | − host->host_no, sdev_channel(dev), sdev_id(dev), dev->lun); | |
| 543 | − switch (cmd->cmnd[0]) { | |
| 544 | − case SERVICE_ACTION_IN_16: | |
| 545 | − if (!(aac->raw_io_interface) || | |
| 546 | − !(aac->raw_io_64) || | |
| 547 | − ((cmd->cmnd[1] & 0x1f) != SAI_READ_CAPACITY_16)) | |
| 548 | − break; | |
| 549 | − case INQUIRY: | |
| 550 | − case READ_CAPACITY: | |
| 551 | − /* Mark associated FIB to not complete, eh handler does this */ | |
| 613 | + bus = aac_logical_to_phys(scmd_channel(cmd)); | |
| 614 | + cid = scmd_id(cmd); | |
| 615 | + if (aac->hba_map[bus][cid].devtype == AAC_DEVTYPE_NATIVE_RAW) { | |
| 616 | + struct fib *fib; | |
| 617 | + struct aac_hba_tm_req *tmf; | |
| 618 | + int status; | |
| 619 | + u64 address; | |
| 620 | + __le32 managed_request_id; | |
| 621 | + | |
| 622 | + pr_err("%s: Host adapter abort request (%d,%d,%d,%d)\n", | |
| 623 | + AAC_DRIVERNAME, | |
| 624 | + host->host_no, sdev_channel(dev), sdev_id(dev), (int)dev->lun); | |
| 625 | + | |
| 626 | + found = 0; | |
| 552 | 627 | for (count = 0; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) { |
| 553 | − struct fib * fib = &aac->fibs[count]; | |
| 554 | − if (fib->hw_fib_va->header.XferState && | |
| 555 | − (fib->flags & FIB_CONTEXT_FLAG) && | |
| 556 | − (fib->callback_data == cmd)) { | |
| 557 | − fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT; | |
| 558 | − cmd->SCp.phase = AAC_OWNER_ERROR_HANDLER; | |
| 628 | + fib = &aac->fibs[count]; | |
| 629 | + if (*(u8 *)fib->hw_fib_va != 0 && | |
| 630 | + (fib->flags & FIB_CONTEXT_FLAG_NATIVE_HBA) && | |
| 631 | + (fib->callback_data == cmd)) { | |
| 632 | + found = 1; | |
| 633 | + managed_request_id = ((struct aac_hba_cmd_req *) | |
| 634 | + fib->hw_fib_va)->request_id; | |
| 635 | + break; | |
| 636 | + } | |
| 637 | + } | |
| 638 | + if (!found) | |
| 639 | + return ret; | |
| 640 | + | |
| 641 | + /* start a HBA_TMF_ABORT_TASK TMF request */ | |
| 642 | + fib = aac_fib_alloc(aac); | |
| 643 | + if (!fib) | |
| 644 | + return ret; | |
| 645 | + | |
| 646 | + tmf = (struct aac_hba_tm_req *)fib->hw_fib_va; | |
| 647 | + memset(tmf, 0, sizeof(*tmf)); | |
| 648 | + tmf->tmf = HBA_TMF_ABORT_TASK; | |
| 649 | + tmf->it_nexus = aac->hba_map[bus][cid].rmw_nexus; | |
| 650 | + tmf->lun[1] = cmd->device->lun; | |
| 651 | + | |
| 652 | + address = (u64)fib->hw_error_pa; | |
| 653 | + tmf->error_ptr_hi = cpu_to_le32((u32)(address >> 32)); | |
| 654 | + tmf->error_ptr_lo = cpu_to_le32((u32)(address & 0xffffffff)); | |
| 655 | + tmf->error_length = cpu_to_le32(FW_ERROR_BUFFER_SIZE); | |
| 656 | + | |
| 657 | + fib->hbacmd_size = sizeof(*tmf); | |
| 658 | + cmd->SCp.sent_command = 0; | |
| 659 | + | |
| 660 | + status = aac_hba_send(HBA_IU_TYPE_SCSI_TM_REQ, fib, | |
| 661 | + (fib_callback) aac_hba_callback, | |
| 662 | + (void *) cmd); | |
| 663 | + | |
| 664 | + /* Wait up to 2 minutes for completion */ | |
| 665 | + for (count = 0; count < 120; ++count) { | |
| 666 | + if (cmd->SCp.sent_command) { | |
| 559 | 667 | ret = SUCCESS; |
| 668 | + break; | |
| 560 | 669 | } |
| 670 | + msleep(1000); | |
| 561 | 671 | } |
| 562 | − break; | |
| 563 | − case TEST_UNIT_READY: | |
| 564 | − /* Mark associated FIB to not complete, eh handler does this */ | |
| 565 | − for (count = 0; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) { | |
| 566 | − struct scsi_cmnd * command; | |
| 567 | − struct fib * fib = &aac->fibs[count]; | |
| 568 | − if ((fib->hw_fib_va->header.XferState & cpu_to_le32(Async | NoResponseExpected)) && | |
| 569 | − (fib->flags & FIB_CONTEXT_FLAG) && | |
| 570 | − ((command = fib->callback_data)) && | |
| 571 | − (command->device == cmd->device)) { | |
| 572 | − fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT; | |
| 573 | − command->SCp.phase = AAC_OWNER_ERROR_HANDLER; | |
| 574 | − if (command == cmd) | |
| 672 | + | |
| 673 | + if (ret != SUCCESS) | |
| 674 | + pr_err("%s: Host adapter abort request timed out\n", | |
| 675 | + AAC_DRIVERNAME); | |
| 676 | + } else { | |
| 677 | + pr_err( | |
| 678 | + "%s: Host adapter abort request.\n" | |
| 679 | + "%s: Outstanding commands on (%d,%d,%d,%d):\n", | |
| 680 | + AAC_DRIVERNAME, AAC_DRIVERNAME, | |
| 681 | + host->host_no, sdev_channel(dev), sdev_id(dev), | |
| 682 | + (int)dev->lun); | |
| 683 | + switch (cmd->cmnd[0]) { | |
| 684 | + case SERVICE_ACTION_IN_16: | |
| 685 | + if (!(aac->raw_io_interface) || | |
| 686 | + !(aac->raw_io_64) || | |
| 687 | + ((cmd->cmnd[1] & 0x1f) != SAI_READ_CAPACITY_16)) | |
| 688 | + break; | |
| 689 | + case INQUIRY: | |
| 690 | + case READ_CAPACITY: | |
| 691 | + /* | |
| 692 | + * Mark associated FIB to not complete, | |
| 693 | + * eh handler does this | |
| 694 | + */ | |
| 695 | + for (count = 0; | |
| 696 | + count < (host->can_queue + AAC_NUM_MGT_FIB); | |
| 697 | + ++count) { | |
| 698 | + struct fib *fib = &aac->fibs[count]; | |
| 699 | + | |
| 700 | + if (fib->hw_fib_va->header.XferState && | |
| 701 | + (fib->flags & FIB_CONTEXT_FLAG) && | |
| 702 | + (fib->callback_data == cmd)) { | |
| 703 | + fib->flags |= | |
| 704 | + FIB_CONTEXT_FLAG_TIMED_OUT; | |
| 705 | + cmd->SCp.phase = | |
| 706 | + AAC_OWNER_ERROR_HANDLER; | |
| 575 | 707 | ret = SUCCESS; |
| 708 | + } | |
| 709 | + } | |
| 710 | + break; | |
| 711 | + case TEST_UNIT_READY: | |
| 712 | + /* | |
| 713 | + * Mark associated FIB to not complete, | |
| 714 | + * eh handler does this | |
| 715 | + */ | |
| 716 | + for (count = 0; | |
| 717 | + count < (host->can_queue + AAC_NUM_MGT_FIB); | |
| 718 | + ++count) { | |
| 719 | + struct scsi_cmnd *command; | |
| 720 | + struct fib *fib = &aac->fibs[count]; | |
| 721 | + | |
| 722 | + command = fib->callback_data; | |
| 723 | + | |
| 724 | + if ((fib->hw_fib_va->header.XferState & | |
| 725 | + cpu_to_le32 | |
| 726 | + (Async | NoResponseExpected)) && | |
| 727 | + (fib->flags & FIB_CONTEXT_FLAG) && | |
| 728 | + ((command)) && | |
| 729 | + (command->device == cmd->device)) { | |
| 730 | + fib->flags |= | |
| 731 | + FIB_CONTEXT_FLAG_TIMED_OUT; | |
| 732 | + command->SCp.phase = | |
| 733 | + AAC_OWNER_ERROR_HANDLER; | |
| 734 | + if (command == cmd) | |
| 735 | + ret = SUCCESS; | |
| 736 | + } | |
| 576 | 737 | } |
| 738 | + break; | |
| 577 | 739 | } |
| 578 | 740 | } |
| 579 | 741 | return ret; |
| @@ -588,70 +750,165 @@ static int aac_eh_reset(struct scsi_cmnd* cmd) · 8 unmodified lines | ||
| 588 | 750 | { |
| 589 | 751 | struct scsi_device * dev = cmd->device; |
| 590 | 752 | struct Scsi_Host * host = dev->host; |
| 591 | − struct scsi_cmnd * command; | |
| 592 | − int count; | |
| 593 | 753 | struct aac_dev * aac = (struct aac_dev *)host->hostdata; |
| 594 | − unsigned long flags; | |
| 595 | − | |
| 596 | − /* Mark the associated FIB to not complete, eh handler does this */ | |
| 597 | − for (count = 0; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) { | |
| 598 | − struct fib * fib = &aac->fibs[count]; | |
| 599 | − if (fib->hw_fib_va->header.XferState && | |
| 600 | − (fib->flags & FIB_CONTEXT_FLAG) && | |
| 601 | − (fib->callback_data == cmd)) { | |
| 602 | − fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT; | |
| 603 | − cmd->SCp.phase = AAC_OWNER_ERROR_HANDLER; | |
| 754 | + int count; | |
| 755 | + u32 bus, cid; | |
| 756 | + int ret = FAILED; | |
| 757 | + | |
| 758 | + bus = aac_logical_to_phys(scmd_channel(cmd)); | |
| 759 | + cid = scmd_id(cmd); | |
| 760 | + if (bus < AAC_MAX_BUSES && cid < AAC_MAX_TARGETS && | |
| 761 | + aac->hba_map[bus][cid].devtype == AAC_DEVTYPE_NATIVE_RAW) { | |
| 762 | + struct fib *fib; | |
| 763 | + int status; | |
| 764 | + u64 address; | |
| 765 | + u8 command; | |
| 766 | + | |
| 767 | + pr_err("%s: Host adapter reset request. SCSI hang ?\n", | |
| 768 | + AAC_DRIVERNAME); | |
| 769 | + | |
| 770 | + fib = aac_fib_alloc(aac); | |
| 771 | + if (!fib) | |
| 772 | + return ret; | |
| 773 | + | |
| 774 | + | |
| 775 | + if (aac->hba_map[bus][cid].reset_state == 0) { | |
| 776 | + struct aac_hba_tm_req *tmf; | |
| 777 | + | |
| 778 | + /* start a HBA_TMF_LUN_RESET TMF request */ | |
| 779 | + tmf = (struct aac_hba_tm_req *)fib->hw_fib_va; | |
| 780 | + memset(tmf, 0, sizeof(*tmf)); | |
| 781 | + tmf->tmf = HBA_TMF_LUN_RESET; | |
| 782 | + tmf->it_nexus = aac->hba_map[bus][cid].rmw_nexus; | |
| 783 | + tmf->lun[1] = cmd->device->lun; | |
| 784 | + | |
| 785 | + address = (u64)fib->hw_error_pa; | |
| 786 | + tmf->error_ptr_hi = cpu_to_le32 | |
| 787 | + ((u32)(address >> 32)); | |
| 788 | + tmf->error_ptr_lo = cpu_to_le32 | |
| 789 | + ((u32)(address & 0xffffffff)); | |
| 790 | + tmf->error_length = cpu_to_le32(FW_ERROR_BUFFER_SIZE); | |
| 791 | + fib->hbacmd_size = sizeof(*tmf); | |
| 792 | + | |
| 793 | + command = HBA_IU_TYPE_SCSI_TM_REQ; | |
| 794 | + aac->hba_map[bus][cid].reset_state++; | |
| 795 | + } else if (aac->hba_map[bus][cid].reset_state >= 1) { | |
| 796 | + struct aac_hba_reset_req *rst; | |
| 797 | + | |
| 798 | + /* already tried, start a hard reset now */ | |
| 799 | + rst = (struct aac_hba_reset_req *)fib->hw_fib_va; | |
| 800 | + memset(rst, 0, sizeof(*rst)); | |
| 801 | + /* reset_type is already zero... */ | |
| 802 | + rst->it_nexus = aac->hba_map[bus][cid].rmw_nexus; | |
| 803 | + | |
| 804 | + address = (u64)fib->hw_error_pa; | |
| 805 | + rst->error_ptr_hi = cpu_to_le32((u32)(address >> 32)); | |
| 806 | + rst->error_ptr_lo = cpu_to_le32 | |
| 807 | + ((u32)(address & 0xffffffff)); | |
| 808 | + rst->error_length = cpu_to_le32(FW_ERROR_BUFFER_SIZE); | |
| 809 | + fib->hbacmd_size = sizeof(*rst); | |
| 810 | + | |
| 811 | + command = HBA_IU_TYPE_SATA_REQ; | |
| 812 | + aac->hba_map[bus][cid].reset_state = 0; | |
| 604 | 813 | } |
| 605 | − } | |
| 606 | − printk(KERN_ERR "%s: Host adapter reset request. SCSI hang ?\n", | |
| 607 | − AAC_DRIVERNAME); | |
| 814 | + cmd->SCp.sent_command = 0; | |
| 608 | 815 | |
| 609 | − if ((count = aac_check_health(aac))) | |
| 610 | − return count; | |
| 611 | − /* | |
| 612 | − * Wait for all commands to complete to this specific | |
| 613 | − * target (block maximum 60 seconds). | |
| 614 | − */ | |
| 615 | − for (count = 60; count; --count) { | |
| 616 | − int active = aac->in_reset; | |
| 816 | + status = aac_hba_send(command, fib, | |
| 817 | + (fib_callback) aac_hba_callback, | |
| 818 | + (void *) cmd); | |
| 617 | 819 | |
| 618 | − if (active == 0) | |
| 619 | − __shost_for_each_device(dev, host) { | |
| 620 | − spin_lock_irqsave(&dev->list_lock, flags); | |
| 621 | − list_for_each_entry(command, &dev->cmd_list, list) { | |
| 622 | − if ((command != cmd) && | |
| 623 | − (command->SCp.phase == AAC_OWNER_FIRMWARE)) { | |
| 624 | − active++; | |
| 625 | − break; | |
| 626 | − } | |
| 627 | − } | |
| 628 | − spin_unlock_irqrestore(&dev->list_lock, flags); | |
| 629 | − if (active) | |
| 820 | + /* Wait up to 2 minutes for completion */ | |
| 821 | + for (count = 0; count < 120; ++count) { | |
| 822 | + if (cmd->SCp.sent_command) { | |
| 823 | + ret = SUCCESS; | |
| 630 | 824 | break; |
| 825 | + } | |
| 826 | + msleep(1000); | |
| 827 | + } | |
| 631 | 828 | |
| 829 | + if (ret != SUCCESS) | |
| 830 | + pr_err("%s: Host adapter reset request timed out\n", | |
| 831 | + AAC_DRIVERNAME); | |
| 832 | + } else { | |
| 833 | + struct scsi_cmnd *command; | |
| 834 | + unsigned long flags; | |
| 835 | + | |
| 836 | + /* Mark the assoc. FIB to not complete, eh handler does this */ | |
| 837 | + for (count = 0; | |
| 838 | + count < (host->can_queue + AAC_NUM_MGT_FIB); | |
| 839 | + ++count) { | |
| 840 | + struct fib *fib = &aac->fibs[count]; | |
| 841 | + | |
| 842 | + if (fib->hw_fib_va->header.XferState && | |
| 843 | + (fib->flags & FIB_CONTEXT_FLAG) && | |
| 844 | + (fib->callback_data == cmd)) { | |
| 845 | + fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT; | |
| 846 | + cmd->SCp.phase = AAC_OWNER_ERROR_HANDLER; | |
| 847 | + } | |
| 632 | 848 | } |
| 849 | + | |
| 850 | + pr_err("%s: Host adapter reset request. SCSI hang ?\n", | |
| 851 | + AAC_DRIVERNAME); | |
| 852 | + | |
| 853 | + count = aac_check_health(aac); | |
| 854 | + if (count) | |
| 855 | + return count; | |
| 633 | 856 | /* |
| 634 | − * We can exit If all the commands are complete | |
| 857 | + * Wait for all commands to complete to this specific | |
| 858 | + * target (block maximum 60 seconds). | |
| 635 | 859 | */ |
| 636 | − if (active == 0) | |
| 637 | − return SUCCESS; | |
| 638 | − ssleep(1); | |
| 860 | + for (count = 60; count; --count) { | |
| 861 | + int active = aac->in_reset; | |
| 862 | + | |
| 863 | + if (active == 0) | |
| 864 | + __shost_for_each_device(dev, host) { | |
| 865 | + spin_lock_irqsave(&dev->list_lock, flags); | |
| 866 | + list_for_each_entry(command, &dev->cmd_list, | |
| 867 | + list) { | |
| 868 | + if ((command != cmd) && | |
| 869 | + (command->SCp.phase == | |
| 870 | + AAC_OWNER_FIRMWARE)) { | |
| 871 | + active++; | |
| 872 | + break; | |
| 873 | + } | |
| 874 | + } | |
| 875 | + spin_unlock_irqrestore(&dev->list_lock, flags); | |
| 876 | + if (active) | |
| 877 | + break; | |
| 878 | + | |
| 879 | + } | |
| 880 | + /* | |
| 881 | + * We can exit If all the commands are complete | |
| 882 | + */ | |
| 883 | + if (active == 0) | |
| 884 | + return SUCCESS; | |
| 885 | + ssleep(1); | |
| 886 | + } | |
| 887 | + pr_err("%s: SCSI bus appears hung\n", AAC_DRIVERNAME); | |
| 888 | + | |
| 889 | + /* | |
| 890 | + * This adapter needs a blind reset, only do so for | |
| 891 | + * Adapters that support a register, instead of a commanded, | |
| 892 | + * reset. | |
| 893 | + */ | |
| 894 | + if (((aac->supplement_adapter_info.SupportedOptions2 & | |
| 895 | + AAC_OPTION_MU_RESET) || | |
| 896 | + (aac->supplement_adapter_info.SupportedOptions2 & | |
| 897 | + AAC_OPTION_DOORBELL_RESET)) && | |
| 898 | + aac_check_reset && | |
| 899 | + ((aac_check_reset != 1) || | |
| 900 | + !(aac->supplement_adapter_info.SupportedOptions2 & | |
| 901 | + AAC_OPTION_IGNORE_RESET))) { | |
| 902 | + /* Bypass wait for command quiesce */ | |
| 903 | + aac_reset_adapter(aac, 2, IOP_HWSOFT_RESET); | |
| 904 | + } | |
| 905 | + ret = SUCCESS; | |
| 639 | 906 | } |
| 640 | − printk(KERN_ERR "%s: SCSI bus appears hung\n", AAC_DRIVERNAME); | |
| 641 | 907 | /* |
| 642 | − * This adapter needs a blind reset, only do so for Adapters that | |
| 643 | − * support a register, instead of a commanded, reset. | |
| 908 | + * Cause an immediate retry of the command with a ten second delay | |
| 909 | + * after successful tur | |
| 644 | 910 | */ |
| 645 | − if (((aac->supplement_adapter_info.SupportedOptions2 & | |
| 646 | − AAC_OPTION_MU_RESET) || | |
| 647 | − (aac->supplement_adapter_info.SupportedOptions2 & | |
| 648 | − AAC_OPTION_DOORBELL_RESET)) && | |
| 649 | − aac_check_reset && | |
| 650 | − ((aac_check_reset != 1) || | |
| 651 | − !(aac->supplement_adapter_info.SupportedOptions2 & | |
| 652 | − AAC_OPTION_IGNORE_RESET))) | |
| 653 | − aac_reset_adapter(aac, 2); /* Bypass wait for command quiesce */ | |
| 654 | − return SUCCESS; /* Cause an immediate retry of the command with a ten second delay after successful tur */ | |
| 911 | + return ret; | |
| 655 | 912 | } |
| 656 | 913 | |
| 657 | 914 | /** |
| @@ -911,10 +1168,16 @@ static ssize_t aac_store_reset_adapter(struct device *device, · 253 unmodified lines | ||
| 911 | 1168 | const char *buf, size_t count) |
| 912 | 1169 | { |
| 913 | 1170 | int retval = -EACCES; |
| 1171 | + int bled = 0; | |
| 1172 | + struct aac_dev *aac; | |
| 1173 | + | |
| 914 | 1174 | |
| 915 | 1175 | if (!capable(CAP_SYS_ADMIN)) |
| 916 | 1176 | return retval; |
| 917 | − retval = aac_reset_adapter((struct aac_dev*)class_to_shost(device)->hostdata, buf[0] == '!'); | |
| 1177 | + | |
| 1178 | + aac = (struct aac_dev *)class_to_shost(device)->hostdata; | |
| 1179 | + bled = buf[0] == '!' ? 1:0; | |
| 1180 | + retval = aac_reset_adapter(aac, bled, IOP_HWSOFT_RESET); | |
| 918 | 1181 | if (retval >= 0) |
| 919 | 1182 | retval = count; |
| 920 | 1183 | return retval; |
| @@ -1070,6 +1333,7 @@ static void __aac_shutdown(struct aac_dev * aac) · 149 unmodified lines | ||
| 1070 | 1333 | { |
| 1071 | 1334 | int i; |
| 1072 | 1335 | |
| 1336 | + aac->adapter_shutdown = 1; | |
| 1073 | 1337 | aac_send_shutdown(aac); |
| 1074 | 1338 | |
| 1075 | 1339 | if (aac->aif_thread) { |
| @@ -1285,7 +1549,7 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) · 209 unmodified lines | ||
| 1285 | 1549 | else |
| 1286 | 1550 | shost->this_id = shost->max_id; |
| 1287 | 1551 | |
| 1288 | − if (aac_drivers[index].quirks & AAC_QUIRK_SRC) | |
| 1552 | + if (!aac->sa_firmware && aac_drivers[index].quirks & AAC_QUIRK_SRC) | |
| 1289 | 1553 | aac_intr_normal(aac, 0, 2, 0, NULL); |
| 1290 | 1554 | |
| 1291 | 1555 | /* |
| @@ -1327,35 +1591,12 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) · 35 unmodified lines | ||
| 1327 | 1591 | |
| 1328 | 1592 | static void aac_release_resources(struct aac_dev *aac) |
| 1329 | 1593 | { |
| 1330 | − int i; | |
| 1331 | − | |
| 1332 | 1594 | aac_adapter_disable_int(aac); |
| 1333 | − if (aac->pdev->device == PMC_DEVICE_S6 || | |
| 1334 | − aac->pdev->device == PMC_DEVICE_S7 || | |
| 1335 | − aac->pdev->device == PMC_DEVICE_S8 || | |
| 1336 | − aac->pdev->device == PMC_DEVICE_S9) { | |
| 1337 | − if (aac->max_msix > 1) { | |
| 1338 | − for (i = 0; i < aac->max_msix; i++) | |
| 1339 | − free_irq(pci_irq_vector(aac->pdev, i), | |
| 1340 | − &(aac->aac_msix[i])); | |
| 1341 | − } else { | |
| 1342 | − free_irq(aac->pdev->irq, &(aac->aac_msix[0])); | |
| 1343 | − } | |
| 1344 | − } else { | |
| 1345 | − free_irq(aac->pdev->irq, aac); | |
| 1346 | − } | |
| 1347 | − if (aac->msi) | |
| 1348 | − pci_disable_msi(aac->pdev); | |
| 1349 | − else if (aac->max_msix > 1) | |
| 1350 | − pci_disable_msix(aac->pdev); | |
| 1351 | − | |
| 1595 | + aac_free_irq(aac); | |
| 1352 | 1596 | } |
| 1353 | 1597 | |
| 1354 | 1598 | static int aac_acquire_resources(struct aac_dev *dev) |
| 1355 | 1599 | { |
| 1356 | − int i, j; | |
| 1357 | − int instance = dev->id; | |
| 1358 | − const char *name = dev->name; | |
| 1359 | 1600 | unsigned long status; |
| 1360 | 1601 | /* |
| 1361 | 1602 | * First clear out all interrupts. Then enable the one's that we |
| @@ -1377,37 +1618,8 @@ static int aac_acquire_resources(struct aac_dev *dev) · 15 unmodified lines | ||
| 1377 | 1618 | if (dev->msi_enabled) |
| 1378 | 1619 | aac_src_access_devreg(dev, AAC_ENABLE_MSIX); |
| 1379 | 1620 | |
| 1380 | − if (!dev->sync_mode && dev->msi_enabled && dev->max_msix > 1) { | |
| 1381 | − for (i = 0; i < dev->max_msix; i++) { | |
| 1382 | − dev->aac_msix[i].vector_no = i; | |
| 1383 | − dev->aac_msix[i].dev = dev; | |
| 1384 | − | |
| 1385 | − if (request_irq(pci_irq_vector(dev->pdev, i), | |
| 1386 | − dev->a_ops.adapter_intr, | |
| 1387 | − 0, "aacraid", &(dev->aac_msix[i]))) { | |
| 1388 | − printk(KERN_ERR "%s%d: Failed to register IRQ for vector %d.\n", | |
| 1389 | − name, instance, i); | |
| 1390 | − for (j = 0 ; j < i ; j++) | |
| 1391 | − free_irq(pci_irq_vector(dev->pdev, j), | |
| 1392 | − &(dev->aac_msix[j])); | |
| 1393 | − pci_disable_msix(dev->pdev); | |
| 1394 | − goto error_iounmap; | |
| 1395 | − } | |
| 1396 | − } | |
| 1397 | − } else { | |
| 1398 | − dev->aac_msix[0].vector_no = 0; | |
| 1399 | − dev->aac_msix[0].dev = dev; | |
| 1400 | − | |
| 1401 | − if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr, | |
| 1402 | − IRQF_SHARED, "aacraid", | |
| 1403 | − &(dev->aac_msix[0])) < 0) { | |
| 1404 | − if (dev->msi) | |
| 1405 | − pci_disable_msi(dev->pdev); | |
| 1406 | − printk(KERN_ERR "%s%d: Interrupt unavailable.\n", | |
| 1407 | − name, instance); | |
| 1408 | − goto error_iounmap; | |
| 1409 | − } | |
| 1410 | − } | |
| 1621 | + if (aac_acquire_irq(dev)) | |
| 1622 | + goto error_iounmap; | |
| 1411 | 1623 | |
| 1412 | 1624 | aac_adapter_enable_int(dev); |
| 1413 | 1625 | |
| @@ -1420,7 +1632,7 @@ static int aac_acquire_resources(struct aac_dev *dev) · 6 unmodified lines | ||
| 1420 | 1632 | /* After EEH recovery or suspend resume, max_msix count |
| 1421 | 1633 | * may change, therfore updating in init as well. |
| 1422 | 1634 | */ |
| 1423 | − dev->init->Sa_MSIXVectors = cpu_to_le32(dev->max_msix); | |
| 1635 | + dev->init->r7.no_of_msix_vectors = cpu_to_le32(dev->max_msix); | |
| 1424 | 1636 | aac_adapter_start(dev); |
| 1425 | 1637 | } |
| 1426 | 1638 | return 0; |
| @@ -5,7 +5,8 @@ · 4 unmodified lines | ||
| 5 | 5 | * Adaptec aacraid device driver for Linux. |
| 6 | 6 | * |
| 7 | 7 | * Copyright (c) 2000-2010 Adaptec, Inc. |
| 8 | − * 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | |
| 8 | + * 2010-2015 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | |
| 9 | + * 2016-2017 Microsemi Corp. (aacraid@microsemi.com) | |
| 9 | 10 | * |
| 10 | 11 | * This program is free software; you can redistribute it and/or modify |
| 11 | 12 | * it under the terms of the GNU General Public License as published by |
| @@ -6,7 +6,8 @@ · 5 unmodified lines | ||
| 6 | 6 | * Adaptec aacraid device driver for Linux. |
| 7 | 7 | * |
| 8 | 8 | * Copyright (c) 2000-2010 Adaptec, Inc. |
| 9 | − * 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | |
| 9 | + * 2010-2015 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | |
| 10 | + * 2016-2017 Microsemi Corp. (aacraid@microsemi.com) | |
| 10 | 11 | * |
| 11 | 12 | * This program is free software; you can redistribute it and/or modify |
| 12 | 13 | * it under the terms of the GNU General Public License as published by |
| @@ -60,7 +61,7 @@ static int aac_rkt_select_comm(struct aac_dev *dev, int comm) · 47 unmodified lines | ||
| 60 | 61 | * case warrants this half baked, but convenient, check here. |
| 61 | 62 | */ |
| 62 | 63 | if (dev->scsi_host_ptr->can_queue > AAC_NUM_IO_FIB_RKT) { |
| 63 | − dev->init->MaxIoCommands = | |
| 64 | + dev->init->r7.max_io_commands = | |
| 64 | 65 | cpu_to_le32(AAC_NUM_IO_FIB_RKT + AAC_NUM_MGT_FIB); |
| 65 | 66 | dev->scsi_host_ptr->can_queue = AAC_NUM_IO_FIB_RKT; |
| 66 | 67 | } |
| @@ -6,7 +6,8 @@ · 5 unmodified lines | ||
| 6 | 6 | * Adaptec aacraid device driver for Linux. |
| 7 | 7 | * |
| 8 | 8 | * Copyright (c) 2000-2010 Adaptec, Inc. |
| 9 | − * 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | |
| 9 | + * 2010-2015 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | |
| 10 | + * 2016-2017 Microsemi Corp. (aacraid@microsemi.com) | |
| 10 | 11 | * |
| 11 | 12 | * This program is free software; you can redistribute it and/or modify |
| 12 | 13 | * it under the terms of the GNU General Public License as published by |
| @@ -315,10 +316,10 @@ static void aac_rx_notify_adapter(struct aac_dev *dev, u32 event) · 302 unmodified lines | ||
| 315 | 316 | |
| 316 | 317 | static void aac_rx_start_adapter(struct aac_dev *dev) |
| 317 | 318 | { |
| 318 | − struct aac_init *init; | |
| 319 | + union aac_init *init; | |
| 319 | 320 | |
| 320 | 321 | init = dev->init; |
| 321 | − init->HostElapsedSeconds = cpu_to_le32(get_seconds()); | |
| 322 | + init->r7.host_elapsed_seconds = cpu_to_le32(get_seconds()); | |
| 322 | 323 | // We can only use a 32 bit address here |
| 323 | 324 | rx_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, |
| 324 | 325 | 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL); |
| @@ -470,7 +471,7 @@ static int aac_rx_ioremap(struct aac_dev * dev, u32 size) · 145 unmodified lines | ||
| 470 | 471 | return 0; |
| 471 | 472 | } |
| 472 | 473 | |
| 473 | −static int aac_rx_restart_adapter(struct aac_dev *dev, int bled) | |
| 474 | +static int aac_rx_restart_adapter(struct aac_dev *dev, int bled, u8 reset_type) | |
| 474 | 475 | { |
| 475 | 476 | u32 var = 0; |
| 476 | 477 | |
| @@ -559,7 +560,7 @@ int _aac_rx_init(struct aac_dev *dev) · 82 unmodified lines | ||
| 559 | 560 | dev->a_ops.adapter_enable_int = aac_rx_disable_interrupt; |
| 560 | 561 | dev->OIMR = status = rx_readb (dev, MUnit.OIMR); |
| 561 | 562 | if ((((status & 0x0c) != 0x0c) || aac_reset_devices || reset_devices) && |
| 562 | − !aac_rx_restart_adapter(dev, 0)) | |
| 563 | + !aac_rx_restart_adapter(dev, 0, IOP_HWSOFT_RESET)) | |
| 563 | 564 | /* Make sure the Hardware FIFO is empty */ |
| 564 | 565 | while ((++restart < 512) && |
| 565 | 566 | (rx_readl(dev, MUnit.OutboundQueue) != 0xFFFFFFFFL)); |
| @@ -568,7 +569,8 @@ int _aac_rx_init(struct aac_dev *dev) · 2 unmodified lines | ||
| 568 | 569 | */ |
| 569 | 570 | status = rx_readl(dev, MUnit.OMRx[0]); |
| 570 | 571 | if (status & KERNEL_PANIC) { |
| 571 | − if (aac_rx_restart_adapter(dev, aac_rx_check_health(dev))) | |
| 572 | + if (aac_rx_restart_adapter(dev, | |
| 573 | + aac_rx_check_health(dev), IOP_HWSOFT_RESET)) | |
| 572 | 574 | goto error_iounmap; |
| 573 | 575 | ++restart; |
| 574 | 576 | } |
| @@ -606,7 +608,8 @@ int _aac_rx_init(struct aac_dev *dev) · 31 unmodified lines | ||
| 606 | 608 | ((startup_timeout > 60) |
| 607 | 609 | ? (startup_timeout - 60) |
| 608 | 610 | : (startup_timeout / 2))))) { |
| 609 | − if (likely(!aac_rx_restart_adapter(dev, aac_rx_check_health(dev)))) | |
| 611 | + if (likely(!aac_rx_restart_adapter(dev, | |
| 612 | + aac_rx_check_health(dev), IOP_HWSOFT_RESET))) | |
| 610 | 613 | start = jiffies; |
| 611 | 614 | ++restart; |
| 612 | 615 | } |
| @@ -6,7 +6,8 @@ · 5 unmodified lines | ||
| 6 | 6 | * Adaptec aacraid device driver for Linux. |
| 7 | 7 | * |
| 8 | 8 | * Copyright (c) 2000-2010 Adaptec, Inc. |
| 9 | − * 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | |
| 9 | + * 2010-2015 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | |
| 10 | + * 2016-2017 Microsemi Corp. (aacraid@microsemi.com) | |
| 10 | 11 | * |
| 11 | 12 | * This program is free software; you can redistribute it and/or modify |
| 12 | 13 | * it under the terms of the GNU General Public License as published by |
| @@ -245,19 +246,19 @@ static void aac_sa_interrupt_adapter (struct aac_dev *dev) · 232 unmodified lines | ||
| 245 | 246 | |
| 246 | 247 | static void aac_sa_start_adapter(struct aac_dev *dev) |
| 247 | 248 | { |
| 248 | − struct aac_init *init; | |
| 249 | + union aac_init *init; | |
| 249 | 250 | /* |
| 250 | 251 | * Fill in the remaining pieces of the init. |
| 251 | 252 | */ |
| 252 | 253 | init = dev->init; |
| 253 | − init->HostElapsedSeconds = cpu_to_le32(get_seconds()); | |
| 254 | + init->r7.host_elapsed_seconds = cpu_to_le32(get_seconds()); | |
| 254 | 255 | /* We can only use a 32 bit address here */ |
| 255 | 256 | sa_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, |
| 256 | 257 | (u32)(ulong)dev->init_pa, 0, 0, 0, 0, 0, |
| 257 | 258 | NULL, NULL, NULL, NULL, NULL); |
| 258 | 259 | } |
| 259 | 260 | |
| 260 | −static int aac_sa_restart_adapter(struct aac_dev *dev, int bled) | |
| 261 | +static int aac_sa_restart_adapter(struct aac_dev *dev, int bled, u8 reset_type) | |
| 261 | 262 | { |
| 262 | 263 | return -EINVAL; |
| 263 | 264 | } |
| @@ -6,7 +6,8 @@ · 5 unmodified lines | ||
| 6 | 6 | * Adaptec aacraid device driver for Linux. |
| 7 | 7 | * |
| 8 | 8 | * Copyright (c) 2000-2010 Adaptec, Inc. |
| 9 | − * 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | |
| 9 | + * 2010-2015 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | |
| 10 | + * 2016-2017 Microsemi Corp. (aacraid@microsemi.com) | |
| 10 | 11 | * |
| 11 | 12 | * This program is free software; you can redistribute it and/or modify |
| 12 | 13 | * it under the terms of the GNU General Public License as published by |
| @@ -135,8 +136,16 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id) · 122 unmodified lines | ||
| 135 | 136 | |
| 136 | 137 | if (mode & AAC_INT_MODE_AIF) { |
| 137 | 138 | /* handle AIF */ |
| 138 | − if (dev->aif_thread && dev->fsa_dev) | |
| 139 | − aac_intr_normal(dev, 0, 2, 0, NULL); | |
| 139 | + if (dev->sa_firmware) { | |
| 140 | + u32 events = src_readl(dev, MUnit.SCR0); | |
| 141 | + | |
| 142 | + aac_intr_normal(dev, events, 1, 0, NULL); | |
| 143 | + writel(events, &dev->IndexRegs->Mailbox[0]); | |
| 144 | + src_writel(dev, MUnit.IDR, 1 << 23); | |
| 145 | + } else { | |
| 146 | + if (dev->aif_thread && dev->fsa_dev) | |
| 147 | + aac_intr_normal(dev, 0, 2, 0, NULL); | |
| 148 | + } | |
| 140 | 149 | if (dev->msi_enabled) |
| 141 | 150 | aac_src_access_devreg(dev, AAC_CLEAR_AIF_BIT); |
| 142 | 151 | mode = 0; |
| @@ -148,17 +157,19 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id) · 5 unmodified lines | ||
| 148 | 157 | for (;;) { |
| 149 | 158 | isFastResponse = 0; |
| 150 | 159 | /* remove toggle bit (31) */ |
| 151 | − handle = (dev->host_rrq[index] & 0x7fffffff); | |
| 152 | − /* check fast response bit (30) */ | |
| 160 | + handle = le32_to_cpu((dev->host_rrq[index]) | |
| 161 | + & 0x7fffffff); | |
| 162 | + /* check fast response bits (30, 1) */ | |
| 153 | 163 | if (handle & 0x40000000) |
| 154 | 164 | isFastResponse = 1; |
| 155 | 165 | handle &= 0x0000ffff; |
| 156 | 166 | if (handle == 0) |
| 157 | 167 | break; |
| 168 | + handle >>= 2; | |
| 158 | 169 | if (dev->msi_enabled && dev->max_msix > 1) |
| 159 | 170 | atomic_dec(&dev->rrq_outstanding[vector_no]); |
| 171 | + aac_intr_normal(dev, handle, 0, isFastResponse, NULL); | |
| 160 | 172 | dev->host_rrq[index++] = 0; |
| 161 | − aac_intr_normal(dev, handle-1, 0, isFastResponse, NULL); | |
| 162 | 173 | if (index == (vector_no + 1) * dev->vector_cap) |
| 163 | 174 | index = vector_no * dev->vector_cap; |
| 164 | 175 | dev->host_rrq_idx[vector_no] = index; |
| @@ -384,7 +395,7 @@ static void aac_src_notify_adapter(struct aac_dev *dev, u32 event) · 219 unmodified lines | ||
| 384 | 395 | |
| 385 | 396 | static void aac_src_start_adapter(struct aac_dev *dev) |
| 386 | 397 | { |
| 387 | − struct aac_init *init; | |
| 398 | + union aac_init *init; | |
| 388 | 399 | int i; |
| 389 | 400 | |
| 390 | 401 | /* reset host_rrq_idx first */ |
| @@ -392,14 +403,26 @@ static void aac_src_start_adapter(struct aac_dev *dev) · 1 unmodified line | ||
| 392 | 403 | dev->host_rrq_idx[i] = i * dev->vector_cap; |
| 393 | 404 | atomic_set(&dev->rrq_outstanding[i], 0); |
| 394 | 405 | } |
| 406 | + atomic_set(&dev->msix_counter, 0); | |
| 395 | 407 | dev->fibs_pushed_no = 0; |
| 396 | 408 | |
| 397 | 409 | init = dev->init; |
| 398 | − init->HostElapsedSeconds = cpu_to_le32(get_seconds()); | |
| 410 | + if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE3) { | |
| 411 | + init->r8.host_elapsed_seconds = cpu_to_le32(get_seconds()); | |
| 412 | + src_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, | |
| 413 | + lower_32_bits(dev->init_pa), | |
| 414 | + upper_32_bits(dev->init_pa), | |
| 415 | + sizeof(struct _r8) + | |
| 416 | + (AAC_MAX_HRRQ - 1) * sizeof(struct _rrq), | |
| 417 | + 0, 0, 0, NULL, NULL, NULL, NULL, NULL); | |
| 418 | + } else { | |
| 419 | + init->r7.host_elapsed_seconds = cpu_to_le32(get_seconds()); | |
| 420 | + // We can only use a 32 bit address here | |
| 421 | + src_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, | |
| 422 | + (u32)(ulong)dev->init_pa, 0, 0, 0, 0, 0, | |
| 423 | + NULL, NULL, NULL, NULL, NULL); | |
| 424 | + } | |
| 399 | 425 | |
| 400 | − /* We can only use a 32 bit address here */ | |
| 401 | − src_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, | |
| 402 | − 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL); | |
| 403 | 426 | } |
| 404 | 427 | |
| 405 | 428 | /** |
| @@ -435,6 +458,11 @@ static int aac_src_check_health(struct aac_dev *dev) · 29 unmodified lines | ||
| 435 | 458 | return 0; |
| 436 | 459 | } |
| 437 | 460 | |
| 461 | +static inline u32 aac_get_vector(struct aac_dev *dev) | |
| 462 | +{ | |
| 463 | + return atomic_inc_return(&dev->msix_counter)%dev->max_msix; | |
| 464 | +} | |
| 465 | + | |
| 438 | 466 | /** |
| 439 | 467 | * aac_src_deliver_message |
| 440 | 468 | * @fib: fib to issue |
| @@ -448,66 +476,125 @@ static int aac_src_deliver_message(struct fib *fib) · 7 unmodified lines | ||
| 448 | 476 | u32 fibsize; |
| 449 | 477 | dma_addr_t address; |
| 450 | 478 | struct aac_fib_xporthdr *pFibX; |
| 479 | + int native_hba; | |
| 451 | 480 | #if !defined(writeq) |
| 452 | 481 | unsigned long flags; |
| 453 | 482 | #endif |
| 454 | 483 | |
| 455 | − u16 hdr_size = le16_to_cpu(fib->hw_fib_va->header.Size); | |
| 456 | 484 | u16 vector_no; |
| 457 | 485 | |
| 458 | 486 | atomic_inc(&q->numpending); |
| 459 | 487 | |
| 460 | − if (dev->msi_enabled && fib->hw_fib_va->header.Command != AifRequest && | |
| 461 | − dev->max_msix > 1) { | |
| 462 | − vector_no = fib->vector_no; | |
| 463 | − fib->hw_fib_va->header.Handle += (vector_no << 16); | |
| 488 | + native_hba = (fib->flags & FIB_CONTEXT_FLAG_NATIVE_HBA) ? 1 : 0; | |
| 489 | + | |
| 490 | + | |
| 491 | + if (dev->msi_enabled && dev->max_msix > 1 && | |
| 492 | + (native_hba || fib->hw_fib_va->header.Command != AifRequest)) { | |
| 493 | + | |
| 494 | + if ((dev->comm_interface == AAC_COMM_MESSAGE_TYPE3) | |
| 495 | + && dev->sa_firmware) | |
| 496 | + vector_no = aac_get_vector(dev); | |
| 497 | + else | |
| 498 | + vector_no = fib->vector_no; | |
| 499 | + | |
| 500 | + if (native_hba) { | |
| 501 | + if (fib->flags & FIB_CONTEXT_FLAG_NATIVE_HBA_TMF) { | |
| 502 | + struct aac_hba_tm_req *tm_req; | |
| 503 | + | |
| 504 | + tm_req = (struct aac_hba_tm_req *) | |
| 505 | + fib->hw_fib_va; | |
| 506 | + if (tm_req->iu_type == | |
| 507 | + HBA_IU_TYPE_SCSI_TM_REQ) { | |
| 508 | + ((struct aac_hba_tm_req *) | |
| 509 | + fib->hw_fib_va)->reply_qid | |
| 510 | + = vector_no; | |
| 511 | + ((struct aac_hba_tm_req *) | |
| 512 | + fib->hw_fib_va)->request_id | |
| 513 | + += (vector_no << 16); | |
| 514 | + } else { | |
| 515 | + ((struct aac_hba_reset_req *) | |
| 516 | + fib->hw_fib_va)->reply_qid | |
| 517 | + = vector_no; | |
| 518 | + ((struct aac_hba_reset_req *) | |
| 519 | + fib->hw_fib_va)->request_id | |
| 520 | + += (vector_no << 16); | |
| 521 | + } | |
| 522 | + } else { | |
| 523 | + ((struct aac_hba_cmd_req *) | |
| 524 | + fib->hw_fib_va)->reply_qid | |
| 525 | + = vector_no; | |
| 526 | + ((struct aac_hba_cmd_req *) | |
| 527 | + fib->hw_fib_va)->request_id | |
| 528 | + += (vector_no << 16); | |
| 529 | + } | |
| 530 | + } else { | |
| 531 | + fib->hw_fib_va->header.Handle += (vector_no << 16); | |
| 532 | + } | |
| 464 | 533 | } else { |
| 465 | 534 | vector_no = 0; |
| 466 | 535 | } |
| 467 | 536 | |
| 468 | 537 | atomic_inc(&dev->rrq_outstanding[vector_no]); |
| 469 | 538 | |
| 470 | − if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2) { | |
| 471 | − /* Calculate the amount to the fibsize bits */ | |
| 472 | − fibsize = (hdr_size + 127) / 128 - 1; | |
| 473 | − if (fibsize > (ALIGN32 - 1)) | |
| 474 | − return -EMSGSIZE; | |
| 475 | − /* New FIB header, 32-bit */ | |
| 539 | + if (native_hba) { | |
| 476 | 540 | address = fib->hw_fib_pa; |
| 477 | − fib->hw_fib_va->header.StructType = FIB_MAGIC2; | |
| 478 | − fib->hw_fib_va->header.SenderFibAddress = (u32)address; | |
| 479 | − fib->hw_fib_va->header.u.TimeStamp = 0; | |
| 480 | − BUG_ON(upper_32_bits(address) != 0L); | |
| 541 | + fibsize = (fib->hbacmd_size + 127) / 128 - 1; | |
| 542 | + if (fibsize > 31) | |
| 543 | + fibsize = 31; | |
| 481 | 544 | address |= fibsize; |
| 545 | +#if defined(writeq) | |
| 546 | + src_writeq(dev, MUnit.IQN_L, (u64)address); | |
| 547 | +#else | |
| 548 | + spin_lock_irqsave(&fib->dev->iq_lock, flags); | |
| 549 | + src_writel(dev, MUnit.IQN_H, | |
| 550 | + upper_32_bits(address) & 0xffffffff); | |
| 551 | + src_writel(dev, MUnit.IQN_L, address & 0xffffffff); | |
| 552 | + spin_unlock_irqrestore(&fib->dev->iq_lock, flags); | |
| 553 | +#endif | |
| 482 | 554 | } else { |
| 483 | − /* Calculate the amount to the fibsize bits */ | |
| 484 | − fibsize = (sizeof(struct aac_fib_xporthdr) + hdr_size + 127) / 128 - 1; | |
| 485 | − if (fibsize > (ALIGN32 - 1)) | |
| 486 | − return -EMSGSIZE; | |
| 487 | − | |
| 488 | − /* Fill XPORT header */ | |
| 489 | − pFibX = (void *)fib->hw_fib_va - sizeof(struct aac_fib_xporthdr); | |
| 490 | − pFibX->Handle = cpu_to_le32(fib->hw_fib_va->header.Handle); | |
| 491 | − pFibX->HostAddress = cpu_to_le64(fib->hw_fib_pa); | |
| 492 | − pFibX->Size = cpu_to_le32(hdr_size); | |
| 493 | − | |
| 494 | − /* | |
| 495 | − * The xport header has been 32-byte aligned for us so that fibsize | |
| 496 | − * can be masked out of this address by hardware. -- BenC | |
| 497 | − */ | |
| 498 | − address = fib->hw_fib_pa - sizeof(struct aac_fib_xporthdr); | |
| 499 | − if (address & (ALIGN32 - 1)) | |
| 500 | − return -EINVAL; | |
| 555 | + if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2 || | |
| 556 | + dev->comm_interface == AAC_COMM_MESSAGE_TYPE3) { | |
| 557 | + /* Calculate the amount to the fibsize bits */ | |
| 558 | + fibsize = (le16_to_cpu(fib->hw_fib_va->header.Size) | |
| 559 | + + 127) / 128 - 1; | |
| 560 | + /* New FIB header, 32-bit */ | |
| 561 | + address = fib->hw_fib_pa; | |
| 562 | + fib->hw_fib_va->header.StructType = FIB_MAGIC2; | |
| 563 | + fib->hw_fib_va->header.SenderFibAddress = | |
| 564 | + cpu_to_le32((u32)address); | |
| 565 | + fib->hw_fib_va->header.u.TimeStamp = 0; | |
| 566 | + WARN_ON(upper_32_bits(address) != 0L); | |
| 567 | + } else { | |
| 568 | + /* Calculate the amount to the fibsize bits */ | |
| 569 | + fibsize = (sizeof(struct aac_fib_xporthdr) + | |
| 570 | + le16_to_cpu(fib->hw_fib_va->header.Size) | |
| 571 | + + 127) / 128 - 1; | |
| 572 | + /* Fill XPORT header */ | |
| 573 | + pFibX = (struct aac_fib_xporthdr *) | |
| 574 | + ((unsigned char *)fib->hw_fib_va - | |
| 575 | + sizeof(struct aac_fib_xporthdr)); | |
| 576 | + pFibX->Handle = fib->hw_fib_va->header.Handle; | |
| 577 | + pFibX->HostAddress = | |
| 578 | + cpu_to_le64((u64)fib->hw_fib_pa); | |
| 579 | + pFibX->Size = cpu_to_le32( | |
| 580 | + le16_to_cpu(fib->hw_fib_va->header.Size)); | |
| 581 | + address = fib->hw_fib_pa - | |
| 582 | + (u64)sizeof(struct aac_fib_xporthdr); | |
| 583 | + } | |
| 584 | + if (fibsize > 31) | |
| 585 | + fibsize = 31; | |
| 501 | 586 | address |= fibsize; |
| 502 | − } | |
| 587 | + | |
| 503 | 588 | #if defined(writeq) |
| 504 | − src_writeq(dev, MUnit.IQ_L, (u64)address); | |
| 589 | + src_writeq(dev, MUnit.IQ_L, (u64)address); | |
| 505 | 590 | #else |
| 506 | − spin_lock_irqsave(&fib->dev->iq_lock, flags); | |
| 507 | − src_writel(dev, MUnit.IQ_H, upper_32_bits(address) & 0xffffffff); | |
| 508 | − src_writel(dev, MUnit.IQ_L, address & 0xffffffff); | |
| 509 | − spin_unlock_irqrestore(&fib->dev->iq_lock, flags); | |
| 591 | + spin_lock_irqsave(&fib->dev->iq_lock, flags); | |
| 592 | + src_writel(dev, MUnit.IQ_H, | |
| 593 | + upper_32_bits(address) & 0xffffffff); | |
| 594 | + src_writel(dev, MUnit.IQ_L, address & 0xffffffff); | |
| 595 | + spin_unlock_irqrestore(&fib->dev->iq_lock, flags); | |
| 510 | 596 | #endif |
| 597 | + } | |
| 511 | 598 | return 0; |
| 512 | 599 | } |
| 513 | 600 | |
| @@ -553,52 +640,117 @@ static int aac_srcv_ioremap(struct aac_dev *dev, u32 size) · 39 unmodified lines | ||
| 553 | 640 | dev->base = dev->regs.src.bar0 = NULL; |
| 554 | 641 | return 0; |
| 555 | 642 | } |
| 643 | + | |
| 644 | + dev->regs.src.bar1 = | |
| 645 | + ioremap(pci_resource_start(dev->pdev, 2), AAC_MIN_SRCV_BAR1_SIZE); | |
| 646 | + dev->base = NULL; | |
| 647 | + if (dev->regs.src.bar1 == NULL) | |
| 648 | + return -1; | |
| 556 | 649 | dev->base = dev->regs.src.bar0 = ioremap(dev->base_start, size); |
| 557 | − if (dev->base == NULL) | |
| 650 | + if (dev->base == NULL) { | |
| 651 | + iounmap(dev->regs.src.bar1); | |
| 652 | + dev->regs.src.bar1 = NULL; | |
| 558 | 653 | return -1; |
| 654 | + } | |
| 559 | 655 | dev->IndexRegs = &((struct src_registers __iomem *) |
| 560 | 656 | dev->base)->u.denali.IndexRegs; |
| 561 | 657 | return 0; |
| 562 | 658 | } |
| 563 | 659 | |
| 564 | −static int aac_src_restart_adapter(struct aac_dev *dev, int bled) | |
| 660 | +static void aac_set_intx_mode(struct aac_dev *dev) | |
| 661 | +{ | |
| 662 | + if (dev->msi_enabled) { | |
| 663 | + aac_src_access_devreg(dev, AAC_ENABLE_INTX); | |
| 664 | + dev->msi_enabled = 0; | |
| 665 | + msleep(5000); /* Delay 5 seconds */ | |
| 666 | + } | |
| 667 | +} | |
| 668 | + | |
| 669 | +static void aac_send_iop_reset(struct aac_dev *dev, int bled) | |
| 565 | 670 | { |
| 566 | 671 | u32 var, reset_mask; |
| 567 | 672 | |
| 568 | − if (bled >= 0) { | |
| 569 | − if (bled) | |
| 570 | − printk(KERN_ERR "%s%d: adapter kernel panic'd %x.\n", | |
| 673 | + bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS, | |
| 674 | + 0, 0, 0, 0, 0, 0, &var, | |
| 675 | + &reset_mask, NULL, NULL, NULL); | |
| 676 | + | |
| 677 | + if ((bled || var != 0x00000001) && !dev->doorbell_mask) | |
| 678 | + bled = -EINVAL; | |
| 679 | + else if (dev->doorbell_mask) { | |
| 680 | + reset_mask = dev->doorbell_mask; | |
| 681 | + bled = 0; | |
| 682 | + var = 0x00000001; | |
| 683 | + } | |
| 684 | + | |
| 685 | + aac_set_intx_mode(dev); | |
| 686 | + | |
| 687 | + if (!bled && (dev->supplement_adapter_info.SupportedOptions2 & | |
| 688 | + AAC_OPTION_DOORBELL_RESET)) { | |
| 689 | + src_writel(dev, MUnit.IDR, reset_mask); | |
| 690 | + } else { | |
| 691 | + src_writel(dev, MUnit.IDR, 0x100); | |
| 692 | + } | |
| 693 | + msleep(30000); | |
| 694 | +} | |
| 695 | + | |
| 696 | +static void aac_send_hardware_soft_reset(struct aac_dev *dev) | |
| 697 | +{ | |
| 698 | + u_int32_t val; | |
| 699 | + | |
| 700 | + val = readl(((char *)(dev->base) + IBW_SWR_OFFSET)); | |
| 701 | + val |= 0x01; | |
| 702 | + writel(val, ((char *)(dev->base) + IBW_SWR_OFFSET)); | |
| 703 | + msleep_interruptible(20000); | |
| 704 | +} | |
| 705 | + | |
| 706 | +static int aac_src_restart_adapter(struct aac_dev *dev, int bled, u8 reset_type) | |
| 707 | +{ | |
| 708 | + unsigned long status, start; | |
| 709 | + | |
| 710 | + if (bled < 0) | |
| 711 | + goto invalid_out; | |
| 712 | + | |
| 713 | + if (bled) | |
| 714 | + pr_err("%s%d: adapter kernel panic'd %x.\n", | |
| 571 | 715 | dev->name, dev->id, bled); |
| 572 | − dev->a_ops.adapter_enable_int = aac_src_disable_interrupt; | |
| 573 | − bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS, | |
| 574 | − 0, 0, 0, 0, 0, 0, &var, &reset_mask, NULL, NULL, NULL); | |
| 575 | − if ((bled || (var != 0x00000001)) && | |
| 576 | − !dev->doorbell_mask) | |
| 577 | − return -EINVAL; | |
| 578 | − else if (dev->doorbell_mask) { | |
| 579 | − reset_mask = dev->doorbell_mask; | |
| 580 | − bled = 0; | |
| 581 | − var = 0x00000001; | |
| 582 | − } | |
| 583 | 716 | |
| 584 | − if ((dev->pdev->device == PMC_DEVICE_S7 || | |
| 585 | − dev->pdev->device == PMC_DEVICE_S8 || | |
| 586 | − dev->pdev->device == PMC_DEVICE_S9) && dev->msi_enabled) { | |
| 587 | − aac_src_access_devreg(dev, AAC_ENABLE_INTX); | |
| 588 | − dev->msi_enabled = 0; | |
| 589 | − msleep(5000); /* Delay 5 seconds */ | |
| 590 | − } | |
| 717 | + dev->a_ops.adapter_enable_int = aac_src_disable_interrupt; | |
| 591 | 718 | |
| 592 | − if (!bled && (dev->supplement_adapter_info.SupportedOptions2 & | |
| 593 | − AAC_OPTION_DOORBELL_RESET)) { | |
| 594 | − src_writel(dev, MUnit.IDR, reset_mask); | |
| 595 | − ssleep(45); | |
| 596 | − } else { | |
| 597 | − src_writel(dev, MUnit.IDR, 0x100); | |
| 598 | − ssleep(45); | |
| 719 | + switch (reset_type) { | |
| 720 | + case IOP_HWSOFT_RESET: | |
| 721 | + aac_send_iop_reset(dev, bled); | |
| 722 | + /* | |
| 723 | + * Check to see if KERNEL_UP_AND_RUNNING | |
| 724 | + * Wait for the adapter to be up and running. | |
| 725 | + * If !KERNEL_UP_AND_RUNNING issue HW Soft Reset | |
| 726 | + */ | |
| 727 | + status = src_readl(dev, MUnit.OMR); | |
| 728 | + if (dev->sa_firmware | |
| 729 | + && !(status & KERNEL_UP_AND_RUNNING)) { | |
| 730 | + start = jiffies; | |
| 731 | + do { | |
| 732 | + status = src_readl(dev, MUnit.OMR); | |
| 733 | + if (time_after(jiffies, | |
| 734 | + start+HZ*SOFT_RESET_TIME)) { | |
| 735 | + aac_send_hardware_soft_reset(dev); | |
| 736 | + start = jiffies; | |
| 737 | + } | |
| 738 | + } while (!(status & KERNEL_UP_AND_RUNNING)); | |
| 599 | 739 | } |
| 740 | + break; | |
| 741 | + case HW_SOFT_RESET: | |
| 742 | + if (dev->sa_firmware) { | |
| 743 | + aac_send_hardware_soft_reset(dev); | |
| 744 | + aac_set_intx_mode(dev); | |
| 745 | + } | |
| 746 | + break; | |
| 747 | + default: | |
| 748 | + aac_send_iop_reset(dev, bled); | |
| 749 | + break; | |
| 600 | 750 | } |
| 601 | 751 | |
| 752 | +invalid_out: | |
| 753 | + | |
| 602 | 754 | if (src_readl(dev, MUnit.OMR) & KERNEL_PANIC) |
| 603 | 755 | return -ENODEV; |
| 604 | 756 | |
| @@ -653,14 +805,15 @@ int aac_src_init(struct aac_dev *dev) · 48 unmodified lines | ||
| 653 | 805 | dev->a_ops.adapter_sync_cmd = src_sync_cmd; |
| 654 | 806 | dev->a_ops.adapter_enable_int = aac_src_disable_interrupt; |
| 655 | 807 | if ((aac_reset_devices || reset_devices) && |
| 656 | − !aac_src_restart_adapter(dev, 0)) | |
| 808 | + !aac_src_restart_adapter(dev, 0, IOP_HWSOFT_RESET)) | |
| 657 | 809 | ++restart; |
| 658 | 810 | /* |
| 659 | 811 | * Check to see if the board panic'd while booting. |
| 660 | 812 | */ |
| 661 | 813 | status = src_readl(dev, MUnit.OMR); |
| 662 | 814 | if (status & KERNEL_PANIC) { |
| 663 | − if (aac_src_restart_adapter(dev, aac_src_check_health(dev))) | |
| 815 | + if (aac_src_restart_adapter(dev, | |
| 816 | + aac_src_check_health(dev), IOP_HWSOFT_RESET)) | |
| 664 | 817 | goto error_iounmap; |
| 665 | 818 | ++restart; |
| 666 | 819 | } |
| @@ -701,7 +854,7 @@ int aac_src_init(struct aac_dev *dev) · 34 unmodified lines | ||
| 701 | 854 | ? (startup_timeout - 60) |
| 702 | 855 | : (startup_timeout / 2))))) { |
| 703 | 856 | if (likely(!aac_src_restart_adapter(dev, |
| 704 | − aac_src_check_health(dev)))) | |
| 857 | + aac_src_check_health(dev), IOP_HWSOFT_RESET))) | |
| 705 | 858 | start = jiffies; |
| 706 | 859 | ++restart; |
| 707 | 860 | } |
| @@ -798,7 +951,7 @@ int aac_srcv_init(struct aac_dev *dev) · 90 unmodified lines | ||
| 798 | 951 | dev->a_ops.adapter_sync_cmd = src_sync_cmd; |
| 799 | 952 | dev->a_ops.adapter_enable_int = aac_src_disable_interrupt; |
| 800 | 953 | if ((aac_reset_devices || reset_devices) && |
| 801 | − !aac_src_restart_adapter(dev, 0)) | |
| 954 | + !aac_src_restart_adapter(dev, 0, IOP_HWSOFT_RESET)) | |
| 802 | 955 | ++restart; |
| 803 | 956 | /* |
| 804 | 957 | * Check to see if flash update is running. |
| @@ -827,7 +980,8 @@ int aac_srcv_init(struct aac_dev *dev) · 22 unmodified lines | ||
| 827 | 980 | */ |
| 828 | 981 | status = src_readl(dev, MUnit.OMR); |
| 829 | 982 | if (status & KERNEL_PANIC) { |
| 830 | − if (aac_src_restart_adapter(dev, aac_src_check_health(dev))) | |
| 983 | + if (aac_src_restart_adapter(dev, | |
| 984 | + aac_src_check_health(dev), IOP_HWSOFT_RESET)) | |
| 831 | 985 | goto error_iounmap; |
| 832 | 986 | ++restart; |
| 833 | 987 | } |
| @@ -866,7 +1020,8 @@ int aac_srcv_init(struct aac_dev *dev) · 32 unmodified lines | ||
| 866 | 1020 | ((startup_timeout > 60) |
| 867 | 1021 | ? (startup_timeout - 60) |
| 868 | 1022 | : (startup_timeout / 2))))) { |
| 869 | − if (likely(!aac_src_restart_adapter(dev, aac_src_check_health(dev)))) | |
| 1023 | + if (likely(!aac_src_restart_adapter(dev, | |
| 1024 | + aac_src_check_health(dev), IOP_HWSOFT_RESET))) | |
| 870 | 1025 | start = jiffies; |
| 871 | 1026 | ++restart; |
| 872 | 1027 | } |
| @@ -897,7 +1052,8 @@ int aac_srcv_init(struct aac_dev *dev) · 24 unmodified lines | ||
| 897 | 1052 | |
| 898 | 1053 | if (aac_init_adapter(dev) == NULL) |
| 899 | 1054 | goto error_iounmap; |
| 900 | − if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE2) | |
| 1055 | + if ((dev->comm_interface != AAC_COMM_MESSAGE_TYPE2) && | |
| 1056 | + (dev->comm_interface != AAC_COMM_MESSAGE_TYPE3)) | |
| 901 | 1057 | goto error_iounmap; |
| 902 | 1058 | if (dev->msi_enabled) |
| 903 | 1059 | aac_src_access_devreg(dev, AAC_ENABLE_MSIX); |
| @@ -905,9 +1061,9 @@ int aac_srcv_init(struct aac_dev *dev) · 1 unmodified line | ||
| 905 | 1061 | if (aac_acquire_irq(dev)) |
| 906 | 1062 | goto error_iounmap; |
| 907 | 1063 | |
| 908 | − dev->dbg_base = dev->base_start; | |
| 909 | − dev->dbg_base_mapped = dev->base; | |
| 910 | − dev->dbg_size = dev->base_size; | |
| 1064 | + dev->dbg_base = pci_resource_start(dev->pdev, 2); | |
| 1065 | + dev->dbg_base_mapped = dev->regs.src.bar1; | |
| 1066 | + dev->dbg_size = AAC_MIN_SRCV_BAR1_SIZE; | |
| 911 | 1067 | dev->a_ops.adapter_enable_int = aac_src_enable_interrupt_message; |
| 912 | 1068 | |
| 913 | 1069 | aac_adapter_enable_int(dev); |
| @@ -178,37 +178,6 @@ static int scsi_dma_is_ignored_buserr(unsigned char dma_stat) · 177 unmodified lines | ||
| 178 | 178 | } |
| 179 | 179 | |
| 180 | 180 | |
| 181 | −#if 0 | |
| 182 | −/* Dead code... wasn't called anyway :-) and causes some trouble, because at | |
| 183 | − * end-of-DMA, both SCSI ints are triggered simultaneously, so the NCR int has | |
| 184 | − * to clear the DMA int pending bit before it allows other level 6 interrupts. | |
| 185 | − */ | |
| 186 | −static void scsi_dma_buserr(int irq, void *dummy) | |
| 187 | −{ | |
| 188 | − unsigned char dma_stat = tt_scsi_dma.dma_ctrl; | |
| 189 | − | |
| 190 | − /* Don't do anything if a NCR interrupt is pending. Probably it's just | |
| 191 | − * masked... */ | |
| 192 | − if (atari_irq_pending(IRQ_TT_MFP_SCSI)) | |
| 193 | − return; | |
| 194 | − | |
| 195 | − printk("Bad SCSI DMA interrupt! dma_addr=0x%08lx dma_stat=%02x dma_cnt=%08lx\n", | |
| 196 | − SCSI_DMA_READ_P(dma_addr), dma_stat, SCSI_DMA_READ_P(dma_cnt)); | |
| 197 | − if (dma_stat & 0x80) { | |
| 198 | − if (!scsi_dma_is_ignored_buserr(dma_stat)) | |
| 199 | − printk("SCSI DMA bus error -- bad DMA programming!\n"); | |
| 200 | − } else { | |
| 201 | − /* Under normal circumstances we never should get to this point, | |
| 202 | − * since both interrupts are triggered simultaneously and the 5380 | |
| 203 | − * int has higher priority. When this irq is handled, that DMA | |
| 204 | − * interrupt is cleared. So a warning message is printed here. | |
| 205 | − */ | |
| 206 | − printk("SCSI DMA intr ?? -- this shouldn't happen!\n"); | |
| 207 | − } | |
| 208 | −} | |
| 209 | −#endif | |
| 210 | − | |
| 211 | − | |
| 212 | 181 | static irqreturn_t scsi_tt_intr(int irq, void *dev) |
| 213 | 182 | { |
| 214 | 183 | struct Scsi_Host *instance = dev; |
| @@ -713,7 +682,8 @@ static int atari_scsi_bus_reset(struct scsi_cmnd *cmd) · 498 unmodified lines | ||
| 713 | 682 | if (IS_A_TT()) { |
| 714 | 683 | tt_scsi_dma.dma_ctrl = 0; |
| 715 | 684 | } else { |
| 716 | − st_dma.dma_mode_status = 0x90; | |
| 685 | + if (stdma_is_locked_by(scsi_falcon_intr)) | |
| 686 | + st_dma.dma_mode_status = 0x90; | |
| 717 | 687 | atari_dma_active = 0; |
| 718 | 688 | atari_dma_orig_addr = NULL; |
| 719 | 689 | } |
| @@ -813,7 +783,7 @@ static int __init atari_scsi_probe(struct platform_device *pdev) · 93 unmodified lines | ||
| 813 | 783 | return -ENOMEM; |
| 814 | 784 | } |
| 815 | 785 | atari_dma_phys_buffer = atari_stram_to_phys(atari_dma_buffer); |
| 816 | − atari_dma_orig_addr = 0; | |
| 786 | + atari_dma_orig_addr = NULL; | |
| 817 | 787 | } |
| 818 | 788 | |
| 819 | 789 | instance = scsi_host_alloc(&atari_scsi_template, |
| @@ -84,7 +84,6 @@ static inline void queue_tail_inc(struct be_queue_info *q) · 83 unmodified lines | ||
| 84 | 84 | /*ISCSI */ |
| 85 | 85 | |
| 86 | 86 | struct be_aic_obj { /* Adaptive interrupt coalescing (AIC) info */ |
| 87 | − bool enable; | |
| 88 | 87 | u32 min_eqd; /* in usecs */ |
| 89 | 88 | u32 max_eqd; /* in usecs */ |
| 90 | 89 | u32 prev_eqd; /* in usecs */ |
| @@ -94,8 +93,6 @@ struct be_aic_obj { /* Adaptive interrupt coalescing (AIC) info */ · 3 unmodified lines | ||
| 94 | 93 | }; |
| 95 | 94 | |
| 96 | 95 | struct be_eq_obj { |
| 97 | − bool todo_mcc_cq; | |
| 98 | − bool todo_cq; | |
| 99 | 96 | u32 cq_count; |
| 100 | 97 | struct be_queue_info q; |
| 101 | 98 | struct beiscsi_hba *phba; |
| @@ -676,10 +676,10 @@ void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len, · 675 unmodified lines | ||
| 676 | 676 | bool embedded, u8 sge_cnt) |
| 677 | 677 | { |
| 678 | 678 | if (embedded) |
| 679 | − wrb->embedded |= MCC_WRB_EMBEDDED_MASK; | |
| 679 | + wrb->emb_sgecnt_special |= MCC_WRB_EMBEDDED_MASK; | |
| 680 | 680 | else |
| 681 | − wrb->embedded |= (sge_cnt & MCC_WRB_SGE_CNT_MASK) << | |
| 682 | − MCC_WRB_SGE_CNT_SHIFT; | |
| 681 | + wrb->emb_sgecnt_special |= (sge_cnt & MCC_WRB_SGE_CNT_MASK) << | |
| 682 | + MCC_WRB_SGE_CNT_SHIFT; | |
| 683 | 683 | wrb->payload_length = payload_len; |
| 684 | 684 | be_dws_cpu_to_le(wrb, 8); |
| 685 | 685 | } |
| @@ -1599,7 +1599,7 @@ int beiscsi_cmd_function_reset(struct beiscsi_hba *phba) · 913 unmodified lines | ||
| 1599 | 1599 | { |
| 1600 | 1600 | struct be_ctrl_info *ctrl = &phba->ctrl; |
| 1601 | 1601 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); |
| 1602 | − struct be_post_sgl_pages_req *req = embedded_payload(wrb); | |
| 1602 | + struct be_post_sgl_pages_req *req; | |
| 1603 | 1603 | int status; |
| 1604 | 1604 | |
| 1605 | 1605 | mutex_lock(&ctrl->mbox_lock); |
| @@ -1700,31 +1700,34 @@ int beiscsi_cmd_iscsi_cleanup(struct beiscsi_hba *phba, unsigned short ulp) · 94 unmodified lines | ||
| 1700 | 1700 | struct be_ctrl_info *ctrl = &phba->ctrl; |
| 1701 | 1701 | struct iscsi_cleanup_req_v1 *req_v1; |
| 1702 | 1702 | struct iscsi_cleanup_req *req; |
| 1703 | + u16 hdr_ring_id, data_ring_id; | |
| 1703 | 1704 | struct be_mcc_wrb *wrb; |
| 1704 | 1705 | int status; |
| 1705 | 1706 | |
| 1706 | 1707 | mutex_lock(&ctrl->mbox_lock); |
| 1707 | 1708 | wrb = wrb_from_mbox(&ctrl->mbox_mem); |
| 1708 | − req = embedded_payload(wrb); | |
| 1709 | − be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | |
| 1710 | − be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, | |
| 1711 | − OPCODE_COMMON_ISCSI_CLEANUP, sizeof(*req)); | |
| 1712 | 1709 | |
| 1713 | − /** | |
| 1714 | − * TODO: Check with FW folks the chute value to be set. | |
| 1715 | − * For now, use the ULP_MASK as the chute value. | |
| 1716 | − */ | |
| 1710 | + hdr_ring_id = HWI_GET_DEF_HDRQ_ID(phba, ulp); | |
| 1711 | + data_ring_id = HWI_GET_DEF_BUFQ_ID(phba, ulp); | |
| 1717 | 1712 | if (is_chip_be2_be3r(phba)) { |
| 1713 | + req = embedded_payload(wrb); | |
| 1714 | + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | |
| 1715 | + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, | |
| 1716 | + OPCODE_COMMON_ISCSI_CLEANUP, sizeof(*req)); | |
| 1718 | 1717 | req->chute = (1 << ulp); |
| 1719 | − req->hdr_ring_id = HWI_GET_DEF_HDRQ_ID(phba, ulp); | |
| 1720 | − req->data_ring_id = HWI_GET_DEF_BUFQ_ID(phba, ulp); | |
| 1718 | + /* BE2/BE3 FW creates 8-bit ring id */ | |
| 1719 | + req->hdr_ring_id = hdr_ring_id; | |
| 1720 | + req->data_ring_id = data_ring_id; | |
| 1721 | 1721 | } else { |
| 1722 | − req_v1 = (struct iscsi_cleanup_req_v1 *)req; | |
| 1722 | + req_v1 = embedded_payload(wrb); | |
| 1723 | + be_wrb_hdr_prepare(wrb, sizeof(*req_v1), true, 0); | |
| 1724 | + be_cmd_hdr_prepare(&req_v1->hdr, CMD_SUBSYSTEM_ISCSI, | |
| 1725 | + OPCODE_COMMON_ISCSI_CLEANUP, | |
| 1726 | + sizeof(*req_v1)); | |
| 1723 | 1727 | req_v1->hdr.version = 1; |
| 1724 | − req_v1->hdr_ring_id = cpu_to_le16(HWI_GET_DEF_HDRQ_ID(phba, | |
| 1725 | − ulp)); | |
| 1726 | − req_v1->data_ring_id = cpu_to_le16(HWI_GET_DEF_BUFQ_ID(phba, | |
| 1727 | − ulp)); | |
| 1728 | + req_v1->chute = (1 << ulp); | |
| 1729 | + req_v1->hdr_ring_id = cpu_to_le16(hdr_ring_id); | |
| 1730 | + req_v1->data_ring_id = cpu_to_le16(data_ring_id); | |
| 1728 | 1731 | } |
| 1729 | 1732 | |
| 1730 | 1733 | status = be_mbox_notify(ctrl); |
| @@ -31,10 +31,16 @@ struct be_sge { · 30 unmodified lines | ||
| 31 | 31 | __le32 len; |
| 32 | 32 | }; |
| 33 | 33 | |
| 34 | −#define MCC_WRB_SGE_CNT_SHIFT 3 /* bits 3 - 7 of dword 0 */ | |
| 35 | −#define MCC_WRB_SGE_CNT_MASK 0x1F /* bits 3 - 7 of dword 0 */ | |
| 36 | 34 | struct be_mcc_wrb { |
| 37 | − u32 embedded; /* dword 0 */ | |
| 35 | + u32 emb_sgecnt_special; /* dword 0 */ | |
| 36 | + /* bits 0 - embedded */ | |
| 37 | + /* bits 1 - 2 reserved */ | |
| 38 | + /* bits 3 - 7 sge count */ | |
| 39 | + /* bits 8 - 23 reserved */ | |
| 40 | + /* bits 24 - 31 special */ | |
| 41 | +#define MCC_WRB_EMBEDDED_MASK 1 | |
| 42 | +#define MCC_WRB_SGE_CNT_SHIFT 3 | |
| 43 | +#define MCC_WRB_SGE_CNT_MASK 0x1F | |
| 38 | 44 | u32 payload_length; /* dword 1 */ |
| 39 | 45 | u32 tag0; /* dword 2 */ |
| 40 | 46 | u32 tag1; /* dword 3 */ |
| @@ -1133,11 +1139,6 @@ struct tcp_connect_and_offload_out { · 1092 unmodified lines | ||
| 1133 | 1139 | |
| 1134 | 1140 | } __packed; |
| 1135 | 1141 | |
| 1136 | −struct be_mcc_wrb_context { | |
| 1137 | − struct MCC_WRB *wrb; | |
| 1138 | − int *users_final_status; | |
| 1139 | −} __packed; | |
| 1140 | − | |
| 1141 | 1142 | #define DB_DEF_PDU_RING_ID_MASK 0x3FFF /* bits 0 - 13 */ |
| 1142 | 1143 | #define DB_DEF_PDU_CQPROC_MASK 0x3FFF /* bits 16 - 29 */ |
| 1143 | 1144 | #define DB_DEF_PDU_REARM_SHIFT 14 |
| @@ -165,33 +165,6 @@ beiscsi_conn_create(struct iscsi_cls_session *cls_session, u32 cid) · 164 unmodified lines | ||
| 165 | 165 | return cls_conn; |
| 166 | 166 | } |
| 167 | 167 | |
| 168 | −/** | |
| 169 | − * beiscsi_bindconn_cid - Bind the beiscsi_conn with phba connection table | |
| 170 | − * @beiscsi_conn: The pointer to beiscsi_conn structure | |
| 171 | − * @phba: The phba instance | |
| 172 | − * @cid: The cid to free | |
| 173 | − */ | |
| 174 | −static int beiscsi_bindconn_cid(struct beiscsi_hba *phba, | |
| 175 | − struct beiscsi_conn *beiscsi_conn, | |
| 176 | − unsigned int cid) | |
| 177 | −{ | |
| 178 | − uint16_t cri_index = BE_GET_CRI_FROM_CID(cid); | |
| 179 | − | |
| 180 | − if (phba->conn_table[cri_index]) { | |
| 181 | − beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | |
| 182 | − "BS_%d : Connection table already occupied. Detected clash\n"); | |
| 183 | − | |
| 184 | − return -EINVAL; | |
| 185 | − } else { | |
| 186 | − beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, | |
| 187 | − "BS_%d : phba->conn_table[%d]=%p(beiscsi_conn)\n", | |
| 188 | − cri_index, beiscsi_conn); | |
| 189 | − | |
| 190 | − phba->conn_table[cri_index] = beiscsi_conn; | |
| 191 | − } | |
| 192 | − return 0; | |
| 193 | −} | |
| 194 | − | |
| 195 | 168 | /** |
| 196 | 169 | * beiscsi_conn_bind - Binds iscsi session/connection with TCP connection |
| 197 | 170 | * @cls_session: pointer to iscsi cls session |
| @@ -212,6 +185,7 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session, · 14 unmodified lines | ||
| 212 | 185 | struct hwi_wrb_context *pwrb_context; |
| 213 | 186 | struct beiscsi_endpoint *beiscsi_ep; |
| 214 | 187 | struct iscsi_endpoint *ep; |
| 188 | + uint16_t cri_index; | |
| 215 | 189 | |
| 216 | 190 | ep = iscsi_lookup_endpoint(transport_fd); |
| 217 | 191 | if (!ep) |
| @@ -229,20 +203,34 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session, · 11 unmodified lines | ||
| 229 | 203 | |
| 230 | 204 | return -EEXIST; |
| 231 | 205 | } |
| 232 | − | |
| 233 | − pwrb_context = &phwi_ctrlr->wrb_context[BE_GET_CRI_FROM_CID( | |
| 234 | − beiscsi_ep->ep_cid)]; | |
| 206 | + cri_index = BE_GET_CRI_FROM_CID(beiscsi_ep->ep_cid); | |
| 207 | + if (phba->conn_table[cri_index]) { | |
| 208 | + if (beiscsi_conn != phba->conn_table[cri_index] || | |
| 209 | + beiscsi_ep != phba->conn_table[cri_index]->ep) { | |
| 210 | + __beiscsi_log(phba, KERN_ERR, | |
| 211 | + "BS_%d : conn_table not empty at %u: cid %u conn %p:%p\n", | |
| 212 | + cri_index, | |
| 213 | + beiscsi_ep->ep_cid, | |
| 214 | + beiscsi_conn, | |
| 215 | + phba->conn_table[cri_index]); | |
| 216 | + return -EINVAL; | |
| 217 | + } | |
| 218 | + } | |
| 235 | 219 | |
| 236 | 220 | beiscsi_conn->beiscsi_conn_cid = beiscsi_ep->ep_cid; |
| 237 | 221 | beiscsi_conn->ep = beiscsi_ep; |
| 238 | 222 | beiscsi_ep->conn = beiscsi_conn; |
| 223 | + /** | |
| 224 | + * Each connection is associated with a WRBQ kept in wrb_context. | |
| 225 | + * Store doorbell offset for transmit path. | |
| 226 | + */ | |
| 227 | + pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; | |
| 239 | 228 | beiscsi_conn->doorbell_offset = pwrb_context->doorbell_offset; |
| 240 | − | |
| 241 | 229 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, |
| 242 | − "BS_%d : beiscsi_conn=%p conn=%p ep_cid=%d\n", | |
| 243 | − beiscsi_conn, conn, beiscsi_ep->ep_cid); | |
| 244 | − | |
| 245 | − return beiscsi_bindconn_cid(phba, beiscsi_conn, beiscsi_ep->ep_cid); | |
| 230 | + "BS_%d : cid %d phba->conn_table[%u]=%p\n", | |
| 231 | + beiscsi_ep->ep_cid, cri_index, beiscsi_conn); | |
| 232 | + phba->conn_table[cri_index] = beiscsi_conn; | |
| 233 | + return 0; | |
| 246 | 234 | } |
| 247 | 235 | |
| 248 | 236 | static int beiscsi_iface_create_ipv4(struct beiscsi_hba *phba) |
| @@ -973,9 +961,9 @@ int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn) · 724 unmodified lines | ||
| 973 | 961 | */ |
| 974 | 962 | static int beiscsi_get_cid(struct beiscsi_hba *phba) |
| 975 | 963 | { |
| 976 | − unsigned short cid = 0xFFFF, cid_from_ulp; | |
| 977 | − struct ulp_cid_info *cid_info = NULL; | |
| 978 | 964 | uint16_t cid_avlbl_ulp0, cid_avlbl_ulp1; |
| 965 | + unsigned short cid, cid_from_ulp; | |
| 966 | + struct ulp_cid_info *cid_info; | |
| 979 | 967 | |
| 980 | 968 | /* Find the ULP which has more CID available */ |
| 981 | 969 | cid_avlbl_ulp0 = (phba->cid_array_info[BEISCSI_ULP0]) ? |
| @@ -984,20 +972,27 @@ static int beiscsi_get_cid(struct beiscsi_hba *phba) · 2 unmodified lines | ||
| 984 | 972 | BEISCSI_ULP1_AVLBL_CID(phba) : 0; |
| 985 | 973 | cid_from_ulp = (cid_avlbl_ulp0 > cid_avlbl_ulp1) ? |
| 986 | 974 | BEISCSI_ULP0 : BEISCSI_ULP1; |
| 987 | − | |
| 988 | − if (test_bit(cid_from_ulp, (void *)&phba->fw_config.ulp_supported)) { | |
| 989 | − cid_info = phba->cid_array_info[cid_from_ulp]; | |
| 990 | − if (!cid_info->avlbl_cids) | |
| 991 | − return cid; | |
| 992 | − | |
| 993 | − cid = cid_info->cid_array[cid_info->cid_alloc++]; | |
| 994 | − | |
| 995 | − if (cid_info->cid_alloc == BEISCSI_GET_CID_COUNT( | |
| 996 | − phba, cid_from_ulp)) | |
| 997 | − cid_info->cid_alloc = 0; | |
| 998 | − | |
| 999 | − cid_info->avlbl_cids--; | |
| 975 | + /** | |
| 976 | + * If iSCSI protocol is loaded only on ULP 0, and when cid_avlbl_ulp | |
| 977 | + * is ZERO for both, ULP 1 is returned. | |
| 978 | + * Check if ULP is loaded before getting new CID. | |
| 979 | + */ | |
| 980 | + if (!test_bit(cid_from_ulp, (void *)&phba->fw_config.ulp_supported)) | |
| 981 | + return BE_INVALID_CID; | |
| 982 | + | |
| 983 | + cid_info = phba->cid_array_info[cid_from_ulp]; | |
| 984 | + cid = cid_info->cid_array[cid_info->cid_alloc]; | |
| 985 | + if (!cid_info->avlbl_cids || cid == BE_INVALID_CID) { | |
| 986 | + __beiscsi_log(phba, KERN_ERR, | |
| 987 | + "BS_%d : failed to get cid: available %u:%u\n", | |
| 988 | + cid_info->avlbl_cids, cid_info->cid_free); | |
| 989 | + return BE_INVALID_CID; | |
| 1000 | 990 | } |
| 991 | + /* empty the slot */ | |
| 992 | + cid_info->cid_array[cid_info->cid_alloc++] = BE_INVALID_CID; | |
| 993 | + if (cid_info->cid_alloc == BEISCSI_GET_CID_COUNT(phba, cid_from_ulp)) | |
| 994 | + cid_info->cid_alloc = 0; | |
| 995 | + cid_info->avlbl_cids--; | |
| 1001 | 996 | return cid; |
| 1002 | 997 | } |
| 1003 | 998 | |
| @@ -1008,22 +1003,28 @@ static int beiscsi_get_cid(struct beiscsi_hba *phba) · 4 unmodified lines | ||
| 1008 | 1003 | */ |
| 1009 | 1004 | static void beiscsi_put_cid(struct beiscsi_hba *phba, unsigned short cid) |
| 1010 | 1005 | { |
| 1011 | − uint16_t cid_post_ulp; | |
| 1012 | − struct hwi_controller *phwi_ctrlr; | |
| 1013 | − struct hwi_wrb_context *pwrb_context; | |
| 1014 | − struct ulp_cid_info *cid_info = NULL; | |
| 1015 | 1006 | uint16_t cri_index = BE_GET_CRI_FROM_CID(cid); |
| 1007 | + struct hwi_wrb_context *pwrb_context; | |
| 1008 | + struct hwi_controller *phwi_ctrlr; | |
| 1009 | + struct ulp_cid_info *cid_info; | |
| 1010 | + uint16_t cid_post_ulp; | |
| 1016 | 1011 | |
| 1017 | 1012 | phwi_ctrlr = phba->phwi_ctrlr; |
| 1018 | 1013 | pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; |
| 1019 | 1014 | cid_post_ulp = pwrb_context->ulp_num; |
| 1020 | 1015 | |
| 1021 | 1016 | cid_info = phba->cid_array_info[cid_post_ulp]; |
| 1022 | − cid_info->avlbl_cids++; | |
| 1023 | − | |
| 1017 | + /* fill only in empty slot */ | |
| 1018 | + if (cid_info->cid_array[cid_info->cid_free] != BE_INVALID_CID) { | |
| 1019 | + __beiscsi_log(phba, KERN_ERR, | |
| 1020 | + "BS_%d : failed to put cid %u: available %u:%u\n", | |
| 1021 | + cid, cid_info->avlbl_cids, cid_info->cid_free); | |
| 1022 | + return; | |
| 1023 | + } | |
| 1024 | 1024 | cid_info->cid_array[cid_info->cid_free++] = cid; |
| 1025 | 1025 | if (cid_info->cid_free == BEISCSI_GET_CID_COUNT(phba, cid_post_ulp)) |
| 1026 | 1026 | cid_info->cid_free = 0; |
| 1027 | + cid_info->avlbl_cids++; | |
| 1027 | 1028 | } |
| 1028 | 1029 | |
| 1029 | 1030 | /** |
| @@ -1037,8 +1038,8 @@ static void beiscsi_free_ep(struct beiscsi_endpoint *beiscsi_ep) · 7 unmodified lines | ||
| 1037 | 1038 | |
| 1038 | 1039 | beiscsi_put_cid(phba, beiscsi_ep->ep_cid); |
| 1039 | 1040 | beiscsi_ep->phba = NULL; |
| 1040 | − phba->ep_array[BE_GET_CRI_FROM_CID | |
| 1041 | − (beiscsi_ep->ep_cid)] = NULL; | |
| 1041 | + /* clear this to track freeing in beiscsi_ep_disconnect */ | |
| 1042 | + phba->ep_array[BE_GET_CRI_FROM_CID(beiscsi_ep->ep_cid)] = NULL; | |
| 1042 | 1043 | |
| 1043 | 1044 | /** |
| 1044 | 1045 | * Check if any connection resource allocated by driver |
| @@ -1049,6 +1050,11 @@ static void beiscsi_free_ep(struct beiscsi_endpoint *beiscsi_ep) · 4 unmodified lines | ||
| 1049 | 1050 | return; |
| 1050 | 1051 | |
| 1051 | 1052 | beiscsi_conn = beiscsi_ep->conn; |
| 1053 | + /** | |
| 1054 | + * Break ep->conn link here so that completions after | |
| 1055 | + * this are ignored. | |
| 1056 | + */ | |
| 1057 | + beiscsi_ep->conn = NULL; | |
| 1052 | 1058 | if (beiscsi_conn->login_in_progress) { |
| 1053 | 1059 | beiscsi_free_mgmt_task_handles(beiscsi_conn, |
| 1054 | 1060 | beiscsi_conn->task); |
| @@ -1079,7 +1085,7 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep, · 24 unmodified lines | ||
| 1079 | 1085 | "BS_%d : In beiscsi_open_conn\n"); |
| 1080 | 1086 | |
| 1081 | 1087 | beiscsi_ep->ep_cid = beiscsi_get_cid(phba); |
| 1082 | − if (beiscsi_ep->ep_cid == 0xFFFF) { | |
| 1088 | + if (beiscsi_ep->ep_cid == BE_INVALID_CID) { | |
| 1083 | 1089 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, |
| 1084 | 1090 | "BS_%d : No free cid available\n"); |
| 1085 | 1091 | return ret; |
| @@ -1114,7 +1120,7 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep, · 28 unmodified lines | ||
| 1114 | 1120 | nonemb_cmd.size = req_memsize; |
| 1115 | 1121 | memset(nonemb_cmd.va, 0, nonemb_cmd.size); |
| 1116 | 1122 | tag = mgmt_open_connection(phba, dst_addr, beiscsi_ep, &nonemb_cmd); |
| 1117 | − if (tag <= 0) { | |
| 1123 | + if (!tag) { | |
| 1118 | 1124 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, |
| 1119 | 1125 | "BS_%d : mgmt_open_connection Failed for cid=%d\n", |
| 1120 | 1126 | beiscsi_ep->ep_cid); |
| @@ -1284,26 +1290,6 @@ static int beiscsi_close_conn(struct beiscsi_endpoint *beiscsi_ep, int flag) · 163 unmodified lines | ||
| 1284 | 1290 | return ret; |
| 1285 | 1291 | } |
| 1286 | 1292 | |
| 1287 | −/** | |
| 1288 | − * beiscsi_unbind_conn_to_cid - Unbind the beiscsi_conn from phba conn table | |
| 1289 | − * @phba: The phba instance | |
| 1290 | − * @cid: The cid to free | |
| 1291 | − */ | |
| 1292 | −static int beiscsi_unbind_conn_to_cid(struct beiscsi_hba *phba, | |
| 1293 | − unsigned int cid) | |
| 1294 | −{ | |
| 1295 | − uint16_t cri_index = BE_GET_CRI_FROM_CID(cid); | |
| 1296 | − | |
| 1297 | − if (phba->conn_table[cri_index]) | |
| 1298 | − phba->conn_table[cri_index] = NULL; | |
| 1299 | − else { | |
| 1300 | − beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, | |
| 1301 | − "BS_%d : Connection table Not occupied.\n"); | |
| 1302 | − return -EINVAL; | |
| 1303 | − } | |
| 1304 | − return 0; | |
| 1305 | −} | |
| 1306 | − | |
| 1307 | 1293 | /** |
| 1308 | 1294 | * beiscsi_ep_disconnect - Tears down the TCP connection |
| 1309 | 1295 | * @ep: endpoint to be used |
| @@ -1318,13 +1304,23 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep) · 8 unmodified lines | ||
| 1318 | 1304 | unsigned int tag; |
| 1319 | 1305 | uint8_t mgmt_invalidate_flag, tcp_upload_flag; |
| 1320 | 1306 | unsigned short savecfg_flag = CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH; |
| 1307 | + uint16_t cri_index; | |
| 1321 | 1308 | |
| 1322 | 1309 | beiscsi_ep = ep->dd_data; |
| 1323 | 1310 | phba = beiscsi_ep->phba; |
| 1324 | 1311 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, |
| 1325 | − "BS_%d : In beiscsi_ep_disconnect for ep_cid = %d\n", | |
| 1312 | + "BS_%d : In beiscsi_ep_disconnect for ep_cid = %u\n", | |
| 1326 | 1313 | beiscsi_ep->ep_cid); |
| 1327 | 1314 | |
| 1315 | + cri_index = BE_GET_CRI_FROM_CID(beiscsi_ep->ep_cid); | |
| 1316 | + if (!phba->ep_array[cri_index]) { | |
| 1317 | + __beiscsi_log(phba, KERN_ERR, | |
| 1318 | + "BS_%d : ep_array at %u cid %u empty\n", | |
| 1319 | + cri_index, | |
| 1320 | + beiscsi_ep->ep_cid); | |
| 1321 | + return; | |
| 1322 | + } | |
| 1323 | + | |
| 1328 | 1324 | if (beiscsi_ep->conn) { |
| 1329 | 1325 | beiscsi_conn = beiscsi_ep->conn; |
| 1330 | 1326 | iscsi_suspend_queue(beiscsi_conn->conn); |
| @@ -1356,7 +1352,12 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep) · 25 unmodified lines | ||
| 1356 | 1352 | free_ep: |
| 1357 | 1353 | msleep(BEISCSI_LOGOUT_SYNC_DELAY); |
| 1358 | 1354 | beiscsi_free_ep(beiscsi_ep); |
| 1359 | − beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid); | |
| 1355 | + if (!phba->conn_table[cri_index]) | |
| 1356 | + __beiscsi_log(phba, KERN_ERR, | |
| 1357 | + "BS_%d : conn_table empty at %u: cid %u\n", | |
| 1358 | + cri_index, | |
| 1359 | + beiscsi_ep->ep_cid); | |
| 1360 | + phba->conn_table[cri_index] = NULL; | |
| 1360 | 1361 | iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep); |
| 1361 | 1362 | } |
| 1362 | 1363 | |
| @@ -67,8 +67,6 @@ beiscsi_##_name##_disp(struct device *dev,\ · 66 unmodified lines | ||
| 67 | 67 | { \ |
| 68 | 68 | struct Scsi_Host *shost = class_to_shost(dev);\ |
| 69 | 69 | struct beiscsi_hba *phba = iscsi_host_priv(shost); \ |
| 70 | − uint32_t param_val = 0; \ | |
| 71 | − param_val = phba->attr_##_name;\ | |
| 72 | 70 | return snprintf(buf, PAGE_SIZE, "%d\n",\ |
| 73 | 71 | phba->attr_##_name);\ |
| 74 | 72 | } |
| @@ -218,160 +216,156 @@ static int beiscsi_slave_configure(struct scsi_device *sdev) · 143 unmodified lines | ||
| 218 | 216 | |
| 219 | 217 | static int beiscsi_eh_abort(struct scsi_cmnd *sc) |
| 220 | 218 | { |
| 219 | + struct iscsi_task *abrt_task = (struct iscsi_task *)sc->SCp.ptr; | |
| 221 | 220 | struct iscsi_cls_session *cls_session; |
| 222 | − struct iscsi_task *aborted_task = (struct iscsi_task *)sc->SCp.ptr; | |
| 223 | − struct beiscsi_io_task *aborted_io_task; | |
| 224 | − struct iscsi_conn *conn; | |
| 221 | + struct beiscsi_io_task *abrt_io_task; | |
| 225 | 222 | struct beiscsi_conn *beiscsi_conn; |
| 226 | − struct beiscsi_hba *phba; | |
| 227 | 223 | struct iscsi_session *session; |
| 228 | − struct invalidate_command_table *inv_tbl; | |
| 229 | − struct be_dma_mem nonemb_cmd; | |
| 230 | − unsigned int cid, tag, num_invalidate; | |
| 224 | + struct invldt_cmd_tbl inv_tbl; | |
| 225 | + struct beiscsi_hba *phba; | |
| 226 | + struct iscsi_conn *conn; | |
| 231 | 227 | int rc; |
| 232 | 228 | |
| 233 | 229 | cls_session = starget_to_session(scsi_target(sc->device)); |
| 234 | 230 | session = cls_session->dd_data; |
| 235 | 231 | |
| 236 | − spin_lock_bh(&session->frwd_lock); | |
| 237 | − if (!aborted_task || !aborted_task->sc) { | |
| 238 | − /* we raced */ | |
| 239 | − spin_unlock_bh(&session->frwd_lock); | |
| 240 | − return SUCCESS; | |
| 241 | − } | |
| 242 | − | |
| 243 | − aborted_io_task = aborted_task->dd_data; | |
| 244 | − if (!aborted_io_task->scsi_cmnd) { | |
| 245 | − /* raced or invalid command */ | |
| 246 | − spin_unlock_bh(&session->frwd_lock); | |
| 232 | + /* check if we raced, task just got cleaned up under us */ | |
| 233 | + spin_lock_bh(&session->back_lock); | |
| 234 | + if (!abrt_task || !abrt_task->sc) { | |
| 235 | + spin_unlock_bh(&session->back_lock); | |
| 247 | 236 | return SUCCESS; |
| 248 | 237 | } |
| 249 | − spin_unlock_bh(&session->frwd_lock); | |
| 250 | − /* Invalidate WRB Posted for this Task */ | |
| 251 | − AMAP_SET_BITS(struct amap_iscsi_wrb, invld, | |
| 252 | − aborted_io_task->pwrb_handle->pwrb, | |
| 253 | − 1); | |
| 254 | − | |
| 255 | − conn = aborted_task->conn; | |
| 238 | + /* get a task ref till FW processes the req for the ICD used */ | |
| 239 | + __iscsi_get_task(abrt_task); | |
| 240 | + abrt_io_task = abrt_task->dd_data; | |
| 241 | + conn = abrt_task->conn; | |
| 256 | 242 | beiscsi_conn = conn->dd_data; |
| 257 | 243 | phba = beiscsi_conn->phba; |
| 258 | − | |
| 259 | − /* invalidate iocb */ | |
| 260 | − cid = beiscsi_conn->beiscsi_conn_cid; | |
| 261 | − inv_tbl = phba->inv_tbl; | |
| 262 | − memset(inv_tbl, 0x0, sizeof(*inv_tbl)); | |
| 263 | − inv_tbl->cid = cid; | |
| 264 | − inv_tbl->icd = aborted_io_task->psgl_handle->sgl_index; | |
| 265 | − num_invalidate = 1; | |
| 266 | − nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev, | |
| 267 | − sizeof(struct invalidate_commands_params_in), | |
| 268 | − &nonemb_cmd.dma); | |
| 269 | − if (nonemb_cmd.va == NULL) { | |
| 270 | − beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_EH, | |
| 271 | − "BM_%d : Failed to allocate memory for" | |
| 272 | − "mgmt_invalidate_icds\n"); | |
| 273 | − return FAILED; | |
| 244 | + /* mark WRB invalid which have been not processed by FW yet */ | |
| 245 | + if (is_chip_be2_be3r(phba)) { | |
| 246 | + AMAP_SET_BITS(struct amap_iscsi_wrb, invld, | |
| 247 | + abrt_io_task->pwrb_handle->pwrb, 1); | |
| 248 | + } else { | |
| 249 | + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, invld, | |
| 250 | + abrt_io_task->pwrb_handle->pwrb, 1); | |
| 274 | 251 | } |
| 275 | − nonemb_cmd.size = sizeof(struct invalidate_commands_params_in); | |
| 252 | + inv_tbl.cid = beiscsi_conn->beiscsi_conn_cid; | |
| 253 | + inv_tbl.icd = abrt_io_task->psgl_handle->sgl_index; | |
| 254 | + spin_unlock_bh(&session->back_lock); | |
| 276 | 255 | |
| 277 | − tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate, | |
| 278 | − cid, &nonemb_cmd); | |
| 279 | − if (!tag) { | |
| 256 | + rc = beiscsi_mgmt_invalidate_icds(phba, &inv_tbl, 1); | |
| 257 | + iscsi_put_task(abrt_task); | |
| 258 | + if (rc) { | |
| 280 | 259 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_EH, |
| 281 | − "BM_%d : mgmt_invalidate_icds could not be" | |
| 282 | − "submitted\n"); | |
| 283 | − pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, | |
| 284 | − nonemb_cmd.va, nonemb_cmd.dma); | |
| 285 | − | |
| 260 | + "BM_%d : sc %p invalidation failed %d\n", | |
| 261 | + sc, rc); | |
| 286 | 262 | return FAILED; |
| 287 | 263 | } |
| 288 | 264 | |
| 289 | − rc = beiscsi_mccq_compl_wait(phba, tag, NULL, &nonemb_cmd); | |
| 290 | − if (rc != -EBUSY) | |
| 291 | − pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, | |
| 292 | − nonemb_cmd.va, nonemb_cmd.dma); | |
| 293 | − | |
| 294 | 265 | return iscsi_eh_abort(sc); |
| 295 | 266 | } |
| 296 | 267 | |
| 297 | 268 | static int beiscsi_eh_device_reset(struct scsi_cmnd *sc) |
| 298 | 269 | { |
| 299 | − struct iscsi_task *abrt_task; | |
| 300 | − struct beiscsi_io_task *abrt_io_task; | |
| 301 | − struct iscsi_conn *conn; | |
| 270 | + struct beiscsi_invldt_cmd_tbl { | |
| 271 | + struct invldt_cmd_tbl tbl[BE_INVLDT_CMD_TBL_SZ]; | |
| 272 | + struct iscsi_task *task[BE_INVLDT_CMD_TBL_SZ]; | |
| 273 | + } *inv_tbl; | |
| 274 | + struct iscsi_cls_session *cls_session; | |
| 302 | 275 | struct beiscsi_conn *beiscsi_conn; |
| 303 | − struct beiscsi_hba *phba; | |
| 276 | + struct beiscsi_io_task *io_task; | |
| 304 | 277 | struct iscsi_session *session; |
| 305 | − struct iscsi_cls_session *cls_session; | |
| 306 | − struct invalidate_command_table *inv_tbl; | |
| 307 | − struct be_dma_mem nonemb_cmd; | |
| 308 | − unsigned int cid, tag, i, num_invalidate; | |
| 309 | − int rc; | |
| 278 | + struct beiscsi_hba *phba; | |
| 279 | + struct iscsi_conn *conn; | |
| 280 | + struct iscsi_task *task; | |
| 281 | + unsigned int i, nents; | |
| 282 | + int rc, more = 0; | |
| 310 | 283 | |
| 311 | − /* invalidate iocbs */ | |
| 312 | 284 | cls_session = starget_to_session(scsi_target(sc->device)); |
| 313 | 285 | session = cls_session->dd_data; |
| 286 | + | |
| 314 | 287 | spin_lock_bh(&session->frwd_lock); |
| 315 | 288 | if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN) { |
| 316 | 289 | spin_unlock_bh(&session->frwd_lock); |
| 317 | 290 | return FAILED; |
| 318 | 291 | } |
| 292 | + | |
| 319 | 293 | conn = session->leadconn; |
| 320 | 294 | beiscsi_conn = conn->dd_data; |
| 321 | 295 | phba = beiscsi_conn->phba; |
| 322 | − cid = beiscsi_conn->beiscsi_conn_cid; | |
| 323 | − inv_tbl = phba->inv_tbl; | |
| 324 | − memset(inv_tbl, 0x0, sizeof(*inv_tbl) * BE2_CMDS_PER_CXN); | |
| 325 | − num_invalidate = 0; | |
| 296 | + | |
| 297 | + inv_tbl = kzalloc(sizeof(*inv_tbl), GFP_ATOMIC); | |
| 298 | + if (!inv_tbl) { | |
| 299 | + spin_unlock_bh(&session->frwd_lock); | |
| 300 | + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_EH, | |
| 301 | + "BM_%d : invldt_cmd_tbl alloc failed\n"); | |
| 302 | + return FAILED; | |
| 303 | + } | |
| 304 | + nents = 0; | |
| 305 | + /* take back_lock to prevent task from getting cleaned up under us */ | |
| 306 | + spin_lock(&session->back_lock); | |
| 326 | 307 | for (i = 0; i < conn->session->cmds_max; i++) { |
| 327 | − abrt_task = conn->session->cmds[i]; | |
| 328 | − abrt_io_task = abrt_task->dd_data; | |
| 329 | − if (!abrt_task->sc || abrt_task->state == ISCSI_TASK_FREE) | |
| 308 | + task = conn->session->cmds[i]; | |
| 309 | + if (!task->sc) | |
| 330 | 310 | continue; |
| 331 | 311 | |
| 332 | − if (sc->device->lun != abrt_task->sc->device->lun) | |
| 312 | + if (sc->device->lun != task->sc->device->lun) | |
| 333 | 313 | continue; |
| 314 | + /** | |
| 315 | + * Can't fit in more cmds? Normally this won't happen b'coz | |
| 316 | + * BEISCSI_CMD_PER_LUN is same as BE_INVLDT_CMD_TBL_SZ. | |
| 317 | + */ | |
| 318 | + if (nents == BE_INVLDT_CMD_TBL_SZ) { | |
| 319 | + more = 1; | |
| 320 | + break; | |
| 321 | + } | |
| 334 | 322 | |
| 335 | − /* Invalidate WRB Posted for this Task */ | |
| 336 | − AMAP_SET_BITS(struct amap_iscsi_wrb, invld, | |
| 337 | − abrt_io_task->pwrb_handle->pwrb, | |
| 338 | − 1); | |
| 323 | + /* get a task ref till FW processes the req for the ICD used */ | |
| 324 | + __iscsi_get_task(task); | |
| 325 | + io_task = task->dd_data; | |
| 326 | + /* mark WRB invalid which have been not processed by FW yet */ | |
| 327 | + if (is_chip_be2_be3r(phba)) { | |
| 328 | + AMAP_SET_BITS(struct amap_iscsi_wrb, invld, | |
| 329 | + io_task->pwrb_handle->pwrb, 1); | |
| 330 | + } else { | |
| 331 | + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, invld, | |
| 332 | + io_task->pwrb_handle->pwrb, 1); | |
| 333 | + } | |
| 339 | 334 | |
| 340 | − inv_tbl->cid = cid; | |
| 341 | − inv_tbl->icd = abrt_io_task->psgl_handle->sgl_index; | |
| 342 | − num_invalidate++; | |
| 343 | − inv_tbl++; | |
| 335 | + inv_tbl->tbl[nents].cid = beiscsi_conn->beiscsi_conn_cid; | |
| 336 | + inv_tbl->tbl[nents].icd = io_task->psgl_handle->sgl_index; | |
| 337 | + inv_tbl->task[nents] = task; | |
| 338 | + nents++; | |
| 344 | 339 | } |
| 340 | + spin_unlock_bh(&session->back_lock); | |
| 345 | 341 | spin_unlock_bh(&session->frwd_lock); |
| 346 | − inv_tbl = phba->inv_tbl; | |
| 347 | 342 | |
| 348 | − nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev, | |
| 349 | − sizeof(struct invalidate_commands_params_in), | |
| 350 | − &nonemb_cmd.dma); | |
| 351 | − if (nonemb_cmd.va == NULL) { | |
| 343 | + rc = SUCCESS; | |
| 344 | + if (!nents) | |
| 345 | + goto end_reset; | |
| 346 | + | |
| 347 | + if (more) { | |
| 352 | 348 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_EH, |
| 353 | − "BM_%d : Failed to allocate memory for" | |
| 354 | − "mgmt_invalidate_icds\n"); | |
| 355 | − return FAILED; | |
| 349 | + "BM_%d : number of cmds exceeds size of invalidation table\n"); | |
| 350 | + rc = FAILED; | |
| 351 | + goto end_reset; | |
| 356 | 352 | } |
| 357 | − nonemb_cmd.size = sizeof(struct invalidate_commands_params_in); | |
| 358 | − memset(nonemb_cmd.va, 0, nonemb_cmd.size); | |
| 359 | − tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate, | |
| 360 | − cid, &nonemb_cmd); | |
| 361 | − if (!tag) { | |
| 353 | + | |
| 354 | + if (beiscsi_mgmt_invalidate_icds(phba, &inv_tbl->tbl[0], nents)) { | |
| 362 | 355 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_EH, |
| 363 | − "BM_%d : mgmt_invalidate_icds could not be" | |
| 364 | − " submitted\n"); | |
| 365 | − pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, | |
| 366 | − nonemb_cmd.va, nonemb_cmd.dma); | |
| 367 | − return FAILED; | |
| 356 | + "BM_%d : cid %u scmds invalidation failed\n", | |
| 357 | + beiscsi_conn->beiscsi_conn_cid); | |
| 358 | + rc = FAILED; | |
| 368 | 359 | } |
| 369 | 360 | |
| 370 | − rc = beiscsi_mccq_compl_wait(phba, tag, NULL, &nonemb_cmd); | |
| 371 | − if (rc != -EBUSY) | |
| 372 | − pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, | |
| 373 | − nonemb_cmd.va, nonemb_cmd.dma); | |
| 374 | − return iscsi_eh_device_reset(sc); | |
| 361 | +end_reset: | |
| 362 | + for (i = 0; i < nents; i++) | |
| 363 | + iscsi_put_task(inv_tbl->task[i]); | |
| 364 | + kfree(inv_tbl); | |
| 365 | + | |
| 366 | + if (rc == SUCCESS) | |
| 367 | + rc = iscsi_eh_device_reset(sc); | |
| 368 | + return rc; | |
| 375 | 369 | } |
| 376 | 370 | |
| 377 | 371 | /*------------------- PCI Driver operations and data ----------------- */ |
| @@ -395,6 +389,7 @@ static struct scsi_host_template beiscsi_sht = { · 17 unmodified lines | ||
| 395 | 389 | .change_queue_depth = scsi_change_queue_depth, |
| 396 | 390 | .slave_configure = beiscsi_slave_configure, |
| 397 | 391 | .target_alloc = iscsi_target_alloc, |
| 392 | + .eh_timed_out = iscsi_eh_cmd_timed_out, | |
| 398 | 393 | .eh_abort_handler = beiscsi_eh_abort, |
| 399 | 394 | .eh_device_reset_handler = beiscsi_eh_device_reset, |
| 400 | 395 | .eh_target_reset_handler = iscsi_eh_session_reset, |
| @@ -646,7 +641,6 @@ static void beiscsi_get_params(struct beiscsi_hba *phba) · 245 unmodified lines | ||
| 646 | 641 | phba->params.num_sge_per_io = BE2_SGE; |
| 647 | 642 | phba->params.defpdu_hdr_sz = BE2_DEFPDU_HDR_SZ; |
| 648 | 643 | phba->params.defpdu_data_sz = BE2_DEFPDU_DATA_SZ; |
| 649 | − phba->params.eq_timer = 64; | |
| 650 | 644 | phba->params.num_eq_entries = 1024; |
| 651 | 645 | phba->params.num_cq_entries = 1024; |
| 652 | 646 | phba->params.wrbs_per_cxn = 256; |
| @@ -964,6 +958,10 @@ beiscsi_get_wrb_handle(struct hwi_wrb_context *pwrb_context, · 311 unmodified lines | ||
| 964 | 958 | unsigned long flags; |
| 965 | 959 | |
| 966 | 960 | spin_lock_irqsave(&pwrb_context->wrb_lock, flags); |
| 961 | + if (!pwrb_context->wrb_handles_available) { | |
| 962 | + spin_unlock_irqrestore(&pwrb_context->wrb_lock, flags); | |
| 963 | + return NULL; | |
| 964 | + } | |
| 967 | 965 | pwrb_handle = pwrb_context->pwrb_handle_base[pwrb_context->alloc_index]; |
| 968 | 966 | pwrb_context->wrb_handles_available--; |
| 969 | 967 | if (pwrb_context->alloc_index == (wrbs_per_cxn - 1)) |
| @@ -1014,6 +1012,7 @@ beiscsi_put_wrb_handle(struct hwi_wrb_context *pwrb_context, · 44 unmodified lines | ||
| 1014 | 1012 | pwrb_context->free_index = 0; |
| 1015 | 1013 | else |
| 1016 | 1014 | pwrb_context->free_index++; |
| 1015 | + pwrb_handle->pio_handle = NULL; | |
| 1017 | 1016 | spin_unlock_irqrestore(&pwrb_context->wrb_lock, flags); |
| 1018 | 1017 | } |
| 1019 | 1018 | |
| @@ -1224,6 +1223,7 @@ hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn, · 204 unmodified lines | ||
| 1224 | 1223 | uint16_t wrb_index, cid, cri_index; |
| 1225 | 1224 | struct hwi_controller *phwi_ctrlr; |
| 1226 | 1225 | struct wrb_handle *pwrb_handle; |
| 1226 | + struct iscsi_session *session; | |
| 1227 | 1227 | struct iscsi_task *task; |
| 1228 | 1228 | |
| 1229 | 1229 | phwi_ctrlr = phba->phwi_ctrlr; |
| @@ -1242,8 +1242,12 @@ hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn, · 12 unmodified lines | ||
| 1242 | 1242 | cri_index = BE_GET_CRI_FROM_CID(cid); |
| 1243 | 1243 | pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; |
| 1244 | 1244 | pwrb_handle = pwrb_context->pwrb_handle_basestd[wrb_index]; |
| 1245 | + session = beiscsi_conn->conn->session; | |
| 1246 | + spin_lock_bh(&session->back_lock); | |
| 1245 | 1247 | task = pwrb_handle->pio_handle; |
| 1246 | − iscsi_put_task(task); | |
| 1248 | + if (task) | |
| 1249 | + __iscsi_put_task(task); | |
| 1250 | + spin_unlock_bh(&session->back_lock); | |
| 1247 | 1251 | } |
| 1248 | 1252 | |
| 1249 | 1253 | static void |
| @@ -1323,16 +1327,15 @@ static void adapter_get_sol_cqe(struct beiscsi_hba *phba, · 73 unmodified lines | ||
| 1323 | 1327 | static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn, |
| 1324 | 1328 | struct beiscsi_hba *phba, struct sol_cqe *psol) |
| 1325 | 1329 | { |
| 1326 | − struct hwi_wrb_context *pwrb_context; | |
| 1327 | − struct wrb_handle *pwrb_handle; | |
| 1328 | − struct iscsi_wrb *pwrb = NULL; | |
| 1329 | − struct hwi_controller *phwi_ctrlr; | |
| 1330 | − struct iscsi_task *task; | |
| 1331 | − unsigned int type; | |
| 1332 | 1330 | struct iscsi_conn *conn = beiscsi_conn->conn; |
| 1333 | 1331 | struct iscsi_session *session = conn->session; |
| 1334 | 1332 | struct common_sol_cqe csol_cqe = {0}; |
| 1333 | + struct hwi_wrb_context *pwrb_context; | |
| 1334 | + struct hwi_controller *phwi_ctrlr; | |
| 1335 | + struct wrb_handle *pwrb_handle; | |
| 1336 | + struct iscsi_task *task; | |
| 1335 | 1337 | uint16_t cri_index = 0; |
| 1338 | + uint8_t type; | |
| 1336 | 1339 | |
| 1337 | 1340 | phwi_ctrlr = phba->phwi_ctrlr; |
| 1338 | 1341 | |
| @@ -1345,11 +1348,14 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn, · 6 unmodified lines | ||
| 1345 | 1348 | pwrb_handle = pwrb_context->pwrb_handle_basestd[ |
| 1346 | 1349 | csol_cqe.wrb_index]; |
| 1347 | 1350 | |
| 1351 | + spin_lock_bh(&session->back_lock); | |
| 1348 | 1352 | task = pwrb_handle->pio_handle; |
| 1349 | − pwrb = pwrb_handle->pwrb; | |
| 1353 | + if (!task) { | |
| 1354 | + spin_unlock_bh(&session->back_lock); | |
| 1355 | + return; | |
| 1356 | + } | |
| 1350 | 1357 | type = ((struct beiscsi_io_task *)task->dd_data)->wrb_type; |
| 1351 | 1358 | |
| 1352 | − spin_lock_bh(&session->back_lock); | |
| 1353 | 1359 | switch (type) { |
| 1354 | 1360 | case HWH_TYPE_IO: |
| 1355 | 1361 | case HWH_TYPE_IO_RD: |
| @@ -1711,13 +1717,12 @@ beiscsi_hdq_post_handles(struct beiscsi_hba *phba, · 355 unmodified lines | ||
| 1711 | 1717 | struct list_head *hfree_list; |
| 1712 | 1718 | struct phys_addr *pasync_sge; |
| 1713 | 1719 | u32 ring_id, doorbell = 0; |
| 1714 | − u16 index, num_entries; | |
| 1715 | 1720 | u32 doorbell_offset; |
| 1716 | 1721 | u16 prod = 0, cons; |
| 1722 | + u16 index; | |
| 1717 | 1723 | |
| 1718 | 1724 | phwi_ctrlr = phba->phwi_ctrlr; |
| 1719 | 1725 | pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr, ulp_num); |
| 1720 | − num_entries = pasync_ctx->num_entries; | |
| 1721 | 1726 | if (header) { |
| 1722 | 1727 | cons = pasync_ctx->async_header.free_entries; |
| 1723 | 1728 | hfree_list = &pasync_ctx->async_header.free_list; |
| @@ -2374,13 +2379,10 @@ static int hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task) · 650 unmodified lines | ||
| 2374 | 2379 | static void beiscsi_find_mem_req(struct beiscsi_hba *phba) |
| 2375 | 2380 | { |
| 2376 | 2381 | uint8_t mem_descr_index, ulp_num; |
| 2377 | − unsigned int num_cq_pages, num_async_pdu_buf_pages; | |
| 2382 | + unsigned int num_async_pdu_buf_pages; | |
| 2378 | 2383 | unsigned int num_async_pdu_data_pages, wrb_sz_per_cxn; |
| 2379 | 2384 | unsigned int num_async_pdu_buf_sgl_pages, num_async_pdu_data_sgl_pages; |
| 2380 | 2385 | |
| 2381 | − num_cq_pages = PAGES_REQUIRED(phba->params.num_cq_entries * \ | |
| 2382 | − sizeof(struct sol_cqe)); | |
| 2383 | − | |
| 2384 | 2386 | phba->params.hwi_ws_sz = sizeof(struct hwi_controller); |
| 2385 | 2387 | |
| 2386 | 2388 | phba->mem_req[ISCSI_MEM_GLOBAL_HEADER] = 2 * |
| @@ -2737,7 +2739,7 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) · 350 unmodified lines | ||
| 2737 | 2739 | |
| 2738 | 2740 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { |
| 2739 | 2741 | if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { |
| 2740 | − /* get async_ctx for each ULP */ | |
| 2742 | + /* get async_ctx for each ULP */ | |
| 2741 | 2743 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; |
| 2742 | 2744 | mem_descr += (HWI_MEM_ASYNC_PDU_CONTEXT_ULP0 + |
| 2743 | 2745 | (ulp_num * MEM_DESCR_OFFSET)); |
| @@ -3367,7 +3369,7 @@ beiscsi_create_wrb_rings(struct beiscsi_hba *phba, · 623 unmodified lines | ||
| 3367 | 3369 | struct hwi_context_memory *phwi_context, |
| 3368 | 3370 | struct hwi_controller *phwi_ctrlr) |
| 3369 | 3371 | { |
| 3370 | − unsigned int wrb_mem_index, offset, size, num_wrb_rings; | |
| 3372 | + unsigned int num_wrb_rings; | |
| 3371 | 3373 | u64 pa_addr_lo; |
| 3372 | 3374 | unsigned int idx, num, i, ulp_num; |
| 3373 | 3375 | struct mem_array *pwrb_arr; |
| @@ -3432,10 +3434,6 @@ beiscsi_create_wrb_rings(struct beiscsi_hba *phba, · 58 unmodified lines | ||
| 3432 | 3434 | } |
| 3433 | 3435 | |
| 3434 | 3436 | for (i = 0; i < phba->params.cxns_per_ctrl; i++) { |
| 3435 | − wrb_mem_index = 0; | |
| 3436 | − offset = 0; | |
| 3437 | − size = 0; | |
| 3438 | − | |
| 3439 | 3437 | if (ulp_count > 1) { |
| 3440 | 3438 | ulp_base_num = (ulp_base_num + 1) % BEISCSI_ULP_COUNT; |
| 3441 | 3439 | |
| @@ -3663,7 +3661,6 @@ static void hwi_cleanup_port(struct beiscsi_hba *phba) · 221 unmodified lines | ||
| 3663 | 3661 | struct be_ctrl_info *ctrl = &phba->ctrl; |
| 3664 | 3662 | struct hwi_controller *phwi_ctrlr; |
| 3665 | 3663 | struct hwi_context_memory *phwi_context; |
| 3666 | − struct hd_async_context *pasync_ctx; | |
| 3667 | 3664 | int i, eq_for_mcc, ulp_num; |
| 3668 | 3665 | |
| 3669 | 3666 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) |
| @@ -3700,8 +3697,6 @@ static void hwi_cleanup_port(struct beiscsi_hba *phba) · 30 unmodified lines | ||
| 3700 | 3697 | q = &phwi_context->be_def_dataq[ulp_num]; |
| 3701 | 3698 | if (q->created) |
| 3702 | 3699 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_DPDUQ); |
| 3703 | − | |
| 3704 | − pasync_ctx = phwi_ctrlr->phwi_ctxt->pasync_ctx[ulp_num]; | |
| 3705 | 3700 | } |
| 3706 | 3701 | } |
| 3707 | 3702 | |
| @@ -3804,7 +3799,6 @@ static int hwi_init_port(struct beiscsi_hba *phba) · 96 unmodified lines | ||
| 3804 | 3799 | /** |
| 3805 | 3800 | * Now that the default PDU rings have been created, |
| 3806 | 3801 | * let EP know about it. |
| 3807 | − * Call beiscsi_cmd_iscsi_cleanup before posting? | |
| 3808 | 3802 | */ |
| 3809 | 3803 | beiscsi_hdq_post_handles(phba, BEISCSI_DEFQ_HDR, |
| 3810 | 3804 | ulp_num); |
| @@ -3850,14 +3844,6 @@ static int hwi_init_port(struct beiscsi_hba *phba) · 39 unmodified lines | ||
| 3850 | 3844 | phwi_ctrlr->wrb_context[cri].cid] = |
| 3851 | 3845 | async_arr_idx++; |
| 3852 | 3846 | } |
| 3853 | − /** | |
| 3854 | − * Now that the default PDU rings have been created, | |
| 3855 | − * let EP know about it. | |
| 3856 | − */ | |
| 3857 | − beiscsi_hdq_post_handles(phba, BEISCSI_DEFQ_HDR, | |
| 3858 | − ulp_num); | |
| 3859 | − beiscsi_hdq_post_handles(phba, BEISCSI_DEFQ_DATA, | |
| 3860 | − ulp_num); | |
| 3861 | 3847 | } |
| 3862 | 3848 | } |
| 3863 | 3849 | |
| @@ -3934,31 +3920,6 @@ static void beiscsi_free_mem(struct beiscsi_hba *phba) · 70 unmodified lines | ||
| 3934 | 3920 | kfree(phba->phwi_ctrlr); |
| 3935 | 3921 | } |
| 3936 | 3922 | |
| 3937 | −static int beiscsi_init_controller(struct beiscsi_hba *phba) | |
| 3938 | −{ | |
| 3939 | − int ret = -ENOMEM; | |
| 3940 | − | |
| 3941 | − ret = beiscsi_get_memory(phba); | |
| 3942 | − if (ret < 0) { | |
| 3943 | − beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | |
| 3944 | − "BM_%d : beiscsi_dev_probe -" | |
| 3945 | − "Failed in beiscsi_alloc_memory\n"); | |
| 3946 | − return ret; | |
| 3947 | − } | |
| 3948 | − | |
| 3949 | − ret = hwi_init_controller(phba); | |
| 3950 | − if (ret) | |
| 3951 | − goto free_init; | |
| 3952 | − beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | |
| 3953 | − "BM_%d : Return success from beiscsi_init_controller"); | |
| 3954 | − | |
| 3955 | − return 0; | |
| 3956 | − | |
| 3957 | −free_init: | |
| 3958 | − beiscsi_free_mem(phba); | |
| 3959 | − return ret; | |
| 3960 | −} | |
| 3961 | − | |
| 3962 | 3923 | static int beiscsi_init_sgl_handle(struct beiscsi_hba *phba) |
| 3963 | 3924 | { |
| 3964 | 3925 | struct be_mem_descriptor *mem_descr_sglh, *mem_descr_sg; |
| @@ -4089,9 +4050,10 @@ static int hba_setup_cid_tbls(struct beiscsi_hba *phba) · 124 unmodified lines | ||
| 4089 | 4050 | } |
| 4090 | 4051 | |
| 4091 | 4052 | /* Allocate memory for CID array */ |
| 4092 | − ptr_cid_info->cid_array = kzalloc(sizeof(void *) * | |
| 4093 | − BEISCSI_GET_CID_COUNT(phba, | |
| 4094 | − ulp_num), GFP_KERNEL); | |
| 4053 | + ptr_cid_info->cid_array = | |
| 4054 | + kcalloc(BEISCSI_GET_CID_COUNT(phba, ulp_num), | |
| 4055 | + sizeof(*ptr_cid_info->cid_array), | |
| 4056 | + GFP_KERNEL); | |
| 4095 | 4057 | if (!ptr_cid_info->cid_array) { |
| 4096 | 4058 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
| 4097 | 4059 | "BM_%d : Failed to allocate memory" |
| @@ -4231,33 +4193,30 @@ static int beiscsi_init_port(struct beiscsi_hba *phba) · 133 unmodified lines | ||
| 4231 | 4193 | { |
| 4232 | 4194 | int ret; |
| 4233 | 4195 | |
| 4234 | − ret = beiscsi_init_controller(phba); | |
| 4196 | + ret = hwi_init_controller(phba); | |
| 4235 | 4197 | if (ret < 0) { |
| 4236 | 4198 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
| 4237 | − "BM_%d : beiscsi_dev_probe - Failed in" | |
| 4238 | − "beiscsi_init_controller\n"); | |
| 4199 | + "BM_%d : init controller failed\n"); | |
| 4239 | 4200 | return ret; |
| 4240 | 4201 | } |
| 4241 | 4202 | ret = beiscsi_init_sgl_handle(phba); |
| 4242 | 4203 | if (ret < 0) { |
| 4243 | 4204 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
| 4244 | − "BM_%d : beiscsi_dev_probe - Failed in" | |
| 4245 | − "beiscsi_init_sgl_handle\n"); | |
| 4246 | − goto do_cleanup_ctrlr; | |
| 4205 | + "BM_%d : init sgl handles failed\n"); | |
| 4206 | + goto cleanup_port; | |
| 4247 | 4207 | } |
| 4248 | 4208 | |
| 4249 | 4209 | ret = hba_setup_cid_tbls(phba); |
| 4250 | 4210 | if (ret < 0) { |
| 4251 | 4211 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
| 4252 | − "BM_%d : Failed in hba_setup_cid_tbls\n"); | |
| 4212 | + "BM_%d : setup CID table failed\n"); | |
| 4253 | 4213 | kfree(phba->io_sgl_hndl_base); |
| 4254 | 4214 | kfree(phba->eh_sgl_hndl_base); |
| 4255 | − goto do_cleanup_ctrlr; | |
| 4215 | + goto cleanup_port; | |
| 4256 | 4216 | } |
| 4257 | − | |
| 4258 | 4217 | return ret; |
| 4259 | 4218 | |
| 4260 | −do_cleanup_ctrlr: | |
| 4219 | +cleanup_port: | |
| 4261 | 4220 | hwi_cleanup_port(phba); |
| 4262 | 4221 | return ret; |
| 4263 | 4222 | } |
| @@ -5417,10 +5376,10 @@ static int beiscsi_enable_port(struct beiscsi_hba *phba) · 1153 unmodified lines | ||
| 5417 | 5376 | |
| 5418 | 5377 | phba->shost->max_id = phba->params.cxns_per_ctrl; |
| 5419 | 5378 | phba->shost->can_queue = phba->params.ios_per_ctrl; |
| 5420 | − ret = hwi_init_controller(phba); | |
| 5421 | − if (ret) { | |
| 5379 | + ret = beiscsi_init_port(phba); | |
| 5380 | + if (ret < 0) { | |
| 5422 | 5381 | __beiscsi_log(phba, KERN_ERR, |
| 5423 | − "BM_%d : init controller failed %d\n", ret); | |
| 5382 | + "BM_%d : init port failed\n"); | |
| 5424 | 5383 | goto disable_msix; |
| 5425 | 5384 | } |
| 5426 | 5385 | |
| @@ -5526,6 +5485,7 @@ static void beiscsi_disable_port(struct beiscsi_hba *phba, int unload) · 99 unmodified lines | ||
| 5526 | 5485 | cancel_work_sync(&pbe_eq->mcc_work); |
| 5527 | 5486 | } |
| 5528 | 5487 | hwi_cleanup_port(phba); |
| 5488 | + beiscsi_cleanup_port(phba); | |
| 5529 | 5489 | } |
| 5530 | 5490 | |
| 5531 | 5491 | static void beiscsi_sess_work(struct work_struct *work) |
| @@ -5638,11 +5598,12 @@ static void beiscsi_eeh_resume(struct pci_dev *pdev) · 106 unmodified lines | ||
| 5638 | 5598 | static int beiscsi_dev_probe(struct pci_dev *pcidev, |
| 5639 | 5599 | const struct pci_device_id *id) |
| 5640 | 5600 | { |
| 5641 | − struct beiscsi_hba *phba = NULL; | |
| 5642 | − struct hwi_controller *phwi_ctrlr; | |
| 5643 | 5601 | struct hwi_context_memory *phwi_context; |
| 5602 | + struct hwi_controller *phwi_ctrlr; | |
| 5603 | + struct beiscsi_hba *phba = NULL; | |
| 5644 | 5604 | struct be_eq_obj *pbe_eq; |
| 5645 | 5605 | unsigned int s_handle; |
| 5606 | + char wq_name[20]; | |
| 5646 | 5607 | int ret, i; |
| 5647 | 5608 | |
| 5648 | 5609 | ret = beiscsi_enable_pci(pcidev); |
| @@ -5680,6 +5641,8 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, · 31 unmodified lines | ||
| 5680 | 5641 | case OC_DEVICE_ID2: |
| 5681 | 5642 | phba->generation = BE_GEN2; |
| 5682 | 5643 | phba->iotask_fn = beiscsi_iotask; |
| 5644 | + dev_warn(&pcidev->dev, | |
| 5645 | + "Obsolete/Unsupported BE2 Adapter Family\n"); | |
| 5683 | 5646 | break; |
| 5684 | 5647 | case BE_DEVICE_ID2: |
| 5685 | 5648 | case OC_DEVICE_ID3: |
| @@ -5735,11 +5698,18 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, · 49 unmodified lines | ||
| 5735 | 5698 | |
| 5736 | 5699 | phba->shost->max_id = phba->params.cxns_per_ctrl; |
| 5737 | 5700 | phba->shost->can_queue = phba->params.ios_per_ctrl; |
| 5701 | + ret = beiscsi_get_memory(phba); | |
| 5702 | + if (ret < 0) { | |
| 5703 | + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | |
| 5704 | + "BM_%d : alloc host mem failed\n"); | |
| 5705 | + goto free_port; | |
| 5706 | + } | |
| 5707 | + | |
| 5738 | 5708 | ret = beiscsi_init_port(phba); |
| 5739 | 5709 | if (ret < 0) { |
| 5740 | 5710 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
| 5741 | − "BM_%d : beiscsi_dev_probe-" | |
| 5742 | − "Failed in beiscsi_init_port\n"); | |
| 5711 | + "BM_%d : init port failed\n"); | |
| 5712 | + beiscsi_free_mem(phba); | |
| 5743 | 5713 | goto free_port; |
| 5744 | 5714 | } |
| 5745 | 5715 | |
| @@ -5754,9 +5724,9 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, · 8 unmodified lines | ||
| 5754 | 5724 | |
| 5755 | 5725 | phba->ctrl.mcc_alloc_index = phba->ctrl.mcc_free_index = 0; |
| 5756 | 5726 | |
| 5757 | − snprintf(phba->wq_name, sizeof(phba->wq_name), "beiscsi_%02x_wq", | |
| 5727 | + snprintf(wq_name, sizeof(wq_name), "beiscsi_%02x_wq", | |
| 5758 | 5728 | phba->shost->host_no); |
| 5759 | − phba->wq = alloc_workqueue("%s", WQ_MEM_RECLAIM, 1, phba->wq_name); | |
| 5729 | + phba->wq = alloc_workqueue("%s", WQ_MEM_RECLAIM, 1, wq_name); | |
| 5760 | 5730 | if (!phba->wq) { |
| 5761 | 5731 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
| 5762 | 5732 | "BM_%d : beiscsi_dev_probe-" |
| @@ -5881,7 +5851,6 @@ static void beiscsi_remove(struct pci_dev *pcidev) · 118 unmodified lines | ||
| 5881 | 5851 | |
| 5882 | 5852 | /* free all resources */ |
| 5883 | 5853 | destroy_workqueue(phba->wq); |
| 5884 | − beiscsi_cleanup_port(phba); | |
| 5885 | 5854 | beiscsi_free_mem(phba); |
| 5886 | 5855 | |
| 5887 | 5856 | /* ctrl uninit */ |
| @@ -36,7 +36,7 @@ · 35 unmodified lines | ||
| 36 | 36 | #include <scsi/scsi_transport_iscsi.h> |
| 37 | 37 | |
| 38 | 38 | #define DRV_NAME "be2iscsi" |
| 39 | −#define BUILD_STR "11.2.0.0" | |
| 39 | +#define BUILD_STR "11.2.1.0" | |
| 40 | 40 | #define BE_NAME "Emulex OneConnect" \ |
| 41 | 41 | "Open-iSCSI Driver version" BUILD_STR |
| 42 | 42 | #define DRV_DESC BE_NAME " " "Driver" |
| @@ -57,7 +57,6 @@ · 14 unmodified lines | ||
| 57 | 57 | |
| 58 | 58 | #define BE2_IO_DEPTH 1024 |
| 59 | 59 | #define BE2_MAX_SESSIONS 256 |
| 60 | −#define BE2_CMDS_PER_CXN 128 | |
| 61 | 60 | #define BE2_TMFS 16 |
| 62 | 61 | #define BE2_NOPOUT_REQ 16 |
| 63 | 62 | #define BE2_SGE 32 |
| @@ -72,8 +71,13 @@ · 8 unmodified lines | ||
| 72 | 71 | |
| 73 | 72 | #define BEISCSI_SGLIST_ELEMENTS 30 |
| 74 | 73 | |
| 75 | −#define BEISCSI_CMD_PER_LUN 128 /* scsi_host->cmd_per_lun */ | |
| 76 | −#define BEISCSI_MAX_SECTORS 1024 /* scsi_host->max_sectors */ | |
| 74 | +/** | |
| 75 | + * BE_INVLDT_CMD_TBL_SZ is 128 which is total number commands that can | |
| 76 | + * be invalidated at a time, consider it before changing the value of | |
| 77 | + * BEISCSI_CMD_PER_LUN. | |
| 78 | + */ | |
| 79 | +#define BEISCSI_CMD_PER_LUN 128 /* scsi_host->cmd_per_lun */ | |
| 80 | +#define BEISCSI_MAX_SECTORS 1024 /* scsi_host->max_sectors */ | |
| 77 | 81 | #define BEISCSI_TEMPLATE_HDR_PER_CXN_SIZE 128 /* Template size per cxn */ |
| 78 | 82 | |
| 79 | 83 | #define BEISCSI_MAX_CMD_LEN 16 /* scsi_host->max_cmd_len */ |
| @@ -239,19 +243,7 @@ struct hba_parameters { · 159 unmodified lines | ||
| 239 | 243 | unsigned int num_cq_entries; |
| 240 | 244 | unsigned int num_eq_entries; |
| 241 | 245 | unsigned int wrbs_per_cxn; |
| 242 | − unsigned int crashmode; | |
| 243 | − unsigned int hba_num; | |
| 244 | − | |
| 245 | − unsigned int mgmt_ws_sz; | |
| 246 | 246 | unsigned int hwi_ws_sz; |
| 247 | − | |
| 248 | − unsigned int eto; | |
| 249 | − unsigned int ldto; | |
| 250 | − | |
| 251 | − unsigned int dbg_flags; | |
| 252 | − unsigned int num_cxn; | |
| 253 | − | |
| 254 | − unsigned int eq_timer; | |
| 255 | 247 | /** |
| 256 | 248 | * These are calculated from other params. They're here |
| 257 | 249 | * for debug purposes |
| @@ -272,11 +264,6 @@ struct hba_parameters { · 14 unmodified lines | ||
| 272 | 264 | unsigned int num_sge; |
| 273 | 265 | }; |
| 274 | 266 | |
| 275 | −struct invalidate_command_table { | |
| 276 | − unsigned short icd; | |
| 277 | − unsigned short cid; | |
| 278 | −} __packed; | |
| 279 | − | |
| 280 | 267 | #define BEISCSI_GET_ULP_FROM_CRI(phwi_ctrlr, cri) \ |
| 281 | 268 | (phwi_ctrlr->wrb_context[cri].ulp_num) |
| 282 | 269 | struct hwi_wrb_context { |
| @@ -334,7 +321,6 @@ struct beiscsi_hba { · 51 unmodified lines | ||
| 334 | 321 | struct be_bus_address pci_pa; /* CSR */ |
| 335 | 322 | /* PCI representation of our HBA */ |
| 336 | 323 | struct pci_dev *pcidev; |
| 337 | − unsigned short asic_revision; | |
| 338 | 324 | unsigned int num_cpus; |
| 339 | 325 | unsigned int nxt_cqid; |
| 340 | 326 | struct msix_entry msix_entries[MAX_CPUS]; |
| @@ -355,9 +341,9 @@ struct beiscsi_hba { · 14 unmodified lines | ||
| 355 | 341 | spinlock_t io_sgl_lock; |
| 356 | 342 | spinlock_t mgmt_sgl_lock; |
| 357 | 343 | spinlock_t async_pdu_lock; |
| 358 | − unsigned int age; | |
| 359 | 344 | struct list_head hba_queue; |
| 360 | 345 | #define BE_MAX_SESSION 2048 |
| 346 | +#define BE_INVALID_CID 0xffff | |
| 361 | 347 | #define BE_SET_CID_TO_CRI(cri_index, cid) \ |
| 362 | 348 | (phba->cid_to_cri_map[cid] = cri_index) |
| 363 | 349 | #define BE_GET_CRI_FROM_CID(cid) (phba->cid_to_cri_map[cid]) |
| @@ -425,12 +411,10 @@ struct beiscsi_hba { · 61 unmodified lines | ||
| 425 | 411 | u8 port_name; |
| 426 | 412 | u8 port_speed; |
| 427 | 413 | char fw_ver_str[BEISCSI_VER_STRLEN]; |
| 428 | − char wq_name[20]; | |
| 429 | 414 | struct workqueue_struct *wq; /* The actuak work queue */ |
| 430 | 415 | struct be_ctrl_info ctrl; |
| 431 | 416 | unsigned int generation; |
| 432 | 417 | unsigned int interface_handle; |
| 433 | − struct invalidate_command_table inv_tbl[128]; | |
| 434 | 418 | |
| 435 | 419 | struct be_aic_obj aic_obj[MAX_CPUS]; |
| 436 | 420 | unsigned int attr_log_enable; |
| @@ -525,10 +509,6 @@ struct beiscsi_io_task { · 88 unmodified lines | ||
| 525 | 509 | struct scsi_cmnd *scsi_cmnd; |
| 526 | 510 | int num_sg; |
| 527 | 511 | struct hwi_wrb_context *pwrb_context; |
| 528 | − unsigned int cmd_sn; | |
| 529 | − unsigned int flags; | |
| 530 | − unsigned short cid; | |
| 531 | − unsigned short header_len; | |
| 532 | 512 | itt_t libiscsi_itt; |
| 533 | 513 | struct be_cmd_bhs *cmd_bhs; |
| 534 | 514 | struct be_bus_address bhs_pa; |
| @@ -842,7 +822,7 @@ struct amap_iscsi_wrb_v2 { · 307 unmodified lines | ||
| 842 | 822 | u8 diff_enbl; /* DWORD 11 */ |
| 843 | 823 | u8 u_run; /* DWORD 11 */ |
| 844 | 824 | u8 o_run; /* DWORD 11 */ |
| 845 | − u8 invalid; /* DWORD 11 */ | |
| 825 | + u8 invld; /* DWORD 11 */ | |
| 846 | 826 | u8 dsp; /* DWORD 11 */ |
| 847 | 827 | u8 dmsg; /* DWORD 11 */ |
| 848 | 828 | u8 rsvd4; /* DWORD 11 */ |
| @@ -1042,10 +1022,8 @@ struct hwi_controller { · 193 unmodified lines | ||
| 1042 | 1022 | struct list_head io_sgl_list; |
| 1043 | 1023 | struct list_head eh_sgl_list; |
| 1044 | 1024 | struct sgl_handle *psgl_handle_base; |
| 1045 | − unsigned int wrb_mem_index; | |
| 1046 | 1025 | |
| 1047 | 1026 | struct hwi_wrb_context *wrb_context; |
| 1048 | − struct mcc_wrb *pmcc_wrb_base; | |
| 1049 | 1027 | struct be_ring default_pdu_hdr[BEISCSI_ULP_COUNT]; |
| 1050 | 1028 | struct be_ring default_pdu_data[BEISCSI_ULP_COUNT]; |
| 1051 | 1029 | struct hwi_context_memory *phwi_ctxt; |
| @@ -1062,9 +1040,7 @@ enum hwh_type_enum { · 10 unmodified lines | ||
| 1062 | 1040 | }; |
| 1063 | 1041 | |
| 1064 | 1042 | struct wrb_handle { |
| 1065 | − enum hwh_type_enum type; | |
| 1066 | 1043 | unsigned short wrb_index; |
| 1067 | − | |
| 1068 | 1044 | struct iscsi_task *pio_handle; |
| 1069 | 1045 | struct iscsi_wrb *pwrb; |
| 1070 | 1046 | }; |
| @@ -66,7 +66,6 @@ unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl, · 65 unmodified lines | ||
| 66 | 66 | struct bsg_job *job, |
| 67 | 67 | struct be_dma_mem *nonemb_cmd) |
| 68 | 68 | { |
| 69 | − struct be_cmd_resp_hdr *resp; | |
| 70 | 69 | struct be_mcc_wrb *wrb; |
| 71 | 70 | struct be_sge *mcc_sge; |
| 72 | 71 | unsigned int tag = 0; |
| @@ -76,7 +75,6 @@ unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl, · 3 unmodified lines | ||
| 76 | 75 | |
| 77 | 76 | nonemb_cmd->size = job->request_payload.payload_len; |
| 78 | 77 | memset(nonemb_cmd->va, 0, nonemb_cmd->size); |
| 79 | − resp = nonemb_cmd->va; | |
| 80 | 78 | region = bsg_req->rqst_data.h_vendor.vendor_cmd[1]; |
| 81 | 79 | sector_size = bsg_req->rqst_data.h_vendor.vendor_cmd[2]; |
| 82 | 80 | sector = bsg_req->rqst_data.h_vendor.vendor_cmd[3]; |
| @@ -128,50 +126,6 @@ unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl, · 45 unmodified lines | ||
| 128 | 126 | return tag; |
| 129 | 127 | } |
| 130 | 128 | |
| 131 | −unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba, | |
| 132 | − struct invalidate_command_table *inv_tbl, | |
| 133 | − unsigned int num_invalidate, unsigned int cid, | |
| 134 | − struct be_dma_mem *nonemb_cmd) | |
| 135 | − | |
| 136 | −{ | |
| 137 | − struct be_ctrl_info *ctrl = &phba->ctrl; | |
| 138 | − struct be_mcc_wrb *wrb; | |
| 139 | − struct be_sge *sge; | |
| 140 | − struct invalidate_commands_params_in *req; | |
| 141 | − unsigned int i, tag; | |
| 142 | − | |
| 143 | − mutex_lock(&ctrl->mbox_lock); | |
| 144 | − wrb = alloc_mcc_wrb(phba, &tag); | |
| 145 | − if (!wrb) { | |
| 146 | − mutex_unlock(&ctrl->mbox_lock); | |
| 147 | − return 0; | |
| 148 | − } | |
| 149 | − | |
| 150 | − req = nonemb_cmd->va; | |
| 151 | − memset(req, 0, sizeof(*req)); | |
| 152 | − sge = nonembedded_sgl(wrb); | |
| 153 | − | |
| 154 | − be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); | |
| 155 | − be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, | |
| 156 | − OPCODE_COMMON_ISCSI_ERROR_RECOVERY_INVALIDATE_COMMANDS, | |
| 157 | − sizeof(*req)); | |
| 158 | − req->ref_handle = 0; | |
| 159 | − req->cleanup_type = CMD_ISCSI_COMMAND_INVALIDATE; | |
| 160 | − for (i = 0; i < num_invalidate; i++) { | |
| 161 | − req->table[i].icd = inv_tbl->icd; | |
| 162 | − req->table[i].cid = inv_tbl->cid; | |
| 163 | − req->icd_count++; | |
| 164 | − inv_tbl++; | |
| 165 | − } | |
| 166 | − sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); | |
| 167 | − sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); | |
| 168 | − sge->len = cpu_to_le32(nonemb_cmd->size); | |
| 169 | − | |
| 170 | − be_mcc_notify(phba, tag); | |
| 171 | − mutex_unlock(&ctrl->mbox_lock); | |
| 172 | − return tag; | |
| 173 | −} | |
| 174 | − | |
| 175 | 129 | unsigned int mgmt_invalidate_connection(struct beiscsi_hba *phba, |
| 176 | 130 | struct beiscsi_endpoint *beiscsi_ep, |
| 177 | 131 | unsigned short cid, |
| @@ -1066,7 +1020,6 @@ unsigned int beiscsi_boot_reopen_sess(struct beiscsi_hba *phba) · 888 unmodified lines | ||
| 1066 | 1020 | unsigned int beiscsi_boot_get_sinfo(struct beiscsi_hba *phba) |
| 1067 | 1021 | { |
| 1068 | 1022 | struct be_ctrl_info *ctrl = &phba->ctrl; |
| 1069 | − struct be_cmd_get_session_resp *resp; | |
| 1070 | 1023 | struct be_cmd_get_session_req *req; |
| 1071 | 1024 | struct be_dma_mem *nonemb_cmd; |
| 1072 | 1025 | struct be_mcc_wrb *wrb; |
| @@ -1081,7 +1034,7 @@ unsigned int beiscsi_boot_get_sinfo(struct beiscsi_hba *phba) · 8 unmodified lines | ||
| 1081 | 1034 | } |
| 1082 | 1035 | |
| 1083 | 1036 | nonemb_cmd = &phba->boot_struct.nonemb_cmd; |
| 1084 | − nonemb_cmd->size = sizeof(*resp); | |
| 1037 | + nonemb_cmd->size = sizeof(struct be_cmd_get_session_resp); | |
| 1085 | 1038 | nonemb_cmd->va = pci_alloc_consistent(phba->ctrl.pdev, |
| 1086 | 1039 | nonemb_cmd->size, |
| 1087 | 1040 | &nonemb_cmd->dma); |
| @@ -1096,7 +1049,7 @@ unsigned int beiscsi_boot_get_sinfo(struct beiscsi_hba *phba) · 8 unmodified lines | ||
| 1096 | 1049 | be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); |
| 1097 | 1050 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, |
| 1098 | 1051 | OPCODE_ISCSI_INI_SESSION_GET_A_SESSION, |
| 1099 | − sizeof(*resp)); | |
| 1052 | + sizeof(struct be_cmd_get_session_resp)); | |
| 1100 | 1053 | req->session_handle = phba->boot_struct.s_handle; |
| 1101 | 1054 | sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); |
| 1102 | 1055 | sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); |
| @@ -1309,7 +1262,8 @@ beiscsi_adap_family_disp(struct device *dev, struct device_attribute *attr, · 206 unmodified lines | ||
| 1309 | 1262 | case BE_DEVICE_ID1: |
| 1310 | 1263 | case OC_DEVICE_ID1: |
| 1311 | 1264 | case OC_DEVICE_ID2: |
| 1312 | − return snprintf(buf, PAGE_SIZE, "BE2 Adapter Family\n"); | |
| 1265 | + return snprintf(buf, PAGE_SIZE, | |
| 1266 | + "Obsolete/Unsupported BE2 Adapter Family\n"); | |
| 1313 | 1267 | break; |
| 1314 | 1268 | case BE_DEVICE_ID2: |
| 1315 | 1269 | case OC_DEVICE_ID3: |
| @@ -1341,7 +1295,7 @@ beiscsi_phys_port_disp(struct device *dev, struct device_attribute *attr, · 25 unmodified lines | ||
| 1341 | 1295 | struct Scsi_Host *shost = class_to_shost(dev); |
| 1342 | 1296 | struct beiscsi_hba *phba = iscsi_host_priv(shost); |
| 1343 | 1297 | |
| 1344 | − return snprintf(buf, PAGE_SIZE, "Port Identifier : %d\n", | |
| 1298 | + return snprintf(buf, PAGE_SIZE, "Port Identifier : %u\n", | |
| 1345 | 1299 | phba->fw_config.phys_port); |
| 1346 | 1300 | } |
| 1347 | 1301 | |
| @@ -1494,3 +1448,64 @@ void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params, · 146 unmodified lines | ||
| 1494 | 1448 | (params->dw[offsetof(struct amap_beiscsi_offload_params, |
| 1495 | 1449 | exp_statsn) / 32] + 1)); |
| 1496 | 1450 | } |
| 1451 | + | |
| 1452 | +int beiscsi_mgmt_invalidate_icds(struct beiscsi_hba *phba, | |
| 1453 | + struct invldt_cmd_tbl *inv_tbl, | |
| 1454 | + unsigned int nents) | |
| 1455 | +{ | |
| 1456 | + struct be_ctrl_info *ctrl = &phba->ctrl; | |
| 1457 | + struct invldt_cmds_params_in *req; | |
| 1458 | + struct be_dma_mem nonemb_cmd; | |
| 1459 | + struct be_mcc_wrb *wrb; | |
| 1460 | + unsigned int i, tag; | |
| 1461 | + struct be_sge *sge; | |
| 1462 | + int rc; | |
| 1463 | + | |
| 1464 | + if (!nents || nents > BE_INVLDT_CMD_TBL_SZ) | |
| 1465 | + return -EINVAL; | |
| 1466 | + | |
| 1467 | + nonemb_cmd.size = sizeof(union be_invldt_cmds_params); | |
| 1468 | + nonemb_cmd.va = pci_zalloc_consistent(phba->ctrl.pdev, | |
| 1469 | + nonemb_cmd.size, | |
| 1470 | + &nonemb_cmd.dma); | |
| 1471 | + if (!nonemb_cmd.va) { | |
| 1472 | + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_EH, | |
| 1473 | + "BM_%d : invldt_cmds_params alloc failed\n"); | |
| 1474 | + return -ENOMEM; | |
| 1475 | + } | |
| 1476 | + | |
| 1477 | + mutex_lock(&ctrl->mbox_lock); | |
| 1478 | + wrb = alloc_mcc_wrb(phba, &tag); | |
| 1479 | + if (!wrb) { | |
| 1480 | + mutex_unlock(&ctrl->mbox_lock); | |
| 1481 | + pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, | |
| 1482 | + nonemb_cmd.va, nonemb_cmd.dma); | |
| 1483 | + return -ENOMEM; | |
| 1484 | + } | |
| 1485 | + | |
| 1486 | + req = nonemb_cmd.va; | |
| 1487 | + be_wrb_hdr_prepare(wrb, nonemb_cmd.size, false, 1); | |
| 1488 | + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, | |
| 1489 | + OPCODE_COMMON_ISCSI_ERROR_RECOVERY_INVALIDATE_COMMANDS, | |
| 1490 | + sizeof(*req)); | |
| 1491 | + req->ref_handle = 0; | |
| 1492 | + req->cleanup_type = CMD_ISCSI_COMMAND_INVALIDATE; | |
| 1493 | + for (i = 0; i < nents; i++) { | |
| 1494 | + req->table[i].icd = inv_tbl[i].icd; | |
| 1495 | + req->table[i].cid = inv_tbl[i].cid; | |
| 1496 | + req->icd_count++; | |
| 1497 | + } | |
| 1498 | + sge = nonembedded_sgl(wrb); | |
| 1499 | + sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma)); | |
| 1500 | + sge->pa_lo = cpu_to_le32(lower_32_bits(nonemb_cmd.dma)); | |
| 1501 | + sge->len = cpu_to_le32(nonemb_cmd.size); | |
| 1502 | + | |
| 1503 | + be_mcc_notify(phba, tag); | |
| 1504 | + mutex_unlock(&ctrl->mbox_lock); | |
| 1505 | + | |
| 1506 | + rc = beiscsi_mccq_compl_wait(phba, tag, NULL, &nonemb_cmd); | |
| 1507 | + if (rc != -EBUSY) | |
| 1508 | + pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, | |
| 1509 | + nonemb_cmd.va, nonemb_cmd.dma); | |
| 1510 | + return rc; | |
| 1511 | +} | |
| @@ -36,66 +36,6 @@ · 35 unmodified lines | ||
| 36 | 36 | #define PCICFG_UE_STATUS_MASK_LOW 0xA8 |
| 37 | 37 | #define PCICFG_UE_STATUS_MASK_HI 0xAC |
| 38 | 38 | |
| 39 | −/** | |
| 40 | − * Pseudo amap definition in which each bit of the actual structure is defined | |
| 41 | − * as a byte: used to calculate offset/shift/mask of each field | |
| 42 | − */ | |
| 43 | −struct amap_mcc_sge { | |
| 44 | − u8 pa_lo[32]; /* dword 0 */ | |
| 45 | − u8 pa_hi[32]; /* dword 1 */ | |
| 46 | − u8 length[32]; /* DWORD 2 */ | |
| 47 | −} __packed; | |
| 48 | − | |
| 49 | −/** | |
| 50 | − * Pseudo amap definition in which each bit of the actual structure is defined | |
| 51 | − * as a byte: used to calculate offset/shift/mask of each field | |
| 52 | − */ | |
| 53 | −struct amap_mcc_wrb_payload { | |
| 54 | − union { | |
| 55 | − struct amap_mcc_sge sgl[19]; | |
| 56 | − u8 embedded[59 * 32]; /* DWORDS 57 to 115 */ | |
| 57 | − } u; | |
| 58 | −} __packed; | |
| 59 | − | |
| 60 | −/** | |
| 61 | − * Pseudo amap definition in which each bit of the actual structure is defined | |
| 62 | − * as a byte: used to calculate offset/shift/mask of each field | |
| 63 | − */ | |
| 64 | −struct amap_mcc_wrb { | |
| 65 | − u8 embedded; /* DWORD 0 */ | |
| 66 | − u8 rsvd0[2]; /* DWORD 0 */ | |
| 67 | − u8 sge_count[5]; /* DWORD 0 */ | |
| 68 | − u8 rsvd1[16]; /* DWORD 0 */ | |
| 69 | − u8 special[8]; /* DWORD 0 */ | |
| 70 | − u8 payload_length[32]; | |
| 71 | − u8 tag[64]; /* DWORD 2 */ | |
| 72 | − u8 rsvd2[32]; /* DWORD 4 */ | |
| 73 | − struct amap_mcc_wrb_payload payload; | |
| 74 | −}; | |
| 75 | − | |
| 76 | −struct mcc_sge { | |
| 77 | − u32 pa_lo; /* dword 0 */ | |
| 78 | − u32 pa_hi; /* dword 1 */ | |
| 79 | − u32 length; /* DWORD 2 */ | |
| 80 | −} __packed; | |
| 81 | − | |
| 82 | −struct mcc_wrb_payload { | |
| 83 | − union { | |
| 84 | − struct mcc_sge sgl[19]; | |
| 85 | − u32 embedded[59]; /* DWORDS 57 to 115 */ | |
| 86 | − } u; | |
| 87 | −} __packed; | |
| 88 | − | |
| 89 | −#define MCC_WRB_EMBEDDED_MASK 0x00000001 | |
| 90 | − | |
| 91 | −struct mcc_wrb { | |
| 92 | − u32 dw[0]; /* DWORD 0 */ | |
| 93 | − u32 payload_length; | |
| 94 | − u32 tag[2]; /* DWORD 2 */ | |
| 95 | − u32 rsvd2[1]; /* DWORD 4 */ | |
| 96 | − struct mcc_wrb_payload payload; | |
| 97 | −}; | |
| 98 | − | |
| 99 | 39 | int mgmt_open_connection(struct beiscsi_hba *phba, |
| 100 | 40 | struct sockaddr *dst_addr, |
| 101 | 41 | struct beiscsi_endpoint *beiscsi_ep, |
| @@ -104,10 +44,6 @@ int mgmt_open_connection(struct beiscsi_hba *phba, · 2 unmodified lines | ||
| 104 | 44 | unsigned int mgmt_upload_connection(struct beiscsi_hba *phba, |
| 105 | 45 | unsigned short cid, |
| 106 | 46 | unsigned int upload_flag); |
| 107 | −unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba, | |
| 108 | − struct invalidate_command_table *inv_tbl, | |
| 109 | − unsigned int num_invalidate, unsigned int cid, | |
| 110 | − struct be_dma_mem *nonemb_cmd); | |
| 111 | 47 | unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl, |
| 112 | 48 | struct beiscsi_hba *phba, |
| 113 | 49 | struct bsg_job *job, |
| @@ -134,24 +70,31 @@ union iscsi_invalidate_connection_params { · 20 unmodified lines | ||
| 134 | 70 | struct iscsi_invalidate_connection_params_out response; |
| 135 | 71 | } __packed; |
| 136 | 72 | |
| 137 | −struct invalidate_commands_params_in { | |
| 73 | +#define BE_INVLDT_CMD_TBL_SZ 128 | |
| 74 | +struct invldt_cmd_tbl { | |
| 75 | + unsigned short icd; | |
| 76 | + unsigned short cid; | |
| 77 | +} __packed; | |
| 78 | + | |
| 79 | +struct invldt_cmds_params_in { | |
| 138 | 80 | struct be_cmd_req_hdr hdr; |
| 139 | 81 | unsigned int ref_handle; |
| 140 | 82 | unsigned int icd_count; |
| 141 | − struct invalidate_command_table table[128]; | |
| 83 | + struct invldt_cmd_tbl table[BE_INVLDT_CMD_TBL_SZ]; | |
| 142 | 84 | unsigned short cleanup_type; |
| 143 | 85 | unsigned short unused; |
| 144 | 86 | } __packed; |
| 145 | 87 | |
| 146 | −struct invalidate_commands_params_out { | |
| 88 | +struct invldt_cmds_params_out { | |
| 89 | + struct be_cmd_resp_hdr hdr; | |
| 147 | 90 | unsigned int ref_handle; |
| 148 | 91 | unsigned int icd_count; |
| 149 | − unsigned int icd_status[128]; | |
| 92 | + unsigned int icd_status[BE_INVLDT_CMD_TBL_SZ]; | |
| 150 | 93 | } __packed; |
| 151 | 94 | |
| 152 | −union invalidate_commands_params { | |
| 153 | − struct invalidate_commands_params_in request; | |
| 154 | − struct invalidate_commands_params_out response; | |
| 95 | +union be_invldt_cmds_params { | |
| 96 | + struct invldt_cmds_params_in request; | |
| 97 | + struct invldt_cmds_params_out response; | |
| 155 | 98 | } __packed; |
| 156 | 99 | |
| 157 | 100 | struct mgmt_hba_attributes { |
| @@ -231,16 +174,6 @@ struct be_bsg_vendor_cmd { · 73 unmodified lines | ||
| 231 | 174 | |
| 232 | 175 | #define GET_MGMT_CONTROLLER_WS(phba) (phba->pmgmt_ws) |
| 233 | 176 | |
| 234 | −/* MGMT CMD flags */ | |
| 235 | − | |
| 236 | −#define MGMT_CMDH_FREE (1<<0) | |
| 237 | − | |
| 238 | −/* --- MGMT_ERROR_CODES --- */ | |
| 239 | −/* Error Codes returned in the status field of the CMD response header */ | |
| 240 | −#define MGMT_STATUS_SUCCESS 0 /* The CMD completed without errors */ | |
| 241 | −#define MGMT_STATUS_FAILED 1 /* Error status in the Status field of */ | |
| 242 | − /* the CMD_RESPONSE_HEADER */ | |
| 243 | − | |
| 244 | 177 | #define ISCSI_GET_PDU_TEMPLATE_ADDRESS(pc, pa) {\ |
| 245 | 178 | pa->lo = phba->init_mem[ISCSI_MEM_GLOBAL_HEADER].mem_array[0].\ |
| 246 | 179 | bus_address.u.a32.address_lo; \ |
| @@ -270,6 +203,9 @@ unsigned int mgmt_invalidate_connection(struct beiscsi_hba *phba, · 23 unmodified lines | ||
| 270 | 203 | unsigned short cid, |
| 271 | 204 | unsigned short issue_reset, |
| 272 | 205 | unsigned short savecfg_flag); |
| 206 | +int beiscsi_mgmt_invalidate_icds(struct beiscsi_hba *phba, | |
| 207 | + struct invldt_cmd_tbl *inv_tbl, | |
| 208 | + unsigned int nents); | |
| 273 | 209 | |
| 274 | 210 | int beiscsi_if_en_dhcp(struct beiscsi_hba *phba, u32 ip_type); |
| 275 | 211 | |
| @@ -27,24 +27,6 @@ · 26 unmodified lines | ||
| 27 | 27 | |
| 28 | 28 | BFA_TRC_FILE(FCS, FCS); |
| 29 | 29 | |
| 30 | −/* | |
| 31 | − * FCS sub-modules | |
| 32 | − */ | |
| 33 | −struct bfa_fcs_mod_s { | |
| 34 | − void (*attach) (struct bfa_fcs_s *fcs); | |
| 35 | − void (*modinit) (struct bfa_fcs_s *fcs); | |
| 36 | − void (*modexit) (struct bfa_fcs_s *fcs); | |
| 37 | −}; | |
| 38 | − | |
| 39 | −#define BFA_FCS_MODULE(_mod) { _mod ## _modinit, _mod ## _modexit } | |
| 40 | − | |
| 41 | −static struct bfa_fcs_mod_s fcs_modules[] = { | |
| 42 | − { bfa_fcs_port_attach, NULL, NULL }, | |
| 43 | − { bfa_fcs_uf_attach, NULL, NULL }, | |
| 44 | − { bfa_fcs_fabric_attach, bfa_fcs_fabric_modinit, | |
| 45 | − bfa_fcs_fabric_modexit }, | |
| 46 | −}; | |
| 47 | − | |
| 48 | 30 | /* |
| 49 | 31 | * fcs_api BFA FCS API |
| 50 | 32 | */ |
| @@ -58,52 +40,19 @@ bfa_fcs_exit_comp(void *fcs_cbarg) · 7 unmodified lines | ||
| 58 | 40 | complete(&bfad->comp); |
| 59 | 41 | } |
| 60 | 42 | |
| 61 | − | |
| 62 | − | |
| 63 | 43 | /* |
| 64 | − * fcs_api BFA FCS API | |
| 65 | − */ | |
| 66 | − | |
| 67 | −/* | |
| 68 | − * fcs attach -- called once to initialize data structures at driver attach time | |
| 44 | + * fcs initialization, called once after bfa initialization is complete | |
| 69 | 45 | */ |
| 70 | 46 | void |
| 71 | −bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad, | |
| 72 | − bfa_boolean_t min_cfg) | |
| 47 | +bfa_fcs_init(struct bfa_fcs_s *fcs) | |
| 73 | 48 | { |
| 74 | − int i; | |
| 75 | − struct bfa_fcs_mod_s *mod; | |
| 76 | − | |
| 77 | − fcs->bfa = bfa; | |
| 78 | − fcs->bfad = bfad; | |
| 79 | − fcs->min_cfg = min_cfg; | |
| 80 | − fcs->num_rport_logins = 0; | |
| 81 | − | |
| 82 | − bfa->fcs = BFA_TRUE; | |
| 83 | − fcbuild_init(); | |
| 84 | − | |
| 85 | − for (i = 0; i < ARRAY_SIZE(fcs_modules); i++) { | |
| 86 | − mod = &fcs_modules[i]; | |
| 87 | − if (mod->attach) | |
| 88 | − mod->attach(fcs); | |
| 89 | − } | |
| 49 | + bfa_sm_send_event(&fcs->fabric, BFA_FCS_FABRIC_SM_CREATE); | |
| 50 | + bfa_trc(fcs, 0); | |
| 90 | 51 | } |
| 91 | 52 | |
| 92 | 53 | /* |
| 93 | − * fcs initialization, called once after bfa initialization is complete | |
| 54 | + * fcs_api BFA FCS API | |
| 94 | 55 | */ |
| 95 | −void | |
| 96 | −bfa_fcs_init(struct bfa_fcs_s *fcs) | |
| 97 | −{ | |
| 98 | − int i; | |
| 99 | − struct bfa_fcs_mod_s *mod; | |
| 100 | − | |
| 101 | − for (i = 0; i < ARRAY_SIZE(fcs_modules); i++) { | |
| 102 | − mod = &fcs_modules[i]; | |
| 103 | − if (mod->modinit) | |
| 104 | − mod->modinit(fcs); | |
| 105 | − } | |
| 106 | −} | |
| 107 | 56 | |
| 108 | 57 | /* |
| 109 | 58 | * FCS update cfg - reset the pwwn/nwwn of fabric base logical port |
| @@ -180,26 +129,14 @@ bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs, · 70 unmodified lines | ||
| 180 | 129 | void |
| 181 | 130 | bfa_fcs_exit(struct bfa_fcs_s *fcs) |
| 182 | 131 | { |
| 183 | − struct bfa_fcs_mod_s *mod; | |
| 184 | − int nmods, i; | |
| 185 | − | |
| 186 | 132 | bfa_wc_init(&fcs->wc, bfa_fcs_exit_comp, fcs); |
| 187 | − | |
| 188 | − nmods = ARRAY_SIZE(fcs_modules); | |
| 189 | − | |
| 190 | − for (i = 0; i < nmods; i++) { | |
| 191 | − | |
| 192 | − mod = &fcs_modules[i]; | |
| 193 | − if (mod->modexit) { | |
| 194 | − bfa_wc_up(&fcs->wc); | |
| 195 | − mod->modexit(fcs); | |
| 196 | − } | |
| 197 | − } | |
| 198 | − | |
| 133 | + bfa_wc_up(&fcs->wc); | |
| 134 | + bfa_trc(fcs, 0); | |
| 135 | + bfa_lps_delete(fcs->fabric.lps); | |
| 136 | + bfa_sm_send_event(&fcs->fabric, BFA_FCS_FABRIC_SM_DELETE); | |
| 199 | 137 | bfa_wc_wait(&fcs->wc); |
| 200 | 138 | } |
| 201 | 139 | |
| 202 | − | |
| 203 | 140 | /* |
| 204 | 141 | * Fabric module implementation. |
| 205 | 142 | */ |
| @@ -1127,62 +1064,6 @@ bfa_fcs_fabric_stop_comp(void *cbarg) · 921 unmodified lines | ||
| 1127 | 1064 | * fcs_fabric_public fabric public functions |
| 1128 | 1065 | */ |
| 1129 | 1066 | |
| 1130 | −/* | |
| 1131 | − * Attach time initialization. | |
| 1132 | − */ | |
| 1133 | −void | |
| 1134 | −bfa_fcs_fabric_attach(struct bfa_fcs_s *fcs) | |
| 1135 | −{ | |
| 1136 | − struct bfa_fcs_fabric_s *fabric; | |
| 1137 | − | |
| 1138 | − fabric = &fcs->fabric; | |
| 1139 | − memset(fabric, 0, sizeof(struct bfa_fcs_fabric_s)); | |
| 1140 | − | |
| 1141 | − /* | |
| 1142 | − * Initialize base fabric. | |
| 1143 | − */ | |
| 1144 | − fabric->fcs = fcs; | |
| 1145 | − INIT_LIST_HEAD(&fabric->vport_q); | |
| 1146 | − INIT_LIST_HEAD(&fabric->vf_q); | |
| 1147 | − fabric->lps = bfa_lps_alloc(fcs->bfa); | |
| 1148 | − WARN_ON(!fabric->lps); | |
| 1149 | − | |
| 1150 | − /* | |
| 1151 | − * Initialize fabric delete completion handler. Fabric deletion is | |
| 1152 | − * complete when the last vport delete is complete. | |
| 1153 | − */ | |
| 1154 | − bfa_wc_init(&fabric->wc, bfa_fcs_fabric_delete_comp, fabric); | |
| 1155 | − bfa_wc_up(&fabric->wc); /* For the base port */ | |
| 1156 | − | |
| 1157 | − bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit); | |
| 1158 | − bfa_fcs_lport_attach(&fabric->bport, fabric->fcs, FC_VF_ID_NULL, NULL); | |
| 1159 | −} | |
| 1160 | − | |
| 1161 | −void | |
| 1162 | −bfa_fcs_fabric_modinit(struct bfa_fcs_s *fcs) | |
| 1163 | −{ | |
| 1164 | − bfa_sm_send_event(&fcs->fabric, BFA_FCS_FABRIC_SM_CREATE); | |
| 1165 | − bfa_trc(fcs, 0); | |
| 1166 | −} | |
| 1167 | − | |
| 1168 | −/* | |
| 1169 | − * Module cleanup | |
| 1170 | − */ | |
| 1171 | −void | |
| 1172 | −bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs) | |
| 1173 | −{ | |
| 1174 | − struct bfa_fcs_fabric_s *fabric; | |
| 1175 | − | |
| 1176 | − bfa_trc(fcs, 0); | |
| 1177 | − | |
| 1178 | − /* | |
| 1179 | − * Cleanup base fabric. | |
| 1180 | − */ | |
| 1181 | − fabric = &fcs->fabric; | |
| 1182 | − bfa_lps_delete(fabric->lps); | |
| 1183 | − bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELETE); | |
| 1184 | −} | |
| 1185 | − | |
| 1186 | 1067 | /* |
| 1187 | 1068 | * Fabric module stop -- stop FCS actions |
| 1188 | 1069 | */ |
| @@ -1633,12 +1514,6 @@ bfa_fcs_port_event_handler(void *cbarg, enum bfa_port_linkstate event) · 444 unmodified lines | ||
| 1633 | 1514 | } |
| 1634 | 1515 | } |
| 1635 | 1516 | |
| 1636 | −void | |
| 1637 | −bfa_fcs_port_attach(struct bfa_fcs_s *fcs) | |
| 1638 | −{ | |
| 1639 | − bfa_fcport_event_register(fcs->bfa, bfa_fcs_port_event_handler, fcs); | |
| 1640 | −} | |
| 1641 | − | |
| 1642 | 1517 | /* |
| 1643 | 1518 | * BFA FCS UF ( Unsolicited Frames) |
| 1644 | 1519 | */ |
| @@ -1706,8 +1581,44 @@ bfa_fcs_uf_recv(void *cbarg, struct bfa_uf_s *uf) · 61 unmodified lines | ||
| 1706 | 1581 | bfa_uf_free(uf); |
| 1707 | 1582 | } |
| 1708 | 1583 | |
| 1584 | +/* | |
| 1585 | + * fcs attach -- called once to initialize data structures at driver attach time | |
| 1586 | + */ | |
| 1709 | 1587 | void |
| 1710 | −bfa_fcs_uf_attach(struct bfa_fcs_s *fcs) | |
| 1588 | +bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad, | |
| 1589 | + bfa_boolean_t min_cfg) | |
| 1711 | 1590 | { |
| 1591 | + struct bfa_fcs_fabric_s *fabric = &fcs->fabric; | |
| 1592 | + | |
| 1593 | + fcs->bfa = bfa; | |
| 1594 | + fcs->bfad = bfad; | |
| 1595 | + fcs->min_cfg = min_cfg; | |
| 1596 | + fcs->num_rport_logins = 0; | |
| 1597 | + | |
| 1598 | + bfa->fcs = BFA_TRUE; | |
| 1599 | + fcbuild_init(); | |
| 1600 | + | |
| 1601 | + bfa_fcport_event_register(fcs->bfa, bfa_fcs_port_event_handler, fcs); | |
| 1712 | 1602 | bfa_uf_recv_register(fcs->bfa, bfa_fcs_uf_recv, fcs); |
| 1603 | + | |
| 1604 | + memset(fabric, 0, sizeof(struct bfa_fcs_fabric_s)); | |
| 1605 | + | |
| 1606 | + /* | |
| 1607 | + * Initialize base fabric. | |
| 1608 | + */ | |
| 1609 | + fabric->fcs = fcs; | |
| 1610 | + INIT_LIST_HEAD(&fabric->vport_q); | |
| 1611 | + INIT_LIST_HEAD(&fabric->vf_q); | |
| 1612 | + fabric->lps = bfa_lps_alloc(fcs->bfa); | |
| 1613 | + WARN_ON(!fabric->lps); | |
| 1614 | + | |
| 1615 | + /* | |
| 1616 | + * Initialize fabric delete completion handler. Fabric deletion is | |
| 1617 | + * complete when the last vport delete is complete. | |
| 1618 | + */ | |
| 1619 | + bfa_wc_init(&fabric->wc, bfa_fcs_fabric_delete_comp, fabric); | |
| 1620 | + bfa_wc_up(&fabric->wc); /* For the base port */ | |
| 1621 | + | |
| 1622 | + bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit); | |
| 1623 | + bfa_fcs_lport_attach(&fabric->bport, fabric->fcs, FC_VF_ID_NULL, NULL); | |
| 1713 | 1624 | } |
| @@ -808,9 +808,7 @@ void bfa_fcs_vf_get_ports(bfa_fcs_vf_t *vf, wwn_t vpwwn[], int *nports); · 807 unmodified lines | ||
| 808 | 808 | /* |
| 809 | 809 | * fabric protected interface functions |
| 810 | 810 | */ |
| 811 | −void bfa_fcs_fabric_attach(struct bfa_fcs_s *fcs); | |
| 812 | 811 | void bfa_fcs_fabric_modinit(struct bfa_fcs_s *fcs); |
| 813 | −void bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs); | |
| 814 | 812 | void bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s *fabric); |
| 815 | 813 | void bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric); |
| 816 | 814 | void bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s *fabric, |
| @@ -827,8 +825,6 @@ void bfa_fcs_fabric_nsymb_init(struct bfa_fcs_fabric_s *fabric); · 10 unmodified lines | ||
| 827 | 825 | void bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric, |
| 828 | 826 | wwn_t fabric_name); |
| 829 | 827 | u16 bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric); |
| 830 | −void bfa_fcs_uf_attach(struct bfa_fcs_s *fcs); | |
| 831 | −void bfa_fcs_port_attach(struct bfa_fcs_s *fcs); | |
| 832 | 828 | void bfa_fcs_fabric_modstop(struct bfa_fcs_s *fcs); |
| 833 | 829 | void bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric, |
| 834 | 830 | enum bfa_fcs_fabric_event event); |
| @@ -813,6 +813,7 @@ struct scsi_host_template bfad_im_scsi_host_template = { · 812 unmodified lines | ||
| 813 | 813 | .name = BFAD_DRIVER_NAME, |
| 814 | 814 | .info = bfad_im_info, |
| 815 | 815 | .queuecommand = bfad_im_queuecommand, |
| 816 | + .eh_timed_out = fc_eh_timed_out, | |
| 816 | 817 | .eh_abort_handler = bfad_im_abort_handler, |
| 817 | 818 | .eh_device_reset_handler = bfad_im_reset_lun_handler, |
| 818 | 819 | .eh_bus_reset_handler = bfad_im_reset_bus_handler, |
| @@ -835,6 +836,7 @@ struct scsi_host_template bfad_im_vport_template = { · 16 unmodified lines | ||
| 835 | 836 | .name = BFAD_DRIVER_NAME, |
| 836 | 837 | .info = bfad_im_info, |
| 837 | 838 | .queuecommand = bfad_im_queuecommand, |
| 839 | + .eh_timed_out = fc_eh_timed_out, | |
| 838 | 840 | .eh_abort_handler = bfad_im_abort_handler, |
| 839 | 841 | .eh_device_reset_handler = bfad_im_reset_lun_handler, |
| 840 | 842 | .eh_bus_reset_handler = bfad_im_reset_bus_handler, |
| @@ -2947,6 +2947,7 @@ static struct scsi_host_template bnx2fc_shost_template = { · 2946 unmodified lines | ||
| 2947 | 2947 | .module = THIS_MODULE, |
| 2948 | 2948 | .name = "QLogic Offload FCoE Initiator", |
| 2949 | 2949 | .queuecommand = bnx2fc_queuecommand, |
| 2950 | + .eh_timed_out = fc_eh_timed_out, | |
| 2950 | 2951 | .eh_abort_handler = bnx2fc_eh_abort, /* abts */ |
| 2951 | 2952 | .eh_device_reset_handler = bnx2fc_eh_device_reset, /* lun reset */ |
| 2952 | 2953 | .eh_target_reset_handler = bnx2fc_eh_target_reset, /* tgt reset */ |
| @@ -2259,6 +2259,7 @@ static struct scsi_host_template bnx2i_host_template = { · 2258 unmodified lines | ||
| 2259 | 2259 | .name = "QLogic Offload iSCSI Initiator", |
| 2260 | 2260 | .proc_name = "bnx2i", |
| 2261 | 2261 | .queuecommand = iscsi_queuecommand, |
| 2262 | + .eh_timed_out = iscsi_eh_cmd_timed_out, | |
| 2262 | 2263 | .eh_abort_handler = iscsi_eh_abort, |
| 2263 | 2264 | .eh_device_reset_handler = iscsi_eh_device_reset, |
| 2264 | 2265 | .eh_target_reset_handler = iscsi_eh_recover_target, |
| @@ -2270,6 +2270,7 @@ struct scsi_host_template csio_fcoe_shost_template = { · 2269 unmodified lines | ||
| 2270 | 2270 | .name = CSIO_DRV_DESC, |
| 2271 | 2271 | .proc_name = KBUILD_MODNAME, |
| 2272 | 2272 | .queuecommand = csio_queuecommand, |
| 2273 | + .eh_timed_out = fc_eh_timed_out, | |
| 2273 | 2274 | .eh_abort_handler = csio_eh_abort_handler, |
| 2274 | 2275 | .eh_device_reset_handler = csio_eh_lun_reset_handler, |
| 2275 | 2276 | .slave_alloc = csio_slave_alloc, |
| @@ -2289,6 +2290,7 @@ struct scsi_host_template csio_fcoe_shost_vport_template = { · 13 unmodified lines | ||
| 2289 | 2290 | .name = CSIO_DRV_DESC, |
| 2290 | 2291 | .proc_name = KBUILD_MODNAME, |
| 2291 | 2292 | .queuecommand = csio_queuecommand, |
| 2293 | + .eh_timed_out = fc_eh_timed_out, | |
| 2292 | 2294 | .eh_abort_handler = csio_eh_abort_handler, |
| 2293 | 2295 | .eh_device_reset_handler = csio_eh_lun_reset_handler, |
| 2294 | 2296 | .slave_alloc = csio_slave_alloc, |
| @@ -90,6 +90,7 @@ static struct scsi_host_template cxgb3i_host_template = { · 89 unmodified lines | ||
| 90 | 90 | .sg_tablesize = SG_ALL, |
| 91 | 91 | .max_sectors = 0xFFFF, |
| 92 | 92 | .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN, |
| 93 | + .eh_timed_out = iscsi_eh_cmd_timed_out, | |
| 93 | 94 | .eh_abort_handler = iscsi_eh_abort, |
| 94 | 95 | .eh_device_reset_handler = iscsi_eh_device_reset, |
| 95 | 96 | .eh_target_reset_handler = iscsi_eh_recover_target, |
| @@ -103,6 +103,7 @@ static struct scsi_host_template cxgb4i_host_template = { · 102 unmodified lines | ||
| 103 | 103 | .sg_tablesize = SG_ALL, |
| 104 | 104 | .max_sectors = 0xFFFF, |
| 105 | 105 | .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN, |
| 106 | + .eh_timed_out = iscsi_eh_cmd_timed_out, | |
| 106 | 107 | .eh_abort_handler = iscsi_eh_abort, |
| 107 | 108 | .eh_device_reset_handler = iscsi_eh_device_reset, |
| 108 | 109 | .eh_target_reset_handler = iscsi_eh_recover_target, |
| @@ -54,6 +54,9 @@ extern const struct file_operations cxlflash_cxl_fops; · 53 unmodified lines | ||
| 54 | 54 | /* RRQ for master issued cmds */ |
| 55 | 55 | #define NUM_RRQ_ENTRY CXLFLASH_MAX_CMDS |
| 56 | 56 | |
| 57 | +/* SQ for master issued cmds */ | |
| 58 | +#define NUM_SQ_ENTRY CXLFLASH_MAX_CMDS | |
| 59 | + | |
| 57 | 60 | |
| 58 | 61 | static inline void check_sizes(void) |
| 59 | 62 | { |
| @@ -155,8 +158,8 @@ static inline struct afu_cmd *sc_to_afucz(struct scsi_cmnd *sc) · 95 unmodified lines | ||
| 155 | 158 | |
| 156 | 159 | struct afu { |
| 157 | 160 | /* Stuff requiring alignment go first. */ |
| 158 | − | |
| 159 | − u64 rrq_entry[NUM_RRQ_ENTRY]; /* 2K RRQ */ | |
| 161 | + struct sisl_ioarcb sq[NUM_SQ_ENTRY]; /* 16K SQ */ | |
| 162 | + u64 rrq_entry[NUM_RRQ_ENTRY]; /* 2K RRQ */ | |
| 160 | 163 | |
| 161 | 164 | /* Beware of alignment till here. Preferably introduce new |
| 162 | 165 | * fields after this point |
| @@ -171,9 +174,13 @@ struct afu { · 8 unmodified lines | ||
| 171 | 174 | struct sisl_host_map __iomem *host_map; /* MC host map */ |
| 172 | 175 | struct sisl_ctrl_map __iomem *ctrl_map; /* MC control map */ |
| 173 | 176 | |
| 174 | − struct kref mapcount; | |
| 175 | − | |
| 176 | 177 | ctx_hndl_t ctx_hndl; /* master's context handle */ |
| 178 | + | |
| 179 | + atomic_t hsq_credits; | |
| 180 | + spinlock_t hsq_slock; | |
| 181 | + struct sisl_ioarcb *hsq_start; | |
| 182 | + struct sisl_ioarcb *hsq_end; | |
| 183 | + struct sisl_ioarcb *hsq_curr; | |
| 177 | 184 | u64 *hrrq_start; |
| 178 | 185 | u64 *hrrq_end; |
| 179 | 186 | u64 *hrrq_curr; |
| @@ -191,6 +198,23 @@ struct afu { · 11 unmodified lines | ||
| 191 | 198 | |
| 192 | 199 | }; |
| 193 | 200 | |
| 201 | +static inline bool afu_is_cmd_mode(struct afu *afu, u64 cmd_mode) | |
| 202 | +{ | |
| 203 | + u64 afu_cap = afu->interface_version >> SISL_INTVER_CAP_SHIFT; | |
| 204 | + | |
| 205 | + return afu_cap & cmd_mode; | |
| 206 | +} | |
| 207 | + | |
| 208 | +static inline bool afu_is_sq_cmd_mode(struct afu *afu) | |
| 209 | +{ | |
| 210 | + return afu_is_cmd_mode(afu, SISL_INTVER_CAP_SQ_CMD_MODE); | |
| 211 | +} | |
| 212 | + | |
| 213 | +static inline bool afu_is_ioarrin_cmd_mode(struct afu *afu) | |
| 214 | +{ | |
| 215 | + return afu_is_cmd_mode(afu, SISL_INTVER_CAP_IOARRIN_CMD_MODE); | |
| 216 | +} | |
| 217 | + | |
| 194 | 218 | static inline u64 lun_to_lunid(u64 lun) |
| 195 | 219 | { |
| 196 | 220 | __be64 lun_id; |
| @@ -32,11 +32,13 @@ · 31 unmodified lines | ||
| 32 | 32 | */ |
| 33 | 33 | static struct llun_info *create_local(struct scsi_device *sdev, u8 *wwid) |
| 34 | 34 | { |
| 35 | + struct cxlflash_cfg *cfg = shost_priv(sdev->host); | |
| 36 | + struct device *dev = &cfg->dev->dev; | |
| 35 | 37 | struct llun_info *lli = NULL; |
| 36 | 38 | |
| 37 | 39 | lli = kzalloc(sizeof(*lli), GFP_KERNEL); |
| 38 | 40 | if (unlikely(!lli)) { |
| 39 | − pr_err("%s: could not allocate lli\n", __func__); | |
| 41 | + dev_err(dev, "%s: could not allocate lli\n", __func__); | |
| 40 | 42 | goto out; |
| 41 | 43 | } |
| 42 | 44 | |
| @@ -58,11 +60,13 @@ out: · 15 unmodified lines | ||
| 58 | 60 | */ |
| 59 | 61 | static struct glun_info *create_global(struct scsi_device *sdev, u8 *wwid) |
| 60 | 62 | { |
| 63 | + struct cxlflash_cfg *cfg = shost_priv(sdev->host); | |
| 64 | + struct device *dev = &cfg->dev->dev; | |
| 61 | 65 | struct glun_info *gli = NULL; |
| 62 | 66 | |
| 63 | 67 | gli = kzalloc(sizeof(*gli), GFP_KERNEL); |
| 64 | 68 | if (unlikely(!gli)) { |
| 65 | − pr_err("%s: could not allocate gli\n", __func__); | |
| 69 | + dev_err(dev, "%s: could not allocate gli\n", __func__); | |
| 66 | 70 | goto out; |
| 67 | 71 | } |
| 68 | 72 | |
| @@ -129,10 +133,10 @@ static struct glun_info *lookup_global(u8 *wwid) · 60 unmodified lines | ||
| 129 | 133 | */ |
| 130 | 134 | static struct llun_info *find_and_create_lun(struct scsi_device *sdev, u8 *wwid) |
| 131 | 135 | { |
| 136 | + struct cxlflash_cfg *cfg = shost_priv(sdev->host); | |
| 137 | + struct device *dev = &cfg->dev->dev; | |
| 132 | 138 | struct llun_info *lli = NULL; |
| 133 | 139 | struct glun_info *gli = NULL; |
| 134 | − struct Scsi_Host *shost = sdev->host; | |
| 135 | − struct cxlflash_cfg *cfg = shost_priv(shost); | |
| 136 | 140 | |
| 137 | 141 | if (unlikely(!wwid)) |
| 138 | 142 | goto out; |
| @@ -165,7 +169,7 @@ static struct llun_info *find_and_create_lun(struct scsi_device *sdev, u8 *wwid) · 26 unmodified lines | ||
| 165 | 169 | list_add(&gli->list, &global.gluns); |
| 166 | 170 | |
| 167 | 171 | out: |
| 168 | − pr_debug("%s: returning %p\n", __func__, lli); | |
| 172 | + dev_dbg(dev, "%s: returning lli=%p, gli=%p\n", __func__, lli, gli); | |
| 169 | 173 | return lli; |
| 170 | 174 | } |
| 171 | 175 | |
| @@ -225,17 +229,18 @@ void cxlflash_term_global_luns(void) · 53 unmodified lines | ||
| 225 | 229 | int cxlflash_manage_lun(struct scsi_device *sdev, |
| 226 | 230 | struct dk_cxlflash_manage_lun *manage) |
| 227 | 231 | { |
| 228 | − int rc = 0; | |
| 232 | + struct cxlflash_cfg *cfg = shost_priv(sdev->host); | |
| 233 | + struct device *dev = &cfg->dev->dev; | |
| 229 | 234 | struct llun_info *lli = NULL; |
| 235 | + int rc = 0; | |
| 230 | 236 | u64 flags = manage->hdr.flags; |
| 231 | 237 | u32 chan = sdev->channel; |
| 232 | 238 | |
| 233 | 239 | mutex_lock(&global.mutex); |
| 234 | 240 | lli = find_and_create_lun(sdev, manage->wwid); |
| 235 | − pr_debug("%s: ENTER: WWID = %016llX%016llX, flags = %016llX li = %p\n", | |
| 236 | − __func__, get_unaligned_be64(&manage->wwid[0]), | |
| 237 | − get_unaligned_be64(&manage->wwid[8]), | |
| 238 | − manage->hdr.flags, lli); | |
| 241 | + dev_dbg(dev, "%s: WWID=%016llx%016llx, flags=%016llx lli=%p\n", | |
| 242 | + __func__, get_unaligned_be64(&manage->wwid[0]), | |
| 243 | + get_unaligned_be64(&manage->wwid[8]), manage->hdr.flags, lli); | |
| 239 | 244 | if (unlikely(!lli)) { |
| 240 | 245 | rc = -ENOMEM; |
| 241 | 246 | goto out; |
| @@ -265,11 +270,11 @@ int cxlflash_manage_lun(struct scsi_device *sdev, · 23 unmodified lines | ||
| 265 | 270 | } |
| 266 | 271 | } |
| 267 | 272 | |
| 268 | − pr_debug("%s: port_sel = %08X chan = %u lun_id = %016llX\n", __func__, | |
| 269 | − lli->port_sel, chan, lli->lun_id[chan]); | |
| 273 | + dev_dbg(dev, "%s: port_sel=%08x chan=%u lun_id=%016llx\n", | |
| 274 | + __func__, lli->port_sel, chan, lli->lun_id[chan]); | |
| 270 | 275 | |
| 271 | 276 | out: |
| 272 | 277 | mutex_unlock(&global.mutex); |
| 273 | − pr_debug("%s: returning rc=%d\n", __func__, rc); | |
| 278 | + dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc); | |
| 274 | 279 | return rc; |
| 275 | 280 | } |
| @@ -43,6 +43,9 @@ MODULE_LICENSE("GPL"); · 42 unmodified lines | ||
| 43 | 43 | */ |
| 44 | 44 | static void process_cmd_err(struct afu_cmd *cmd, struct scsi_cmnd *scp) |
| 45 | 45 | { |
| 46 | + struct afu *afu = cmd->parent; | |
| 47 | + struct cxlflash_cfg *cfg = afu->parent; | |
| 48 | + struct device *dev = &cfg->dev->dev; | |
| 46 | 49 | struct sisl_ioarcb *ioarcb; |
| 47 | 50 | struct sisl_ioasa *ioasa; |
| 48 | 51 | u32 resid; |
| @@ -56,21 +59,20 @@ static void process_cmd_err(struct afu_cmd *cmd, struct scsi_cmnd *scp) · 7 unmodified lines | ||
| 56 | 59 | if (ioasa->rc.flags & SISL_RC_FLAGS_UNDERRUN) { |
| 57 | 60 | resid = ioasa->resid; |
| 58 | 61 | scsi_set_resid(scp, resid); |
| 59 | − pr_debug("%s: cmd underrun cmd = %p scp = %p, resid = %d\n", | |
| 60 | − __func__, cmd, scp, resid); | |
| 62 | + dev_dbg(dev, "%s: cmd underrun cmd = %p scp = %p, resid = %d\n", | |
| 63 | + __func__, cmd, scp, resid); | |
| 61 | 64 | } |
| 62 | 65 | |
| 63 | 66 | if (ioasa->rc.flags & SISL_RC_FLAGS_OVERRUN) { |
| 64 | − pr_debug("%s: cmd underrun cmd = %p scp = %p\n", | |
| 65 | − __func__, cmd, scp); | |
| 67 | + dev_dbg(dev, "%s: cmd underrun cmd = %p scp = %p\n", | |
| 68 | + __func__, cmd, scp); | |
| 66 | 69 | scp->result = (DID_ERROR << 16); |
| 67 | 70 | } |
| 68 | 71 | |
| 69 | − pr_debug("%s: cmd failed afu_rc=%d scsi_rc=%d fc_rc=%d " | |
| 70 | − "afu_extra=0x%X, scsi_extra=0x%X, fc_extra=0x%X\n", | |
| 71 | − __func__, ioasa->rc.afu_rc, ioasa->rc.scsi_rc, | |
| 72 | − ioasa->rc.fc_rc, ioasa->afu_extra, ioasa->scsi_extra, | |
| 73 | − ioasa->fc_extra); | |
| 72 | + dev_dbg(dev, "%s: cmd failed afu_rc=%02x scsi_rc=%02x fc_rc=%02x " | |
| 73 | + "afu_extra=%02x scsi_extra=%02x fc_extra=%02x\n", __func__, | |
| 74 | + ioasa->rc.afu_rc, ioasa->rc.scsi_rc, ioasa->rc.fc_rc, | |
| 75 | + ioasa->afu_extra, ioasa->scsi_extra, ioasa->fc_extra); | |
| 74 | 76 | |
| 75 | 77 | if (ioasa->rc.scsi_rc) { |
| 76 | 78 | /* We have a SCSI status */ |
| @@ -159,6 +161,7 @@ static void cmd_complete(struct afu_cmd *cmd) · 82 unmodified lines | ||
| 159 | 161 | ulong lock_flags; |
| 160 | 162 | struct afu *afu = cmd->parent; |
| 161 | 163 | struct cxlflash_cfg *cfg = afu->parent; |
| 164 | + struct device *dev = &cfg->dev->dev; | |
| 162 | 165 | bool cmd_is_tmf; |
| 163 | 166 | |
| 164 | 167 | if (cmd->scp) { |
| @@ -170,9 +173,8 @@ static void cmd_complete(struct afu_cmd *cmd) · 5 unmodified lines | ||
| 170 | 173 | |
| 171 | 174 | cmd_is_tmf = cmd->cmd_tmf; |
| 172 | 175 | |
| 173 | − pr_debug_ratelimited("%s: calling scsi_done scp=%p result=%X " | |
| 174 | − "ioasc=%d\n", __func__, scp, scp->result, | |
| 175 | − cmd->sa.ioasc); | |
| 176 | + dev_dbg_ratelimited(dev, "%s:scp=%p result=%08x ioasc=%08x\n", | |
| 177 | + __func__, scp, scp->result, cmd->sa.ioasc); | |
| 176 | 178 | |
| 177 | 179 | scsi_dma_unmap(scp); |
| 178 | 180 | scp->scsi_done(scp); |
| @@ -188,10 +190,11 @@ static void cmd_complete(struct afu_cmd *cmd) · 9 unmodified lines | ||
| 188 | 190 | } |
| 189 | 191 | |
| 190 | 192 | /** |
| 191 | − * context_reset_ioarrin() - reset command owner context via IOARRIN register | |
| 193 | + * context_reset() - reset command owner context via specified register | |
| 192 | 194 | * @cmd: AFU command that timed out. |
| 195 | + * @reset_reg: MMIO register to perform reset. | |
| 193 | 196 | */ |
| 194 | −static void context_reset_ioarrin(struct afu_cmd *cmd) | |
| 197 | +static void context_reset(struct afu_cmd *cmd, __be64 __iomem *reset_reg) | |
| 195 | 198 | { |
| 196 | 199 | int nretry = 0; |
| 197 | 200 | u64 rrin = 0x1; |
| @@ -199,21 +202,43 @@ static void context_reset_ioarrin(struct afu_cmd *cmd) · 1 unmodified line | ||
| 199 | 202 | struct cxlflash_cfg *cfg = afu->parent; |
| 200 | 203 | struct device *dev = &cfg->dev->dev; |
| 201 | 204 | |
| 202 | − pr_debug("%s: cmd=%p\n", __func__, cmd); | |
| 205 | + dev_dbg(dev, "%s: cmd=%p\n", __func__, cmd); | |
| 203 | 206 | |
| 204 | − writeq_be(rrin, &afu->host_map->ioarrin); | |
| 207 | + writeq_be(rrin, reset_reg); | |
| 205 | 208 | do { |
| 206 | − rrin = readq_be(&afu->host_map->ioarrin); | |
| 209 | + rrin = readq_be(reset_reg); | |
| 207 | 210 | if (rrin != 0x1) |
| 208 | 211 | break; |
| 209 | 212 | /* Double delay each time */ |
| 210 | 213 | udelay(1 << nretry); |
| 211 | 214 | } while (nretry++ < MC_ROOM_RETRY_CNT); |
| 212 | 215 | |
| 213 | − dev_dbg(dev, "%s: returning rrin=0x%016llX nretry=%d\n", | |
| 216 | + dev_dbg(dev, "%s: returning rrin=%016llx nretry=%d\n", | |
| 214 | 217 | __func__, rrin, nretry); |
| 215 | 218 | } |
| 216 | 219 | |
| 220 | +/** | |
| 221 | + * context_reset_ioarrin() - reset command owner context via IOARRIN register | |
| 222 | + * @cmd: AFU command that timed out. | |
| 223 | + */ | |
| 224 | +static void context_reset_ioarrin(struct afu_cmd *cmd) | |
| 225 | +{ | |
| 226 | + struct afu *afu = cmd->parent; | |
| 227 | + | |
| 228 | + context_reset(cmd, &afu->host_map->ioarrin); | |
| 229 | +} | |
| 230 | + | |
| 231 | +/** | |
| 232 | + * context_reset_sq() - reset command owner context w/ SQ Context Reset register | |
| 233 | + * @cmd: AFU command that timed out. | |
| 234 | + */ | |
| 235 | +static void context_reset_sq(struct afu_cmd *cmd) | |
| 236 | +{ | |
| 237 | + struct afu *afu = cmd->parent; | |
| 238 | + | |
| 239 | + context_reset(cmd, &afu->host_map->sq_ctx_reset); | |
| 240 | +} | |
| 241 | + | |
| 217 | 242 | /** |
| 218 | 243 | * send_cmd_ioarrin() - sends an AFU command via IOARRIN register |
| 219 | 244 | * @afu: AFU associated with the host. |
| @@ -251,8 +276,51 @@ static int send_cmd_ioarrin(struct afu *afu, struct afu_cmd *cmd) · 31 unmodified lines | ||
| 251 | 276 | writeq_be((u64)&cmd->rcb, &afu->host_map->ioarrin); |
| 252 | 277 | out: |
| 253 | 278 | spin_unlock_irqrestore(&afu->rrin_slock, lock_flags); |
| 254 | − pr_devel("%s: cmd=%p len=%d ea=%p rc=%d\n", __func__, cmd, | |
| 255 | − cmd->rcb.data_len, (void *)cmd->rcb.data_ea, rc); | |
| 279 | + dev_dbg(dev, "%s: cmd=%p len=%u ea=%016llx rc=%d\n", __func__, | |
| 280 | + cmd, cmd->rcb.data_len, cmd->rcb.data_ea, rc); | |
| 281 | + return rc; | |
| 282 | +} | |
| 283 | + | |
| 284 | +/** | |
| 285 | + * send_cmd_sq() - sends an AFU command via SQ ring | |
| 286 | + * @afu: AFU associated with the host. | |
| 287 | + * @cmd: AFU command to send. | |
| 288 | + * | |
| 289 | + * Return: | |
| 290 | + * 0 on success, SCSI_MLQUEUE_HOST_BUSY on failure | |
| 291 | + */ | |
| 292 | +static int send_cmd_sq(struct afu *afu, struct afu_cmd *cmd) | |
| 293 | +{ | |
| 294 | + struct cxlflash_cfg *cfg = afu->parent; | |
| 295 | + struct device *dev = &cfg->dev->dev; | |
| 296 | + int rc = 0; | |
| 297 | + int newval; | |
| 298 | + ulong lock_flags; | |
| 299 | + | |
| 300 | + newval = atomic_dec_if_positive(&afu->hsq_credits); | |
| 301 | + if (newval <= 0) { | |
| 302 | + rc = SCSI_MLQUEUE_HOST_BUSY; | |
| 303 | + goto out; | |
| 304 | + } | |
| 305 | + | |
| 306 | + cmd->rcb.ioasa = &cmd->sa; | |
| 307 | + | |
| 308 | + spin_lock_irqsave(&afu->hsq_slock, lock_flags); | |
| 309 | + | |
| 310 | + *afu->hsq_curr = cmd->rcb; | |
| 311 | + if (afu->hsq_curr < afu->hsq_end) | |
| 312 | + afu->hsq_curr++; | |
| 313 | + else | |
| 314 | + afu->hsq_curr = afu->hsq_start; | |
| 315 | + writeq_be((u64)afu->hsq_curr, &afu->host_map->sq_tail); | |
| 316 | + | |
| 317 | + spin_unlock_irqrestore(&afu->hsq_slock, lock_flags); | |
| 318 | +out: | |
| 319 | + dev_dbg(dev, "%s: cmd=%p len=%u ea=%016llx ioasa=%p rc=%d curr=%p " | |
| 320 | + "head=%016llx tail=%016llx\n", __func__, cmd, cmd->rcb.data_len, | |
| 321 | + cmd->rcb.data_ea, cmd->rcb.ioasa, rc, afu->hsq_curr, | |
| 322 | + readq_be(&afu->host_map->sq_head), | |
| 323 | + readq_be(&afu->host_map->sq_tail)); | |
| 256 | 324 | return rc; |
| 257 | 325 | } |
| 258 | 326 | |
| @@ -266,6 +334,8 @@ out: · 7 unmodified lines | ||
| 266 | 334 | */ |
| 267 | 335 | static int wait_resp(struct afu *afu, struct afu_cmd *cmd) |
| 268 | 336 | { |
| 337 | + struct cxlflash_cfg *cfg = afu->parent; | |
| 338 | + struct device *dev = &cfg->dev->dev; | |
| 269 | 339 | int rc = 0; |
| 270 | 340 | ulong timeout = msecs_to_jiffies(cmd->rcb.timeout * 2 * 1000); |
| 271 | 341 | |
| @@ -276,10 +346,8 @@ static int wait_resp(struct afu *afu, struct afu_cmd *cmd) · 4 unmodified lines | ||
| 276 | 346 | } |
| 277 | 347 | |
| 278 | 348 | if (unlikely(cmd->sa.ioasc != 0)) { |
| 279 | − pr_err("%s: CMD 0x%X failed, IOASC: flags 0x%X, afu_rc 0x%X, " | |
| 280 | − "scsi_rc 0x%X, fc_rc 0x%X\n", __func__, cmd->rcb.cdb[0], | |
| 281 | − cmd->sa.rc.flags, cmd->sa.rc.afu_rc, cmd->sa.rc.scsi_rc, | |
| 282 | − cmd->sa.rc.fc_rc); | |
| 349 | + dev_err(dev, "%s: cmd %02x failed, ioasc=%08x\n", | |
| 350 | + __func__, cmd->rcb.cdb[0], cmd->sa.ioasc); | |
| 283 | 351 | rc = -1; |
| 284 | 352 | } |
| 285 | 353 | |
| @@ -298,8 +366,7 @@ static int wait_resp(struct afu *afu, struct afu_cmd *cmd) · 12 unmodified lines | ||
| 298 | 366 | static int send_tmf(struct afu *afu, struct scsi_cmnd *scp, u64 tmfcmd) |
| 299 | 367 | { |
| 300 | 368 | u32 port_sel = scp->device->channel + 1; |
| 301 | − struct Scsi_Host *host = scp->device->host; | |
| 302 | − struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)host->hostdata; | |
| 369 | + struct cxlflash_cfg *cfg = shost_priv(scp->device->host); | |
| 303 | 370 | struct afu_cmd *cmd = sc_to_afucz(scp); |
| 304 | 371 | struct device *dev = &cfg->dev->dev; |
| 305 | 372 | ulong lock_flags; |
| @@ -344,7 +411,7 @@ static int send_tmf(struct afu *afu, struct scsi_cmnd *scp, u64 tmfcmd) · 38 unmodified lines | ||
| 344 | 411 | to); |
| 345 | 412 | if (!to) { |
| 346 | 413 | cfg->tmf_active = false; |
| 347 | − dev_err(dev, "%s: TMF timed out!\n", __func__); | |
| 414 | + dev_err(dev, "%s: TMF timed out\n", __func__); | |
| 348 | 415 | rc = -1; |
| 349 | 416 | } |
| 350 | 417 | spin_unlock_irqrestore(&cfg->tmf_slock, lock_flags); |
| @@ -352,16 +419,6 @@ out: · 1 unmodified line | ||
| 352 | 419 | return rc; |
| 353 | 420 | } |
| 354 | 421 | |
| 355 | −static void afu_unmap(struct kref *ref) | |
| 356 | −{ | |
| 357 | − struct afu *afu = container_of(ref, struct afu, mapcount); | |
| 358 | − | |
| 359 | − if (likely(afu->afu_map)) { | |
| 360 | − cxl_psa_unmap((void __iomem *)afu->afu_map); | |
| 361 | − afu->afu_map = NULL; | |
| 362 | − } | |
| 363 | −} | |
| 364 | − | |
| 365 | 422 | /** |
| 366 | 423 | * cxlflash_driver_info() - information handler for this host driver |
| 367 | 424 | * @host: SCSI host associated with device. |
| @@ -382,7 +439,7 @@ static const char *cxlflash_driver_info(struct Scsi_Host *host) · 14 unmodified lines | ||
| 382 | 439 | */ |
| 383 | 440 | static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp) |
| 384 | 441 | { |
| 385 | − struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)host->hostdata; | |
| 442 | + struct cxlflash_cfg *cfg = shost_priv(host); | |
| 386 | 443 | struct afu *afu = cfg->afu; |
| 387 | 444 | struct device *dev = &cfg->dev->dev; |
| 388 | 445 | struct afu_cmd *cmd = sc_to_afucz(scp); |
| @@ -392,10 +449,9 @@ static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp) · 3 unmodified lines | ||
| 392 | 449 | ulong lock_flags; |
| 393 | 450 | int nseg = 0; |
| 394 | 451 | int rc = 0; |
| 395 | − int kref_got = 0; | |
| 396 | 452 | |
| 397 | 453 | dev_dbg_ratelimited(dev, "%s: (scp=%p) %d/%d/%d/%llu " |
| 398 | − "cdb=(%08X-%08X-%08X-%08X)\n", | |
| 454 | + "cdb=(%08x-%08x-%08x-%08x)\n", | |
| 399 | 455 | __func__, scp, host->host_no, scp->device->channel, |
| 400 | 456 | scp->device->id, scp->device->lun, |
| 401 | 457 | get_unaligned_be32(&((u32 *)scp->cmnd)[0]), |
| @@ -417,11 +473,11 @@ static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp) · 15 unmodified lines | ||
| 417 | 473 | |
| 418 | 474 | switch (cfg->state) { |
| 419 | 475 | case STATE_RESET: |
| 420 | − dev_dbg_ratelimited(dev, "%s: device is in reset!\n", __func__); | |
| 476 | + dev_dbg_ratelimited(dev, "%s: device is in reset\n", __func__); | |
| 421 | 477 | rc = SCSI_MLQUEUE_HOST_BUSY; |
| 422 | 478 | goto out; |
| 423 | 479 | case STATE_FAILTERM: |
| 424 | − dev_dbg_ratelimited(dev, "%s: device has failed!\n", __func__); | |
| 480 | + dev_dbg_ratelimited(dev, "%s: device has failed\n", __func__); | |
| 425 | 481 | scp->result = (DID_NO_CONNECT << 16); |
| 426 | 482 | scp->scsi_done(scp); |
| 427 | 483 | rc = 0; |
| @@ -430,13 +486,10 @@ static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp) · 2 unmodified lines | ||
| 430 | 486 | break; |
| 431 | 487 | } |
| 432 | 488 | |
| 433 | − kref_get(&cfg->afu->mapcount); | |
| 434 | − kref_got = 1; | |
| 435 | − | |
| 436 | 489 | if (likely(sg)) { |
| 437 | 490 | nseg = scsi_dma_map(scp); |
| 438 | 491 | if (unlikely(nseg < 0)) { |
| 439 | − dev_err(dev, "%s: Fail DMA map!\n", __func__); | |
| 492 | + dev_err(dev, "%s: Fail DMA map\n", __func__); | |
| 440 | 493 | rc = SCSI_MLQUEUE_HOST_BUSY; |
| 441 | 494 | goto out; |
| 442 | 495 | } |
| @@ -463,9 +516,6 @@ static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp) · 20 unmodified lines | ||
| 463 | 516 | if (unlikely(rc)) |
| 464 | 517 | scsi_dma_unmap(scp); |
| 465 | 518 | out: |
| 466 | − if (kref_got) | |
| 467 | − kref_put(&afu->mapcount, afu_unmap); | |
| 468 | − pr_devel("%s: returning rc=%d\n", __func__, rc); | |
| 469 | 519 | return rc; |
| 470 | 520 | } |
| 471 | 521 | |
| @@ -503,13 +553,15 @@ static void free_mem(struct cxlflash_cfg *cfg) · 31 unmodified lines | ||
| 503 | 553 | * |
| 504 | 554 | * Safe to call with AFU in a partially allocated/initialized state. |
| 505 | 555 | * |
| 506 | − * Waits for any active internal AFU commands to timeout and then unmaps | |
| 507 | − * the MMIO space. | |
| 556 | + * Cancels scheduled worker threads, waits for any active internal AFU | |
| 557 | + * commands to timeout and then unmaps the MMIO space. | |
| 508 | 558 | */ |
| 509 | 559 | static void stop_afu(struct cxlflash_cfg *cfg) |
| 510 | 560 | { |
| 511 | 561 | struct afu *afu = cfg->afu; |
| 512 | 562 | |
| 563 | + cancel_work_sync(&cfg->work_q); | |
| 564 | + | |
| 513 | 565 | if (likely(afu)) { |
| 514 | 566 | while (atomic_read(&afu->cmds_active)) |
| 515 | 567 | ssleep(1); |
| @@ -517,7 +569,6 @@ static void stop_afu(struct cxlflash_cfg *cfg) · 1 unmodified line | ||
| 517 | 569 | cxl_psa_unmap((void __iomem *)afu->afu_map); |
| 518 | 570 | afu->afu_map = NULL; |
| 519 | 571 | } |
| 520 | − kref_put(&afu->mapcount, afu_unmap); | |
| 521 | 572 | } |
| 522 | 573 | } |
| 523 | 574 | |
| @@ -585,6 +636,8 @@ static void term_mc(struct cxlflash_cfg *cfg) · 61 unmodified lines | ||
| 585 | 636 | */ |
| 586 | 637 | static void term_afu(struct cxlflash_cfg *cfg) |
| 587 | 638 | { |
| 639 | + struct device *dev = &cfg->dev->dev; | |
| 640 | + | |
| 588 | 641 | /* |
| 589 | 642 | * Tear down is carefully orchestrated to ensure |
| 590 | 643 | * no interrupts can come in when the problem state |
| @@ -600,7 +653,7 @@ static void term_afu(struct cxlflash_cfg *cfg) · 9 unmodified lines | ||
| 600 | 653 | |
| 601 | 654 | term_mc(cfg); |
| 602 | 655 | |
| 603 | − pr_debug("%s: returning\n", __func__); | |
| 656 | + dev_dbg(dev, "%s: returning\n", __func__); | |
| 604 | 657 | } |
| 605 | 658 | |
| 606 | 659 | /** |
| @@ -627,8 +680,7 @@ static void notify_shutdown(struct cxlflash_cfg *cfg, bool wait) · 20 unmodified lines | ||
| 627 | 680 | return; |
| 628 | 681 | |
| 629 | 682 | if (!afu || !afu->afu_map) { |
| 630 | − dev_dbg(dev, "%s: The problem state area is not mapped\n", | |
| 631 | − __func__); | |
| 683 | + dev_dbg(dev, "%s: Problem state area not mapped\n", __func__); | |
| 632 | 684 | return; |
| 633 | 685 | } |
| 634 | 686 | |
| @@ -670,10 +722,11 @@ static void notify_shutdown(struct cxlflash_cfg *cfg, bool wait) · 35 unmodified lines | ||
| 670 | 722 | static void cxlflash_remove(struct pci_dev *pdev) |
| 671 | 723 | { |
| 672 | 724 | struct cxlflash_cfg *cfg = pci_get_drvdata(pdev); |
| 725 | + struct device *dev = &pdev->dev; | |
| 673 | 726 | ulong lock_flags; |
| 674 | 727 | |
| 675 | 728 | if (!pci_is_enabled(pdev)) { |
| 676 | − pr_debug("%s: Device is disabled\n", __func__); | |
| 729 | + dev_dbg(dev, "%s: Device is disabled\n", __func__); | |
| 677 | 730 | return; |
| 678 | 731 | } |
| 679 | 732 | |
| @@ -699,7 +752,6 @@ static void cxlflash_remove(struct pci_dev *pdev) · 19 unmodified lines | ||
| 699 | 752 | scsi_remove_host(cfg->host); |
| 700 | 753 | /* fall through */ |
| 701 | 754 | case INIT_STATE_AFU: |
| 702 | − cancel_work_sync(&cfg->work_q); | |
| 703 | 755 | term_afu(cfg); |
| 704 | 756 | case INIT_STATE_PCI: |
| 705 | 757 | pci_disable_device(pdev); |
| @@ -709,7 +761,7 @@ static void cxlflash_remove(struct pci_dev *pdev) · 3 unmodified lines | ||
| 709 | 761 | break; |
| 710 | 762 | } |
| 711 | 763 | |
| 712 | − pr_debug("%s: returning\n", __func__); | |
| 764 | + dev_dbg(dev, "%s: returning\n", __func__); | |
| 713 | 765 | } |
| 714 | 766 | |
| 715 | 767 | /** |
| @@ -727,7 +779,7 @@ static int alloc_mem(struct cxlflash_cfg *cfg) · 11 unmodified lines | ||
| 727 | 779 | int rc = 0; |
| 728 | 780 | struct device *dev = &cfg->dev->dev; |
| 729 | 781 | |
| 730 | − /* AFU is ~12k, i.e. only one 64k page or up to four 4k pages */ | |
| 782 | + /* AFU is ~28k, i.e. only one 64k page or up to seven 4k pages */ | |
| 731 | 783 | cfg->afu = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, |
| 732 | 784 | get_order(sizeof(struct afu))); |
| 733 | 785 | if (unlikely(!cfg->afu)) { |
| @@ -751,6 +803,7 @@ out: · 17 unmodified lines | ||
| 751 | 803 | static int init_pci(struct cxlflash_cfg *cfg) |
| 752 | 804 | { |
| 753 | 805 | struct pci_dev *pdev = cfg->dev; |
| 806 | + struct device *dev = &cfg->dev->dev; | |
| 754 | 807 | int rc = 0; |
| 755 | 808 | |
| 756 | 809 | rc = pci_enable_device(pdev); |
| @@ -761,15 +814,14 @@ static int init_pci(struct cxlflash_cfg *cfg) · 4 unmodified lines | ||
| 761 | 814 | } |
| 762 | 815 | |
| 763 | 816 | if (rc) { |
| 764 | − dev_err(&pdev->dev, "%s: Cannot enable adapter\n", | |
| 765 | − __func__); | |
| 817 | + dev_err(dev, "%s: Cannot enable adapter\n", __func__); | |
| 766 | 818 | cxlflash_wait_for_pci_err_recovery(cfg); |
| 767 | 819 | goto out; |
| 768 | 820 | } |
| 769 | 821 | } |
| 770 | 822 | |
| 771 | 823 | out: |
| 772 | − pr_debug("%s: returning rc=%d\n", __func__, rc); | |
| 824 | + dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc); | |
| 773 | 825 | return rc; |
| 774 | 826 | } |
| 775 | 827 | |
| @@ -782,19 +834,19 @@ out: · 6 unmodified lines | ||
| 782 | 834 | static int init_scsi(struct cxlflash_cfg *cfg) |
| 783 | 835 | { |
| 784 | 836 | struct pci_dev *pdev = cfg->dev; |
| 837 | + struct device *dev = &cfg->dev->dev; | |
| 785 | 838 | int rc = 0; |
| 786 | 839 | |
| 787 | 840 | rc = scsi_add_host(cfg->host, &pdev->dev); |
| 788 | 841 | if (rc) { |
| 789 | − dev_err(&pdev->dev, "%s: scsi_add_host failed (rc=%d)\n", | |
| 790 | − __func__, rc); | |
| 842 | + dev_err(dev, "%s: scsi_add_host failed rc=%d\n", __func__, rc); | |
| 791 | 843 | goto out; |
| 792 | 844 | } |
| 793 | 845 | |
| 794 | 846 | scsi_scan_host(cfg->host); |
| 795 | 847 | |
| 796 | 848 | out: |
| 797 | − pr_debug("%s: returning rc=%d\n", __func__, rc); | |
| 849 | + dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc); | |
| 798 | 850 | return rc; |
| 799 | 851 | } |
| 800 | 852 | |
| @@ -844,16 +896,12 @@ static void set_port_offline(__be64 __iomem *fc_regs) · 43 unmodified lines | ||
| 844 | 896 | * Return: |
| 845 | 897 | * TRUE (1) when the specified port is online |
| 846 | 898 | * FALSE (0) when the specified port fails to come online after timeout |
| 847 | − * -EINVAL when @delay_us is less than 1000 | |
| 848 | 899 | */ |
| 849 | −static int wait_port_online(__be64 __iomem *fc_regs, u32 delay_us, u32 nretry) | |
| 900 | +static bool wait_port_online(__be64 __iomem *fc_regs, u32 delay_us, u32 nretry) | |
| 850 | 901 | { |
| 851 | 902 | u64 status; |
| 852 | 903 | |
| 853 | − if (delay_us < 1000) { | |
| 854 | − pr_err("%s: invalid delay specified %d\n", __func__, delay_us); | |
| 855 | − return -EINVAL; | |
| 856 | − } | |
| 904 | + WARN_ON(delay_us < 1000); | |
| 857 | 905 | |
| 858 | 906 | do { |
| 859 | 907 | msleep(delay_us / 1000); |
| @@ -877,16 +925,12 @@ static int wait_port_online(__be64 __iomem *fc_regs, u32 delay_us, u32 nretry) · 17 unmodified lines | ||
| 877 | 925 | * Return: |
| 878 | 926 | * TRUE (1) when the specified port is offline |
| 879 | 927 | * FALSE (0) when the specified port fails to go offline after timeout |
| 880 | − * -EINVAL when @delay_us is less than 1000 | |
| 881 | 928 | */ |
| 882 | −static int wait_port_offline(__be64 __iomem *fc_regs, u32 delay_us, u32 nretry) | |
| 929 | +static bool wait_port_offline(__be64 __iomem *fc_regs, u32 delay_us, u32 nretry) | |
| 883 | 930 | { |
| 884 | 931 | u64 status; |
| 885 | 932 | |
| 886 | − if (delay_us < 1000) { | |
| 887 | − pr_err("%s: invalid delay specified %d\n", __func__, delay_us); | |
| 888 | − return -EINVAL; | |
| 889 | − } | |
| 933 | + WARN_ON(delay_us < 1000); | |
| 890 | 934 | |
| 891 | 935 | do { |
| 892 | 936 | msleep(delay_us / 1000); |
| @@ -915,11 +959,14 @@ static int wait_port_offline(__be64 __iomem *fc_regs, u32 delay_us, u32 nretry) · 22 unmodified lines | ||
| 915 | 959 | static void afu_set_wwpn(struct afu *afu, int port, __be64 __iomem *fc_regs, |
| 916 | 960 | u64 wwpn) |
| 917 | 961 | { |
| 962 | + struct cxlflash_cfg *cfg = afu->parent; | |
| 963 | + struct device *dev = &cfg->dev->dev; | |
| 964 | + | |
| 918 | 965 | set_port_offline(fc_regs); |
| 919 | 966 | if (!wait_port_offline(fc_regs, FC_PORT_STATUS_RETRY_INTERVAL_US, |
| 920 | 967 | FC_PORT_STATUS_RETRY_CNT)) { |
| 921 | − pr_debug("%s: wait on port %d to go offline timed out\n", | |
| 922 | − __func__, port); | |
| 968 | + dev_dbg(dev, "%s: wait on port %d to go offline timed out\n", | |
| 969 | + __func__, port); | |
| 923 | 970 | } |
| 924 | 971 | |
| 925 | 972 | writeq_be(wwpn, &fc_regs[FC_PNAME / 8]); |
| @@ -927,8 +974,8 @@ static void afu_set_wwpn(struct afu *afu, int port, __be64 __iomem *fc_regs, · 1 unmodified line | ||
| 927 | 974 | set_port_online(fc_regs); |
| 928 | 975 | if (!wait_port_online(fc_regs, FC_PORT_STATUS_RETRY_INTERVAL_US, |
| 929 | 976 | FC_PORT_STATUS_RETRY_CNT)) { |
| 930 | − pr_debug("%s: wait on port %d to go online timed out\n", | |
| 931 | − __func__, port); | |
| 977 | + dev_dbg(dev, "%s: wait on port %d to go online timed out\n", | |
| 978 | + __func__, port); | |
| 932 | 979 | } |
| 933 | 980 | } |
| 934 | 981 | |
| @@ -947,6 +994,8 @@ static void afu_set_wwpn(struct afu *afu, int port, __be64 __iomem *fc_regs, · 12 unmodified lines | ||
| 947 | 994 | */ |
| 948 | 995 | static void afu_link_reset(struct afu *afu, int port, __be64 __iomem *fc_regs) |
| 949 | 996 | { |
| 997 | + struct cxlflash_cfg *cfg = afu->parent; | |
| 998 | + struct device *dev = &cfg->dev->dev; | |
| 950 | 999 | u64 port_sel; |
| 951 | 1000 | |
| 952 | 1001 | /* first switch the AFU to the other links, if any */ |
| @@ -958,21 +1007,21 @@ static void afu_link_reset(struct afu *afu, int port, __be64 __iomem *fc_regs) · 5 unmodified lines | ||
| 958 | 1007 | set_port_offline(fc_regs); |
| 959 | 1008 | if (!wait_port_offline(fc_regs, FC_PORT_STATUS_RETRY_INTERVAL_US, |
| 960 | 1009 | FC_PORT_STATUS_RETRY_CNT)) |
| 961 | − pr_err("%s: wait on port %d to go offline timed out\n", | |
| 962 | − __func__, port); | |
| 1010 | + dev_err(dev, "%s: wait on port %d to go offline timed out\n", | |
| 1011 | + __func__, port); | |
| 963 | 1012 | |
| 964 | 1013 | set_port_online(fc_regs); |
| 965 | 1014 | if (!wait_port_online(fc_regs, FC_PORT_STATUS_RETRY_INTERVAL_US, |
| 966 | 1015 | FC_PORT_STATUS_RETRY_CNT)) |
| 967 | − pr_err("%s: wait on port %d to go online timed out\n", | |
| 968 | − __func__, port); | |
| 1016 | + dev_err(dev, "%s: wait on port %d to go online timed out\n", | |
| 1017 | + __func__, port); | |
| 969 | 1018 | |
| 970 | 1019 | /* switch back to include this port */ |
| 971 | 1020 | port_sel |= (1ULL << port); |
| 972 | 1021 | writeq_be(port_sel, &afu->afu_map->global.regs.afu_port_sel); |
| 973 | 1022 | cxlflash_afu_sync(afu, 0, 0, AFU_GSYNC); |
| 974 | 1023 | |
| 975 | − pr_debug("%s: returning port_sel=%lld\n", __func__, port_sel); | |
| 1024 | + dev_dbg(dev, "%s: returning port_sel=%016llx\n", __func__, port_sel); | |
| 976 | 1025 | } |
| 977 | 1026 | |
| 978 | 1027 | /* |
| @@ -1082,6 +1131,8 @@ static void afu_err_intr_init(struct afu *afu) · 103 unmodified lines | ||
| 1082 | 1131 | static irqreturn_t cxlflash_sync_err_irq(int irq, void *data) |
| 1083 | 1132 | { |
| 1084 | 1133 | struct afu *afu = (struct afu *)data; |
| 1134 | + struct cxlflash_cfg *cfg = afu->parent; | |
| 1135 | + struct device *dev = &cfg->dev->dev; | |
| 1085 | 1136 | u64 reg; |
| 1086 | 1137 | u64 reg_unmasked; |
| 1087 | 1138 | |
| @@ -1089,18 +1140,17 @@ static irqreturn_t cxlflash_sync_err_irq(int irq, void *data) · 1 unmodified line | ||
| 1089 | 1140 | reg_unmasked = (reg & SISL_ISTATUS_UNMASK); |
| 1090 | 1141 | |
| 1091 | 1142 | if (reg_unmasked == 0UL) { |
| 1092 | − pr_err("%s: %llX: spurious interrupt, intr_status %016llX\n", | |
| 1093 | − __func__, (u64)afu, reg); | |
| 1143 | + dev_err(dev, "%s: spurious interrupt, intr_status=%016llx\n", | |
| 1144 | + __func__, reg); | |
| 1094 | 1145 | goto cxlflash_sync_err_irq_exit; |
| 1095 | 1146 | } |
| 1096 | 1147 | |
| 1097 | − pr_err("%s: %llX: unexpected interrupt, intr_status %016llX\n", | |
| 1098 | − __func__, (u64)afu, reg); | |
| 1148 | + dev_err(dev, "%s: unexpected interrupt, intr_status=%016llx\n", | |
| 1149 | + __func__, reg); | |
| 1099 | 1150 | |
| 1100 | 1151 | writeq_be(reg_unmasked, &afu->host_map->intr_clear); |
| 1101 | 1152 | |
| 1102 | 1153 | cxlflash_sync_err_irq_exit: |
| 1103 | − pr_debug("%s: returning rc=%d\n", __func__, IRQ_HANDLED); | |
| 1104 | 1154 | return IRQ_HANDLED; |
| 1105 | 1155 | } |
| 1106 | 1156 | |
| @@ -1115,6 +1165,8 @@ static irqreturn_t cxlflash_rrq_irq(int irq, void *data) · 8 unmodified lines | ||
| 1115 | 1165 | { |
| 1116 | 1166 | struct afu *afu = (struct afu *)data; |
| 1117 | 1167 | struct afu_cmd *cmd; |
| 1168 | + struct sisl_ioasa *ioasa; | |
| 1169 | + struct sisl_ioarcb *ioarcb; | |
| 1118 | 1170 | bool toggle = afu->toggle; |
| 1119 | 1171 | u64 entry, |
| 1120 | 1172 | *hrrq_start = afu->hrrq_start, |
| @@ -1128,7 +1180,16 @@ static irqreturn_t cxlflash_rrq_irq(int irq, void *data) · 7 unmodified lines | ||
| 1128 | 1180 | if ((entry & SISL_RESP_HANDLE_T_BIT) != toggle) |
| 1129 | 1181 | break; |
| 1130 | 1182 | |
| 1131 | − cmd = (struct afu_cmd *)(entry & ~SISL_RESP_HANDLE_T_BIT); | |
| 1183 | + entry &= ~SISL_RESP_HANDLE_T_BIT; | |
| 1184 | + | |
| 1185 | + if (afu_is_sq_cmd_mode(afu)) { | |
| 1186 | + ioasa = (struct sisl_ioasa *)entry; | |
| 1187 | + cmd = container_of(ioasa, struct afu_cmd, sa); | |
| 1188 | + } else { | |
| 1189 | + ioarcb = (struct sisl_ioarcb *)entry; | |
| 1190 | + cmd = container_of(ioarcb, struct afu_cmd, rcb); | |
| 1191 | + } | |
| 1192 | + | |
| 1132 | 1193 | cmd_complete(cmd); |
| 1133 | 1194 | |
| 1134 | 1195 | /* Advance to next entry or wrap and flip the toggle bit */ |
| @@ -1138,6 +1199,8 @@ static irqreturn_t cxlflash_rrq_irq(int irq, void *data) · 3 unmodified lines | ||
| 1138 | 1199 | hrrq_curr = hrrq_start; |
| 1139 | 1200 | toggle ^= SISL_RESP_HANDLE_T_BIT; |
| 1140 | 1201 | } |
| 1202 | + | |
| 1203 | + atomic_inc(&afu->hsq_credits); | |
| 1141 | 1204 | } |
| 1142 | 1205 | |
| 1143 | 1206 | afu->hrrq_curr = hrrq_curr; |
| @@ -1169,7 +1232,7 @@ static irqreturn_t cxlflash_async_err_irq(int irq, void *data) · 25 unmodified lines | ||
| 1169 | 1232 | reg_unmasked = (reg & SISL_ASTATUS_UNMASK); |
| 1170 | 1233 | |
| 1171 | 1234 | if (reg_unmasked == 0) { |
| 1172 | − dev_err(dev, "%s: spurious interrupt, aintr_status 0x%016llX\n", | |
| 1235 | + dev_err(dev, "%s: spurious interrupt, aintr_status=%016llx\n", | |
| 1173 | 1236 | __func__, reg); |
| 1174 | 1237 | goto out; |
| 1175 | 1238 | } |
| @@ -1185,7 +1248,7 @@ static irqreturn_t cxlflash_async_err_irq(int irq, void *data) · 9 unmodified lines | ||
| 1185 | 1248 | |
| 1186 | 1249 | port = info->port; |
| 1187 | 1250 | |
| 1188 | − dev_err(dev, "%s: FC Port %d -> %s, fc_status 0x%08llX\n", | |
| 1251 | + dev_err(dev, "%s: FC Port %d -> %s, fc_status=%016llx\n", | |
| 1189 | 1252 | __func__, port, info->desc, |
| 1190 | 1253 | readq_be(&global->fc_regs[port][FC_STATUS / 8])); |
| 1191 | 1254 | |
| @@ -1198,7 +1261,6 @@ static irqreturn_t cxlflash_async_err_irq(int irq, void *data) · 6 unmodified lines | ||
| 1198 | 1261 | __func__, port); |
| 1199 | 1262 | cfg->lr_state = LINK_RESET_REQUIRED; |
| 1200 | 1263 | cfg->lr_port = port; |
| 1201 | − kref_get(&cfg->afu->mapcount); | |
| 1202 | 1264 | schedule_work(&cfg->work_q); |
| 1203 | 1265 | } |
| 1204 | 1266 | |
| @@ -1210,7 +1272,7 @@ static irqreturn_t cxlflash_async_err_irq(int irq, void *data) · 5 unmodified lines | ||
| 1210 | 1272 | * should be the same and tracing one is sufficient. |
| 1211 | 1273 | */ |
| 1212 | 1274 | |
| 1213 | − dev_err(dev, "%s: fc %d: clearing fc_error 0x%08llX\n", | |
| 1275 | + dev_err(dev, "%s: fc %d: clearing fc_error=%016llx\n", | |
| 1214 | 1276 | __func__, port, reg); |
| 1215 | 1277 | |
| 1216 | 1278 | writeq_be(reg, &global->fc_regs[port][FC_ERROR / 8]); |
| @@ -1219,13 +1281,11 @@ static irqreturn_t cxlflash_async_err_irq(int irq, void *data) · 2 unmodified lines | ||
| 1219 | 1281 | |
| 1220 | 1282 | if (info->action & SCAN_HOST) { |
| 1221 | 1283 | atomic_inc(&cfg->scan_host_needed); |
| 1222 | − kref_get(&cfg->afu->mapcount); | |
| 1223 | 1284 | schedule_work(&cfg->work_q); |
| 1224 | 1285 | } |
| 1225 | 1286 | } |
| 1226 | 1287 | |
| 1227 | 1288 | out: |
| 1228 | − dev_dbg(dev, "%s: returning IRQ_HANDLED, afu=%p\n", __func__, afu); | |
| 1229 | 1289 | return IRQ_HANDLED; |
| 1230 | 1290 | } |
| 1231 | 1291 | |
| @@ -1237,13 +1297,14 @@ out: · 5 unmodified lines | ||
| 1237 | 1297 | */ |
| 1238 | 1298 | static int start_context(struct cxlflash_cfg *cfg) |
| 1239 | 1299 | { |
| 1300 | + struct device *dev = &cfg->dev->dev; | |
| 1240 | 1301 | int rc = 0; |
| 1241 | 1302 | |
| 1242 | 1303 | rc = cxl_start_context(cfg->mcctx, |
| 1243 | 1304 | cfg->afu->work.work_element_descriptor, |
| 1244 | 1305 | NULL); |
| 1245 | 1306 | |
| 1246 | − pr_debug("%s: returning rc=%d\n", __func__, rc); | |
| 1307 | + dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc); | |
| 1247 | 1308 | return rc; |
| 1248 | 1309 | } |
| 1249 | 1310 | |
| @@ -1256,7 +1317,8 @@ static int start_context(struct cxlflash_cfg *cfg) · 6 unmodified lines | ||
| 1256 | 1317 | */ |
| 1257 | 1318 | static int read_vpd(struct cxlflash_cfg *cfg, u64 wwpn[]) |
| 1258 | 1319 | { |
| 1259 | − struct pci_dev *dev = cfg->dev; | |
| 1320 | + struct device *dev = &cfg->dev->dev; | |
| 1321 | + struct pci_dev *pdev = cfg->dev; | |
| 1260 | 1322 | int rc = 0; |
| 1261 | 1323 | int ro_start, ro_size, i, j, k; |
| 1262 | 1324 | ssize_t vpd_size; |
| @@ -1265,10 +1327,10 @@ static int read_vpd(struct cxlflash_cfg *cfg, u64 wwpn[]) · 2 unmodified lines | ||
| 1265 | 1327 | char *wwpn_vpd_tags[NUM_FC_PORTS] = { "V5", "V6" }; |
| 1266 | 1328 | |
| 1267 | 1329 | /* Get the VPD data from the device */ |
| 1268 | − vpd_size = cxl_read_adapter_vpd(dev, vpd_data, sizeof(vpd_data)); | |
| 1330 | + vpd_size = cxl_read_adapter_vpd(pdev, vpd_data, sizeof(vpd_data)); | |
| 1269 | 1331 | if (unlikely(vpd_size <= 0)) { |
| 1270 | − dev_err(&dev->dev, "%s: Unable to read VPD (size = %ld)\n", | |
| 1271 | − __func__, vpd_size); | |
| 1332 | + dev_err(dev, "%s: Unable to read VPD (size = %ld)\n", | |
| 1333 | + __func__, vpd_size); | |
| 1272 | 1334 | rc = -ENODEV; |
| 1273 | 1335 | goto out; |
| 1274 | 1336 | } |
| @@ -1277,8 +1339,7 @@ static int read_vpd(struct cxlflash_cfg *cfg, u64 wwpn[]) · 2 unmodified lines | ||
| 1277 | 1339 | ro_start = pci_vpd_find_tag(vpd_data, 0, vpd_size, |
| 1278 | 1340 | PCI_VPD_LRDT_RO_DATA); |
| 1279 | 1341 | if (unlikely(ro_start < 0)) { |
| 1280 | − dev_err(&dev->dev, "%s: VPD Read-only data not found\n", | |
| 1281 | − __func__); | |
| 1342 | + dev_err(dev, "%s: VPD Read-only data not found\n", __func__); | |
| 1282 | 1343 | rc = -ENODEV; |
| 1283 | 1344 | goto out; |
| 1284 | 1345 | } |
| @@ -1288,8 +1349,8 @@ static int read_vpd(struct cxlflash_cfg *cfg, u64 wwpn[]) · 3 unmodified lines | ||
| 1288 | 1349 | j = ro_size; |
| 1289 | 1350 | i = ro_start + PCI_VPD_LRDT_TAG_SIZE; |
| 1290 | 1351 | if (unlikely((i + j) > vpd_size)) { |
| 1291 | − pr_debug("%s: Might need to read more VPD (%d > %ld)\n", | |
| 1292 | − __func__, (i + j), vpd_size); | |
| 1352 | + dev_dbg(dev, "%s: Might need to read more VPD (%d > %ld)\n", | |
| 1353 | + __func__, (i + j), vpd_size); | |
| 1293 | 1354 | ro_size = vpd_size - i; |
| 1294 | 1355 | } |
| 1295 | 1356 | |
| @@ -1307,8 +1368,8 @@ static int read_vpd(struct cxlflash_cfg *cfg, u64 wwpn[]) · 11 unmodified lines | ||
| 1307 | 1368 | |
| 1308 | 1369 | i = pci_vpd_find_info_keyword(vpd_data, i, j, wwpn_vpd_tags[k]); |
| 1309 | 1370 | if (unlikely(i < 0)) { |
| 1310 | − dev_err(&dev->dev, "%s: Port %d WWPN not found " | |
| 1311 | − "in VPD\n", __func__, k); | |
| 1371 | + dev_err(dev, "%s: Port %d WWPN not found in VPD\n", | |
| 1372 | + __func__, k); | |
| 1312 | 1373 | rc = -ENODEV; |
| 1313 | 1374 | goto out; |
| 1314 | 1375 | } |
| @@ -1316,9 +1377,8 @@ static int read_vpd(struct cxlflash_cfg *cfg, u64 wwpn[]) · 1 unmodified line | ||
| 1316 | 1377 | j = pci_vpd_info_field_size(&vpd_data[i]); |
| 1317 | 1378 | i += PCI_VPD_INFO_FLD_HDR_SIZE; |
| 1318 | 1379 | if (unlikely((i + j > vpd_size) || (j != WWPN_LEN))) { |
| 1319 | − dev_err(&dev->dev, "%s: Port %d WWPN incomplete or " | |
| 1320 | − "VPD corrupt\n", | |
| 1321 | − __func__, k); | |
| 1380 | + dev_err(dev, "%s: Port %d WWPN incomplete or bad VPD\n", | |
| 1381 | + __func__, k); | |
| 1322 | 1382 | rc = -ENODEV; |
| 1323 | 1383 | goto out; |
| 1324 | 1384 | } |
| @@ -1326,15 +1386,15 @@ static int read_vpd(struct cxlflash_cfg *cfg, u64 wwpn[]) · 1 unmodified line | ||
| 1326 | 1386 | memcpy(tmp_buf, &vpd_data[i], WWPN_LEN); |
| 1327 | 1387 | rc = kstrtoul(tmp_buf, WWPN_LEN, (ulong *)&wwpn[k]); |
| 1328 | 1388 | if (unlikely(rc)) { |
| 1329 | − dev_err(&dev->dev, "%s: Fail to convert port %d WWPN " | |
| 1330 | − "to integer\n", __func__, k); | |
| 1389 | + dev_err(dev, "%s: WWPN conversion failed for port %d\n", | |
| 1390 | + __func__, k); | |
| 1331 | 1391 | rc = -ENODEV; |
| 1332 | 1392 | goto out; |
| 1333 | 1393 | } |
| 1334 | 1394 | } |
| 1335 | 1395 | |
| 1336 | 1396 | out: |
| 1337 | − pr_debug("%s: returning rc=%d\n", __func__, rc); | |
| 1397 | + dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc); | |
| 1338 | 1398 | return rc; |
| 1339 | 1399 | } |
| 1340 | 1400 | |
| @@ -1388,12 +1448,18 @@ static int init_global(struct cxlflash_cfg *cfg) · 47 unmodified lines | ||
| 1388 | 1448 | goto out; |
| 1389 | 1449 | } |
| 1390 | 1450 | |
| 1391 | − pr_debug("%s: wwpn0=0x%llX wwpn1=0x%llX\n", __func__, wwpn[0], wwpn[1]); | |
| 1451 | + dev_dbg(dev, "%s: wwpn0=%016llx wwpn1=%016llx\n", | |
| 1452 | + __func__, wwpn[0], wwpn[1]); | |
| 1392 | 1453 | |
| 1393 | − /* Set up RRQ in AFU for master issued cmds */ | |
| 1454 | + /* Set up RRQ and SQ in AFU for master issued cmds */ | |
| 1394 | 1455 | writeq_be((u64) afu->hrrq_start, &afu->host_map->rrq_start); |
| 1395 | 1456 | writeq_be((u64) afu->hrrq_end, &afu->host_map->rrq_end); |
| 1396 | 1457 | |
| 1458 | + if (afu_is_sq_cmd_mode(afu)) { | |
| 1459 | + writeq_be((u64)afu->hsq_start, &afu->host_map->sq_start); | |
| 1460 | + writeq_be((u64)afu->hsq_end, &afu->host_map->sq_end); | |
| 1461 | + } | |
| 1462 | + | |
| 1397 | 1463 | /* AFU configuration */ |
| 1398 | 1464 | reg = readq_be(&afu->afu_map->global.regs.afu_config); |
| 1399 | 1465 | reg |= SISL_AFUCONF_AR_ALL|SISL_AFUCONF_ENDIAN; |
| @@ -1443,7 +1509,6 @@ static int init_global(struct cxlflash_cfg *cfg) · 43 unmodified lines | ||
| 1443 | 1509 | &afu->ctrl_map->ctx_cap); |
| 1444 | 1510 | /* Initialize heartbeat */ |
| 1445 | 1511 | afu->hb = readq_be(&afu->afu_map->global.regs.afu_hb); |
| 1446 | − | |
| 1447 | 1512 | out: |
| 1448 | 1513 | return rc; |
| 1449 | 1514 | } |
| @@ -1455,6 +1520,7 @@ out: · 5 unmodified lines | ||
| 1455 | 1520 | static int start_afu(struct cxlflash_cfg *cfg) |
| 1456 | 1521 | { |
| 1457 | 1522 | struct afu *afu = cfg->afu; |
| 1523 | + struct device *dev = &cfg->dev->dev; | |
| 1458 | 1524 | int rc = 0; |
| 1459 | 1525 | |
| 1460 | 1526 | init_pcr(cfg); |
| @@ -1468,9 +1534,20 @@ static int start_afu(struct cxlflash_cfg *cfg) · 7 unmodified lines | ||
| 1468 | 1534 | afu->hrrq_curr = afu->hrrq_start; |
| 1469 | 1535 | afu->toggle = 1; |
| 1470 | 1536 | |
| 1537 | + /* Initialize SQ */ | |
| 1538 | + if (afu_is_sq_cmd_mode(afu)) { | |
| 1539 | + memset(&afu->sq, 0, sizeof(afu->sq)); | |
| 1540 | + afu->hsq_start = &afu->sq[0]; | |
| 1541 | + afu->hsq_end = &afu->sq[NUM_SQ_ENTRY - 1]; | |
| 1542 | + afu->hsq_curr = afu->hsq_start; | |
| 1543 | + | |
| 1544 | + spin_lock_init(&afu->hsq_slock); | |
| 1545 | + atomic_set(&afu->hsq_credits, NUM_SQ_ENTRY - 1); | |
| 1546 | + } | |
| 1547 | + | |
| 1471 | 1548 | rc = init_global(cfg); |
| 1472 | 1549 | |
| 1473 | − pr_debug("%s: returning rc=%d\n", __func__, rc); | |
| 1550 | + dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc); | |
| 1474 | 1551 | return rc; |
| 1475 | 1552 | } |
| 1476 | 1553 | |
| @@ -1490,7 +1567,7 @@ static enum undo_level init_intr(struct cxlflash_cfg *cfg, · 13 unmodified lines | ||
| 1490 | 1567 | |
| 1491 | 1568 | rc = cxl_allocate_afu_irqs(ctx, 3); |
| 1492 | 1569 | if (unlikely(rc)) { |
| 1493 | − dev_err(dev, "%s: call to allocate_afu_irqs failed rc=%d!\n", | |
| 1570 | + dev_err(dev, "%s: allocate_afu_irqs failed rc=%d\n", | |
| 1494 | 1571 | __func__, rc); |
| 1495 | 1572 | level = UNDO_NOOP; |
| 1496 | 1573 | goto out; |
| @@ -1499,8 +1576,7 @@ static enum undo_level init_intr(struct cxlflash_cfg *cfg, · 2 unmodified lines | ||
| 1499 | 1576 | rc = cxl_map_afu_irq(ctx, 1, cxlflash_sync_err_irq, afu, |
| 1500 | 1577 | "SISL_MSI_SYNC_ERROR"); |
| 1501 | 1578 | if (unlikely(rc <= 0)) { |
| 1502 | − dev_err(dev, "%s: IRQ 1 (SISL_MSI_SYNC_ERROR) map failed!\n", | |
| 1503 | − __func__); | |
| 1579 | + dev_err(dev, "%s: SISL_MSI_SYNC_ERROR map failed\n", __func__); | |
| 1504 | 1580 | level = FREE_IRQ; |
| 1505 | 1581 | goto out; |
| 1506 | 1582 | } |
| @@ -1508,8 +1584,7 @@ static enum undo_level init_intr(struct cxlflash_cfg *cfg, · 1 unmodified line | ||
| 1508 | 1584 | rc = cxl_map_afu_irq(ctx, 2, cxlflash_rrq_irq, afu, |
| 1509 | 1585 | "SISL_MSI_RRQ_UPDATED"); |
| 1510 | 1586 | if (unlikely(rc <= 0)) { |
| 1511 | − dev_err(dev, "%s: IRQ 2 (SISL_MSI_RRQ_UPDATED) map failed!\n", | |
| 1512 | − __func__); | |
| 1587 | + dev_err(dev, "%s: SISL_MSI_RRQ_UPDATED map failed\n", __func__); | |
| 1513 | 1588 | level = UNMAP_ONE; |
| 1514 | 1589 | goto out; |
| 1515 | 1590 | } |
| @@ -1517,8 +1592,7 @@ static enum undo_level init_intr(struct cxlflash_cfg *cfg, · 1 unmodified line | ||
| 1517 | 1592 | rc = cxl_map_afu_irq(ctx, 3, cxlflash_async_err_irq, afu, |
| 1518 | 1593 | "SISL_MSI_ASYNC_ERROR"); |
| 1519 | 1594 | if (unlikely(rc <= 0)) { |
| 1520 | − dev_err(dev, "%s: IRQ 3 (SISL_MSI_ASYNC_ERROR) map failed!\n", | |
| 1521 | − __func__); | |
| 1595 | + dev_err(dev, "%s: SISL_MSI_ASYNC_ERROR map failed\n", __func__); | |
| 1522 | 1596 | level = UNMAP_TWO; |
| 1523 | 1597 | goto out; |
| 1524 | 1598 | } |
| @@ -1552,15 +1626,13 @@ static int init_mc(struct cxlflash_cfg *cfg) · 27 unmodified lines | ||
| 1552 | 1626 | /* During initialization reset the AFU to start from a clean slate */ |
| 1553 | 1627 | rc = cxl_afu_reset(cfg->mcctx); |
| 1554 | 1628 | if (unlikely(rc)) { |
| 1555 | − dev_err(dev, "%s: initial AFU reset failed rc=%d\n", | |
| 1556 | − __func__, rc); | |
| 1629 | + dev_err(dev, "%s: AFU reset failed rc=%d\n", __func__, rc); | |
| 1557 | 1630 | goto ret; |
| 1558 | 1631 | } |
| 1559 | 1632 | |
| 1560 | 1633 | level = init_intr(cfg, ctx); |
| 1561 | 1634 | if (unlikely(level)) { |
| 1562 | − dev_err(dev, "%s: setting up interrupts failed rc=%d\n", | |
| 1563 | − __func__, rc); | |
| 1635 | + dev_err(dev, "%s: interrupt init failed rc=%d\n", __func__, rc); | |
| 1564 | 1636 | goto out; |
| 1565 | 1637 | } |
| 1566 | 1638 | |
| @@ -1575,7 +1647,7 @@ static int init_mc(struct cxlflash_cfg *cfg) · 8 unmodified lines | ||
| 1575 | 1647 | goto out; |
| 1576 | 1648 | } |
| 1577 | 1649 | ret: |
| 1578 | − pr_debug("%s: returning rc=%d\n", __func__, rc); | |
| 1650 | + dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc); | |
| 1579 | 1651 | return rc; |
| 1580 | 1652 | out: |
| 1581 | 1653 | term_intr(cfg, level); |
| @@ -1602,7 +1674,7 @@ static int init_afu(struct cxlflash_cfg *cfg) · 20 unmodified lines | ||
| 1602 | 1674 | |
| 1603 | 1675 | rc = init_mc(cfg); |
| 1604 | 1676 | if (rc) { |
| 1605 | − dev_err(dev, "%s: call to init_mc failed, rc=%d!\n", | |
| 1677 | + dev_err(dev, "%s: init_mc failed rc=%d\n", | |
| 1606 | 1678 | __func__, rc); |
| 1607 | 1679 | goto out; |
| 1608 | 1680 | } |
| @@ -1610,11 +1682,10 @@ static int init_afu(struct cxlflash_cfg *cfg) · 1 unmodified line | ||
| 1610 | 1682 | /* Map the entire MMIO space of the AFU */ |
| 1611 | 1683 | afu->afu_map = cxl_psa_map(cfg->mcctx); |
| 1612 | 1684 | if (!afu->afu_map) { |
| 1613 | − dev_err(dev, "%s: call to cxl_psa_map failed!\n", __func__); | |
| 1685 | + dev_err(dev, "%s: cxl_psa_map failed\n", __func__); | |
| 1614 | 1686 | rc = -ENOMEM; |
| 1615 | 1687 | goto err1; |
| 1616 | 1688 | } |
| 1617 | − kref_init(&afu->mapcount); | |
| 1618 | 1689 | |
| 1619 | 1690 | /* No byte reverse on reading afu_version or string will be backwards */ |
| 1620 | 1691 | reg = readq(&afu->afu_map->global.regs.afu_version); |
| @@ -1622,24 +1693,28 @@ static int init_afu(struct cxlflash_cfg *cfg) · 1 unmodified line | ||
| 1622 | 1693 | afu->interface_version = |
| 1623 | 1694 | readq_be(&afu->afu_map->global.regs.interface_version); |
| 1624 | 1695 | if ((afu->interface_version + 1) == 0) { |
| 1625 | − pr_err("Back level AFU, please upgrade. AFU version %s " | |
| 1626 | − "interface version 0x%llx\n", afu->version, | |
| 1696 | + dev_err(dev, "Back level AFU, please upgrade. AFU version %s " | |
| 1697 | + "interface version %016llx\n", afu->version, | |
| 1627 | 1698 | afu->interface_version); |
| 1628 | 1699 | rc = -EINVAL; |
| 1629 | − goto err2; | |
| 1700 | + goto err1; | |
| 1630 | 1701 | } |
| 1631 | 1702 | |
| 1632 | − afu->send_cmd = send_cmd_ioarrin; | |
| 1633 | − afu->context_reset = context_reset_ioarrin; | |
| 1703 | + if (afu_is_sq_cmd_mode(afu)) { | |
| 1704 | + afu->send_cmd = send_cmd_sq; | |
| 1705 | + afu->context_reset = context_reset_sq; | |
| 1706 | + } else { | |
| 1707 | + afu->send_cmd = send_cmd_ioarrin; | |
| 1708 | + afu->context_reset = context_reset_ioarrin; | |
| 1709 | + } | |
| 1634 | 1710 | |
| 1635 | − pr_debug("%s: afu version %s, interface version 0x%llX\n", __func__, | |
| 1636 | − afu->version, afu->interface_version); | |
| 1711 | + dev_dbg(dev, "%s: afu_ver=%s interface_ver=%016llx\n", __func__, | |
| 1712 | + afu->version, afu->interface_version); | |
| 1637 | 1713 | |
| 1638 | 1714 | rc = start_afu(cfg); |
| 1639 | 1715 | if (rc) { |
| 1640 | − dev_err(dev, "%s: call to start_afu failed, rc=%d!\n", | |
| 1641 | − __func__, rc); | |
| 1642 | − goto err2; | |
| 1716 | + dev_err(dev, "%s: start_afu failed, rc=%d\n", __func__, rc); | |
| 1717 | + goto err1; | |
| 1643 | 1718 | } |
| 1644 | 1719 | |
| 1645 | 1720 | afu_err_intr_init(cfg->afu); |
| @@ -1649,11 +1724,9 @@ static int init_afu(struct cxlflash_cfg *cfg) · 3 unmodified lines | ||
| 1649 | 1724 | /* Restore the LUN mappings */ |
| 1650 | 1725 | cxlflash_restore_luntable(cfg); |
| 1651 | 1726 | out: |
| 1652 | − pr_debug("%s: returning rc=%d\n", __func__, rc); | |
| 1727 | + dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc); | |
| 1653 | 1728 | return rc; |
| 1654 | 1729 | |
| 1655 | −err2: | |
| 1656 | − kref_put(&afu->mapcount, afu_unmap); | |
| 1657 | 1730 | err1: |
| 1658 | 1731 | term_intr(cfg, UNMAP_THREE); |
| 1659 | 1732 | term_mc(cfg); |
| @@ -1693,7 +1766,8 @@ int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx_hndl_u, · 33 unmodified lines | ||
| 1693 | 1766 | static DEFINE_MUTEX(sync_active); |
| 1694 | 1767 | |
| 1695 | 1768 | if (cfg->state != STATE_NORMAL) { |
| 1696 | − pr_debug("%s: Sync not required! (%u)\n", __func__, cfg->state); | |
| 1769 | + dev_dbg(dev, "%s: Sync not required state=%u\n", | |
| 1770 | + __func__, cfg->state); | |
| 1697 | 1771 | return 0; |
| 1698 | 1772 | } |
| 1699 | 1773 | |
| @@ -1710,7 +1784,7 @@ int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx_hndl_u, · 10 unmodified lines | ||
| 1710 | 1784 | init_completion(&cmd->cevent); |
| 1711 | 1785 | cmd->parent = afu; |
| 1712 | 1786 | |
| 1713 | − pr_debug("%s: afu=%p cmd=%p %d\n", __func__, afu, cmd, ctx_hndl_u); | |
| 1787 | + dev_dbg(dev, "%s: afu=%p cmd=%p %d\n", __func__, afu, cmd, ctx_hndl_u); | |
| 1714 | 1788 | |
| 1715 | 1789 | cmd->rcb.req_flags = SISL_REQ_FLAGS_AFU_CMD; |
| 1716 | 1790 | cmd->rcb.ctx_id = afu->ctx_hndl; |
| @@ -1735,7 +1809,7 @@ out: · 18 unmodified lines | ||
| 1735 | 1809 | atomic_dec(&afu->cmds_active); |
| 1736 | 1810 | mutex_unlock(&sync_active); |
| 1737 | 1811 | kfree(buf); |
| 1738 | − pr_debug("%s: returning rc=%d\n", __func__, rc); | |
| 1812 | + dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc); | |
| 1739 | 1813 | return rc; |
| 1740 | 1814 | } |
| 1741 | 1815 | |
| @@ -1747,16 +1821,17 @@ out: · 5 unmodified lines | ||
| 1747 | 1821 | */ |
| 1748 | 1822 | static int afu_reset(struct cxlflash_cfg *cfg) |
| 1749 | 1823 | { |
| 1824 | + struct device *dev = &cfg->dev->dev; | |
| 1750 | 1825 | int rc = 0; |
| 1826 | + | |
| 1751 | 1827 | /* Stop the context before the reset. Since the context is |
| 1752 | 1828 | * no longer available restart it after the reset is complete |
| 1753 | 1829 | */ |
| 1754 | − | |
| 1755 | 1830 | term_afu(cfg); |
| 1756 | 1831 | |
| 1757 | 1832 | rc = init_afu(cfg); |
| 1758 | 1833 | |
| 1759 | − pr_debug("%s: returning rc=%d\n", __func__, rc); | |
| 1834 | + dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc); | |
| 1760 | 1835 | return rc; |
| 1761 | 1836 | } |
| 1762 | 1837 | |
| @@ -1785,18 +1860,18 @@ static int cxlflash_eh_device_reset_handler(struct scsi_cmnd *scp) · 22 unmodified lines | ||
| 1785 | 1860 | { |
| 1786 | 1861 | int rc = SUCCESS; |
| 1787 | 1862 | struct Scsi_Host *host = scp->device->host; |
| 1788 | − struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)host->hostdata; | |
| 1863 | + struct cxlflash_cfg *cfg = shost_priv(host); | |
| 1864 | + struct device *dev = &cfg->dev->dev; | |
| 1789 | 1865 | struct afu *afu = cfg->afu; |
| 1790 | 1866 | int rcr = 0; |
| 1791 | 1867 | |
| 1792 | − pr_debug("%s: (scp=%p) %d/%d/%d/%llu " | |
| 1793 | − "cdb=(%08X-%08X-%08X-%08X)\n", __func__, scp, | |
| 1794 | − host->host_no, scp->device->channel, | |
| 1795 | − scp->device->id, scp->device->lun, | |
| 1796 | − get_unaligned_be32(&((u32 *)scp->cmnd)[0]), | |
| 1797 | − get_unaligned_be32(&((u32 *)scp->cmnd)[1]), | |
| 1798 | − get_unaligned_be32(&((u32 *)scp->cmnd)[2]), | |
| 1799 | − get_unaligned_be32(&((u32 *)scp->cmnd)[3])); | |
| 1868 | + dev_dbg(dev, "%s: (scp=%p) %d/%d/%d/%llu " | |
| 1869 | + "cdb=(%08x-%08x-%08x-%08x)\n", __func__, scp, host->host_no, | |
| 1870 | + scp->device->channel, scp->device->id, scp->device->lun, | |
| 1871 | + get_unaligned_be32(&((u32 *)scp->cmnd)[0]), | |
| 1872 | + get_unaligned_be32(&((u32 *)scp->cmnd)[1]), | |
| 1873 | + get_unaligned_be32(&((u32 *)scp->cmnd)[2]), | |
| 1874 | + get_unaligned_be32(&((u32 *)scp->cmnd)[3])); | |
| 1800 | 1875 | |
| 1801 | 1876 | retry: |
| 1802 | 1877 | switch (cfg->state) { |
| @@ -1813,7 +1888,7 @@ retry: · 10 unmodified lines | ||
| 1813 | 1888 | break; |
| 1814 | 1889 | } |
| 1815 | 1890 | |
| 1816 | − pr_debug("%s: returning rc=%d\n", __func__, rc); | |
| 1891 | + dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc); | |
| 1817 | 1892 | return rc; |
| 1818 | 1893 | } |
| 1819 | 1894 | |
| @@ -1835,16 +1910,16 @@ static int cxlflash_eh_host_reset_handler(struct scsi_cmnd *scp) · 15 unmodified lines | ||
| 1835 | 1910 | int rc = SUCCESS; |
| 1836 | 1911 | int rcr = 0; |
| 1837 | 1912 | struct Scsi_Host *host = scp->device->host; |
| 1838 | − struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)host->hostdata; | |
| 1913 | + struct cxlflash_cfg *cfg = shost_priv(host); | |
| 1914 | + struct device *dev = &cfg->dev->dev; | |
| 1839 | 1915 | |
| 1840 | − pr_debug("%s: (scp=%p) %d/%d/%d/%llu " | |
| 1841 | − "cdb=(%08X-%08X-%08X-%08X)\n", __func__, scp, | |
| 1842 | − host->host_no, scp->device->channel, | |
| 1843 | − scp->device->id, scp->device->lun, | |
| 1844 | − get_unaligned_be32(&((u32 *)scp->cmnd)[0]), | |
| 1845 | − get_unaligned_be32(&((u32 *)scp->cmnd)[1]), | |
| 1846 | − get_unaligned_be32(&((u32 *)scp->cmnd)[2]), | |
| 1847 | − get_unaligned_be32(&((u32 *)scp->cmnd)[3])); | |
| 1916 | + dev_dbg(dev, "%s: (scp=%p) %d/%d/%d/%llu " | |
| 1917 | + "cdb=(%08x-%08x-%08x-%08x)\n", __func__, scp, host->host_no, | |
| 1918 | + scp->device->channel, scp->device->id, scp->device->lun, | |
| 1919 | + get_unaligned_be32(&((u32 *)scp->cmnd)[0]), | |
| 1920 | + get_unaligned_be32(&((u32 *)scp->cmnd)[1]), | |
| 1921 | + get_unaligned_be32(&((u32 *)scp->cmnd)[2]), | |
| 1922 | + get_unaligned_be32(&((u32 *)scp->cmnd)[3])); | |
| 1848 | 1923 | |
| 1849 | 1924 | switch (cfg->state) { |
| 1850 | 1925 | case STATE_NORMAL: |
| @@ -1870,7 +1945,7 @@ static int cxlflash_eh_host_reset_handler(struct scsi_cmnd *scp) · 19 unmodified lines | ||
| 1870 | 1945 | break; |
| 1871 | 1946 | } |
| 1872 | 1947 | |
| 1873 | − pr_debug("%s: returning rc=%d\n", __func__, rc); | |
| 1948 | + dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc); | |
| 1874 | 1949 | return rc; |
| 1875 | 1950 | } |
| 1876 | 1951 | |
| @@ -1936,8 +2011,7 @@ static ssize_t port0_show(struct device *dev, · 59 unmodified lines | ||
| 1936 | 2011 | struct device_attribute *attr, |
| 1937 | 2012 | char *buf) |
| 1938 | 2013 | { |
| 1939 | − struct Scsi_Host *shost = class_to_shost(dev); | |
| 1940 | − struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)shost->hostdata; | |
| 2014 | + struct cxlflash_cfg *cfg = shost_priv(class_to_shost(dev)); | |
| 1941 | 2015 | struct afu *afu = cfg->afu; |
| 1942 | 2016 | |
| 1943 | 2017 | return cxlflash_show_port_status(0, afu, buf); |
| @@ -1955,8 +2029,7 @@ static ssize_t port1_show(struct device *dev, · 11 unmodified lines | ||
| 1955 | 2029 | struct device_attribute *attr, |
| 1956 | 2030 | char *buf) |
| 1957 | 2031 | { |
| 1958 | − struct Scsi_Host *shost = class_to_shost(dev); | |
| 1959 | − struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)shost->hostdata; | |
| 2032 | + struct cxlflash_cfg *cfg = shost_priv(class_to_shost(dev)); | |
| 1960 | 2033 | struct afu *afu = cfg->afu; |
| 1961 | 2034 | |
| 1962 | 2035 | return cxlflash_show_port_status(1, afu, buf); |
| @@ -1973,8 +2046,7 @@ static ssize_t port1_show(struct device *dev, · 10 unmodified lines | ||
| 1973 | 2046 | static ssize_t lun_mode_show(struct device *dev, |
| 1974 | 2047 | struct device_attribute *attr, char *buf) |
| 1975 | 2048 | { |
| 1976 | − struct Scsi_Host *shost = class_to_shost(dev); | |
| 1977 | − struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)shost->hostdata; | |
| 2049 | + struct cxlflash_cfg *cfg = shost_priv(class_to_shost(dev)); | |
| 1978 | 2050 | struct afu *afu = cfg->afu; |
| 1979 | 2051 | |
| 1980 | 2052 | return scnprintf(buf, PAGE_SIZE, "%u\n", afu->internal_lun); |
| @@ -2007,7 +2079,7 @@ static ssize_t lun_mode_store(struct device *dev, · 26 unmodified lines | ||
| 2007 | 2079 | const char *buf, size_t count) |
| 2008 | 2080 | { |
| 2009 | 2081 | struct Scsi_Host *shost = class_to_shost(dev); |
| 2010 | − struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)shost->hostdata; | |
| 2082 | + struct cxlflash_cfg *cfg = shost_priv(shost); | |
| 2011 | 2083 | struct afu *afu = cfg->afu; |
| 2012 | 2084 | int rc; |
| 2013 | 2085 | u32 lun_mode; |
| @@ -2069,7 +2141,7 @@ static ssize_t cxlflash_show_port_lun_table(u32 port, · 55 unmodified lines | ||
| 2069 | 2141 | |
| 2070 | 2142 | for (i = 0; i < CXLFLASH_NUM_VLUNS; i++) |
| 2071 | 2143 | bytes += scnprintf(buf + bytes, PAGE_SIZE - bytes, |
| 2072 | − "%03d: %016llX\n", i, readq_be(&fc_port[i])); | |
| 2144 | + "%03d: %016llx\n", i, readq_be(&fc_port[i])); | |
| 2073 | 2145 | return bytes; |
| 2074 | 2146 | } |
| 2075 | 2147 | |
| @@ -2085,8 +2157,7 @@ static ssize_t port0_lun_table_show(struct device *dev, · 9 unmodified lines | ||
| 2085 | 2157 | struct device_attribute *attr, |
| 2086 | 2158 | char *buf) |
| 2087 | 2159 | { |
| 2088 | − struct Scsi_Host *shost = class_to_shost(dev); | |
| 2089 | − struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)shost->hostdata; | |
| 2160 | + struct cxlflash_cfg *cfg = shost_priv(class_to_shost(dev)); | |
| 2090 | 2161 | struct afu *afu = cfg->afu; |
| 2091 | 2162 | |
| 2092 | 2163 | return cxlflash_show_port_lun_table(0, afu, buf); |
| @@ -2104,8 +2175,7 @@ static ssize_t port1_lun_table_show(struct device *dev, · 11 unmodified lines | ||
| 2104 | 2175 | struct device_attribute *attr, |
| 2105 | 2176 | char *buf) |
| 2106 | 2177 | { |
| 2107 | − struct Scsi_Host *shost = class_to_shost(dev); | |
| 2108 | − struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)shost->hostdata; | |
| 2178 | + struct cxlflash_cfg *cfg = shost_priv(class_to_shost(dev)); | |
| 2109 | 2179 | struct afu *afu = cfg->afu; |
| 2110 | 2180 | |
| 2111 | 2181 | return cxlflash_show_port_lun_table(1, afu, buf); |
| @@ -2250,7 +2320,6 @@ static void cxlflash_worker_thread(struct work_struct *work) · 138 unmodified lines | ||
| 2250 | 2320 | |
| 2251 | 2321 | if (atomic_dec_if_positive(&cfg->scan_host_needed) >= 0) |
| 2252 | 2322 | scsi_scan_host(cfg->host); |
| 2253 | − kref_put(&afu->mapcount, afu_unmap); | |
| 2254 | 2323 | } |
| 2255 | 2324 | |
| 2256 | 2325 | /** |
| @@ -2265,6 +2334,7 @@ static int cxlflash_probe(struct pci_dev *pdev, · 8 unmodified lines | ||
| 2265 | 2334 | { |
| 2266 | 2335 | struct Scsi_Host *host; |
| 2267 | 2336 | struct cxlflash_cfg *cfg = NULL; |
| 2337 | + struct device *dev = &pdev->dev; | |
| 2268 | 2338 | struct dev_dependent_vals *ddv; |
| 2269 | 2339 | int rc = 0; |
| 2270 | 2340 | |
| @@ -2276,8 +2346,7 @@ static int cxlflash_probe(struct pci_dev *pdev, · 5 unmodified lines | ||
| 2276 | 2346 | |
| 2277 | 2347 | host = scsi_host_alloc(&driver_template, sizeof(struct cxlflash_cfg)); |
| 2278 | 2348 | if (!host) { |
| 2279 | − dev_err(&pdev->dev, "%s: call to scsi_host_alloc failed!\n", | |
| 2280 | − __func__); | |
| 2349 | + dev_err(dev, "%s: scsi_host_alloc failed\n", __func__); | |
| 2281 | 2350 | rc = -ENOMEM; |
| 2282 | 2351 | goto out; |
| 2283 | 2352 | } |
| @@ -2288,12 +2357,11 @@ static int cxlflash_probe(struct pci_dev *pdev, · 4 unmodified lines | ||
| 2288 | 2357 | host->unique_id = host->host_no; |
| 2289 | 2358 | host->max_cmd_len = CXLFLASH_MAX_CDB_LEN; |
| 2290 | 2359 | |
| 2291 | − cfg = (struct cxlflash_cfg *)host->hostdata; | |
| 2360 | + cfg = shost_priv(host); | |
| 2292 | 2361 | cfg->host = host; |
| 2293 | 2362 | rc = alloc_mem(cfg); |
| 2294 | 2363 | if (rc) { |
| 2295 | − dev_err(&pdev->dev, "%s: call to alloc_mem failed!\n", | |
| 2296 | − __func__); | |
| 2364 | + dev_err(dev, "%s: alloc_mem failed\n", __func__); | |
| 2297 | 2365 | rc = -ENOMEM; |
| 2298 | 2366 | scsi_host_put(cfg->host); |
| 2299 | 2367 | goto out; |
| @@ -2334,30 +2402,27 @@ static int cxlflash_probe(struct pci_dev *pdev, · 34 unmodified lines | ||
| 2334 | 2402 | |
| 2335 | 2403 | rc = init_pci(cfg); |
| 2336 | 2404 | if (rc) { |
| 2337 | − dev_err(&pdev->dev, "%s: call to init_pci " | |
| 2338 | − "failed rc=%d!\n", __func__, rc); | |
| 2405 | + dev_err(dev, "%s: init_pci failed rc=%d\n", __func__, rc); | |
| 2339 | 2406 | goto out_remove; |
| 2340 | 2407 | } |
| 2341 | 2408 | cfg->init_state = INIT_STATE_PCI; |
| 2342 | 2409 | |
| 2343 | 2410 | rc = init_afu(cfg); |
| 2344 | 2411 | if (rc) { |
| 2345 | − dev_err(&pdev->dev, "%s: call to init_afu " | |
| 2346 | − "failed rc=%d!\n", __func__, rc); | |
| 2412 | + dev_err(dev, "%s: init_afu failed rc=%d\n", __func__, rc); | |
| 2347 | 2413 | goto out_remove; |
| 2348 | 2414 | } |
| 2349 | 2415 | cfg->init_state = INIT_STATE_AFU; |
| 2350 | 2416 | |
| 2351 | 2417 | rc = init_scsi(cfg); |
| 2352 | 2418 | if (rc) { |
| 2353 | − dev_err(&pdev->dev, "%s: call to init_scsi " | |
| 2354 | − "failed rc=%d!\n", __func__, rc); | |
| 2419 | + dev_err(dev, "%s: init_scsi failed rc=%d\n", __func__, rc); | |
| 2355 | 2420 | goto out_remove; |
| 2356 | 2421 | } |
| 2357 | 2422 | cfg->init_state = INIT_STATE_SCSI; |
| 2358 | 2423 | |
| 2359 | 2424 | out: |
| 2360 | − pr_debug("%s: returning rc=%d\n", __func__, rc); | |
| 2425 | + dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc); | |
| 2361 | 2426 | return rc; |
| 2362 | 2427 | |
| 2363 | 2428 | out_remove: |
| @@ -2395,7 +2460,7 @@ static pci_ers_result_t cxlflash_pci_error_detected(struct pci_dev *pdev, · 31 unmodified lines | ||
| 2395 | 2460 | drain_ioctls(cfg); |
| 2396 | 2461 | rc = cxlflash_mark_contexts_error(cfg); |
| 2397 | 2462 | if (unlikely(rc)) |
| 2398 | − dev_err(dev, "%s: Failed to mark user contexts!(%d)\n", | |
| 2463 | + dev_err(dev, "%s: Failed to mark user contexts rc=%d\n", | |
| 2399 | 2464 | __func__, rc); |
| 2400 | 2465 | term_afu(cfg); |
| 2401 | 2466 | return PCI_ERS_RESULT_NEED_RESET; |
| @@ -2429,7 +2494,7 @@ static pci_ers_result_t cxlflash_pci_slot_reset(struct pci_dev *pdev) · 27 unmodified lines | ||
| 2429 | 2494 | |
| 2430 | 2495 | rc = init_afu(cfg); |
| 2431 | 2496 | if (unlikely(rc)) { |
| 2432 | − dev_err(dev, "%s: EEH recovery failed! (%d)\n", __func__, rc); | |
| 2497 | + dev_err(dev, "%s: EEH recovery failed rc=%d\n", __func__, rc); | |
| 2433 | 2498 | return PCI_ERS_RESULT_DISCONNECT; |
| 2434 | 2499 | } |
| 2435 | 2500 | |
| @@ -2477,8 +2542,6 @@ static struct pci_driver cxlflash_driver = { · 41 unmodified lines | ||
| 2477 | 2542 | */ |
| 2478 | 2543 | static int __init init_cxlflash(void) |
| 2479 | 2544 | { |
| 2480 | − pr_info("%s: %s\n", __func__, CXLFLASH_ADAPTER_NAME); | |
| 2481 | − | |
| 2482 | 2545 | cxlflash_list_init(); |
| 2483 | 2546 | |
| 2484 | 2547 | return pci_register_driver(&cxlflash_driver); |
| @@ -72,7 +72,10 @@ struct sisl_ioarcb { · 71 unmodified lines | ||
| 72 | 72 | u16 timeout; /* in units specified by req_flags */ |
| 73 | 73 | u32 rsvd1; |
| 74 | 74 | u8 cdb[16]; /* must be in big endian */ |
| 75 | − u64 reserved; /* Reserved area */ | |
| 75 | + union { | |
| 76 | + u64 reserved; /* Reserved for IOARRIN mode */ | |
| 77 | + struct sisl_ioasa *ioasa; /* IOASA EA for SQ Mode */ | |
| 78 | + }; | |
| 76 | 79 | } __packed; |
| 77 | 80 | |
| 78 | 81 | struct sisl_rc { |
| @@ -260,6 +263,11 @@ struct sisl_host_map { · 181 unmodified lines | ||
| 260 | 263 | __be64 cmd_room; |
| 261 | 264 | __be64 ctx_ctrl; /* least significant byte or b56:63 is LISN# */ |
| 262 | 265 | __be64 mbox_w; /* restricted use */ |
| 266 | + __be64 sq_start; /* Submission Queue (R/W): write sequence and */ | |
| 267 | + __be64 sq_end; /* inclusion semantics are the same as RRQ */ | |
| 268 | + __be64 sq_head; /* Submission Queue Head (R): for debugging */ | |
| 269 | + __be64 sq_tail; /* Submission Queue TAIL (R/W): next IOARCB */ | |
| 270 | + __be64 sq_ctx_reset; /* Submission Queue Context Reset (R/W) */ | |
| 263 | 271 | }; |
| 264 | 272 | |
| 265 | 273 | /* per context provisioning & control MMIO */ |
| @@ -348,6 +356,15 @@ struct sisl_global_regs { · 82 unmodified lines | ||
| 348 | 356 | __be64 rsvd[0xf8]; |
| 349 | 357 | __le64 afu_version; |
| 350 | 358 | __be64 interface_version; |
| 359 | +#define SISL_INTVER_CAP_SHIFT 16 | |
| 360 | +#define SISL_INTVER_MAJ_SHIFT 8 | |
| 361 | +#define SISL_INTVER_CAP_MASK 0xFFFFFFFF00000000ULL | |
| 362 | +#define SISL_INTVER_MAJ_MASK 0x00000000FFFF0000ULL | |
| 363 | +#define SISL_INTVER_MIN_MASK 0x000000000000FFFFULL | |
| 364 | +#define SISL_INTVER_CAP_IOARRIN_CMD_MODE 0x800000000000ULL | |
| 365 | +#define SISL_INTVER_CAP_SQ_CMD_MODE 0x400000000000ULL | |
| 366 | +#define SISL_INTVER_CAP_RESERVED_CMD_MODE_A 0x200000000000ULL | |
| 367 | +#define SISL_INTVER_CAP_RESERVED_CMD_MODE_B 0x100000000000ULL | |
| 351 | 368 | }; |
| 352 | 369 | |
| 353 | 370 | #define CXLFLASH_NUM_FC_PORTS 2 |
| @@ -212,7 +212,7 @@ struct ctx_info *get_context(struct cxlflash_cfg *cfg, u64 rctxid, · 211 unmodified lines | ||
| 212 | 212 | } |
| 213 | 213 | |
| 214 | 214 | out: |
| 215 | − dev_dbg(dev, "%s: rctxid=%016llX ctxinfo=%p ctxpid=%u pid=%u " | |
| 215 | + dev_dbg(dev, "%s: rctxid=%016llx ctxinfo=%p ctxpid=%u pid=%u " | |
| 216 | 216 | "ctx_ctrl=%u\n", __func__, rctxid, ctxi, ctxpid, pid, |
| 217 | 217 | ctx_ctrl); |
| 218 | 218 | |
| @@ -260,7 +260,7 @@ static int afu_attach(struct cxlflash_cfg *cfg, struct ctx_info *ctxi) · 41 unmodified lines | ||
| 260 | 260 | writeq_be(val, &ctrl_map->ctx_cap); |
| 261 | 261 | val = readq_be(&ctrl_map->ctx_cap); |
| 262 | 262 | if (val != (SISL_CTX_CAP_READ_CMD | SISL_CTX_CAP_WRITE_CMD)) { |
| 263 | − dev_err(dev, "%s: ctx may be closed val=%016llX\n", | |
| 263 | + dev_err(dev, "%s: ctx may be closed val=%016llx\n", | |
| 264 | 264 | __func__, val); |
| 265 | 265 | rc = -EAGAIN; |
| 266 | 266 | goto out; |
| @@ -302,7 +302,7 @@ out: · 35 unmodified lines | ||
| 302 | 302 | */ |
| 303 | 303 | static int read_cap16(struct scsi_device *sdev, struct llun_info *lli) |
| 304 | 304 | { |
| 305 | − struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; | |
| 305 | + struct cxlflash_cfg *cfg = shost_priv(sdev->host); | |
| 306 | 306 | struct device *dev = &cfg->dev->dev; |
| 307 | 307 | struct glun_info *gli = lli->parent; |
| 308 | 308 | u8 *cmd_buf = NULL; |
| @@ -326,7 +326,7 @@ retry: · 17 unmodified lines | ||
| 326 | 326 | scsi_cmd[1] = SAI_READ_CAPACITY_16; /* service action */ |
| 327 | 327 | put_unaligned_be32(CMD_BUFSIZE, &scsi_cmd[10]); |
| 328 | 328 | |
| 329 | − dev_dbg(dev, "%s: %ssending cmd(0x%x)\n", __func__, | |
| 329 | + dev_dbg(dev, "%s: %ssending cmd(%02x)\n", __func__, | |
| 330 | 330 | retry_cnt ? "re" : "", scsi_cmd[0]); |
| 331 | 331 | |
| 332 | 332 | /* Drop the ioctl read semahpore across lengthy call */ |
| @@ -336,7 +336,7 @@ retry: · 3 unmodified lines | ||
| 336 | 336 | down_read(&cfg->ioctl_rwsem); |
| 337 | 337 | rc = check_state(cfg); |
| 338 | 338 | if (rc) { |
| 339 | − dev_err(dev, "%s: Failed state! result=0x08%X\n", | |
| 339 | + dev_err(dev, "%s: Failed state result=%08x\n", | |
| 340 | 340 | __func__, result); |
| 341 | 341 | rc = -ENODEV; |
| 342 | 342 | goto out; |
| @@ -378,7 +378,7 @@ retry: · 35 unmodified lines | ||
| 378 | 378 | } |
| 379 | 379 | |
| 380 | 380 | if (result) { |
| 381 | − dev_err(dev, "%s: command failed, result=0x%x\n", | |
| 381 | + dev_err(dev, "%s: command failed, result=%08x\n", | |
| 382 | 382 | __func__, result); |
| 383 | 383 | rc = -EIO; |
| 384 | 384 | goto out; |
| @@ -415,29 +415,32 @@ out: · 30 unmodified lines | ||
| 415 | 415 | struct sisl_rht_entry *get_rhte(struct ctx_info *ctxi, res_hndl_t rhndl, |
| 416 | 416 | struct llun_info *lli) |
| 417 | 417 | { |
| 418 | + struct cxlflash_cfg *cfg = ctxi->cfg; | |
| 419 | + struct device *dev = &cfg->dev->dev; | |
| 418 | 420 | struct sisl_rht_entry *rhte = NULL; |
| 419 | 421 | |
| 420 | 422 | if (unlikely(!ctxi->rht_start)) { |
| 421 | − pr_debug("%s: Context does not have allocated RHT!\n", | |
| 423 | + dev_dbg(dev, "%s: Context does not have allocated RHT\n", | |
| 422 | 424 | __func__); |
| 423 | 425 | goto out; |
| 424 | 426 | } |
| 425 | 427 | |
| 426 | 428 | if (unlikely(rhndl >= MAX_RHT_PER_CONTEXT)) { |
| 427 | − pr_debug("%s: Bad resource handle! (%d)\n", __func__, rhndl); | |
| 429 | + dev_dbg(dev, "%s: Bad resource handle rhndl=%d\n", | |
| 430 | + __func__, rhndl); | |
| 428 | 431 | goto out; |
| 429 | 432 | } |
| 430 | 433 | |
| 431 | 434 | if (unlikely(ctxi->rht_lun[rhndl] != lli)) { |
| 432 | − pr_debug("%s: Bad resource handle LUN! (%d)\n", | |
| 433 | − __func__, rhndl); | |
| 435 | + dev_dbg(dev, "%s: Bad resource handle LUN rhndl=%d\n", | |
| 436 | + __func__, rhndl); | |
| 434 | 437 | goto out; |
| 435 | 438 | } |
| 436 | 439 | |
| 437 | 440 | rhte = &ctxi->rht_start[rhndl]; |
| 438 | 441 | if (unlikely(rhte->nmask == 0)) { |
| 439 | − pr_debug("%s: Unopened resource handle! (%d)\n", | |
| 440 | − __func__, rhndl); | |
| 442 | + dev_dbg(dev, "%s: Unopened resource handle rhndl=%d\n", | |
| 443 | + __func__, rhndl); | |
| 441 | 444 | rhte = NULL; |
| 442 | 445 | goto out; |
| 443 | 446 | } |
| @@ -456,6 +459,8 @@ out: · 12 unmodified lines | ||
| 456 | 459 | struct sisl_rht_entry *rhte_checkout(struct ctx_info *ctxi, |
| 457 | 460 | struct llun_info *lli) |
| 458 | 461 | { |
| 462 | + struct cxlflash_cfg *cfg = ctxi->cfg; | |
| 463 | + struct device *dev = &cfg->dev->dev; | |
| 459 | 464 | struct sisl_rht_entry *rhte = NULL; |
| 460 | 465 | int i; |
| 461 | 466 | |
| @@ -470,7 +475,7 @@ struct sisl_rht_entry *rhte_checkout(struct ctx_info *ctxi, · 8 unmodified lines | ||
| 470 | 475 | if (likely(rhte)) |
| 471 | 476 | ctxi->rht_lun[i] = lli; |
| 472 | 477 | |
| 473 | − pr_debug("%s: returning rhte=%p (%d)\n", __func__, rhte, i); | |
| 478 | + dev_dbg(dev, "%s: returning rhte=%p index=%d\n", __func__, rhte, i); | |
| 474 | 479 | return rhte; |
| 475 | 480 | } |
| 476 | 481 | |
| @@ -547,7 +552,7 @@ int cxlflash_lun_attach(struct glun_info *gli, enum lun_mode mode, bool locked) · 70 unmodified lines | ||
| 547 | 552 | if (gli->mode == MODE_NONE) |
| 548 | 553 | gli->mode = mode; |
| 549 | 554 | else if (gli->mode != mode) { |
| 550 | − pr_debug("%s: LUN operating in mode %d, requested mode %d\n", | |
| 555 | + pr_debug("%s: gli_mode=%d requested_mode=%d\n", | |
| 551 | 556 | __func__, gli->mode, mode); |
| 552 | 557 | rc = -EINVAL; |
| 553 | 558 | goto out; |
| @@ -605,7 +610,7 @@ int _cxlflash_disk_release(struct scsi_device *sdev, · 51 unmodified lines | ||
| 605 | 610 | struct ctx_info *ctxi, |
| 606 | 611 | struct dk_cxlflash_release *release) |
| 607 | 612 | { |
| 608 | − struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; | |
| 613 | + struct cxlflash_cfg *cfg = shost_priv(sdev->host); | |
| 609 | 614 | struct device *dev = &cfg->dev->dev; |
| 610 | 615 | struct llun_info *lli = sdev->hostdata; |
| 611 | 616 | struct glun_info *gli = lli->parent; |
| @@ -622,13 +627,13 @@ int _cxlflash_disk_release(struct scsi_device *sdev, · 10 unmodified lines | ||
| 622 | 627 | struct sisl_rht_entry *rhte; |
| 623 | 628 | struct sisl_rht_entry_f1 *rhte_f1; |
| 624 | 629 | |
| 625 | − dev_dbg(dev, "%s: ctxid=%llu rhndl=0x%llx gli->mode=%u gli->users=%u\n", | |
| 630 | + dev_dbg(dev, "%s: ctxid=%llu rhndl=%llu gli->mode=%u gli->users=%u\n", | |
| 626 | 631 | __func__, ctxid, release->rsrc_handle, gli->mode, gli->users); |
| 627 | 632 | |
| 628 | 633 | if (!ctxi) { |
| 629 | 634 | ctxi = get_context(cfg, rctxid, lli, CTX_CTRL_ERR_FALLBACK); |
| 630 | 635 | if (unlikely(!ctxi)) { |
| 631 | − dev_dbg(dev, "%s: Bad context! (%llu)\n", | |
| 636 | + dev_dbg(dev, "%s: Bad context ctxid=%llu\n", | |
| 632 | 637 | __func__, ctxid); |
| 633 | 638 | rc = -EINVAL; |
| 634 | 639 | goto out; |
| @@ -639,7 +644,7 @@ int _cxlflash_disk_release(struct scsi_device *sdev, · 4 unmodified lines | ||
| 639 | 644 | |
| 640 | 645 | rhte = get_rhte(ctxi, rhndl, lli); |
| 641 | 646 | if (unlikely(!rhte)) { |
| 642 | − dev_dbg(dev, "%s: Bad resource handle! (%d)\n", | |
| 647 | + dev_dbg(dev, "%s: Bad resource handle rhndl=%d\n", | |
| 643 | 648 | __func__, rhndl); |
| 644 | 649 | rc = -EINVAL; |
| 645 | 650 | goto out; |
| @@ -758,13 +763,13 @@ static struct ctx_info *create_context(struct cxlflash_cfg *cfg) · 112 unmodified lines | ||
| 758 | 763 | lli = kzalloc((MAX_RHT_PER_CONTEXT * sizeof(*lli)), GFP_KERNEL); |
| 759 | 764 | ws = kzalloc((MAX_RHT_PER_CONTEXT * sizeof(*ws)), GFP_KERNEL); |
| 760 | 765 | if (unlikely(!ctxi || !lli || !ws)) { |
| 761 | − dev_err(dev, "%s: Unable to allocate context!\n", __func__); | |
| 766 | + dev_err(dev, "%s: Unable to allocate context\n", __func__); | |
| 762 | 767 | goto err; |
| 763 | 768 | } |
| 764 | 769 | |
| 765 | 770 | rhte = (struct sisl_rht_entry *)get_zeroed_page(GFP_KERNEL); |
| 766 | 771 | if (unlikely(!rhte)) { |
| 767 | − dev_err(dev, "%s: Unable to allocate RHT!\n", __func__); | |
| 772 | + dev_err(dev, "%s: Unable to allocate RHT\n", __func__); | |
| 768 | 773 | goto err; |
| 769 | 774 | } |
| 770 | 775 | |
| @@ -858,7 +863,7 @@ static int _cxlflash_disk_detach(struct scsi_device *sdev, · 87 unmodified lines | ||
| 858 | 863 | struct ctx_info *ctxi, |
| 859 | 864 | struct dk_cxlflash_detach *detach) |
| 860 | 865 | { |
| 861 | − struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; | |
| 866 | + struct cxlflash_cfg *cfg = shost_priv(sdev->host); | |
| 862 | 867 | struct device *dev = &cfg->dev->dev; |
| 863 | 868 | struct llun_info *lli = sdev->hostdata; |
| 864 | 869 | struct lun_access *lun_access, *t; |
| @@ -875,7 +880,7 @@ static int _cxlflash_disk_detach(struct scsi_device *sdev, · 10 unmodified lines | ||
| 875 | 880 | if (!ctxi) { |
| 876 | 881 | ctxi = get_context(cfg, rctxid, lli, CTX_CTRL_ERR_FALLBACK); |
| 877 | 882 | if (unlikely(!ctxi)) { |
| 878 | − dev_dbg(dev, "%s: Bad context! (%llu)\n", | |
| 883 | + dev_dbg(dev, "%s: Bad context ctxid=%llu\n", | |
| 879 | 884 | __func__, ctxid); |
| 880 | 885 | rc = -EINVAL; |
| 881 | 886 | goto out; |
| @@ -964,7 +969,7 @@ static int cxlflash_cxl_release(struct inode *inode, struct file *file) · 82 unmodified lines | ||
| 964 | 969 | |
| 965 | 970 | ctxid = cxl_process_element(ctx); |
| 966 | 971 | if (unlikely(ctxid < 0)) { |
| 967 | − dev_err(dev, "%s: Context %p was closed! (%d)\n", | |
| 972 | + dev_err(dev, "%s: Context %p was closed ctxid=%d\n", | |
| 968 | 973 | __func__, ctx, ctxid); |
| 969 | 974 | goto out; |
| 970 | 975 | } |
| @@ -973,18 +978,18 @@ static int cxlflash_cxl_release(struct inode *inode, struct file *file) · 2 unmodified lines | ||
| 973 | 978 | if (unlikely(!ctxi)) { |
| 974 | 979 | ctxi = get_context(cfg, ctxid, file, ctrl | CTX_CTRL_CLONE); |
| 975 | 980 | if (!ctxi) { |
| 976 | − dev_dbg(dev, "%s: Context %d already free!\n", | |
| 981 | + dev_dbg(dev, "%s: ctxid=%d already free\n", | |
| 977 | 982 | __func__, ctxid); |
| 978 | 983 | goto out_release; |
| 979 | 984 | } |
| 980 | 985 | |
| 981 | − dev_dbg(dev, "%s: Another process owns context %d!\n", | |
| 986 | + dev_dbg(dev, "%s: Another process owns ctxid=%d\n", | |
| 982 | 987 | __func__, ctxid); |
| 983 | 988 | put_context(ctxi); |
| 984 | 989 | goto out; |
| 985 | 990 | } |
| 986 | 991 | |
| 987 | − dev_dbg(dev, "%s: close for context %d\n", __func__, ctxid); | |
| 992 | + dev_dbg(dev, "%s: close for ctxid=%d\n", __func__, ctxid); | |
| 988 | 993 | |
| 989 | 994 | detach.context_id = ctxi->ctxid; |
| 990 | 995 | list_for_each_entry_safe(lun_access, t, &ctxi->luns, list) |
| @@ -1011,17 +1016,20 @@ static void unmap_context(struct ctx_info *ctxi) · 20 unmodified lines | ||
| 1011 | 1016 | |
| 1012 | 1017 | /** |
| 1013 | 1018 | * get_err_page() - obtains and allocates the error notification page |
| 1019 | + * @cfg: Internal structure associated with the host. | |
| 1014 | 1020 | * |
| 1015 | 1021 | * Return: error notification page on success, NULL on failure |
| 1016 | 1022 | */ |
| 1017 | −static struct page *get_err_page(void) | |
| 1023 | +static struct page *get_err_page(struct cxlflash_cfg *cfg) | |
| 1018 | 1024 | { |
| 1019 | 1025 | struct page *err_page = global.err_page; |
| 1026 | + struct device *dev = &cfg->dev->dev; | |
| 1020 | 1027 | |
| 1021 | 1028 | if (unlikely(!err_page)) { |
| 1022 | 1029 | err_page = alloc_page(GFP_KERNEL); |
| 1023 | 1030 | if (unlikely(!err_page)) { |
| 1024 | − pr_err("%s: Unable to allocate err_page!\n", __func__); | |
| 1031 | + dev_err(dev, "%s: Unable to allocate err_page\n", | |
| 1032 | + __func__); | |
| 1025 | 1033 | goto out; |
| 1026 | 1034 | } |
| 1027 | 1035 | |
| @@ -1039,7 +1047,7 @@ static struct page *get_err_page(void) · 11 unmodified lines | ||
| 1039 | 1047 | } |
| 1040 | 1048 | |
| 1041 | 1049 | out: |
| 1042 | − pr_debug("%s: returning err_page=%p\n", __func__, err_page); | |
| 1050 | + dev_dbg(dev, "%s: returning err_page=%p\n", __func__, err_page); | |
| 1043 | 1051 | return err_page; |
| 1044 | 1052 | } |
| 1045 | 1053 | |
| @@ -1074,14 +1082,14 @@ static int cxlflash_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) · 28 unmodified lines | ||
| 1074 | 1082 | |
| 1075 | 1083 | ctxid = cxl_process_element(ctx); |
| 1076 | 1084 | if (unlikely(ctxid < 0)) { |
| 1077 | − dev_err(dev, "%s: Context %p was closed! (%d)\n", | |
| 1085 | + dev_err(dev, "%s: Context %p was closed ctxid=%d\n", | |
| 1078 | 1086 | __func__, ctx, ctxid); |
| 1079 | 1087 | goto err; |
| 1080 | 1088 | } |
| 1081 | 1089 | |
| 1082 | 1090 | ctxi = get_context(cfg, ctxid, file, ctrl); |
| 1083 | 1091 | if (unlikely(!ctxi)) { |
| 1084 | − dev_dbg(dev, "%s: Bad context! (%d)\n", __func__, ctxid); | |
| 1092 | + dev_dbg(dev, "%s: Bad context ctxid=%d\n", __func__, ctxid); | |
| 1085 | 1093 | goto err; |
| 1086 | 1094 | } |
| 1087 | 1095 | |
| @@ -1091,13 +1099,12 @@ static int cxlflash_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) · 3 unmodified lines | ||
| 1091 | 1099 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); |
| 1092 | 1100 | rc = ctxi->cxl_mmap_vmops->fault(vma, vmf); |
| 1093 | 1101 | } else { |
| 1094 | − dev_dbg(dev, "%s: err recovery active, use err_page!\n", | |
| 1102 | + dev_dbg(dev, "%s: err recovery active, use err_page\n", | |
| 1095 | 1103 | __func__); |
| 1096 | 1104 | |
| 1097 | − err_page = get_err_page(); | |
| 1105 | + err_page = get_err_page(cfg); | |
| 1098 | 1106 | if (unlikely(!err_page)) { |
| 1099 | − dev_err(dev, "%s: Could not obtain error page!\n", | |
| 1100 | − __func__); | |
| 1107 | + dev_err(dev, "%s: Could not get err_page\n", __func__); | |
| 1101 | 1108 | rc = VM_FAULT_RETRY; |
| 1102 | 1109 | goto out; |
| 1103 | 1110 | } |
| @@ -1147,7 +1154,7 @@ static int cxlflash_cxl_mmap(struct file *file, struct vm_area_struct *vma) · 43 unmodified lines | ||
| 1147 | 1154 | |
| 1148 | 1155 | ctxid = cxl_process_element(ctx); |
| 1149 | 1156 | if (unlikely(ctxid < 0)) { |
| 1150 | − dev_err(dev, "%s: Context %p was closed! (%d)\n", | |
| 1157 | + dev_err(dev, "%s: Context %p was closed ctxid=%d\n", | |
| 1151 | 1158 | __func__, ctx, ctxid); |
| 1152 | 1159 | rc = -EIO; |
| 1153 | 1160 | goto out; |
| @@ -1155,7 +1162,7 @@ static int cxlflash_cxl_mmap(struct file *file, struct vm_area_struct *vma) · 1 unmodified line | ||
| 1155 | 1162 | |
| 1156 | 1163 | ctxi = get_context(cfg, ctxid, file, ctrl); |
| 1157 | 1164 | if (unlikely(!ctxi)) { |
| 1158 | − dev_dbg(dev, "%s: Bad context! (%d)\n", __func__, ctxid); | |
| 1165 | + dev_dbg(dev, "%s: Bad context ctxid=%d\n", __func__, ctxid); | |
| 1159 | 1166 | rc = -EIO; |
| 1160 | 1167 | goto out; |
| 1161 | 1168 | } |
| @@ -1251,7 +1258,7 @@ retry: · 89 unmodified lines | ||
| 1251 | 1258 | break; |
| 1252 | 1259 | goto retry; |
| 1253 | 1260 | case STATE_FAILTERM: |
| 1254 | − dev_dbg(dev, "%s: Failed/Terminating!\n", __func__); | |
| 1261 | + dev_dbg(dev, "%s: Failed/Terminating\n", __func__); | |
| 1255 | 1262 | rc = -ENODEV; |
| 1256 | 1263 | break; |
| 1257 | 1264 | default: |
| @@ -1276,7 +1283,7 @@ retry: · 18 unmodified lines | ||
| 1276 | 1283 | static int cxlflash_disk_attach(struct scsi_device *sdev, |
| 1277 | 1284 | struct dk_cxlflash_attach *attach) |
| 1278 | 1285 | { |
| 1279 | − struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; | |
| 1286 | + struct cxlflash_cfg *cfg = shost_priv(sdev->host); | |
| 1280 | 1287 | struct device *dev = &cfg->dev->dev; |
| 1281 | 1288 | struct afu *afu = cfg->afu; |
| 1282 | 1289 | struct llun_info *lli = sdev->hostdata; |
| @@ -1287,6 +1294,7 @@ static int cxlflash_disk_attach(struct scsi_device *sdev, · 4 unmodified lines | ||
| 1287 | 1294 | int rc = 0; |
| 1288 | 1295 | u32 perms; |
| 1289 | 1296 | int ctxid = -1; |
| 1297 | + u64 flags = 0UL; | |
| 1290 | 1298 | u64 rctxid = 0UL; |
| 1291 | 1299 | struct file *file = NULL; |
| 1292 | 1300 | |
| @@ -1302,24 +1310,24 @@ static int cxlflash_disk_attach(struct scsi_device *sdev, · 9 unmodified lines | ||
| 1302 | 1310 | } |
| 1303 | 1311 | |
| 1304 | 1312 | if (gli->max_lba == 0) { |
| 1305 | − dev_dbg(dev, "%s: No capacity info for this LUN (%016llX)\n", | |
| 1313 | + dev_dbg(dev, "%s: No capacity info for LUN=%016llx\n", | |
| 1306 | 1314 | __func__, lli->lun_id[sdev->channel]); |
| 1307 | 1315 | rc = read_cap16(sdev, lli); |
| 1308 | 1316 | if (rc) { |
| 1309 | − dev_err(dev, "%s: Invalid device! (%d)\n", | |
| 1317 | + dev_err(dev, "%s: Invalid device rc=%d\n", | |
| 1310 | 1318 | __func__, rc); |
| 1311 | 1319 | rc = -ENODEV; |
| 1312 | 1320 | goto out; |
| 1313 | 1321 | } |
| 1314 | − dev_dbg(dev, "%s: LBA = %016llX\n", __func__, gli->max_lba); | |
| 1315 | − dev_dbg(dev, "%s: BLK_LEN = %08X\n", __func__, gli->blk_len); | |
| 1322 | + dev_dbg(dev, "%s: LBA = %016llx\n", __func__, gli->max_lba); | |
| 1323 | + dev_dbg(dev, "%s: BLK_LEN = %08x\n", __func__, gli->blk_len); | |
| 1316 | 1324 | } |
| 1317 | 1325 | |
| 1318 | 1326 | if (attach->hdr.flags & DK_CXLFLASH_ATTACH_REUSE_CONTEXT) { |
| 1319 | 1327 | rctxid = attach->context_id; |
| 1320 | 1328 | ctxi = get_context(cfg, rctxid, NULL, 0); |
| 1321 | 1329 | if (!ctxi) { |
| 1322 | − dev_dbg(dev, "%s: Bad context! (%016llX)\n", | |
| 1330 | + dev_dbg(dev, "%s: Bad context rctxid=%016llx\n", | |
| 1323 | 1331 | __func__, rctxid); |
| 1324 | 1332 | rc = -EINVAL; |
| 1325 | 1333 | goto out; |
| @@ -1327,7 +1335,7 @@ static int cxlflash_disk_attach(struct scsi_device *sdev, · 1 unmodified line | ||
| 1327 | 1335 | |
| 1328 | 1336 | list_for_each_entry(lun_access, &ctxi->luns, list) |
| 1329 | 1337 | if (lun_access->lli == lli) { |
| 1330 | − dev_dbg(dev, "%s: Already attached!\n", | |
| 1338 | + dev_dbg(dev, "%s: Already attached\n", | |
| 1331 | 1339 | __func__); |
| 1332 | 1340 | rc = -EINVAL; |
| 1333 | 1341 | goto out; |
| @@ -1336,13 +1344,13 @@ static int cxlflash_disk_attach(struct scsi_device *sdev, · 2 unmodified lines | ||
| 1336 | 1344 | |
| 1337 | 1345 | rc = scsi_device_get(sdev); |
| 1338 | 1346 | if (unlikely(rc)) { |
| 1339 | − dev_err(dev, "%s: Unable to get sdev reference!\n", __func__); | |
| 1347 | + dev_err(dev, "%s: Unable to get sdev reference\n", __func__); | |
| 1340 | 1348 | goto out; |
| 1341 | 1349 | } |
| 1342 | 1350 | |
| 1343 | 1351 | lun_access = kzalloc(sizeof(*lun_access), GFP_KERNEL); |
| 1344 | 1352 | if (unlikely(!lun_access)) { |
| 1345 | − dev_err(dev, "%s: Unable to allocate lun_access!\n", __func__); | |
| 1353 | + dev_err(dev, "%s: Unable to allocate lun_access\n", __func__); | |
| 1346 | 1354 | rc = -ENOMEM; |
| 1347 | 1355 | goto err; |
| 1348 | 1356 | } |
| @@ -1352,7 +1360,7 @@ static int cxlflash_disk_attach(struct scsi_device *sdev, · 3 unmodified lines | ||
| 1352 | 1360 | |
| 1353 | 1361 | /* Non-NULL context indicates reuse (another context reference) */ |
| 1354 | 1362 | if (ctxi) { |
| 1355 | − dev_dbg(dev, "%s: Reusing context for LUN! (%016llX)\n", | |
| 1363 | + dev_dbg(dev, "%s: Reusing context for LUN rctxid=%016llx\n", | |
| 1356 | 1364 | __func__, rctxid); |
| 1357 | 1365 | kref_get(&ctxi->kref); |
| 1358 | 1366 | list_add(&lun_access->list, &ctxi->luns); |
| @@ -1361,7 +1369,7 @@ static int cxlflash_disk_attach(struct scsi_device *sdev, · 2 unmodified lines | ||
| 1361 | 1369 | |
| 1362 | 1370 | ctxi = create_context(cfg); |
| 1363 | 1371 | if (unlikely(!ctxi)) { |
| 1364 | − dev_err(dev, "%s: Failed to create context! (%d)\n", | |
| 1372 | + dev_err(dev, "%s: Failed to create context ctxid=%d\n", | |
| 1365 | 1373 | __func__, ctxid); |
| 1366 | 1374 | goto err; |
| 1367 | 1375 | } |
| @@ -1387,7 +1395,7 @@ static int cxlflash_disk_attach(struct scsi_device *sdev, · 19 unmodified lines | ||
| 1387 | 1395 | |
| 1388 | 1396 | ctxid = cxl_process_element(ctx); |
| 1389 | 1397 | if (unlikely((ctxid >= MAX_CONTEXT) || (ctxid < 0))) { |
| 1390 | − dev_err(dev, "%s: ctxid (%d) invalid!\n", __func__, ctxid); | |
| 1398 | + dev_err(dev, "%s: ctxid=%d invalid\n", __func__, ctxid); | |
| 1391 | 1399 | rc = -EPERM; |
| 1392 | 1400 | goto err; |
| 1393 | 1401 | } |
| @@ -1426,10 +1434,11 @@ static int cxlflash_disk_attach(struct scsi_device *sdev, · 32 unmodified lines | ||
| 1426 | 1434 | |
| 1427 | 1435 | out_attach: |
| 1428 | 1436 | if (fd != -1) |
| 1429 | − attach->hdr.return_flags = DK_CXLFLASH_APP_CLOSE_ADAP_FD; | |
| 1430 | − else | |
| 1431 | − attach->hdr.return_flags = 0; | |
| 1437 | + flags |= DK_CXLFLASH_APP_CLOSE_ADAP_FD; | |
| 1438 | + if (afu_is_sq_cmd_mode(afu)) | |
| 1439 | + flags |= DK_CXLFLASH_CONTEXT_SQ_CMD_MODE; | |
| 1432 | 1440 | |
| 1441 | + attach->hdr.return_flags = flags; | |
| 1433 | 1442 | attach->context_id = ctxi->ctxid; |
| 1434 | 1443 | attach->block_size = gli->blk_len; |
| 1435 | 1444 | attach->mmio_size = sizeof(afu->afu_map->hosts[0].harea); |
| @@ -1520,7 +1529,7 @@ static int recover_context(struct cxlflash_cfg *cfg, · 84 unmodified lines | ||
| 1520 | 1529 | |
| 1521 | 1530 | ctxid = cxl_process_element(ctx); |
| 1522 | 1531 | if (unlikely((ctxid >= MAX_CONTEXT) || (ctxid < 0))) { |
| 1523 | − dev_err(dev, "%s: ctxid (%d) invalid!\n", __func__, ctxid); | |
| 1532 | + dev_err(dev, "%s: ctxid=%d invalid\n", __func__, ctxid); | |
| 1524 | 1533 | rc = -EPERM; |
| 1525 | 1534 | goto err2; |
| 1526 | 1535 | } |
| @@ -1611,12 +1620,13 @@ err1: · 84 unmodified lines | ||
| 1611 | 1620 | static int cxlflash_afu_recover(struct scsi_device *sdev, |
| 1612 | 1621 | struct dk_cxlflash_recover_afu *recover) |
| 1613 | 1622 | { |
| 1614 | − struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; | |
| 1623 | + struct cxlflash_cfg *cfg = shost_priv(sdev->host); | |
| 1615 | 1624 | struct device *dev = &cfg->dev->dev; |
| 1616 | 1625 | struct llun_info *lli = sdev->hostdata; |
| 1617 | 1626 | struct afu *afu = cfg->afu; |
| 1618 | 1627 | struct ctx_info *ctxi = NULL; |
| 1619 | 1628 | struct mutex *mutex = &cfg->ctx_recovery_mutex; |
| 1629 | + u64 flags; | |
| 1620 | 1630 | u64 ctxid = DECODE_CTXID(recover->context_id), |
| 1621 | 1631 | rctxid = recover->context_id; |
| 1622 | 1632 | long reg; |
| @@ -1632,19 +1642,19 @@ static int cxlflash_afu_recover(struct scsi_device *sdev, · 9 unmodified lines | ||
| 1632 | 1642 | goto out; |
| 1633 | 1643 | rc = check_state(cfg); |
| 1634 | 1644 | if (rc) { |
| 1635 | − dev_err(dev, "%s: Failed state! rc=%d\n", __func__, rc); | |
| 1645 | + dev_err(dev, "%s: Failed state rc=%d\n", __func__, rc); | |
| 1636 | 1646 | rc = -ENODEV; |
| 1637 | 1647 | goto out; |
| 1638 | 1648 | } |
| 1639 | 1649 | |
| 1640 | − dev_dbg(dev, "%s: reason 0x%016llX rctxid=%016llX\n", | |
| 1650 | + dev_dbg(dev, "%s: reason=%016llx rctxid=%016llx\n", | |
| 1641 | 1651 | __func__, recover->reason, rctxid); |
| 1642 | 1652 | |
| 1643 | 1653 | retry: |
| 1644 | 1654 | /* Ensure that this process is attached to the context */ |
| 1645 | 1655 | ctxi = get_context(cfg, rctxid, lli, CTX_CTRL_ERR_FALLBACK); |
| 1646 | 1656 | if (unlikely(!ctxi)) { |
| 1647 | − dev_dbg(dev, "%s: Bad context! (%llu)\n", __func__, ctxid); | |
| 1657 | + dev_dbg(dev, "%s: Bad context ctxid=%llu\n", __func__, ctxid); | |
| 1648 | 1658 | rc = -EINVAL; |
| 1649 | 1659 | goto out; |
| 1650 | 1660 | } |
| @@ -1653,12 +1663,12 @@ retry: · 2 unmodified lines | ||
| 1653 | 1663 | retry_recover: |
| 1654 | 1664 | rc = recover_context(cfg, ctxi, &new_adap_fd); |
| 1655 | 1665 | if (unlikely(rc)) { |
| 1656 | − dev_err(dev, "%s: Recovery failed for context %llu (rc=%d)\n", | |
| 1666 | + dev_err(dev, "%s: Recovery failed ctxid=%llu rc=%d\n", | |
| 1657 | 1667 | __func__, ctxid, rc); |
| 1658 | 1668 | if ((rc == -ENODEV) && |
| 1659 | 1669 | ((atomic_read(&cfg->recovery_threads) > 1) || |
| 1660 | 1670 | (lretry--))) { |
| 1661 | − dev_dbg(dev, "%s: Going to try again!\n", | |
| 1671 | + dev_dbg(dev, "%s: Going to try again\n", | |
| 1662 | 1672 | __func__); |
| 1663 | 1673 | mutex_unlock(mutex); |
| 1664 | 1674 | msleep(100); |
| @@ -1672,11 +1682,16 @@ retry_recover: · 7 unmodified lines | ||
| 1672 | 1682 | } |
| 1673 | 1683 | |
| 1674 | 1684 | ctxi->err_recovery_active = false; |
| 1685 | + | |
| 1686 | + flags = DK_CXLFLASH_APP_CLOSE_ADAP_FD | | |
| 1687 | + DK_CXLFLASH_RECOVER_AFU_CONTEXT_RESET; | |
| 1688 | + if (afu_is_sq_cmd_mode(afu)) | |
| 1689 | + flags |= DK_CXLFLASH_CONTEXT_SQ_CMD_MODE; | |
| 1690 | + | |
| 1691 | + recover->hdr.return_flags = flags; | |
| 1675 | 1692 | recover->context_id = ctxi->ctxid; |
| 1676 | 1693 | recover->adap_fd = new_adap_fd; |
| 1677 | 1694 | recover->mmio_size = sizeof(afu->afu_map->hosts[0].harea); |
| 1678 | − recover->hdr.return_flags = DK_CXLFLASH_APP_CLOSE_ADAP_FD | | |
| 1679 | − DK_CXLFLASH_RECOVER_AFU_CONTEXT_RESET; | |
| 1680 | 1695 | goto out; |
| 1681 | 1696 | } |
| 1682 | 1697 | |
| @@ -1699,7 +1714,7 @@ retry_recover: · 16 unmodified lines | ||
| 1699 | 1714 | goto retry; |
| 1700 | 1715 | } |
| 1701 | 1716 | |
| 1702 | − dev_dbg(dev, "%s: MMIO working, no recovery required!\n", __func__); | |
| 1717 | + dev_dbg(dev, "%s: MMIO working, no recovery required\n", __func__); | |
| 1703 | 1718 | out: |
| 1704 | 1719 | if (likely(ctxi)) |
| 1705 | 1720 | put_context(ctxi); |
| @@ -1718,7 +1733,7 @@ out: · 12 unmodified lines | ||
| 1718 | 1733 | static int process_sense(struct scsi_device *sdev, |
| 1719 | 1734 | struct dk_cxlflash_verify *verify) |
| 1720 | 1735 | { |
| 1721 | − struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; | |
| 1736 | + struct cxlflash_cfg *cfg = shost_priv(sdev->host); | |
| 1722 | 1737 | struct device *dev = &cfg->dev->dev; |
| 1723 | 1738 | struct llun_info *lli = sdev->hostdata; |
| 1724 | 1739 | struct glun_info *gli = lli->parent; |
| @@ -1729,7 +1744,7 @@ static int process_sense(struct scsi_device *sdev, · 4 unmodified lines | ||
| 1729 | 1744 | rc = scsi_normalize_sense((const u8 *)&verify->sense_data, |
| 1730 | 1745 | DK_CXLFLASH_VERIFY_SENSE_LEN, &sshdr); |
| 1731 | 1746 | if (!rc) { |
| 1732 | − dev_err(dev, "%s: Failed to normalize sense data!\n", __func__); | |
| 1747 | + dev_err(dev, "%s: Failed to normalize sense data\n", __func__); | |
| 1733 | 1748 | rc = -EINVAL; |
| 1734 | 1749 | goto out; |
| 1735 | 1750 | } |
| @@ -1785,7 +1800,7 @@ static int cxlflash_disk_verify(struct scsi_device *sdev, · 49 unmodified lines | ||
| 1785 | 1800 | { |
| 1786 | 1801 | int rc = 0; |
| 1787 | 1802 | struct ctx_info *ctxi = NULL; |
| 1788 | − struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; | |
| 1803 | + struct cxlflash_cfg *cfg = shost_priv(sdev->host); | |
| 1789 | 1804 | struct device *dev = &cfg->dev->dev; |
| 1790 | 1805 | struct llun_info *lli = sdev->hostdata; |
| 1791 | 1806 | struct glun_info *gli = lli->parent; |
| @@ -1795,20 +1810,20 @@ static int cxlflash_disk_verify(struct scsi_device *sdev, · 3 unmodified lines | ||
| 1795 | 1810 | rctxid = verify->context_id; |
| 1796 | 1811 | u64 last_lba = 0; |
| 1797 | 1812 | |
| 1798 | − dev_dbg(dev, "%s: ctxid=%llu rhndl=%016llX, hint=%016llX, " | |
| 1799 | − "flags=%016llX\n", __func__, ctxid, verify->rsrc_handle, | |
| 1813 | + dev_dbg(dev, "%s: ctxid=%llu rhndl=%016llx, hint=%016llx, " | |
| 1814 | + "flags=%016llx\n", __func__, ctxid, verify->rsrc_handle, | |
| 1800 | 1815 | verify->hint, verify->hdr.flags); |
| 1801 | 1816 | |
| 1802 | 1817 | ctxi = get_context(cfg, rctxid, lli, 0); |
| 1803 | 1818 | if (unlikely(!ctxi)) { |
| 1804 | − dev_dbg(dev, "%s: Bad context! (%llu)\n", __func__, ctxid); | |
| 1819 | + dev_dbg(dev, "%s: Bad context ctxid=%llu\n", __func__, ctxid); | |
| 1805 | 1820 | rc = -EINVAL; |
| 1806 | 1821 | goto out; |
| 1807 | 1822 | } |
| 1808 | 1823 | |
| 1809 | 1824 | rhte = get_rhte(ctxi, rhndl, lli); |
| 1810 | 1825 | if (unlikely(!rhte)) { |
| 1811 | − dev_dbg(dev, "%s: Bad resource handle! (%d)\n", | |
| 1826 | + dev_dbg(dev, "%s: Bad resource handle rhndl=%d\n", | |
| 1812 | 1827 | __func__, rhndl); |
| 1813 | 1828 | rc = -EINVAL; |
| 1814 | 1829 | goto out; |
| @@ -1855,7 +1870,7 @@ static int cxlflash_disk_verify(struct scsi_device *sdev, · 40 unmodified lines | ||
| 1855 | 1870 | out: |
| 1856 | 1871 | if (likely(ctxi)) |
| 1857 | 1872 | put_context(ctxi); |
| 1858 | − dev_dbg(dev, "%s: returning rc=%d llba=%llX\n", | |
| 1873 | + dev_dbg(dev, "%s: returning rc=%d llba=%llx\n", | |
| 1859 | 1874 | __func__, rc, verify->last_lba); |
| 1860 | 1875 | return rc; |
| 1861 | 1876 | } |
| @@ -1907,7 +1922,7 @@ static char *decode_ioctl(int cmd) · 45 unmodified lines | ||
| 1907 | 1922 | */ |
| 1908 | 1923 | static int cxlflash_disk_direct_open(struct scsi_device *sdev, void *arg) |
| 1909 | 1924 | { |
| 1910 | − struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; | |
| 1925 | + struct cxlflash_cfg *cfg = shost_priv(sdev->host); | |
| 1911 | 1926 | struct device *dev = &cfg->dev->dev; |
| 1912 | 1927 | struct afu *afu = cfg->afu; |
| 1913 | 1928 | struct llun_info *lli = sdev->hostdata; |
| @@ -1927,25 +1942,25 @@ static int cxlflash_disk_direct_open(struct scsi_device *sdev, void *arg) · 13 unmodified lines | ||
| 1927 | 1942 | struct ctx_info *ctxi = NULL; |
| 1928 | 1943 | struct sisl_rht_entry *rhte = NULL; |
| 1929 | 1944 | |
| 1930 | − pr_debug("%s: ctxid=%llu ls=0x%llx\n", __func__, ctxid, lun_size); | |
| 1945 | + dev_dbg(dev, "%s: ctxid=%llu ls=%llu\n", __func__, ctxid, lun_size); | |
| 1931 | 1946 | |
| 1932 | 1947 | rc = cxlflash_lun_attach(gli, MODE_PHYSICAL, false); |
| 1933 | 1948 | if (unlikely(rc)) { |
| 1934 | − dev_dbg(dev, "%s: Failed to attach to LUN! (PHYSICAL)\n", | |
| 1935 | − __func__); | |
| 1949 | + dev_dbg(dev, "%s: Failed attach to LUN (PHYSICAL)\n", __func__); | |
| 1936 | 1950 | goto out; |
| 1937 | 1951 | } |
| 1938 | 1952 | |
| 1939 | 1953 | ctxi = get_context(cfg, rctxid, lli, 0); |
| 1940 | 1954 | if (unlikely(!ctxi)) { |
| 1941 | − dev_dbg(dev, "%s: Bad context! (%llu)\n", __func__, ctxid); | |
| 1955 | + dev_dbg(dev, "%s: Bad context ctxid=%llu\n", __func__, ctxid); | |
| 1942 | 1956 | rc = -EINVAL; |
| 1943 | 1957 | goto err1; |
| 1944 | 1958 | } |
| 1945 | 1959 | |
| 1946 | 1960 | rhte = rhte_checkout(ctxi, lli); |
| 1947 | 1961 | if (unlikely(!rhte)) { |
| 1948 | − dev_dbg(dev, "%s: too many opens for this context\n", __func__); | |
| 1962 | + dev_dbg(dev, "%s: Too many opens ctxid=%lld\n", | |
| 1963 | + __func__, ctxid); | |
| 1949 | 1964 | rc = -EMFILE; /* too many opens */ |
| 1950 | 1965 | goto err1; |
| 1951 | 1966 | } |
| @@ -1963,7 +1978,7 @@ static int cxlflash_disk_direct_open(struct scsi_device *sdev, void *arg) · 11 unmodified lines | ||
| 1963 | 1978 | out: |
| 1964 | 1979 | if (likely(ctxi)) |
| 1965 | 1980 | put_context(ctxi); |
| 1966 | − dev_dbg(dev, "%s: returning handle 0x%llx rc=%d llba %lld\n", | |
| 1981 | + dev_dbg(dev, "%s: returning handle=%llu rc=%d llba=%llu\n", | |
| 1967 | 1982 | __func__, rsrc_handle, rc, last_lba); |
| 1968 | 1983 | return rc; |
| 1969 | 1984 | |
| @@ -1985,7 +2000,7 @@ err1: · 15 unmodified lines | ||
| 1985 | 2000 | */ |
| 1986 | 2001 | static int ioctl_common(struct scsi_device *sdev, int cmd) |
| 1987 | 2002 | { |
| 1988 | − struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; | |
| 2003 | + struct cxlflash_cfg *cfg = shost_priv(sdev->host); | |
| 1989 | 2004 | struct device *dev = &cfg->dev->dev; |
| 1990 | 2005 | struct llun_info *lli = sdev->hostdata; |
| 1991 | 2006 | int rc = 0; |
| @@ -2002,7 +2017,7 @@ static int ioctl_common(struct scsi_device *sdev, int cmd) · 10 unmodified lines | ||
| 2002 | 2017 | case DK_CXLFLASH_VLUN_RESIZE: |
| 2003 | 2018 | case DK_CXLFLASH_RELEASE: |
| 2004 | 2019 | case DK_CXLFLASH_DETACH: |
| 2005 | − dev_dbg(dev, "%s: Command override! (%d)\n", | |
| 2020 | + dev_dbg(dev, "%s: Command override rc=%d\n", | |
| 2006 | 2021 | __func__, rc); |
| 2007 | 2022 | rc = 0; |
| 2008 | 2023 | break; |
| @@ -2032,7 +2047,7 @@ int cxlflash_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) · 23 unmodified lines | ||
| 2032 | 2047 | { |
| 2033 | 2048 | typedef int (*sioctl) (struct scsi_device *, void *); |
| 2034 | 2049 | |
| 2035 | − struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; | |
| 2050 | + struct cxlflash_cfg *cfg = shost_priv(sdev->host); | |
| 2036 | 2051 | struct device *dev = &cfg->dev->dev; |
| 2037 | 2052 | struct afu *afu = cfg->afu; |
| 2038 | 2053 | struct dk_cxlflash_hdr *hdr; |
| @@ -2111,7 +2126,7 @@ int cxlflash_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) · 72 unmodified lines | ||
| 2111 | 2126 | } |
| 2112 | 2127 | |
| 2113 | 2128 | if (unlikely(copy_from_user(&buf, arg, size))) { |
| 2114 | − dev_err(dev, "%s: copy_from_user() fail! " | |
| 2129 | + dev_err(dev, "%s: copy_from_user() fail " | |
| 2115 | 2130 | "size=%lu cmd=%d (%s) arg=%p\n", |
| 2116 | 2131 | __func__, size, cmd, decode_ioctl(cmd), arg); |
| 2117 | 2132 | rc = -EFAULT; |
| @@ -2127,7 +2142,7 @@ int cxlflash_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) · 9 unmodified lines | ||
| 2127 | 2142 | } |
| 2128 | 2143 | |
| 2129 | 2144 | if (hdr->rsvd[0] || hdr->rsvd[1] || hdr->rsvd[2] || hdr->return_flags) { |
| 2130 | − dev_dbg(dev, "%s: Reserved/rflags populated!\n", __func__); | |
| 2145 | + dev_dbg(dev, "%s: Reserved/rflags populated\n", __func__); | |
| 2131 | 2146 | rc = -EINVAL; |
| 2132 | 2147 | goto cxlflash_ioctl_exit; |
| 2133 | 2148 | } |
| @@ -2135,7 +2150,7 @@ int cxlflash_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) · 1 unmodified line | ||
| 2135 | 2150 | rc = do_ioctl(sdev, (void *)&buf); |
| 2136 | 2151 | if (likely(!rc)) |
| 2137 | 2152 | if (unlikely(copy_to_user(arg, &buf, size))) { |
| 2138 | − dev_err(dev, "%s: copy_to_user() fail! " | |
| 2153 | + dev_err(dev, "%s: copy_to_user() fail " | |
| 2139 | 2154 | "size=%lu cmd=%d (%s) arg=%p\n", |
| 2140 | 2155 | __func__, size, cmd, decode_ioctl(cmd), arg); |
| 2141 | 2156 | rc = -EFAULT; |
| @@ -66,8 +66,8 @@ static int ba_init(struct ba_lun *ba_lun) · 65 unmodified lines | ||
| 66 | 66 | int last_word_underflow = 0; |
| 67 | 67 | u64 *lam; |
| 68 | 68 | |
| 69 | − pr_debug("%s: Initializing LUN: lun_id = %llX, " | |
| 70 | − "ba_lun->lsize = %lX, ba_lun->au_size = %lX\n", | |
| 69 | + pr_debug("%s: Initializing LUN: lun_id=%016llx " | |
| 70 | + "ba_lun->lsize=%lx ba_lun->au_size=%lX\n", | |
| 71 | 71 | __func__, ba_lun->lun_id, ba_lun->lsize, ba_lun->au_size); |
| 72 | 72 | |
| 73 | 73 | /* Calculate bit map size */ |
| @@ -80,7 +80,7 @@ static int ba_init(struct ba_lun *ba_lun) · 6 unmodified lines | ||
| 80 | 80 | /* Allocate lun information container */ |
| 81 | 81 | bali = kzalloc(sizeof(struct ba_lun_info), GFP_KERNEL); |
| 82 | 82 | if (unlikely(!bali)) { |
| 83 | − pr_err("%s: Failed to allocate lun_info for lun_id %llX\n", | |
| 83 | + pr_err("%s: Failed to allocate lun_info lun_id=%016llx\n", | |
| 84 | 84 | __func__, ba_lun->lun_id); |
| 85 | 85 | return -ENOMEM; |
| 86 | 86 | } |
| @@ -96,7 +96,7 @@ static int ba_init(struct ba_lun *ba_lun) · 9 unmodified lines | ||
| 96 | 96 | GFP_KERNEL); |
| 97 | 97 | if (unlikely(!bali->lun_alloc_map)) { |
| 98 | 98 | pr_err("%s: Failed to allocate lun allocation map: " |
| 99 | − "lun_id = %llX\n", __func__, ba_lun->lun_id); | |
| 99 | + "lun_id=%016llx\n", __func__, ba_lun->lun_id); | |
| 100 | 100 | kfree(bali); |
| 101 | 101 | return -ENOMEM; |
| 102 | 102 | } |
| @@ -125,7 +125,7 @@ static int ba_init(struct ba_lun *ba_lun) · 22 unmodified lines | ||
| 125 | 125 | bali->aun_clone_map = kzalloc((bali->total_aus * sizeof(u8)), |
| 126 | 126 | GFP_KERNEL); |
| 127 | 127 | if (unlikely(!bali->aun_clone_map)) { |
| 128 | − pr_err("%s: Failed to allocate clone map: lun_id = %llX\n", | |
| 128 | + pr_err("%s: Failed to allocate clone map: lun_id=%016llx\n", | |
| 129 | 129 | __func__, ba_lun->lun_id); |
| 130 | 130 | kfree(bali->lun_alloc_map); |
| 131 | 131 | kfree(bali); |
| @@ -136,7 +136,7 @@ static int ba_init(struct ba_lun *ba_lun) · 4 unmodified lines | ||
| 136 | 136 | ba_lun->ba_lun_handle = bali; |
| 137 | 137 | |
| 138 | 138 | pr_debug("%s: Successfully initialized the LUN: " |
| 139 | − "lun_id = %llX, bitmap size = %X, free_aun_cnt = %llX\n", | |
| 139 | + "lun_id=%016llx bitmap size=%x, free_aun_cnt=%llx\n", | |
| 140 | 140 | __func__, ba_lun->lun_id, bali->lun_bmap_size, |
| 141 | 141 | bali->free_aun_cnt); |
| 142 | 142 | return 0; |
| @@ -165,10 +165,9 @@ static int find_free_range(u32 low, · 22 unmodified lines | ||
| 165 | 165 | num_bits = (sizeof(*lam) * BITS_PER_BYTE); |
| 166 | 166 | bit_pos = find_first_bit(lam, num_bits); |
| 167 | 167 | |
| 168 | − pr_devel("%s: Found free bit %llX in LUN " | |
| 169 | − "map entry %llX at bitmap index = %X\n", | |
| 170 | − __func__, bit_pos, bali->lun_alloc_map[i], | |
| 171 | − i); | |
| 168 | + pr_devel("%s: Found free bit %llu in LUN " | |
| 169 | + "map entry %016llx at bitmap index = %d\n", | |
| 170 | + __func__, bit_pos, bali->lun_alloc_map[i], i); | |
| 172 | 171 | |
| 173 | 172 | *bit_word = i; |
| 174 | 173 | bali->free_aun_cnt--; |
| @@ -194,11 +193,11 @@ static u64 ba_alloc(struct ba_lun *ba_lun) · 19 unmodified lines | ||
| 194 | 193 | bali = ba_lun->ba_lun_handle; |
| 195 | 194 | |
| 196 | 195 | pr_debug("%s: Received block allocation request: " |
| 197 | − "lun_id = %llX, free_aun_cnt = %llX\n", | |
| 196 | + "lun_id=%016llx free_aun_cnt=%llx\n", | |
| 198 | 197 | __func__, ba_lun->lun_id, bali->free_aun_cnt); |
| 199 | 198 | |
| 200 | 199 | if (bali->free_aun_cnt == 0) { |
| 201 | − pr_debug("%s: No space left on LUN: lun_id = %llX\n", | |
| 200 | + pr_debug("%s: No space left on LUN: lun_id=%016llx\n", | |
| 202 | 201 | __func__, ba_lun->lun_id); |
| 203 | 202 | return -1ULL; |
| 204 | 203 | } |
| @@ -212,7 +211,7 @@ static u64 ba_alloc(struct ba_lun *ba_lun) · 7 unmodified lines | ||
| 212 | 211 | bali, &bit_word); |
| 213 | 212 | if (bit_pos == -1) { |
| 214 | 213 | pr_debug("%s: Could not find an allocation unit on LUN:" |
| 215 | − " lun_id = %llX\n", __func__, ba_lun->lun_id); | |
| 214 | + " lun_id=%016llx\n", __func__, ba_lun->lun_id); | |
| 216 | 215 | return -1ULL; |
| 217 | 216 | } |
| 218 | 217 | } |
| @@ -223,8 +222,8 @@ static u64 ba_alloc(struct ba_lun *ba_lun) · 4 unmodified lines | ||
| 223 | 222 | else |
| 224 | 223 | bali->free_curr_idx = bit_word; |
| 225 | 224 | |
| 226 | − pr_debug("%s: Allocating AU number %llX, on lun_id %llX, " | |
| 227 | − "free_aun_cnt = %llX\n", __func__, | |
| 225 | + pr_debug("%s: Allocating AU number=%llx lun_id=%016llx " | |
| 226 | + "free_aun_cnt=%llx\n", __func__, | |
| 228 | 227 | ((bit_word * BITS_PER_LONG) + bit_pos), ba_lun->lun_id, |
| 229 | 228 | bali->free_aun_cnt); |
| 230 | 229 | |
| @@ -266,18 +265,18 @@ static int ba_free(struct ba_lun *ba_lun, u64 to_free) · 35 unmodified lines | ||
| 266 | 265 | bali = ba_lun->ba_lun_handle; |
| 267 | 266 | |
| 268 | 267 | if (validate_alloc(bali, to_free)) { |
| 269 | − pr_debug("%s: The AUN %llX is not allocated on lun_id %llX\n", | |
| 268 | + pr_debug("%s: AUN %llx is not allocated on lun_id=%016llx\n", | |
| 270 | 269 | __func__, to_free, ba_lun->lun_id); |
| 271 | 270 | return -1; |
| 272 | 271 | } |
| 273 | 272 | |
| 274 | − pr_debug("%s: Received a request to free AU %llX on lun_id %llX, " | |
| 275 | − "free_aun_cnt = %llX\n", __func__, to_free, ba_lun->lun_id, | |
| 273 | + pr_debug("%s: Received a request to free AU=%llx lun_id=%016llx " | |
| 274 | + "free_aun_cnt=%llx\n", __func__, to_free, ba_lun->lun_id, | |
| 276 | 275 | bali->free_aun_cnt); |
| 277 | 276 | |
| 278 | 277 | if (bali->aun_clone_map[to_free] > 0) { |
| 279 | − pr_debug("%s: AUN %llX on lun_id %llX has been cloned. Clone " | |
| 280 | − "count = %X\n", __func__, to_free, ba_lun->lun_id, | |
| 278 | + pr_debug("%s: AUN %llx lun_id=%016llx cloned. Clone count=%x\n", | |
| 279 | + __func__, to_free, ba_lun->lun_id, | |
| 281 | 280 | bali->aun_clone_map[to_free]); |
| 282 | 281 | bali->aun_clone_map[to_free]--; |
| 283 | 282 | return 0; |
| @@ -294,8 +293,8 @@ static int ba_free(struct ba_lun *ba_lun, u64 to_free) · 10 unmodified lines | ||
| 294 | 293 | else if (idx > bali->free_high_idx) |
| 295 | 294 | bali->free_high_idx = idx; |
| 296 | 295 | |
| 297 | − pr_debug("%s: Successfully freed AU at bit_pos %X, bit map index %X on " | |
| 298 | − "lun_id %llX, free_aun_cnt = %llX\n", __func__, bit_pos, idx, | |
| 296 | + pr_debug("%s: Successfully freed AU bit_pos=%x bit map index=%x " | |
| 297 | + "lun_id=%016llx free_aun_cnt=%llx\n", __func__, bit_pos, idx, | |
| 299 | 298 | ba_lun->lun_id, bali->free_aun_cnt); |
| 300 | 299 | |
| 301 | 300 | return 0; |
| @@ -313,16 +312,16 @@ static int ba_clone(struct ba_lun *ba_lun, u64 to_clone) · 11 unmodified lines | ||
| 313 | 312 | struct ba_lun_info *bali = ba_lun->ba_lun_handle; |
| 314 | 313 | |
| 315 | 314 | if (validate_alloc(bali, to_clone)) { |
| 316 | − pr_debug("%s: AUN %llX is not allocated on lun_id %llX\n", | |
| 315 | + pr_debug("%s: AUN=%llx not allocated on lun_id=%016llx\n", | |
| 317 | 316 | __func__, to_clone, ba_lun->lun_id); |
| 318 | 317 | return -1; |
| 319 | 318 | } |
| 320 | 319 | |
| 321 | − pr_debug("%s: Received a request to clone AUN %llX on lun_id %llX\n", | |
| 320 | + pr_debug("%s: Received a request to clone AUN %llx on lun_id=%016llx\n", | |
| 322 | 321 | __func__, to_clone, ba_lun->lun_id); |
| 323 | 322 | |
| 324 | 323 | if (bali->aun_clone_map[to_clone] == MAX_AUN_CLONE_CNT) { |
| 325 | − pr_debug("%s: AUN %llX on lun_id %llX hit max clones already\n", | |
| 324 | + pr_debug("%s: AUN %llx on lun_id=%016llx hit max clones already\n", | |
| 326 | 325 | __func__, to_clone, ba_lun->lun_id); |
| 327 | 326 | return -1; |
| 328 | 327 | } |
| @@ -433,7 +432,7 @@ static int write_same16(struct scsi_device *sdev, · 104 unmodified lines | ||
| 433 | 432 | u64 offset = lba; |
| 434 | 433 | int left = nblks; |
| 435 | 434 | u32 to = sdev->request_queue->rq_timeout; |
| 436 | − struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; | |
| 435 | + struct cxlflash_cfg *cfg = shost_priv(sdev->host); | |
| 437 | 436 | struct device *dev = &cfg->dev->dev; |
| 438 | 437 | |
| 439 | 438 | cmd_buf = kzalloc(CMD_BUFSIZE, GFP_KERNEL); |
| @@ -459,7 +458,7 @@ static int write_same16(struct scsi_device *sdev, · 19 unmodified lines | ||
| 459 | 458 | down_read(&cfg->ioctl_rwsem); |
| 460 | 459 | rc = check_state(cfg); |
| 461 | 460 | if (rc) { |
| 462 | − dev_err(dev, "%s: Failed state! result=0x08%X\n", | |
| 461 | + dev_err(dev, "%s: Failed state result=%08x\n", | |
| 463 | 462 | __func__, result); |
| 464 | 463 | rc = -ENODEV; |
| 465 | 464 | goto out; |
| @@ -467,7 +466,7 @@ static int write_same16(struct scsi_device *sdev, · 1 unmodified line | ||
| 467 | 466 | |
| 468 | 467 | if (result) { |
| 469 | 468 | dev_err_ratelimited(dev, "%s: command failed for " |
| 470 | − "offset %lld result=0x%x\n", | |
| 469 | + "offset=%lld result=%08x\n", | |
| 471 | 470 | __func__, offset, result); |
| 472 | 471 | rc = -EIO; |
| 473 | 472 | goto out; |
| @@ -480,7 +479,7 @@ out: · 6 unmodified lines | ||
| 480 | 479 | kfree(cmd_buf); |
| 481 | 480 | kfree(scsi_cmd); |
| 482 | 481 | kfree(sense_buf); |
| 483 | − pr_debug("%s: returning rc=%d\n", __func__, rc); | |
| 482 | + dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc); | |
| 484 | 483 | return rc; |
| 485 | 484 | } |
| 486 | 485 | |
| @@ -508,6 +507,8 @@ static int grow_lxt(struct afu *afu, · 21 unmodified lines | ||
| 508 | 507 | struct sisl_rht_entry *rhte, |
| 509 | 508 | u64 *new_size) |
| 510 | 509 | { |
| 510 | + struct cxlflash_cfg *cfg = shost_priv(sdev->host); | |
| 511 | + struct device *dev = &cfg->dev->dev; | |
| 511 | 512 | struct sisl_lxt_entry *lxt = NULL, *lxt_old = NULL; |
| 512 | 513 | struct llun_info *lli = sdev->hostdata; |
| 513 | 514 | struct glun_info *gli = lli->parent; |
| @@ -527,7 +528,8 @@ static int grow_lxt(struct afu *afu, · 13 unmodified lines | ||
| 527 | 528 | mutex_lock(&blka->mutex); |
| 528 | 529 | av_size = ba_space(&blka->ba_lun); |
| 529 | 530 | if (unlikely(av_size <= 0)) { |
| 530 | − pr_debug("%s: ba_space error: av_size %d\n", __func__, av_size); | |
| 531 | + dev_dbg(dev, "%s: ba_space error av_size=%d\n", | |
| 532 | + __func__, av_size); | |
| 531 | 533 | mutex_unlock(&blka->mutex); |
| 532 | 534 | rc = -ENOSPC; |
| 533 | 535 | goto out; |
| @@ -568,8 +570,8 @@ static int grow_lxt(struct afu *afu, · 34 unmodified lines | ||
| 568 | 570 | */ |
| 569 | 571 | aun = ba_alloc(&blka->ba_lun); |
| 570 | 572 | if ((aun == -1ULL) || (aun >= blka->nchunk)) |
| 571 | − pr_debug("%s: ba_alloc error: allocated chunk# %llX, " | |
| 572 | − "max %llX\n", __func__, aun, blka->nchunk - 1); | |
| 573 | + dev_dbg(dev, "%s: ba_alloc error allocated chunk=%llu " | |
| 574 | + "max=%llu\n", __func__, aun, blka->nchunk - 1); | |
| 573 | 575 | |
| 574 | 576 | /* select both ports, use r/w perms from RHT */ |
| 575 | 577 | lxt[i].rlba_base = ((aun << MC_CHUNK_SHIFT) | |
| @@ -599,7 +601,7 @@ static int grow_lxt(struct afu *afu, · 23 unmodified lines | ||
| 599 | 601 | kfree(lxt_old); |
| 600 | 602 | *new_size = my_new_size; |
| 601 | 603 | out: |
| 602 | − pr_debug("%s: returning rc=%d\n", __func__, rc); | |
| 604 | + dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc); | |
| 603 | 605 | return rc; |
| 604 | 606 | } |
| 605 | 607 | |
| @@ -621,6 +623,8 @@ static int shrink_lxt(struct afu *afu, · 15 unmodified lines | ||
| 621 | 623 | struct ctx_info *ctxi, |
| 622 | 624 | u64 *new_size) |
| 623 | 625 | { |
| 626 | + struct cxlflash_cfg *cfg = shost_priv(sdev->host); | |
| 627 | + struct device *dev = &cfg->dev->dev; | |
| 624 | 628 | struct sisl_lxt_entry *lxt, *lxt_old; |
| 625 | 629 | struct llun_info *lli = sdev->hostdata; |
| 626 | 630 | struct glun_info *gli = lli->parent; |
| @@ -706,7 +710,7 @@ static int shrink_lxt(struct afu *afu, · 79 unmodified lines | ||
| 706 | 710 | kfree(lxt_old); |
| 707 | 711 | *new_size = my_new_size; |
| 708 | 712 | out: |
| 709 | − pr_debug("%s: returning rc=%d\n", __func__, rc); | |
| 713 | + dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc); | |
| 710 | 714 | return rc; |
| 711 | 715 | } |
| 712 | 716 | |
| @@ -728,7 +732,8 @@ int _cxlflash_vlun_resize(struct scsi_device *sdev, · 15 unmodified lines | ||
| 728 | 732 | struct ctx_info *ctxi, |
| 729 | 733 | struct dk_cxlflash_resize *resize) |
| 730 | 734 | { |
| 731 | − struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; | |
| 735 | + struct cxlflash_cfg *cfg = shost_priv(sdev->host); | |
| 736 | + struct device *dev = &cfg->dev->dev; | |
| 732 | 737 | struct llun_info *lli = sdev->hostdata; |
| 733 | 738 | struct glun_info *gli = lli->parent; |
| 734 | 739 | struct afu *afu = cfg->afu; |
| @@ -751,13 +756,13 @@ int _cxlflash_vlun_resize(struct scsi_device *sdev, · 16 unmodified lines | ||
| 751 | 756 | nsectors = (resize->req_size * CXLFLASH_BLOCK_SIZE) / gli->blk_len; |
| 752 | 757 | new_size = DIV_ROUND_UP(nsectors, MC_CHUNK_SIZE); |
| 753 | 758 | |
| 754 | − pr_debug("%s: ctxid=%llu rhndl=0x%llx, req_size=0x%llx," | |
| 755 | − "new_size=%llx\n", __func__, ctxid, resize->rsrc_handle, | |
| 756 | − resize->req_size, new_size); | |
| 759 | + dev_dbg(dev, "%s: ctxid=%llu rhndl=%llu req_size=%llu new_size=%llu\n", | |
| 760 | + __func__, ctxid, resize->rsrc_handle, resize->req_size, | |
| 761 | + new_size); | |
| 757 | 762 | |
| 758 | 763 | if (unlikely(gli->mode != MODE_VIRTUAL)) { |
| 759 | − pr_debug("%s: LUN mode does not support resize! (%d)\n", | |
| 760 | − __func__, gli->mode); | |
| 764 | + dev_dbg(dev, "%s: LUN mode does not support resize mode=%d\n", | |
| 765 | + __func__, gli->mode); | |
| 761 | 766 | rc = -EINVAL; |
| 762 | 767 | goto out; |
| 763 | 768 | |
| @@ -766,7 +771,8 @@ int _cxlflash_vlun_resize(struct scsi_device *sdev, · 2 unmodified lines | ||
| 766 | 771 | if (!ctxi) { |
| 767 | 772 | ctxi = get_context(cfg, rctxid, lli, CTX_CTRL_ERR_FALLBACK); |
| 768 | 773 | if (unlikely(!ctxi)) { |
| 769 | − pr_debug("%s: Bad context! (%llu)\n", __func__, ctxid); | |
| 774 | + dev_dbg(dev, "%s: Bad context ctxid=%llu\n", | |
| 775 | + __func__, ctxid); | |
| 770 | 776 | rc = -EINVAL; |
| 771 | 777 | goto out; |
| 772 | 778 | } |
| @@ -776,7 +782,8 @@ int _cxlflash_vlun_resize(struct scsi_device *sdev, · 3 unmodified lines | ||
| 776 | 782 | |
| 777 | 783 | rhte = get_rhte(ctxi, rhndl, lli); |
| 778 | 784 | if (unlikely(!rhte)) { |
| 779 | − pr_debug("%s: Bad resource handle! (%u)\n", __func__, rhndl); | |
| 785 | + dev_dbg(dev, "%s: Bad resource handle rhndl=%u\n", | |
| 786 | + __func__, rhndl); | |
| 780 | 787 | rc = -EINVAL; |
| 781 | 788 | goto out; |
| 782 | 789 | } |
| @@ -794,8 +801,8 @@ int _cxlflash_vlun_resize(struct scsi_device *sdev, · 11 unmodified lines | ||
| 794 | 801 | out: |
| 795 | 802 | if (put_ctx) |
| 796 | 803 | put_context(ctxi); |
| 797 | − pr_debug("%s: resized to %lld returning rc=%d\n", | |
| 798 | − __func__, resize->last_lba, rc); | |
| 804 | + dev_dbg(dev, "%s: resized to %llu returning rc=%d\n", | |
| 805 | + __func__, resize->last_lba, rc); | |
| 799 | 806 | return rc; |
| 800 | 807 | } |
| 801 | 808 | |
| @@ -815,6 +822,7 @@ void cxlflash_restore_luntable(struct cxlflash_cfg *cfg) · 13 unmodified lines | ||
| 815 | 822 | u32 chan; |
| 816 | 823 | u32 lind; |
| 817 | 824 | struct afu *afu = cfg->afu; |
| 825 | + struct device *dev = &cfg->dev->dev; | |
| 818 | 826 | struct sisl_global_map __iomem *agm = &afu->afu_map->global; |
| 819 | 827 | |
| 820 | 828 | mutex_lock(&global.mutex); |
| @@ -828,15 +836,15 @@ void cxlflash_restore_luntable(struct cxlflash_cfg *cfg) · 7 unmodified lines | ||
| 828 | 836 | if (lli->port_sel == BOTH_PORTS) { |
| 829 | 837 | writeq_be(lli->lun_id[0], &agm->fc_port[0][lind]); |
| 830 | 838 | writeq_be(lli->lun_id[1], &agm->fc_port[1][lind]); |
| 831 | − pr_debug("%s: Virtual LUN on slot %d id0=%llx, " | |
| 832 | − "id1=%llx\n", __func__, lind, | |
| 833 | − lli->lun_id[0], lli->lun_id[1]); | |
| 839 | + dev_dbg(dev, "%s: Virtual LUN on slot %d id0=%llx " | |
| 840 | + "id1=%llx\n", __func__, lind, | |
| 841 | + lli->lun_id[0], lli->lun_id[1]); | |
| 834 | 842 | } else { |
| 835 | 843 | chan = PORT2CHAN(lli->port_sel); |
| 836 | 844 | writeq_be(lli->lun_id[chan], &agm->fc_port[chan][lind]); |
| 837 | − pr_debug("%s: Virtual LUN on slot %d chan=%d, " | |
| 838 | − "id=%llx\n", __func__, lind, chan, | |
| 839 | − lli->lun_id[chan]); | |
| 845 | + dev_dbg(dev, "%s: Virtual LUN on slot %d chan=%d " | |
| 846 | + "id=%llx\n", __func__, lind, chan, | |
| 847 | + lli->lun_id[chan]); | |
| 840 | 848 | } |
| 841 | 849 | } |
| 842 | 850 | |
| @@ -860,6 +868,7 @@ static int init_luntable(struct cxlflash_cfg *cfg, struct llun_info *lli) · 17 unmodified lines | ||
| 860 | 868 | u32 lind; |
| 861 | 869 | int rc = 0; |
| 862 | 870 | struct afu *afu = cfg->afu; |
| 871 | + struct device *dev = &cfg->dev->dev; | |
| 863 | 872 | struct sisl_global_map __iomem *agm = &afu->afu_map->global; |
| 864 | 873 | |
| 865 | 874 | mutex_lock(&global.mutex); |
| @@ -882,8 +891,8 @@ static int init_luntable(struct cxlflash_cfg *cfg, struct llun_info *lli) · 16 unmodified lines | ||
| 882 | 891 | writeq_be(lli->lun_id[0], &agm->fc_port[0][lind]); |
| 883 | 892 | writeq_be(lli->lun_id[1], &agm->fc_port[1][lind]); |
| 884 | 893 | cfg->promote_lun_index++; |
| 885 | − pr_debug("%s: Virtual LUN on slot %d id0=%llx, id1=%llx\n", | |
| 886 | − __func__, lind, lli->lun_id[0], lli->lun_id[1]); | |
| 894 | + dev_dbg(dev, "%s: Virtual LUN on slot %d id0=%llx id1=%llx\n", | |
| 895 | + __func__, lind, lli->lun_id[0], lli->lun_id[1]); | |
| 887 | 896 | } else { |
| 888 | 897 | /* |
| 889 | 898 | * If this LUN is visible only from one port, we will put |
| @@ -898,14 +907,14 @@ static int init_luntable(struct cxlflash_cfg *cfg, struct llun_info *lli) · 8 unmodified lines | ||
| 898 | 907 | lind = lli->lun_index = cfg->last_lun_index[chan]; |
| 899 | 908 | writeq_be(lli->lun_id[chan], &agm->fc_port[chan][lind]); |
| 900 | 909 | cfg->last_lun_index[chan]--; |
| 901 | − pr_debug("%s: Virtual LUN on slot %d chan=%d, id=%llx\n", | |
| 902 | − __func__, lind, chan, lli->lun_id[chan]); | |
| 910 | + dev_dbg(dev, "%s: Virtual LUN on slot %d chan=%d id=%llx\n", | |
| 911 | + __func__, lind, chan, lli->lun_id[chan]); | |
| 903 | 912 | } |
| 904 | 913 | |
| 905 | 914 | lli->in_table = true; |
| 906 | 915 | out: |
| 907 | 916 | mutex_unlock(&global.mutex); |
| 908 | − pr_debug("%s: returning rc=%d\n", __func__, rc); | |
| 917 | + dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc); | |
| 909 | 918 | return rc; |
| 910 | 919 | } |
| 911 | 920 | |
| @@ -923,7 +932,7 @@ out: · 11 unmodified lines | ||
| 923 | 932 | */ |
| 924 | 933 | int cxlflash_disk_virtual_open(struct scsi_device *sdev, void *arg) |
| 925 | 934 | { |
| 926 | − struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; | |
| 935 | + struct cxlflash_cfg *cfg = shost_priv(sdev->host); | |
| 927 | 936 | struct device *dev = &cfg->dev->dev; |
| 928 | 937 | struct llun_info *lli = sdev->hostdata; |
| 929 | 938 | struct glun_info *gli = lli->parent; |
| @@ -942,14 +951,14 @@ int cxlflash_disk_virtual_open(struct scsi_device *sdev, void *arg) · 12 unmodified lines | ||
| 942 | 951 | struct ctx_info *ctxi = NULL; |
| 943 | 952 | struct sisl_rht_entry *rhte = NULL; |
| 944 | 953 | |
| 945 | − pr_debug("%s: ctxid=%llu ls=0x%llx\n", __func__, ctxid, lun_size); | |
| 954 | + dev_dbg(dev, "%s: ctxid=%llu ls=%llu\n", __func__, ctxid, lun_size); | |
| 946 | 955 | |
| 947 | 956 | /* Setup the LUNs block allocator on first call */ |
| 948 | 957 | mutex_lock(&gli->mutex); |
| 949 | 958 | if (gli->mode == MODE_NONE) { |
| 950 | 959 | rc = init_vlun(lli); |
| 951 | 960 | if (rc) { |
| 952 | − dev_err(dev, "%s: call to init_vlun failed rc=%d!\n", | |
| 961 | + dev_err(dev, "%s: init_vlun failed rc=%d\n", | |
| 953 | 962 | __func__, rc); |
| 954 | 963 | rc = -ENOMEM; |
| 955 | 964 | goto err0; |
| @@ -958,29 +967,28 @@ int cxlflash_disk_virtual_open(struct scsi_device *sdev, void *arg) · 2 unmodified lines | ||
| 958 | 967 | |
| 959 | 968 | rc = cxlflash_lun_attach(gli, MODE_VIRTUAL, true); |
| 960 | 969 | if (unlikely(rc)) { |
| 961 | − dev_err(dev, "%s: Failed to attach to LUN! (VIRTUAL)\n", | |
| 962 | − __func__); | |
| 970 | + dev_err(dev, "%s: Failed attach to LUN (VIRTUAL)\n", __func__); | |
| 963 | 971 | goto err0; |
| 964 | 972 | } |
| 965 | 973 | mutex_unlock(&gli->mutex); |
| 966 | 974 | |
| 967 | 975 | rc = init_luntable(cfg, lli); |
| 968 | 976 | if (rc) { |
| 969 | − dev_err(dev, "%s: call to init_luntable failed rc=%d!\n", | |
| 970 | − __func__, rc); | |
| 977 | + dev_err(dev, "%s: init_luntable failed rc=%d\n", __func__, rc); | |
| 971 | 978 | goto err1; |
| 972 | 979 | } |
| 973 | 980 | |
| 974 | 981 | ctxi = get_context(cfg, rctxid, lli, 0); |
| 975 | 982 | if (unlikely(!ctxi)) { |
| 976 | − dev_err(dev, "%s: Bad context! (%llu)\n", __func__, ctxid); | |
| 983 | + dev_err(dev, "%s: Bad context ctxid=%llu\n", __func__, ctxid); | |
| 977 | 984 | rc = -EINVAL; |
| 978 | 985 | goto err1; |
| 979 | 986 | } |
| 980 | 987 | |
| 981 | 988 | rhte = rhte_checkout(ctxi, lli); |
| 982 | 989 | if (unlikely(!rhte)) { |
| 983 | − dev_err(dev, "%s: too many opens for this context\n", __func__); | |
| 990 | + dev_err(dev, "%s: too many opens ctxid=%llu\n", | |
| 991 | + __func__, ctxid); | |
| 984 | 992 | rc = -EMFILE; /* too many opens */ |
| 985 | 993 | goto err1; |
| 986 | 994 | } |
| @@ -996,7 +1004,7 @@ int cxlflash_disk_virtual_open(struct scsi_device *sdev, void *arg) · 9 unmodified lines | ||
| 996 | 1004 | resize.rsrc_handle = rsrc_handle; |
| 997 | 1005 | rc = _cxlflash_vlun_resize(sdev, ctxi, &resize); |
| 998 | 1006 | if (rc) { |
| 999 | − dev_err(dev, "%s: resize failed rc %d\n", __func__, rc); | |
| 1007 | + dev_err(dev, "%s: resize failed rc=%d\n", __func__, rc); | |
| 1000 | 1008 | goto err2; |
| 1001 | 1009 | } |
| 1002 | 1010 | last_lba = resize.last_lba; |
| @@ -1013,8 +1021,8 @@ int cxlflash_disk_virtual_open(struct scsi_device *sdev, void *arg) · 10 unmodified lines | ||
| 1013 | 1021 | out: |
| 1014 | 1022 | if (likely(ctxi)) |
| 1015 | 1023 | put_context(ctxi); |
| 1016 | − pr_debug("%s: returning handle 0x%llx rc=%d llba %lld\n", | |
| 1017 | − __func__, rsrc_handle, rc, last_lba); | |
| 1024 | + dev_dbg(dev, "%s: returning handle=%llu rc=%d llba=%llu\n", | |
| 1025 | + __func__, rsrc_handle, rc, last_lba); | |
| 1018 | 1026 | return rc; |
| 1019 | 1027 | |
| 1020 | 1028 | err2: |
| @@ -1047,6 +1055,8 @@ static int clone_lxt(struct afu *afu, · 26 unmodified lines | ||
| 1047 | 1055 | struct sisl_rht_entry *rhte, |
| 1048 | 1056 | struct sisl_rht_entry *rhte_src) |
| 1049 | 1057 | { |
| 1058 | + struct cxlflash_cfg *cfg = afu->parent; | |
| 1059 | + struct device *dev = &cfg->dev->dev; | |
| 1050 | 1060 | struct sisl_lxt_entry *lxt; |
| 1051 | 1061 | u32 ngrps; |
| 1052 | 1062 | u64 aun; /* chunk# allocated by block allocator */ |
| @@ -1101,7 +1111,7 @@ static int clone_lxt(struct afu *afu, · 48 unmodified lines | ||
| 1101 | 1111 | |
| 1102 | 1112 | cxlflash_afu_sync(afu, ctxid, rhndl, AFU_LW_SYNC); |
| 1103 | 1113 | |
| 1104 | − pr_debug("%s: returning\n", __func__); | |
| 1114 | + dev_dbg(dev, "%s: returning\n", __func__); | |
| 1105 | 1115 | return 0; |
| 1106 | 1116 | } |
| 1107 | 1117 | |
| @@ -1120,7 +1130,8 @@ static int clone_lxt(struct afu *afu, · 12 unmodified lines | ||
| 1120 | 1130 | int cxlflash_disk_clone(struct scsi_device *sdev, |
| 1121 | 1131 | struct dk_cxlflash_clone *clone) |
| 1122 | 1132 | { |
| 1123 | − struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; | |
| 1133 | + struct cxlflash_cfg *cfg = shost_priv(sdev->host); | |
| 1134 | + struct device *dev = &cfg->dev->dev; | |
| 1124 | 1135 | struct llun_info *lli = sdev->hostdata; |
| 1125 | 1136 | struct glun_info *gli = lli->parent; |
| 1126 | 1137 | struct blka *blka = &gli->blka; |
| @@ -1140,8 +1151,8 @@ int cxlflash_disk_clone(struct scsi_device *sdev, · 13 unmodified lines | ||
| 1140 | 1151 | bool found; |
| 1141 | 1152 | LIST_HEAD(sidecar); |
| 1142 | 1153 | |
| 1143 | − pr_debug("%s: ctxid_src=%llu ctxid_dst=%llu\n", | |
| 1144 | − __func__, ctxid_src, ctxid_dst); | |
| 1154 | + dev_dbg(dev, "%s: ctxid_src=%llu ctxid_dst=%llu\n", | |
| 1155 | + __func__, ctxid_src, ctxid_dst); | |
| 1145 | 1156 | |
| 1146 | 1157 | /* Do not clone yourself */ |
| 1147 | 1158 | if (unlikely(rctxid_src == rctxid_dst)) { |
| @@ -1151,16 +1162,16 @@ int cxlflash_disk_clone(struct scsi_device *sdev, · 3 unmodified lines | ||
| 1151 | 1162 | |
| 1152 | 1163 | if (unlikely(gli->mode != MODE_VIRTUAL)) { |
| 1153 | 1164 | rc = -EINVAL; |
| 1154 | − pr_debug("%s: Clone not supported on physical LUNs! (%d)\n", | |
| 1155 | − __func__, gli->mode); | |
| 1165 | + dev_dbg(dev, "%s: Only supported on virtual LUNs mode=%u\n", | |
| 1166 | + __func__, gli->mode); | |
| 1156 | 1167 | goto out; |
| 1157 | 1168 | } |
| 1158 | 1169 | |
| 1159 | 1170 | ctxi_src = get_context(cfg, rctxid_src, lli, CTX_CTRL_CLONE); |
| 1160 | 1171 | ctxi_dst = get_context(cfg, rctxid_dst, lli, 0); |
| 1161 | 1172 | if (unlikely(!ctxi_src || !ctxi_dst)) { |
| 1162 | − pr_debug("%s: Bad context! (%llu,%llu)\n", __func__, | |
| 1163 | − ctxid_src, ctxid_dst); | |
| 1173 | + dev_dbg(dev, "%s: Bad context ctxid_src=%llu ctxid_dst=%llu\n", | |
| 1174 | + __func__, ctxid_src, ctxid_dst); | |
| 1164 | 1175 | rc = -EINVAL; |
| 1165 | 1176 | goto out; |
| 1166 | 1177 | } |
| @@ -1185,8 +1196,8 @@ int cxlflash_disk_clone(struct scsi_device *sdev, · 18 unmodified lines | ||
| 1185 | 1196 | lun_access_dst = kzalloc(sizeof(*lun_access_dst), |
| 1186 | 1197 | GFP_KERNEL); |
| 1187 | 1198 | if (unlikely(!lun_access_dst)) { |
| 1188 | − pr_err("%s: Unable to allocate lun_access!\n", | |
| 1189 | − __func__); | |
| 1199 | + dev_err(dev, "%s: lun_access allocation fail\n", | |
| 1200 | + __func__); | |
| 1190 | 1201 | rc = -ENOMEM; |
| 1191 | 1202 | goto out; |
| 1192 | 1203 | } |
| @@ -1197,7 +1208,7 @@ int cxlflash_disk_clone(struct scsi_device *sdev, · 4 unmodified lines | ||
| 1197 | 1208 | } |
| 1198 | 1209 | |
| 1199 | 1210 | if (unlikely(!ctxi_src->rht_out)) { |
| 1200 | − pr_debug("%s: Nothing to clone!\n", __func__); | |
| 1211 | + dev_dbg(dev, "%s: Nothing to clone\n", __func__); | |
| 1201 | 1212 | goto out_success; |
| 1202 | 1213 | } |
| 1203 | 1214 | |
| @@ -1256,7 +1267,7 @@ out: · 52 unmodified lines | ||
| 1256 | 1267 | put_context(ctxi_src); |
| 1257 | 1268 | if (ctxi_dst) |
| 1258 | 1269 | put_context(ctxi_dst); |
| 1259 | − pr_debug("%s: returning rc=%d\n", __func__, rc); | |
| 1270 | + dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc); | |
| 1260 | 1271 | return rc; |
| 1261 | 1272 | |
| 1262 | 1273 | err: |
| @@ -2768,16 +2768,12 @@ static int adpt_i2o_activate_hba(adpt_hba* pHba) · 2767 unmodified lines | ||
| 2768 | 2768 | |
| 2769 | 2769 | static int adpt_i2o_online_hba(adpt_hba* pHba) |
| 2770 | 2770 | { |
| 2771 | − if (adpt_i2o_systab_send(pHba) < 0) { | |
| 2772 | − adpt_i2o_delete_hba(pHba); | |
| 2771 | + if (adpt_i2o_systab_send(pHba) < 0) | |
| 2773 | 2772 | return -1; |
| 2774 | − } | |
| 2775 | 2773 | /* In READY state */ |
| 2776 | 2774 | |
| 2777 | − if (adpt_i2o_enable_hba(pHba) < 0) { | |
| 2778 | − adpt_i2o_delete_hba(pHba); | |
| 2775 | + if (adpt_i2o_enable_hba(pHba) < 0) | |
| 2779 | 2776 | return -1; |
| 2780 | − } | |
| 2781 | 2777 | |
| 2782 | 2778 | /* In OPERATIONAL state */ |
| 2783 | 2779 | return 0; |
| @@ -237,7 +237,7 @@ static void esas2r_claim_interrupts(struct esas2r_adapter *a) · 236 unmodified lines | ||
| 237 | 237 | flags |= IRQF_SHARED; |
| 238 | 238 | |
| 239 | 239 | esas2r_log(ESAS2R_LOG_INFO, |
| 240 | − "esas2r_claim_interrupts irq=%d (%p, %s, %x)", | |
| 240 | + "esas2r_claim_interrupts irq=%d (%p, %s, %lx)", | |
| 241 | 241 | a->pcid->irq, a, a->name, flags); |
| 242 | 242 | |
| 243 | 243 | if (request_irq(a->pcid->irq, |
| @@ -1301,7 +1301,7 @@ int esas2r_ioctl_handler(void *hostdata, int cmd, void __user *arg) · 1300 unmodified lines | ||
| 1301 | 1301 | ioctl = kzalloc(sizeof(struct atto_express_ioctl), GFP_KERNEL); |
| 1302 | 1302 | if (ioctl == NULL) { |
| 1303 | 1303 | esas2r_log(ESAS2R_LOG_WARN, |
| 1304 | − "ioctl_handler kzalloc failed for %d bytes", | |
| 1304 | + "ioctl_handler kzalloc failed for %zu bytes", | |
| 1305 | 1305 | sizeof(struct atto_express_ioctl)); |
| 1306 | 1306 | return -ENOMEM; |
| 1307 | 1307 | } |
| @@ -61,8 +61,8 @@ enum { · 60 unmodified lines | ||
| 61 | 61 | #endif |
| 62 | 62 | }; |
| 63 | 63 | |
| 64 | −int esas2r_log(const long level, const char *format, ...); | |
| 65 | −int esas2r_log_dev(const long level, | |
| 64 | +__printf(2, 3) int esas2r_log(const long level, const char *format, ...); | |
| 65 | +__printf(3, 4) int esas2r_log_dev(const long level, | |
| 66 | 66 | const struct device *dev, |
| 67 | 67 | const char *format, |
| 68 | 68 | ...); |
| @@ -198,7 +198,7 @@ static ssize_t write_hw(struct file *file, struct kobject *kobj, · 197 unmodified lines | ||
| 198 | 198 | GFP_KERNEL); |
| 199 | 199 | if (a->local_atto_ioctl == NULL) { |
| 200 | 200 | esas2r_log(ESAS2R_LOG_WARN, |
| 201 | − "write_hw kzalloc failed for %d bytes", | |
| 201 | + "write_hw kzalloc failed for %zu bytes", | |
| 202 | 202 | sizeof(struct atto_ioctl)); |
| 203 | 203 | return -ENOMEM; |
| 204 | 204 | } |
| @@ -1186,7 +1186,7 @@ retry: · 981 unmodified lines | ||
| 1186 | 1186 | } else { |
| 1187 | 1187 | esas2r_log(ESAS2R_LOG_CRIT, |
| 1188 | 1188 | "unable to allocate a request for a " |
| 1189 | − "device reset (%d:%d)!", | |
| 1189 | + "device reset (%d:%llu)!", | |
| 1190 | 1190 | cmd->device->id, |
| 1191 | 1191 | cmd->device->lun); |
| 1192 | 1192 | } |
| @@ -277,6 +277,7 @@ static struct scsi_host_template fcoe_shost_template = { · 276 unmodified lines | ||
| 277 | 277 | .name = "FCoE Driver", |
| 278 | 278 | .proc_name = FCOE_NAME, |
| 279 | 279 | .queuecommand = fc_queuecommand, |
| 280 | + .eh_timed_out = fc_eh_timed_out, | |
| 280 | 281 | .eh_abort_handler = fc_eh_abort, |
| 281 | 282 | .eh_device_reset_handler = fc_eh_device_reset, |
| 282 | 283 | .eh_host_reset_handler = fc_eh_host_reset, |
| @@ -106,6 +106,7 @@ static struct scsi_host_template fnic_host_template = { · 105 unmodified lines | ||
| 106 | 106 | .module = THIS_MODULE, |
| 107 | 107 | .name = DRV_NAME, |
| 108 | 108 | .queuecommand = fnic_queuecommand, |
| 109 | + .eh_timed_out = fc_eh_timed_out, | |
| 109 | 110 | .eh_abort_handler = fnic_abort_cmd, |
| 110 | 111 | .eh_device_reset_handler = fnic_device_reset, |
| 111 | 112 | .eh_host_reset_handler = fnic_host_reset, |
| @@ -26,14 +26,55 @@ · 25 unmodified lines | ||
| 26 | 26 | #include <linux/blkdev.h> |
| 27 | 27 | #include <linux/module.h> |
| 28 | 28 | #include <scsi/scsi_host.h> |
| 29 | −#include "g_NCR5380.h" | |
| 30 | −#include "NCR5380.h" | |
| 31 | 29 | #include <linux/init.h> |
| 32 | 30 | #include <linux/ioport.h> |
| 33 | 31 | #include <linux/isa.h> |
| 34 | 32 | #include <linux/pnp.h> |
| 35 | 33 | #include <linux/interrupt.h> |
| 36 | 34 | |
| 35 | +/* Definitions for the core NCR5380 driver. */ | |
| 36 | + | |
| 37 | +#define NCR5380_read(reg) \ | |
| 38 | + ioread8(hostdata->io + hostdata->offset + (reg)) | |
| 39 | +#define NCR5380_write(reg, value) \ | |
| 40 | + iowrite8(value, hostdata->io + hostdata->offset + (reg)) | |
| 41 | + | |
| 42 | +#define NCR5380_implementation_fields \ | |
| 43 | + int offset; \ | |
| 44 | + int c400_ctl_status; \ | |
| 45 | + int c400_blk_cnt; \ | |
| 46 | + int c400_host_buf; \ | |
| 47 | + int io_width | |
| 48 | + | |
| 49 | +#define NCR5380_dma_xfer_len generic_NCR5380_dma_xfer_len | |
| 50 | +#define NCR5380_dma_recv_setup generic_NCR5380_pread | |
| 51 | +#define NCR5380_dma_send_setup generic_NCR5380_pwrite | |
| 52 | +#define NCR5380_dma_residual NCR5380_dma_residual_none | |
| 53 | + | |
| 54 | +#define NCR5380_intr generic_NCR5380_intr | |
| 55 | +#define NCR5380_queue_command generic_NCR5380_queue_command | |
| 56 | +#define NCR5380_abort generic_NCR5380_abort | |
| 57 | +#define NCR5380_bus_reset generic_NCR5380_bus_reset | |
| 58 | +#define NCR5380_info generic_NCR5380_info | |
| 59 | + | |
| 60 | +#define NCR5380_io_delay(x) udelay(x) | |
| 61 | + | |
| 62 | +#include "NCR5380.h" | |
| 63 | + | |
| 64 | +#define DRV_MODULE_NAME "g_NCR5380" | |
| 65 | + | |
| 66 | +#define NCR53C400_mem_base 0x3880 | |
| 67 | +#define NCR53C400_host_buffer 0x3900 | |
| 68 | +#define NCR53C400_region_size 0x3a00 | |
| 69 | + | |
| 70 | +#define BOARD_NCR5380 0 | |
| 71 | +#define BOARD_NCR53C400 1 | |
| 72 | +#define BOARD_NCR53C400A 2 | |
| 73 | +#define BOARD_DTC3181E 3 | |
| 74 | +#define BOARD_HP_C2502 4 | |
| 75 | + | |
| 76 | +#define IRQ_AUTO 254 | |
| 77 | + | |
| 37 | 78 | #define MAX_CARDS 8 |
| 38 | 79 | |
| 39 | 80 | /* old-style parameters for compatibility */ |
| @@ -1,56 +0,0 @@ | ||
| 1 | −/* | |
| 2 | − * Generic Generic NCR5380 driver defines | |
| 3 | − * | |
| 4 | − * Copyright 1993, Drew Eckhardt | |
| 5 | − * Visionary Computing | |
| 6 | − * (Unix and Linux consulting and custom programming) | |
| 7 | − * drew@colorado.edu | |
| 8 | − * +1 (303) 440-4894 | |
| 9 | − * | |
| 10 | − * NCR53C400 extensions (c) 1994,1995,1996, Kevin Lentin | |
| 11 | − * K.Lentin@cs.monash.edu.au | |
| 12 | − */ | |
| 13 | − | |
| 14 | −#ifndef GENERIC_NCR5380_H | |
| 15 | −#define GENERIC_NCR5380_H | |
| 16 | − | |
| 17 | −#define DRV_MODULE_NAME "g_NCR5380" | |
| 18 | − | |
| 19 | −#define NCR5380_read(reg) \ | |
| 20 | − ioread8(hostdata->io + hostdata->offset + (reg)) | |
| 21 | −#define NCR5380_write(reg, value) \ | |
| 22 | − iowrite8(value, hostdata->io + hostdata->offset + (reg)) | |
| 23 | − | |
| 24 | −#define NCR5380_implementation_fields \ | |
| 25 | − int offset; \ | |
| 26 | − int c400_ctl_status; \ | |
| 27 | − int c400_blk_cnt; \ | |
| 28 | − int c400_host_buf; \ | |
| 29 | − int io_width; | |
| 30 | − | |
| 31 | −#define NCR53C400_mem_base 0x3880 | |
| 32 | −#define NCR53C400_host_buffer 0x3900 | |
| 33 | −#define NCR53C400_region_size 0x3a00 | |
| 34 | − | |
| 35 | −#define NCR5380_dma_xfer_len generic_NCR5380_dma_xfer_len | |
| 36 | −#define NCR5380_dma_recv_setup generic_NCR5380_pread | |
| 37 | −#define NCR5380_dma_send_setup generic_NCR5380_pwrite | |
| 38 | −#define NCR5380_dma_residual NCR5380_dma_residual_none | |
| 39 | − | |
| 40 | −#define NCR5380_intr generic_NCR5380_intr | |
| 41 | −#define NCR5380_queue_command generic_NCR5380_queue_command | |
| 42 | −#define NCR5380_abort generic_NCR5380_abort | |
| 43 | −#define NCR5380_bus_reset generic_NCR5380_bus_reset | |
| 44 | −#define NCR5380_info generic_NCR5380_info | |
| 45 | − | |
| 46 | −#define NCR5380_io_delay(x) udelay(x) | |
| 47 | − | |
| 48 | −#define BOARD_NCR5380 0 | |
| 49 | −#define BOARD_NCR53C400 1 | |
| 50 | −#define BOARD_NCR53C400A 2 | |
| 51 | −#define BOARD_DTC3181E 3 | |
| 52 | −#define BOARD_HP_C2502 4 | |
| 53 | − | |
| 54 | −#define IRQ_AUTO 254 | |
| 55 | − | |
| 56 | −#endif /* GENERIC_NCR5380_H */ | |
| @@ -95,6 +95,7 @@ struct hisi_sas_port { · 94 unmodified lines | ||
| 95 | 95 | |
| 96 | 96 | struct hisi_sas_cq { |
| 97 | 97 | struct hisi_hba *hisi_hba; |
| 98 | + struct tasklet_struct tasklet; | |
| 98 | 99 | int rd_point; |
| 99 | 100 | int id; |
| 100 | 101 | }; |
| @@ -71,6 +71,8 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task, · 70 unmodified lines | ||
| 71 | 71 | struct hisi_sas_slot *slot) |
| 72 | 72 | { |
| 73 | 73 | struct device *dev = &hisi_hba->pdev->dev; |
| 74 | + struct domain_device *device = task->dev; | |
| 75 | + struct hisi_sas_device *sas_dev = device->lldd_dev; | |
| 74 | 76 | |
| 75 | 77 | if (!slot->task) |
| 76 | 78 | return; |
| @@ -97,6 +99,8 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task, · 20 unmodified lines | ||
| 97 | 99 | slot->task = NULL; |
| 98 | 100 | slot->port = NULL; |
| 99 | 101 | hisi_sas_slot_index_free(hisi_hba, slot->idx); |
| 102 | + if (sas_dev) | |
| 103 | + atomic64_dec(&sas_dev->running_req); | |
| 100 | 104 | /* slot memory is fully zeroed when it is reused */ |
| 101 | 105 | } |
| 102 | 106 | EXPORT_SYMBOL_GPL(hisi_sas_slot_task_free); |
| @@ -141,11 +145,10 @@ static void hisi_sas_slot_abort(struct work_struct *work) · 38 unmodified lines | ||
| 141 | 145 | struct hisi_hba *hisi_hba = dev_to_hisi_hba(task->dev); |
| 142 | 146 | struct scsi_cmnd *cmnd = task->uldd_task; |
| 143 | 147 | struct hisi_sas_tmf_task tmf_task; |
| 144 | − struct domain_device *device = task->dev; | |
| 145 | − struct hisi_sas_device *sas_dev = device->lldd_dev; | |
| 146 | 148 | struct scsi_lun lun; |
| 147 | 149 | struct device *dev = &hisi_hba->pdev->dev; |
| 148 | 150 | int tag = abort_slot->idx; |
| 151 | + unsigned long flags; | |
| 149 | 152 | |
| 150 | 153 | if (!(task->task_proto & SAS_PROTOCOL_SSP)) { |
| 151 | 154 | dev_err(dev, "cannot abort slot for non-ssp task\n"); |
| @@ -159,11 +162,11 @@ static void hisi_sas_slot_abort(struct work_struct *work) · 7 unmodified lines | ||
| 159 | 162 | hisi_sas_debug_issue_ssp_tmf(task->dev, lun.scsi_lun, &tmf_task); |
| 160 | 163 | out: |
| 161 | 164 | /* Do cleanup for this task */ |
| 165 | + spin_lock_irqsave(&hisi_hba->lock, flags); | |
| 162 | 166 | hisi_sas_slot_task_free(hisi_hba, task, abort_slot); |
| 167 | + spin_unlock_irqrestore(&hisi_hba->lock, flags); | |
| 163 | 168 | if (task->task_done) |
| 164 | 169 | task->task_done(task); |
| 165 | − if (sas_dev) | |
| 166 | − atomic64_dec(&sas_dev->running_req); | |
| 167 | 170 | } |
| 168 | 171 | |
| 169 | 172 | static int hisi_sas_task_prep(struct sas_task *task, struct hisi_hba *hisi_hba, |
| @@ -1118,7 +1121,7 @@ hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba, · 948 unmodified lines | ||
| 1118 | 1121 | } |
| 1119 | 1122 | |
| 1120 | 1123 | exit: |
| 1121 | − dev_info(dev, "internal task abort: task to dev %016llx task=%p " | |
| 1124 | + dev_dbg(dev, "internal task abort: task to dev %016llx task=%p " | |
| 1122 | 1125 | "resp: 0x%x sts 0x%x\n", |
| 1123 | 1126 | SAS_ADDR(device->sas_addr), |
| 1124 | 1127 | task, |
| @@ -1450,7 +1453,7 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev, · 325 unmodified lines | ||
| 1450 | 1453 | |
| 1451 | 1454 | refclk = devm_clk_get(&pdev->dev, NULL); |
| 1452 | 1455 | if (IS_ERR(refclk)) |
| 1453 | − dev_info(dev, "no ref clk property\n"); | |
| 1456 | + dev_dbg(dev, "no ref clk property\n"); | |
| 1454 | 1457 | else |
| 1455 | 1458 | hisi_hba->refclk_frequency_mhz = clk_get_rate(refclk) / 1000000; |
| 1456 | 1459 | |
| @@ -1549,10 +1552,6 @@ int hisi_sas_probe(struct platform_device *pdev, · 92 unmodified lines | ||
| 1549 | 1552 | |
| 1550 | 1553 | hisi_sas_init_add(hisi_hba); |
| 1551 | 1554 | |
| 1552 | − rc = hisi_hba->hw->hw_init(hisi_hba); | |
| 1553 | − if (rc) | |
| 1554 | − goto err_out_ha; | |
| 1555 | − | |
| 1556 | 1555 | rc = scsi_add_host(shost, &pdev->dev); |
| 1557 | 1556 | if (rc) |
| 1558 | 1557 | goto err_out_ha; |
| @@ -1561,6 +1560,10 @@ int hisi_sas_probe(struct platform_device *pdev, · 2 unmodified lines | ||
| 1561 | 1560 | if (rc) |
| 1562 | 1561 | goto err_out_register_ha; |
| 1563 | 1562 | |
| 1563 | + rc = hisi_hba->hw->hw_init(hisi_hba); | |
| 1564 | + if (rc) | |
| 1565 | + goto err_out_register_ha; | |
| 1566 | + | |
| 1564 | 1567 | scsi_scan_host(shost); |
| 1565 | 1568 | |
| 1566 | 1569 | return 0; |
| @@ -1596,6 +1596,7 @@ static irqreturn_t cq_interrupt_v1_hw(int irq, void *p) · 1595 unmodified lines | ||
| 1596 | 1596 | hisi_hba->complete_hdr[queue]; |
| 1597 | 1597 | u32 irq_value, rd_point = cq->rd_point, wr_point; |
| 1598 | 1598 | |
| 1599 | + spin_lock(&hisi_hba->lock); | |
| 1599 | 1600 | irq_value = hisi_sas_read32(hisi_hba, OQ_INT_SRC); |
| 1600 | 1601 | |
| 1601 | 1602 | hisi_sas_write32(hisi_hba, OQ_INT_SRC, 1 << queue); |
| @@ -1628,6 +1629,7 @@ static irqreturn_t cq_interrupt_v1_hw(int irq, void *p) · 26 unmodified lines | ||
| 1628 | 1629 | /* update rd_point */ |
| 1629 | 1630 | cq->rd_point = rd_point; |
| 1630 | 1631 | hisi_sas_write32(hisi_hba, COMPL_Q_0_RD_PTR + (0x14 * queue), rd_point); |
| 1632 | + spin_unlock(&hisi_hba->lock); | |
| 1631 | 1633 | |
| 1632 | 1634 | return IRQ_HANDLED; |
| 1633 | 1635 | } |
| @@ -207,6 +207,8 @@ · 206 unmodified lines | ||
| 207 | 207 | #define TXID_AUTO (PORT_BASE + 0xb8) |
| 208 | 208 | #define TXID_AUTO_CT3_OFF 1 |
| 209 | 209 | #define TXID_AUTO_CT3_MSK (0x1 << TXID_AUTO_CT3_OFF) |
| 210 | +#define TX_HARDRST_OFF 2 | |
| 211 | +#define TX_HARDRST_MSK (0x1 << TX_HARDRST_OFF) | |
| 210 | 212 | #define RX_IDAF_DWORD0 (PORT_BASE + 0xc4) |
| 211 | 213 | #define RX_IDAF_DWORD1 (PORT_BASE + 0xc8) |
| 212 | 214 | #define RX_IDAF_DWORD2 (PORT_BASE + 0xcc) |
| @@ -215,6 +217,7 @@ · 2 unmodified lines | ||
| 215 | 217 | #define RX_IDAF_DWORD5 (PORT_BASE + 0xd8) |
| 216 | 218 | #define RX_IDAF_DWORD6 (PORT_BASE + 0xdc) |
| 217 | 219 | #define RXOP_CHECK_CFG_H (PORT_BASE + 0xfc) |
| 220 | +#define CON_CONTROL (PORT_BASE + 0x118) | |
| 218 | 221 | #define DONE_RECEIVED_TIME (PORT_BASE + 0x11c) |
| 219 | 222 | #define CHL_INT0 (PORT_BASE + 0x1b4) |
| 220 | 223 | #define CHL_INT0_HOTPLUG_TOUT_OFF 0 |
| @@ -333,6 +336,11 @@ · 112 unmodified lines | ||
| 333 | 336 | #define ITCT_HDR_MCR_MSK (0xf << ITCT_HDR_MCR_OFF) |
| 334 | 337 | #define ITCT_HDR_VLN_OFF 9 |
| 335 | 338 | #define ITCT_HDR_VLN_MSK (0xf << ITCT_HDR_VLN_OFF) |
| 339 | +#define ITCT_HDR_SMP_TIMEOUT_OFF 16 | |
| 340 | +#define ITCT_HDR_SMP_TIMEOUT_8US 1 | |
| 341 | +#define ITCT_HDR_SMP_TIMEOUT (ITCT_HDR_SMP_TIMEOUT_8US * \ | |
| 342 | + 250) /* 2ms */ | |
| 343 | +#define ITCT_HDR_AWT_CONTINUE_OFF 25 | |
| 336 | 344 | #define ITCT_HDR_PORT_ID_OFF 28 |
| 337 | 345 | #define ITCT_HDR_PORT_ID_MSK (0xf << ITCT_HDR_PORT_ID_OFF) |
| 338 | 346 | /* qw2 */ |
| @@ -526,6 +534,8 @@ enum { · 187 unmodified lines | ||
| 526 | 534 | #define SATA_PROTOCOL_FPDMA 0x8 |
| 527 | 535 | #define SATA_PROTOCOL_ATAPI 0x10 |
| 528 | 536 | |
| 537 | +static void hisi_sas_link_timeout_disable_link(unsigned long data); | |
| 538 | + | |
| 529 | 539 | static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off) |
| 530 | 540 | { |
| 531 | 541 | void __iomem *regs = hisi_hba->regs + off; |
| @@ -693,6 +703,8 @@ static void setup_itct_v2_hw(struct hisi_hba *hisi_hba, · 161 unmodified lines | ||
| 693 | 703 | qw0 |= ((1 << ITCT_HDR_VALID_OFF) | |
| 694 | 704 | (device->linkrate << ITCT_HDR_MCR_OFF) | |
| 695 | 705 | (1 << ITCT_HDR_VLN_OFF) | |
| 706 | + (ITCT_HDR_SMP_TIMEOUT << ITCT_HDR_SMP_TIMEOUT_OFF) | | |
| 707 | + (1 << ITCT_HDR_AWT_CONTINUE_OFF) | | |
| 696 | 708 | (port->id << ITCT_HDR_PORT_ID_OFF)); |
| 697 | 709 | itct->qw0 = cpu_to_le64(qw0); |
| 698 | 710 | |
| @@ -702,7 +714,7 @@ static void setup_itct_v2_hw(struct hisi_hba *hisi_hba, · 3 unmodified lines | ||
| 702 | 714 | |
| 703 | 715 | /* qw2 */ |
| 704 | 716 | if (!dev_is_sata(device)) |
| 705 | − itct->qw2 = cpu_to_le64((500ULL << ITCT_HDR_INLT_OFF) | | |
| 717 | + itct->qw2 = cpu_to_le64((5000ULL << ITCT_HDR_INLT_OFF) | | |
| 706 | 718 | (0x1ULL << ITCT_HDR_BITLT_OFF) | |
| 707 | 719 | (0x32ULL << ITCT_HDR_MCTLT_OFF) | |
| 708 | 720 | (0x1ULL << ITCT_HDR_RTOLT_OFF)); |
| @@ -711,7 +723,7 @@ static void setup_itct_v2_hw(struct hisi_hba *hisi_hba, · 2 unmodified lines | ||
| 711 | 723 | static void free_device_v2_hw(struct hisi_hba *hisi_hba, |
| 712 | 724 | struct hisi_sas_device *sas_dev) |
| 713 | 725 | { |
| 714 | − u64 qw0, dev_id = sas_dev->device_id; | |
| 726 | + u64 dev_id = sas_dev->device_id; | |
| 715 | 727 | struct device *dev = &hisi_hba->pdev->dev; |
| 716 | 728 | struct hisi_sas_itct *itct = &hisi_hba->itct[dev_id]; |
| 717 | 729 | u32 reg_val = hisi_sas_read32(hisi_hba, ENT_INT_SRC3); |
| @@ -735,8 +747,7 @@ static void free_device_v2_hw(struct hisi_hba *hisi_hba, · 17 unmodified lines | ||
| 735 | 747 | dev_dbg(dev, "got clear ITCT done interrupt\n"); |
| 736 | 748 | |
| 737 | 749 | /* invalid the itct state*/ |
| 738 | − qw0 = cpu_to_le64(itct->qw0); | |
| 739 | − qw0 &= ~(1 << ITCT_HDR_VALID_OFF); | |
| 750 | + memset(itct, 0, sizeof(struct hisi_sas_itct)); | |
| 740 | 751 | hisi_sas_write32(hisi_hba, ENT_INT_SRC3, |
| 741 | 752 | ENT_INT_SRC3_ITC_INT_MSK); |
| 742 | 753 | |
| @@ -978,6 +989,50 @@ static void init_reg_v2_hw(struct hisi_hba *hisi_hba) · 235 unmodified lines | ||
| 978 | 989 | upper_32_bits(hisi_hba->initial_fis_dma)); |
| 979 | 990 | } |
| 980 | 991 | |
| 992 | +static void hisi_sas_link_timeout_enable_link(unsigned long data) | |
| 993 | +{ | |
| 994 | + struct hisi_hba *hisi_hba = (struct hisi_hba *)data; | |
| 995 | + int i, reg_val; | |
| 996 | + | |
| 997 | + for (i = 0; i < hisi_hba->n_phy; i++) { | |
| 998 | + reg_val = hisi_sas_phy_read32(hisi_hba, i, CON_CONTROL); | |
| 999 | + if (!(reg_val & BIT(0))) { | |
| 1000 | + hisi_sas_phy_write32(hisi_hba, i, | |
| 1001 | + CON_CONTROL, 0x7); | |
| 1002 | + break; | |
| 1003 | + } | |
| 1004 | + } | |
| 1005 | + | |
| 1006 | + hisi_hba->timer.function = hisi_sas_link_timeout_disable_link; | |
| 1007 | + mod_timer(&hisi_hba->timer, jiffies + msecs_to_jiffies(900)); | |
| 1008 | +} | |
| 1009 | + | |
| 1010 | +static void hisi_sas_link_timeout_disable_link(unsigned long data) | |
| 1011 | +{ | |
| 1012 | + struct hisi_hba *hisi_hba = (struct hisi_hba *)data; | |
| 1013 | + int i, reg_val; | |
| 1014 | + | |
| 1015 | + reg_val = hisi_sas_read32(hisi_hba, PHY_STATE); | |
| 1016 | + for (i = 0; i < hisi_hba->n_phy && reg_val; i++) { | |
| 1017 | + if (reg_val & BIT(i)) { | |
| 1018 | + hisi_sas_phy_write32(hisi_hba, i, | |
| 1019 | + CON_CONTROL, 0x6); | |
| 1020 | + break; | |
| 1021 | + } | |
| 1022 | + } | |
| 1023 | + | |
| 1024 | + hisi_hba->timer.function = hisi_sas_link_timeout_enable_link; | |
| 1025 | + mod_timer(&hisi_hba->timer, jiffies + msecs_to_jiffies(100)); | |
| 1026 | +} | |
| 1027 | + | |
| 1028 | +static void set_link_timer_quirk(struct hisi_hba *hisi_hba) | |
| 1029 | +{ | |
| 1030 | + hisi_hba->timer.data = (unsigned long)hisi_hba; | |
| 1031 | + hisi_hba->timer.function = hisi_sas_link_timeout_disable_link; | |
| 1032 | + hisi_hba->timer.expires = jiffies + msecs_to_jiffies(1000); | |
| 1033 | + add_timer(&hisi_hba->timer); | |
| 1034 | +} | |
| 1035 | + | |
| 981 | 1036 | static int hw_init_v2_hw(struct hisi_hba *hisi_hba) |
| 982 | 1037 | { |
| 983 | 1038 | struct device *dev = &hisi_hba->pdev->dev; |
| @@ -1025,14 +1080,21 @@ static void stop_phy_v2_hw(struct hisi_hba *hisi_hba, int phy_no) · 41 unmodified lines | ||
| 1025 | 1080 | |
| 1026 | 1081 | static void phy_hard_reset_v2_hw(struct hisi_hba *hisi_hba, int phy_no) |
| 1027 | 1082 | { |
| 1083 | + struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; | |
| 1084 | + u32 txid_auto; | |
| 1085 | + | |
| 1028 | 1086 | stop_phy_v2_hw(hisi_hba, phy_no); |
| 1087 | + if (phy->identify.device_type == SAS_END_DEVICE) { | |
| 1088 | + txid_auto = hisi_sas_phy_read32(hisi_hba, phy_no, TXID_AUTO); | |
| 1089 | + hisi_sas_phy_write32(hisi_hba, phy_no, TXID_AUTO, | |
| 1090 | + txid_auto | TX_HARDRST_MSK); | |
| 1091 | + } | |
| 1029 | 1092 | msleep(100); |
| 1030 | 1093 | start_phy_v2_hw(hisi_hba, phy_no); |
| 1031 | 1094 | } |
| 1032 | 1095 | |
| 1033 | −static void start_phys_v2_hw(unsigned long data) | |
| 1096 | +static void start_phys_v2_hw(struct hisi_hba *hisi_hba) | |
| 1034 | 1097 | { |
| 1035 | − struct hisi_hba *hisi_hba = (struct hisi_hba *)data; | |
| 1036 | 1098 | int i; |
| 1037 | 1099 | |
| 1038 | 1100 | for (i = 0; i < hisi_hba->n_phy; i++) |
| @@ -1041,10 +1103,7 @@ static void start_phys_v2_hw(unsigned long data) · 2 unmodified lines | ||
| 1041 | 1103 | |
| 1042 | 1104 | static void phys_init_v2_hw(struct hisi_hba *hisi_hba) |
| 1043 | 1105 | { |
| 1044 | − struct timer_list *timer = &hisi_hba->timer; | |
| 1045 | − | |
| 1046 | − setup_timer(timer, start_phys_v2_hw, (unsigned long)hisi_hba); | |
| 1047 | − mod_timer(timer, jiffies + HZ); | |
| 1106 | + start_phys_v2_hw(hisi_hba); | |
| 1048 | 1107 | } |
| 1049 | 1108 | |
| 1050 | 1109 | static void sl_notify_v2_hw(struct hisi_hba *hisi_hba, int phy_no) |
| @@ -1771,8 +1830,6 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot, · 720 unmodified lines | ||
| 1771 | 1830 | } |
| 1772 | 1831 | |
| 1773 | 1832 | out: |
| 1774 | − if (sas_dev) | |
| 1775 | − atomic64_dec(&sas_dev->running_req); | |
| 1776 | 1833 | |
| 1777 | 1834 | hisi_sas_slot_task_free(hisi_hba, task, slot); |
| 1778 | 1835 | sts = ts->stat; |
| @@ -2020,9 +2077,12 @@ static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba) · 241 unmodified lines | ||
| 2020 | 2077 | if (phy->identify.device_type == SAS_END_DEVICE) |
| 2021 | 2078 | phy->identify.target_port_protocols = |
| 2022 | 2079 | SAS_PROTOCOL_SSP; |
| 2023 | − else if (phy->identify.device_type != SAS_PHY_UNUSED) | |
| 2080 | + else if (phy->identify.device_type != SAS_PHY_UNUSED) { | |
| 2024 | 2081 | phy->identify.target_port_protocols = |
| 2025 | 2082 | SAS_PROTOCOL_SMP; |
| 2083 | + if (!timer_pending(&hisi_hba->timer)) | |
| 2084 | + set_link_timer_quirk(hisi_hba); | |
| 2085 | + } | |
| 2026 | 2086 | queue_work(hisi_hba->wq, &phy->phyup_ws); |
| 2027 | 2087 | |
| 2028 | 2088 | end: |
| @@ -2033,10 +2093,23 @@ end: · 4 unmodified lines | ||
| 2033 | 2093 | return res; |
| 2034 | 2094 | } |
| 2035 | 2095 | |
| 2096 | +static bool check_any_wideports_v2_hw(struct hisi_hba *hisi_hba) | |
| 2097 | +{ | |
| 2098 | + u32 port_state; | |
| 2099 | + | |
| 2100 | + port_state = hisi_sas_read32(hisi_hba, PORT_STATE); | |
| 2101 | + if (port_state & 0x1ff) | |
| 2102 | + return true; | |
| 2103 | + | |
| 2104 | + return false; | |
| 2105 | +} | |
| 2106 | + | |
| 2036 | 2107 | static int phy_down_v2_hw(int phy_no, struct hisi_hba *hisi_hba) |
| 2037 | 2108 | { |
| 2038 | 2109 | int res = 0; |
| 2039 | 2110 | u32 phy_state, sl_ctrl, txid_auto; |
| 2111 | + struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; | |
| 2112 | + struct hisi_sas_port *port = phy->port; | |
| 2040 | 2113 | |
| 2041 | 2114 | hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_NOT_RDY_MSK, 1); |
| 2042 | 2115 | |
| @@ -2046,6 +2119,10 @@ static int phy_down_v2_hw(int phy_no, struct hisi_hba *hisi_hba) · 3 unmodified lines | ||
| 2046 | 2119 | sl_ctrl = hisi_sas_phy_read32(hisi_hba, phy_no, SL_CONTROL); |
| 2047 | 2120 | hisi_sas_phy_write32(hisi_hba, phy_no, SL_CONTROL, |
| 2048 | 2121 | sl_ctrl & ~SL_CONTROL_CTA_MSK); |
| 2122 | + if (port && !get_wideport_bitmap_v2_hw(hisi_hba, port->id)) | |
| 2123 | + if (!check_any_wideports_v2_hw(hisi_hba) && | |
| 2124 | + timer_pending(&hisi_hba->timer)) | |
| 2125 | + del_timer(&hisi_hba->timer); | |
| 2049 | 2126 | |
| 2050 | 2127 | txid_auto = hisi_sas_phy_read32(hisi_hba, phy_no, TXID_AUTO); |
| 2051 | 2128 | hisi_sas_phy_write32(hisi_hba, phy_no, TXID_AUTO, |
| @@ -2481,21 +2558,19 @@ static irqreturn_t fatal_axi_int_v2_hw(int irq_no, void *p) · 429 unmodified lines | ||
| 2481 | 2558 | return IRQ_HANDLED; |
| 2482 | 2559 | } |
| 2483 | 2560 | |
| 2484 | −static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p) | |
| 2561 | +static void cq_tasklet_v2_hw(unsigned long val) | |
| 2485 | 2562 | { |
| 2486 | − struct hisi_sas_cq *cq = p; | |
| 2563 | + struct hisi_sas_cq *cq = (struct hisi_sas_cq *)val; | |
| 2487 | 2564 | struct hisi_hba *hisi_hba = cq->hisi_hba; |
| 2488 | 2565 | struct hisi_sas_slot *slot; |
| 2489 | 2566 | struct hisi_sas_itct *itct; |
| 2490 | 2567 | struct hisi_sas_complete_v2_hdr *complete_queue; |
| 2491 | − u32 irq_value, rd_point = cq->rd_point, wr_point, dev_id; | |
| 2568 | + u32 rd_point = cq->rd_point, wr_point, dev_id; | |
| 2492 | 2569 | int queue = cq->id; |
| 2493 | 2570 | |
| 2494 | 2571 | complete_queue = hisi_hba->complete_hdr[queue]; |
| 2495 | − irq_value = hisi_sas_read32(hisi_hba, OQ_INT_SRC); | |
| 2496 | − | |
| 2497 | − hisi_sas_write32(hisi_hba, OQ_INT_SRC, 1 << queue); | |
| 2498 | 2572 | |
| 2573 | + spin_lock(&hisi_hba->lock); | |
| 2499 | 2574 | wr_point = hisi_sas_read32(hisi_hba, COMPL_Q_0_WR_PTR + |
| 2500 | 2575 | (0x14 * queue)); |
| 2501 | 2576 | |
| @@ -2545,6 +2620,19 @@ static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p) · 43 unmodified lines | ||
| 2545 | 2620 | /* update rd_point */ |
| 2546 | 2621 | cq->rd_point = rd_point; |
| 2547 | 2622 | hisi_sas_write32(hisi_hba, COMPL_Q_0_RD_PTR + (0x14 * queue), rd_point); |
| 2623 | + spin_unlock(&hisi_hba->lock); | |
| 2624 | +} | |
| 2625 | + | |
| 2626 | +static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p) | |
| 2627 | +{ | |
| 2628 | + struct hisi_sas_cq *cq = p; | |
| 2629 | + struct hisi_hba *hisi_hba = cq->hisi_hba; | |
| 2630 | + int queue = cq->id; | |
| 2631 | + | |
| 2632 | + hisi_sas_write32(hisi_hba, OQ_INT_SRC, 1 << queue); | |
| 2633 | + | |
| 2634 | + tasklet_schedule(&cq->tasklet); | |
| 2635 | + | |
| 2548 | 2636 | return IRQ_HANDLED; |
| 2549 | 2637 | } |
| 2550 | 2638 | |
| @@ -2726,6 +2814,8 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba) · 175 unmodified lines | ||
| 2726 | 2814 | |
| 2727 | 2815 | for (i = 0; i < hisi_hba->queue_count; i++) { |
| 2728 | 2816 | int idx = i + 96; /* First cq interrupt is irq96 */ |
| 2817 | + struct hisi_sas_cq *cq = &hisi_hba->cq[i]; | |
| 2818 | + struct tasklet_struct *t = &cq->tasklet; | |
| 2729 | 2819 | |
| 2730 | 2820 | irq = irq_map[idx]; |
| 2731 | 2821 | if (!irq) { |
| @@ -2742,6 +2832,7 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba) · 10 unmodified lines | ||
| 2742 | 2832 | irq, rc); |
| 2743 | 2833 | return -ENOENT; |
| 2744 | 2834 | } |
| 2835 | + tasklet_init(t, cq_tasklet_v2_hw, (unsigned long)cq); | |
| 2745 | 2836 | } |
| 2746 | 2837 | |
| 2747 | 2838 | return 0; |
| @@ -2807,6 +2898,12 @@ static int hisi_sas_v2_probe(struct platform_device *pdev) · 59 unmodified lines | ||
| 2807 | 2898 | |
| 2808 | 2899 | static int hisi_sas_v2_remove(struct platform_device *pdev) |
| 2809 | 2900 | { |
| 2901 | + struct sas_ha_struct *sha = platform_get_drvdata(pdev); | |
| 2902 | + struct hisi_hba *hisi_hba = sha->lldd_ha; | |
| 2903 | + | |
| 2904 | + if (timer_pending(&hisi_hba->timer)) | |
| 2905 | + del_timer(&hisi_hba->timer); | |
| 2906 | + | |
| 2810 | 2907 | return hisi_sas_remove(pdev); |
| 2811 | 2908 | } |
| 2812 | 2909 | |
| @@ -9263,13 +9263,9 @@ static int hpsa_enter_performant_mode(struct ctlr_info *h, u32 trans_support) · 9262 unmodified lines | ||
| 9263 | 9263 | access = SA5_ioaccel_mode1_access; |
| 9264 | 9264 | writel(10, &h->cfgtable->HostWrite.CoalIntDelay); |
| 9265 | 9265 | writel(4, &h->cfgtable->HostWrite.CoalIntCount); |
| 9266 | − } else { | |
| 9267 | − if (trans_support & CFGTBL_Trans_io_accel2) { | |
| 9266 | + } else | |
| 9267 | + if (trans_support & CFGTBL_Trans_io_accel2) | |
| 9268 | 9268 | access = SA5_ioaccel_mode2_access; |
| 9269 | − writel(10, &h->cfgtable->HostWrite.CoalIntDelay); | |
| 9270 | − writel(4, &h->cfgtable->HostWrite.CoalIntCount); | |
| 9271 | − } | |
| 9272 | − } | |
| 9273 | 9269 | writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL); |
| 9274 | 9270 | if (hpsa_wait_for_mode_change_ack(h)) { |
| 9275 | 9271 | dev_err(&h->pdev->dev, |
| @@ -578,38 +578,38 @@ static unsigned long SA5_ioaccel_mode1_completed(struct ctlr_info *h, u8 q) · 577 unmodified lines | ||
| 578 | 578 | } |
| 579 | 579 | |
| 580 | 580 | static struct access_method SA5_access = { |
| 581 | − SA5_submit_command, | |
| 582 | − SA5_intr_mask, | |
| 583 | − SA5_intr_pending, | |
| 584 | − SA5_completed, | |
| 581 | + .submit_command = SA5_submit_command, | |
| 582 | + .set_intr_mask = SA5_intr_mask, | |
| 583 | + .intr_pending = SA5_intr_pending, | |
| 584 | + .command_completed = SA5_completed, | |
| 585 | 585 | }; |
| 586 | 586 | |
| 587 | 587 | static struct access_method SA5_ioaccel_mode1_access = { |
| 588 | − SA5_submit_command, | |
| 589 | − SA5_performant_intr_mask, | |
| 590 | − SA5_ioaccel_mode1_intr_pending, | |
| 591 | − SA5_ioaccel_mode1_completed, | |
| 588 | + .submit_command = SA5_submit_command, | |
| 589 | + .set_intr_mask = SA5_performant_intr_mask, | |
| 590 | + .intr_pending = SA5_ioaccel_mode1_intr_pending, | |
| 591 | + .command_completed = SA5_ioaccel_mode1_completed, | |
| 592 | 592 | }; |
| 593 | 593 | |
| 594 | 594 | static struct access_method SA5_ioaccel_mode2_access = { |
| 595 | − SA5_submit_command_ioaccel2, | |
| 596 | − SA5_performant_intr_mask, | |
| 597 | − SA5_performant_intr_pending, | |
| 598 | − SA5_performant_completed, | |
| 595 | + .submit_command = SA5_submit_command_ioaccel2, | |
| 596 | + .set_intr_mask = SA5_performant_intr_mask, | |
| 597 | + .intr_pending = SA5_performant_intr_pending, | |
| 598 | + .command_completed = SA5_performant_completed, | |
| 599 | 599 | }; |
| 600 | 600 | |
| 601 | 601 | static struct access_method SA5_performant_access = { |
| 602 | − SA5_submit_command, | |
| 603 | − SA5_performant_intr_mask, | |
| 604 | − SA5_performant_intr_pending, | |
| 605 | − SA5_performant_completed, | |
| 602 | + .submit_command = SA5_submit_command, | |
| 603 | + .set_intr_mask = SA5_performant_intr_mask, | |
| 604 | + .intr_pending = SA5_performant_intr_pending, | |
| 605 | + .command_completed = SA5_performant_completed, | |
| 606 | 606 | }; |
| 607 | 607 | |
| 608 | 608 | static struct access_method SA5_performant_access_no_read = { |
| 609 | − SA5_submit_command_no_read, | |
| 610 | − SA5_performant_intr_mask, | |
| 611 | − SA5_performant_intr_pending, | |
| 612 | − SA5_performant_completed, | |
| 609 | + .submit_command = SA5_submit_command_no_read, | |
| 610 | + .set_intr_mask = SA5_performant_intr_mask, | |
| 611 | + .intr_pending = SA5_performant_intr_pending, | |
| 612 | + .command_completed = SA5_performant_completed, | |
| 613 | 613 | }; |
| 614 | 614 | |
| 615 | 615 | struct board_type { |
| @@ -3090,6 +3090,7 @@ static struct scsi_host_template driver_template = { · 3089 unmodified lines | ||
| 3090 | 3090 | .name = "IBM POWER Virtual FC Adapter", |
| 3091 | 3091 | .proc_name = IBMVFC_NAME, |
| 3092 | 3092 | .queuecommand = ibmvfc_queuecommand, |
| 3093 | + .eh_timed_out = fc_eh_timed_out, | |
| 3093 | 3094 | .eh_abort_handler = ibmvfc_eh_abort_handler, |
| 3094 | 3095 | .eh_device_reset_handler = ibmvfc_eh_device_reset_handler, |
| 3095 | 3096 | .eh_target_reset_handler = ibmvfc_eh_target_reset_handler, |
| @@ -2072,6 +2072,7 @@ static struct scsi_host_template driver_template = { · 2071 unmodified lines | ||
| 2072 | 2072 | .name = "IBM POWER Virtual SCSI Adapter " IBMVSCSI_VERSION, |
| 2073 | 2073 | .proc_name = "ibmvscsi", |
| 2074 | 2074 | .queuecommand = ibmvscsi_queuecommand, |
| 2075 | + .eh_timed_out = srp_timed_out, | |
| 2075 | 2076 | .eh_abort_handler = ibmvscsi_eh_abort_handler, |
| 2076 | 2077 | .eh_device_reset_handler = ibmvscsi_eh_device_reset_handler, |
| 2077 | 2078 | .eh_host_reset_handler = ibmvscsi_eh_host_reset_handler, |
| @@ -967,6 +967,7 @@ static struct scsi_host_template iscsi_sw_tcp_sht = { · 966 unmodified lines | ||
| 967 | 967 | .sg_tablesize = 4096, |
| 968 | 968 | .max_sectors = 0xFFFF, |
| 969 | 969 | .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN, |
| 970 | + .eh_timed_out = iscsi_eh_cmd_timed_out, | |
| 970 | 971 | .eh_abort_handler = iscsi_eh_abort, |
| 971 | 972 | .eh_device_reset_handler= iscsi_eh_device_reset, |
| 972 | 973 | .eh_target_reset_handler = iscsi_eh_recover_target, |
| @@ -1930,7 +1930,7 @@ static int iscsi_has_ping_timed_out(struct iscsi_conn *conn) · 1929 unmodified lines | ||
| 1930 | 1930 | return 0; |
| 1931 | 1931 | } |
| 1932 | 1932 | |
| 1933 | −static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc) | |
| 1933 | +enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc) | |
| 1934 | 1934 | { |
| 1935 | 1935 | enum blk_eh_timer_return rc = BLK_EH_NOT_HANDLED; |
| 1936 | 1936 | struct iscsi_task *task = NULL, *running_task; |
| @@ -2063,6 +2063,7 @@ done: · 126 unmodified lines | ||
| 2063 | 2063 | "timer reset" : "nh"); |
| 2064 | 2064 | return rc; |
| 2065 | 2065 | } |
| 2066 | +EXPORT_SYMBOL_GPL(iscsi_eh_cmd_timed_out); | |
| 2066 | 2067 | |
| 2067 | 2068 | static void iscsi_check_transport_timeouts(unsigned long data) |
| 2068 | 2069 | { |
| @@ -2585,8 +2586,6 @@ int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev) · 516 unmodified lines | ||
| 2585 | 2586 | if (!shost->cmd_per_lun) |
| 2586 | 2587 | shost->cmd_per_lun = ISCSI_DEF_CMD_PER_LUN; |
| 2587 | 2588 | |
| 2588 | − if (!shost->transportt->eh_timed_out) | |
| 2589 | − shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out; | |
| 2590 | 2589 | return scsi_add_host(shost, pdev); |
| 2591 | 2590 | } |
| 2592 | 2591 | EXPORT_SYMBOL_GPL(iscsi_host_add); |
| @@ -560,7 +560,6 @@ sas_domain_attach_transport(struct sas_domain_function_template *dft) · 559 unmodified lines | ||
| 560 | 560 | i = to_sas_internal(stt); |
| 561 | 561 | i->dft = dft; |
| 562 | 562 | stt->create_work_queue = 1; |
| 563 | − stt->eh_timed_out = sas_scsi_timed_out; | |
| 564 | 563 | stt->eh_strategy_handler = sas_scsi_recover_host; |
| 565 | 564 | |
| 566 | 565 | return stt; |
| @@ -64,8 +64,6 @@ void sas_unregister_phys(struct sas_ha_struct *sas_ha); · 63 unmodified lines | ||
| 64 | 64 | int sas_register_ports(struct sas_ha_struct *sas_ha); |
| 65 | 65 | void sas_unregister_ports(struct sas_ha_struct *sas_ha); |
| 66 | 66 | |
| 67 | −enum blk_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *); | |
| 68 | − | |
| 69 | 67 | int sas_init_events(struct sas_ha_struct *sas_ha); |
| 70 | 68 | void sas_disable_revalidation(struct sas_ha_struct *ha); |
| 71 | 69 | void sas_enable_revalidation(struct sas_ha_struct *ha); |
| @@ -803,13 +803,6 @@ out: · 802 unmodified lines | ||
| 803 | 803 | shost->host_failed, tries); |
| 804 | 804 | } |
| 805 | 805 | |
| 806 | −enum blk_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd) | |
| 807 | −{ | |
| 808 | − scmd_dbg(cmd, "command %p timed out\n", cmd); | |
| 809 | − | |
| 810 | − return BLK_EH_NOT_HANDLED; | |
| 811 | −} | |
| 812 | − | |
| 813 | 806 | int sas_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) |
| 814 | 807 | { |
| 815 | 808 | struct domain_device *dev = sdev_to_domain_dev(sdev); |
| @@ -727,7 +727,6 @@ struct lpfc_hba { · 726 unmodified lines | ||
| 727 | 727 | uint32_t cfg_fcp_io_channel; |
| 728 | 728 | uint32_t cfg_total_seg_cnt; |
| 729 | 729 | uint32_t cfg_sg_seg_cnt; |
| 730 | − uint32_t cfg_prot_sg_seg_cnt; | |
| 731 | 730 | uint32_t cfg_sg_dma_buf_size; |
| 732 | 731 | uint64_t cfg_soft_wwnn; |
| 733 | 732 | uint64_t cfg_soft_wwpn; |
| @@ -2073,6 +2073,13 @@ lpfc_soft_wwn_enable_store(struct device *dev, struct device_attribute *attr, · 2072 unmodified lines | ||
| 2073 | 2073 | return -EINVAL; |
| 2074 | 2074 | |
| 2075 | 2075 | phba->soft_wwn_enable = 1; |
| 2076 | + | |
| 2077 | + dev_printk(KERN_WARNING, &phba->pcidev->dev, | |
| 2078 | + "lpfc%d: soft_wwpn assignment has been enabled.\n", | |
| 2079 | + phba->brd_no); | |
| 2080 | + dev_printk(KERN_WARNING, &phba->pcidev->dev, | |
| 2081 | + " The soft_wwpn feature is not supported by Broadcom."); | |
| 2082 | + | |
| 2076 | 2083 | return count; |
| 2077 | 2084 | } |
| 2078 | 2085 | static DEVICE_ATTR(lpfc_soft_wwn_enable, S_IWUSR, NULL, |
| @@ -2143,7 +2150,7 @@ lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr, · 64 unmodified lines | ||
| 2143 | 2150 | phba->soft_wwn_enable = 0; |
| 2144 | 2151 | |
| 2145 | 2152 | rc = lpfc_wwn_set(buf, cnt, wwpn); |
| 2146 | − if (!rc) { | |
| 2153 | + if (rc) { | |
| 2147 | 2154 | /* not able to set wwpn, unlock it */ |
| 2148 | 2155 | phba->soft_wwn_enable = 1; |
| 2149 | 2156 | return rc; |
| @@ -2224,7 +2231,7 @@ lpfc_soft_wwnn_store(struct device *dev, struct device_attribute *attr, · 74 unmodified lines | ||
| 2224 | 2231 | return -EINVAL; |
| 2225 | 2232 | |
| 2226 | 2233 | rc = lpfc_wwn_set(buf, cnt, wwnn); |
| 2227 | − if (!rc) { | |
| 2234 | + if (rc) { | |
| 2228 | 2235 | /* Allow wwnn to be set many times, as long as the enable |
| 2229 | 2236 | * is set. However, once the wwpn is set, everything locks. |
| 2230 | 2237 | */ |
| @@ -2435,7 +2442,8 @@ lpfc_oas_vpt_store(struct device *dev, struct device_attribute *attr, · 204 unmodified lines | ||
| 2435 | 2442 | else |
| 2436 | 2443 | phba->cfg_oas_flags &= ~OAS_FIND_ANY_VPORT; |
| 2437 | 2444 | phba->cfg_oas_flags &= ~OAS_LUN_VALID; |
| 2438 | − phba->cfg_oas_priority = phba->cfg_XLanePriority; | |
| 2445 | + if (phba->cfg_oas_priority == 0) | |
| 2446 | + phba->cfg_oas_priority = phba->cfg_XLanePriority; | |
| 2439 | 2447 | phba->sli4_hba.oas_next_lun = FIND_FIRST_OAS_LUN; |
| 2440 | 2448 | return count; |
| 2441 | 2449 | } |
| @@ -2561,7 +2569,7 @@ lpfc_oas_lun_state_set(struct lpfc_hba *phba, uint8_t vpt_wwpn[], · 119 unmodified lines | ||
| 2561 | 2569 | rc = -ENOMEM; |
| 2562 | 2570 | } else { |
| 2563 | 2571 | lpfc_disable_oas_lun(phba, (struct lpfc_name *)vpt_wwpn, |
| 2564 | − (struct lpfc_name *)tgt_wwpn, lun); | |
| 2572 | + (struct lpfc_name *)tgt_wwpn, lun, pri); | |
| 2565 | 2573 | } |
| 2566 | 2574 | return rc; |
| 2567 | 2575 | |
| @@ -2585,7 +2593,8 @@ lpfc_oas_lun_state_set(struct lpfc_hba *phba, uint8_t vpt_wwpn[], · 17 unmodified lines | ||
| 2585 | 2593 | */ |
| 2586 | 2594 | static uint64_t |
| 2587 | 2595 | lpfc_oas_lun_get_next(struct lpfc_hba *phba, uint8_t vpt_wwpn[], |
| 2588 | − uint8_t tgt_wwpn[], uint32_t *lun_status) | |
| 2596 | + uint8_t tgt_wwpn[], uint32_t *lun_status, | |
| 2597 | + uint32_t *lun_pri) | |
| 2589 | 2598 | { |
| 2590 | 2599 | uint64_t found_lun; |
| 2591 | 2600 | |
| @@ -2598,7 +2607,7 @@ lpfc_oas_lun_get_next(struct lpfc_hba *phba, uint8_t vpt_wwpn[], · 6 unmodified lines | ||
| 2598 | 2607 | &phba->sli4_hba.oas_next_lun, |
| 2599 | 2608 | (struct lpfc_name *)vpt_wwpn, |
| 2600 | 2609 | (struct lpfc_name *)tgt_wwpn, |
| 2601 | − &found_lun, lun_status)) | |
| 2610 | + &found_lun, lun_status, lun_pri)) | |
| 2602 | 2611 | return found_lun; |
| 2603 | 2612 | else |
| 2604 | 2613 | return NOT_OAS_ENABLED_LUN; |
| @@ -2670,7 +2679,8 @@ lpfc_oas_lun_show(struct device *dev, struct device_attribute *attr, · 65 unmodified lines | ||
| 2670 | 2679 | |
| 2671 | 2680 | oas_lun = lpfc_oas_lun_get_next(phba, phba->cfg_oas_vpt_wwpn, |
| 2672 | 2681 | phba->cfg_oas_tgt_wwpn, |
| 2673 | − &phba->cfg_oas_lun_status); | |
| 2682 | + &phba->cfg_oas_lun_status, | |
| 2683 | + &phba->cfg_oas_priority); | |
| 2674 | 2684 | if (oas_lun != NOT_OAS_ENABLED_LUN) |
| 2675 | 2685 | phba->cfg_oas_flags |= OAS_LUN_VALID; |
| 2676 | 2686 | |
| @@ -2701,6 +2711,7 @@ lpfc_oas_lun_store(struct device *dev, struct device_attribute *attr, · 24 unmodified lines | ||
| 2701 | 2711 | struct Scsi_Host *shost = class_to_shost(dev); |
| 2702 | 2712 | struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; |
| 2703 | 2713 | uint64_t scsi_lun; |
| 2714 | + uint32_t pri; | |
| 2704 | 2715 | ssize_t rc; |
| 2705 | 2716 | |
| 2706 | 2717 | if (!phba->cfg_fof) |
| @@ -2718,17 +2729,20 @@ lpfc_oas_lun_store(struct device *dev, struct device_attribute *attr, · 11 unmodified lines | ||
| 2718 | 2729 | if (sscanf(buf, "0x%llx", &scsi_lun) != 1) |
| 2719 | 2730 | return -EINVAL; |
| 2720 | 2731 | |
| 2732 | + pri = phba->cfg_oas_priority; | |
| 2733 | + if (pri == 0) | |
| 2734 | + pri = phba->cfg_XLanePriority; | |
| 2735 | + | |
| 2721 | 2736 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, |
| 2722 | 2737 | "3372 Try to set vport 0x%llx target 0x%llx lun:0x%llx " |
| 2723 | 2738 | "priority 0x%x with oas state %d\n", |
| 2724 | 2739 | wwn_to_u64(phba->cfg_oas_vpt_wwpn), |
| 2725 | 2740 | wwn_to_u64(phba->cfg_oas_tgt_wwpn), scsi_lun, |
| 2726 | − phba->cfg_oas_priority, phba->cfg_oas_lun_state); | |
| 2741 | + pri, phba->cfg_oas_lun_state); | |
| 2727 | 2742 | |
| 2728 | 2743 | rc = lpfc_oas_lun_state_change(phba, phba->cfg_oas_vpt_wwpn, |
| 2729 | 2744 | phba->cfg_oas_tgt_wwpn, scsi_lun, |
| 2730 | − phba->cfg_oas_lun_state, | |
| 2731 | − phba->cfg_oas_priority); | |
| 2745 | + phba->cfg_oas_lun_state, pri); | |
| 2732 | 2746 | if (rc) |
| 2733 | 2747 | return rc; |
| 2734 | 2748 | |
| @@ -4669,14 +4683,6 @@ LPFC_ATTR(delay_discovery, 0, 0, 1, · 1934 unmodified lines | ||
| 4669 | 4683 | LPFC_ATTR_R(sg_seg_cnt, LPFC_DEFAULT_SG_SEG_CNT, LPFC_DEFAULT_SG_SEG_CNT, |
| 4670 | 4684 | LPFC_MAX_SG_SEG_CNT, "Max Scatter Gather Segment Count"); |
| 4671 | 4685 | |
| 4672 | −/* | |
| 4673 | − * This parameter will be depricated, the driver cannot limit the | |
| 4674 | − * protection data s/g list. | |
| 4675 | − */ | |
| 4676 | −LPFC_ATTR_R(prot_sg_seg_cnt, LPFC_DEFAULT_SG_SEG_CNT, | |
| 4677 | − LPFC_DEFAULT_SG_SEG_CNT, LPFC_MAX_SG_SEG_CNT, | |
| 4678 | − "Max Protection Scatter Gather Segment Count"); | |
| 4679 | − | |
| 4680 | 4686 | /* |
| 4681 | 4687 | * lpfc_enable_mds_diags: Enable MDS Diagnostics |
| 4682 | 4688 | * 0 = MDS Diagnostics disabled (default) |
| @@ -4766,7 +4772,6 @@ struct device_attribute *lpfc_hba_attrs[] = { · 83 unmodified lines | ||
| 4766 | 4772 | &dev_attr_lpfc_sg_seg_cnt, |
| 4767 | 4773 | &dev_attr_lpfc_max_scsicmpl_time, |
| 4768 | 4774 | &dev_attr_lpfc_stat_data_ctrl, |
| 4769 | − &dev_attr_lpfc_prot_sg_seg_cnt, | |
| 4770 | 4775 | &dev_attr_lpfc_aer_support, |
| 4771 | 4776 | &dev_attr_lpfc_aer_state_cleanup, |
| 4772 | 4777 | &dev_attr_lpfc_sriov_nr_virtfn, |
| @@ -5060,6 +5065,19 @@ lpfc_free_sysfs_attr(struct lpfc_vport *vport) · 287 unmodified lines | ||
| 5060 | 5065 | * Dynamic FC Host Attributes Support |
| 5061 | 5066 | */ |
| 5062 | 5067 | |
| 5068 | +/** | |
| 5069 | + * lpfc_get_host_symbolic_name - Copy symbolic name into the scsi host | |
| 5070 | + * @shost: kernel scsi host pointer. | |
| 5071 | + **/ | |
| 5072 | +static void | |
| 5073 | +lpfc_get_host_symbolic_name(struct Scsi_Host *shost) | |
| 5074 | +{ | |
| 5075 | + struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata; | |
| 5076 | + | |
| 5077 | + lpfc_vport_symbolic_node_name(vport, fc_host_symbolic_name(shost), | |
| 5078 | + sizeof fc_host_symbolic_name(shost)); | |
| 5079 | +} | |
| 5080 | + | |
| 5063 | 5081 | /** |
| 5064 | 5082 | * lpfc_get_host_port_id - Copy the vport DID into the scsi host port id |
| 5065 | 5083 | * @shost: kernel scsi host pointer. |
| @@ -5597,6 +5615,8 @@ struct fc_function_template lpfc_transport_functions = { · 531 unmodified lines | ||
| 5597 | 5615 | .show_host_supported_fc4s = 1, |
| 5598 | 5616 | .show_host_supported_speeds = 1, |
| 5599 | 5617 | .show_host_maxframe_size = 1, |
| 5618 | + | |
| 5619 | + .get_host_symbolic_name = lpfc_get_host_symbolic_name, | |
| 5600 | 5620 | .show_host_symbolic_name = 1, |
| 5601 | 5621 | |
| 5602 | 5622 | /* dynamic attributes the driver supports */ |
| @@ -5664,6 +5684,8 @@ struct fc_function_template lpfc_vport_transport_functions = { · 61 unmodified lines | ||
| 5664 | 5684 | .show_host_supported_fc4s = 1, |
| 5665 | 5685 | .show_host_supported_speeds = 1, |
| 5666 | 5686 | .show_host_maxframe_size = 1, |
| 5687 | + | |
| 5688 | + .get_host_symbolic_name = lpfc_get_host_symbolic_name, | |
| 5667 | 5689 | .show_host_symbolic_name = 1, |
| 5668 | 5690 | |
| 5669 | 5691 | /* dynamic attributes the driver supports */ |
| @@ -5768,7 +5790,6 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) · 98 unmodified lines | ||
| 5768 | 5790 | phba->cfg_soft_wwnn = 0L; |
| 5769 | 5791 | phba->cfg_soft_wwpn = 0L; |
| 5770 | 5792 | lpfc_sg_seg_cnt_init(phba, lpfc_sg_seg_cnt); |
| 5771 | − lpfc_prot_sg_seg_cnt_init(phba, lpfc_prot_sg_seg_cnt); | |
| 5772 | 5793 | lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth); |
| 5773 | 5794 | lpfc_hba_log_verbose_init(phba, lpfc_log_verbose); |
| 5774 | 5795 | lpfc_aer_support_init(phba, lpfc_aer_support); |
| @@ -480,7 +480,7 @@ void lpfc_sli4_offline_eratt(struct lpfc_hba *); · 479 unmodified lines | ||
| 480 | 480 | struct lpfc_device_data *lpfc_create_device_data(struct lpfc_hba *, |
| 481 | 481 | struct lpfc_name *, |
| 482 | 482 | struct lpfc_name *, |
| 483 | − uint64_t, bool); | |
| 483 | + uint64_t, uint32_t, bool); | |
| 484 | 484 | void lpfc_delete_device_data(struct lpfc_hba *, struct lpfc_device_data*); |
| 485 | 485 | struct lpfc_device_data *__lpfc_get_device_data(struct lpfc_hba *, |
| 486 | 486 | struct list_head *list, |
| @@ -489,9 +489,10 @@ struct lpfc_device_data *__lpfc_get_device_data(struct lpfc_hba *, · 2 unmodified lines | ||
| 489 | 489 | bool lpfc_enable_oas_lun(struct lpfc_hba *, struct lpfc_name *, |
| 490 | 490 | struct lpfc_name *, uint64_t, uint8_t); |
| 491 | 491 | bool lpfc_disable_oas_lun(struct lpfc_hba *, struct lpfc_name *, |
| 492 | − struct lpfc_name *, uint64_t); | |
| 492 | + struct lpfc_name *, uint64_t, uint8_t); | |
| 493 | 493 | bool lpfc_find_next_oas_lun(struct lpfc_hba *, struct lpfc_name *, |
| 494 | 494 | struct lpfc_name *, uint64_t *, struct lpfc_name *, |
| 495 | − struct lpfc_name *, uint64_t *, uint32_t *); | |
| 495 | + struct lpfc_name *, uint64_t *, | |
| 496 | + uint32_t *, uint32_t *); | |
| 496 | 497 | int lpfc_sli4_dump_page_a0(struct lpfc_hba *phba, struct lpfcMboxq *mbox); |
| 497 | 498 | void lpfc_mbx_cmpl_rdp_page_a0(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb); |
| @@ -1999,6 +1999,9 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry) · 1998 unmodified lines | ||
| 1999 | 1999 | if (sp->cmn.fcphHigh < FC_PH3) |
| 2000 | 2000 | sp->cmn.fcphHigh = FC_PH3; |
| 2001 | 2001 | |
| 2002 | + sp->cmn.valid_vendor_ver_level = 0; | |
| 2003 | + memset(sp->vendorVersion, 0, sizeof(sp->vendorVersion)); | |
| 2004 | + | |
| 2002 | 2005 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, |
| 2003 | 2006 | "Issue PLOGI: did:x%x", |
| 2004 | 2007 | did, 0, 0); |
| @@ -3990,6 +3993,9 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, · 1985 unmodified lines | ||
| 3990 | 3993 | } else { |
| 3991 | 3994 | memcpy(pcmd, &vport->fc_sparam, |
| 3992 | 3995 | sizeof(struct serv_parm)); |
| 3996 | + | |
| 3997 | + sp->cmn.valid_vendor_ver_level = 0; | |
| 3998 | + memset(sp->vendorVersion, 0, sizeof(sp->vendorVersion)); | |
| 3993 | 3999 | } |
| 3994 | 4000 | |
| 3995 | 4001 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, |
| @@ -8851,8 +8857,7 @@ lpfc_cmpl_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, · 4855 unmodified lines | ||
| 8851 | 8857 | { |
| 8852 | 8858 | struct ls_rjt stat; |
| 8853 | 8859 | |
| 8854 | − if ((cmdiocb->iocb_flag & LPFC_IO_FABRIC) != LPFC_IO_FABRIC) | |
| 8855 | − BUG(); | |
| 8860 | + BUG_ON((cmdiocb->iocb_flag & LPFC_IO_FABRIC) != LPFC_IO_FABRIC); | |
| 8856 | 8861 | |
| 8857 | 8862 | switch (rspiocb->iocb.ulpStatus) { |
| 8858 | 8863 | case IOSTAT_NPORT_RJT: |
| @@ -360,6 +360,12 @@ struct csp { · 359 unmodified lines | ||
| 360 | 360 | * Word 1 Bit 30 in PLOGI request is random offset |
| 361 | 361 | */ |
| 362 | 362 | #define virtual_fabric_support randomOffset /* Word 1, bit 30 */ |
| 363 | +/* | |
| 364 | + * Word 1 Bit 29 in common service parameter is overloaded. | |
| 365 | + * Word 1 Bit 29 in FLOGI response is multiple NPort assignment | |
| 366 | + * Word 1 Bit 29 in FLOGI/PLOGI request is Valid Vendor Version Level | |
| 367 | + */ | |
| 368 | +#define valid_vendor_ver_level response_multiple_NPort /* Word 1, bit 29 */ | |
| 363 | 369 | #ifdef __BIG_ENDIAN_BITFIELD |
| 364 | 370 | uint16_t request_multiple_Nport:1; /* FC Word 1, bit 31 */ |
| 365 | 371 | uint16_t randomOffset:1; /* FC Word 1, bit 30 */ |
| @@ -5452,7 +5452,9 @@ lpfc_slave_alloc(struct scsi_device *sdev) · 5451 unmodified lines | ||
| 5452 | 5452 | device_data = lpfc_create_device_data(phba, |
| 5453 | 5453 | &vport->fc_portname, |
| 5454 | 5454 | &target_wwpn, |
| 5455 | − sdev->lun, true); | |
| 5455 | + sdev->lun, | |
| 5456 | + phba->cfg_XLanePriority, | |
| 5457 | + true); | |
| 5456 | 5458 | if (!device_data) |
| 5457 | 5459 | return -ENOMEM; |
| 5458 | 5460 | spin_lock_irqsave(&phba->devicelock, flags); |
| @@ -5587,7 +5589,7 @@ lpfc_slave_destroy(struct scsi_device *sdev) · 128 unmodified lines | ||
| 5587 | 5589 | struct lpfc_device_data* |
| 5588 | 5590 | lpfc_create_device_data(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn, |
| 5589 | 5591 | struct lpfc_name *target_wwpn, uint64_t lun, |
| 5590 | − bool atomic_create) | |
| 5592 | + uint32_t pri, bool atomic_create) | |
| 5591 | 5593 | { |
| 5592 | 5594 | |
| 5593 | 5595 | struct lpfc_device_data *lun_info; |
| @@ -5614,7 +5616,7 @@ lpfc_create_device_data(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn, · 20 unmodified lines | ||
| 5614 | 5616 | sizeof(struct lpfc_name)); |
| 5615 | 5617 | lun_info->device_id.lun = lun; |
| 5616 | 5618 | lun_info->oas_enabled = false; |
| 5617 | − lun_info->priority = phba->cfg_XLanePriority; | |
| 5619 | + lun_info->priority = pri; | |
| 5618 | 5620 | lun_info->available = false; |
| 5619 | 5621 | return lun_info; |
| 5620 | 5622 | } |
| @@ -5716,7 +5718,8 @@ lpfc_find_next_oas_lun(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn, · 95 unmodified lines | ||
| 5716 | 5718 | struct lpfc_name *found_vport_wwpn, |
| 5717 | 5719 | struct lpfc_name *found_target_wwpn, |
| 5718 | 5720 | uint64_t *found_lun, |
| 5719 | − uint32_t *found_lun_status) | |
| 5721 | + uint32_t *found_lun_status, | |
| 5722 | + uint32_t *found_lun_pri) | |
| 5720 | 5723 | { |
| 5721 | 5724 | |
| 5722 | 5725 | unsigned long flags; |
| @@ -5763,6 +5766,7 @@ lpfc_find_next_oas_lun(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn, · 40 unmodified lines | ||
| 5763 | 5766 | OAS_LUN_STATUS_EXISTS; |
| 5764 | 5767 | else |
| 5765 | 5768 | *found_lun_status = 0; |
| 5769 | + *found_lun_pri = lun_info->priority; | |
| 5766 | 5770 | if (phba->cfg_oas_flags & OAS_FIND_ANY_VPORT) |
| 5767 | 5771 | memset(vport_wwpn, 0x0, |
| 5768 | 5772 | sizeof(struct lpfc_name)); |
| @@ -5824,13 +5828,14 @@ lpfc_enable_oas_lun(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn, · 55 unmodified lines | ||
| 5824 | 5828 | if (lun_info) { |
| 5825 | 5829 | if (!lun_info->oas_enabled) |
| 5826 | 5830 | lun_info->oas_enabled = true; |
| 5831 | + lun_info->priority = pri; | |
| 5827 | 5832 | spin_unlock_irqrestore(&phba->devicelock, flags); |
| 5828 | 5833 | return true; |
| 5829 | 5834 | } |
| 5830 | 5835 | |
| 5831 | 5836 | /* Create an lun info structure and add to list of luns */ |
| 5832 | 5837 | lun_info = lpfc_create_device_data(phba, vport_wwpn, target_wwpn, lun, |
| 5833 | − false); | |
| 5838 | + pri, false); | |
| 5834 | 5839 | if (lun_info) { |
| 5835 | 5840 | lun_info->oas_enabled = true; |
| 5836 | 5841 | lun_info->priority = pri; |
| @@ -5864,7 +5869,7 @@ lpfc_enable_oas_lun(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn, · 27 unmodified lines | ||
| 5864 | 5869 | **/ |
| 5865 | 5870 | bool |
| 5866 | 5871 | lpfc_disable_oas_lun(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn, |
| 5867 | − struct lpfc_name *target_wwpn, uint64_t lun) | |
| 5872 | + struct lpfc_name *target_wwpn, uint64_t lun, uint8_t pri) | |
| 5868 | 5873 | { |
| 5869 | 5874 | |
| 5870 | 5875 | struct lpfc_device_data *lun_info; |
| @@ -5882,6 +5887,7 @@ lpfc_disable_oas_lun(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn, · 11 unmodified lines | ||
| 5882 | 5887 | target_wwpn, lun); |
| 5883 | 5888 | if (lun_info) { |
| 5884 | 5889 | lun_info->oas_enabled = false; |
| 5890 | + lun_info->priority = pri; | |
| 5885 | 5891 | if (!lun_info->available) |
| 5886 | 5892 | lpfc_delete_device_data(phba, lun_info); |
| 5887 | 5893 | spin_unlock_irqrestore(&phba->devicelock, flags); |
| @@ -5923,6 +5929,7 @@ struct scsi_host_template lpfc_template = { · 35 unmodified lines | ||
| 5923 | 5929 | .proc_name = LPFC_DRIVER_NAME, |
| 5924 | 5930 | .info = lpfc_info, |
| 5925 | 5931 | .queuecommand = lpfc_queuecommand, |
| 5932 | + .eh_timed_out = fc_eh_timed_out, | |
| 5926 | 5933 | .eh_abort_handler = lpfc_abort_handler, |
| 5927 | 5934 | .eh_device_reset_handler = lpfc_device_reset_handler, |
| 5928 | 5935 | .eh_target_reset_handler = lpfc_target_reset_handler, |
| @@ -5949,6 +5956,7 @@ struct scsi_host_template lpfc_vport_template = { · 20 unmodified lines | ||
| 5949 | 5956 | .proc_name = LPFC_DRIVER_NAME, |
| 5950 | 5957 | .info = lpfc_info, |
| 5951 | 5958 | .queuecommand = lpfc_queuecommand, |
| 5959 | + .eh_timed_out = fc_eh_timed_out, | |
| 5952 | 5960 | .eh_abort_handler = lpfc_abort_handler, |
| 5953 | 5961 | .eh_device_reset_handler = lpfc_device_reset_handler, |
| 5954 | 5962 | .eh_target_reset_handler = lpfc_target_reset_handler, |
| @@ -120,6 +120,8 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe *wqe) · 119 unmodified lines | ||
| 120 | 120 | if (q->phba->sli3_options & LPFC_SLI4_PHWQ_ENABLED) |
| 121 | 121 | bf_set(wqe_wqid, &wqe->generic.wqe_com, q->queue_id); |
| 122 | 122 | lpfc_sli_pcimem_bcopy(wqe, temp_wqe, q->entry_size); |
| 123 | + /* ensure WQE bcopy flushed before doorbell write */ | |
| 124 | + wmb(); | |
| 123 | 125 | |
| 124 | 126 | /* Update the host index before invoking device */ |
| 125 | 127 | host_index = q->host_index; |
| @@ -6313,7 +6315,8 @@ lpfc_set_host_data(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox) · 6187 unmodified lines | ||
| 6313 | 6315 | LPFC_SLI4_MBX_EMBED); |
| 6314 | 6316 | |
| 6315 | 6317 | mbox->u.mqe.un.set_host_data.param_id = LPFC_SET_HOST_OS_DRIVER_VERSION; |
| 6316 | − mbox->u.mqe.un.set_host_data.param_len = 8; | |
| 6318 | + mbox->u.mqe.un.set_host_data.param_len = | |
| 6319 | + LPFC_HOST_OS_DRIVER_VERSION_SIZE; | |
| 6317 | 6320 | snprintf(mbox->u.mqe.un.set_host_data.data, |
| 6318 | 6321 | LPFC_HOST_OS_DRIVER_VERSION_SIZE, |
| 6319 | 6322 | "Linux %s v"LPFC_DRIVER_VERSION, |
| @@ -10035,6 +10038,7 @@ lpfc_sli_abort_iotag_issue(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, · 3715 unmodified lines | ||
| 10035 | 10038 | iabt->ulpCommand = CMD_CLOSE_XRI_CN; |
| 10036 | 10039 | |
| 10037 | 10040 | abtsiocbp->iocb_cmpl = lpfc_sli_abort_els_cmpl; |
| 10041 | + abtsiocbp->vport = vport; | |
| 10038 | 10042 | |
| 10039 | 10043 | lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI, |
| 10040 | 10044 | "0339 Abort xri x%x, original iotag x%x, " |
| @@ -17226,7 +17230,8 @@ lpfc_drain_txq(struct lpfc_hba *phba) · 7185 unmodified lines | ||
| 17226 | 17230 | unsigned long iflags = 0; |
| 17227 | 17231 | char *fail_msg = NULL; |
| 17228 | 17232 | struct lpfc_sglq *sglq; |
| 17229 | − union lpfc_wqe wqe; | |
| 17233 | + union lpfc_wqe128 wqe128; | |
| 17234 | + union lpfc_wqe *wqe = (union lpfc_wqe *) &wqe128; | |
| 17230 | 17235 | uint32_t txq_cnt = 0; |
| 17231 | 17236 | |
| 17232 | 17237 | spin_lock_irqsave(&pring->ring_lock, iflags); |
| @@ -17265,9 +17270,9 @@ lpfc_drain_txq(struct lpfc_hba *phba) · 32 unmodified lines | ||
| 17265 | 17270 | piocbq->sli4_xritag = sglq->sli4_xritag; |
| 17266 | 17271 | if (NO_XRI == lpfc_sli4_bpl2sgl(phba, piocbq, sglq)) |
| 17267 | 17272 | fail_msg = "to convert bpl to sgl"; |
| 17268 | − else if (lpfc_sli4_iocb2wqe(phba, piocbq, &wqe)) | |
| 17273 | + else if (lpfc_sli4_iocb2wqe(phba, piocbq, wqe)) | |
| 17269 | 17274 | fail_msg = "to convert iocb to wqe"; |
| 17270 | − else if (lpfc_sli4_wq_put(phba->sli4_hba.els_wq, &wqe)) | |
| 17275 | + else if (lpfc_sli4_wq_put(phba->sli4_hba.els_wq, wqe)) | |
| 17271 | 17276 | fail_msg = " - Wq is full"; |
| 17272 | 17277 | else |
| 17273 | 17278 | lpfc_sli_ringtxcmpl_put(phba, pring, piocbq); |
| @@ -18,7 +18,7 @@ · 17 unmodified lines | ||
| 18 | 18 | * included with this package. * |
| 19 | 19 | *******************************************************************/ |
| 20 | 20 | |
| 21 | −#define LPFC_DRIVER_VERSION "11.2.0.2" | |
| 21 | +#define LPFC_DRIVER_VERSION "11.2.0.4" | |
| 22 | 22 | #define LPFC_DRIVER_NAME "lpfc" |
| 23 | 23 | |
| 24 | 24 | /* Used for SLI 2/3 */ |
| @@ -537,6 +537,12 @@ enable_vport(struct fc_vport *fc_vport) · 536 unmodified lines | ||
| 537 | 537 | |
| 538 | 538 | spin_lock_irq(shost->host_lock); |
| 539 | 539 | vport->load_flag |= FC_LOADING; |
| 540 | + if (vport->fc_flag & FC_VPORT_NEEDS_INIT_VPI) { | |
| 541 | + spin_unlock_irq(shost->host_lock); | |
| 542 | + lpfc_issue_init_vpi(vport); | |
| 543 | + goto out; | |
| 544 | + } | |
| 545 | + | |
| 540 | 546 | vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; |
| 541 | 547 | spin_unlock_irq(shost->host_lock); |
| 542 | 548 | |
| @@ -557,6 +563,8 @@ enable_vport(struct fc_vport *fc_vport) · 14 unmodified lines | ||
| 557 | 563 | } else { |
| 558 | 564 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); |
| 559 | 565 | } |
| 566 | + | |
| 567 | +out: | |
| 560 | 568 | lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, |
| 561 | 569 | "1827 Vport Enabled.\n"); |
| 562 | 570 | return VPORT_OK; |
| @@ -154,7 +154,7 @@ __asm__ __volatile__ \ · 153 unmodified lines | ||
| 154 | 154 | static inline int macscsi_pread(struct NCR5380_hostdata *hostdata, |
| 155 | 155 | unsigned char *dst, int len) |
| 156 | 156 | { |
| 157 | − unsigned char *s = hostdata->pdma_io + (INPUT_DATA_REG << 4); | |
| 157 | + u8 __iomem *s = hostdata->pdma_io + (INPUT_DATA_REG << 4); | |
| 158 | 158 | unsigned char *d = dst; |
| 159 | 159 | int n = len; |
| 160 | 160 | int transferred; |
| @@ -257,7 +257,7 @@ static inline int macscsi_pwrite(struct NCR5380_hostdata *hostdata, · 96 unmodified lines | ||
| 257 | 257 | unsigned char *src, int len) |
| 258 | 258 | { |
| 259 | 259 | unsigned char *s = src; |
| 260 | − unsigned char *d = hostdata->pdma_io + (OUTPUT_DATA_REG << 4); | |
| 260 | + u8 __iomem *d = hostdata->pdma_io + (OUTPUT_DATA_REG << 4); | |
| 261 | 261 | int n = len; |
| 262 | 262 | int transferred; |
| 263 | 263 | |
| @@ -381,10 +381,10 @@ static int __init mac_scsi_probe(struct platform_device *pdev) · 117 unmodified lines | ||
| 381 | 381 | |
| 382 | 382 | hostdata = shost_priv(instance); |
| 383 | 383 | hostdata->base = pio_mem->start; |
| 384 | − hostdata->io = (void *)pio_mem->start; | |
| 384 | + hostdata->io = (u8 __iomem *)pio_mem->start; | |
| 385 | 385 | |
| 386 | 386 | if (pdma_mem && setup_use_pdma) |
| 387 | − hostdata->pdma_io = (void *)pdma_mem->start; | |
| 387 | + hostdata->pdma_io = (u8 __iomem *)pdma_mem->start; | |
| 388 | 388 | else |
| 389 | 389 | host_flags |= FLAG_NO_PSEUDO_DMA; |
| 390 | 390 | |
| @@ -35,8 +35,8 @@ · 34 unmodified lines | ||
| 35 | 35 | /* |
| 36 | 36 | * MegaRAID SAS Driver meta data |
| 37 | 37 | */ |
| 38 | −#define MEGASAS_VERSION "06.812.07.00-rc1" | |
| 39 | −#define MEGASAS_RELDATE "August 22, 2016" | |
| 38 | +#define MEGASAS_VERSION "07.701.16.00-rc1" | |
| 39 | +#define MEGASAS_RELDATE "February 2, 2017" | |
| 40 | 40 | |
| 41 | 41 | /* |
| 42 | 42 | * Device IDs |
| @@ -56,6 +56,11 @@ · 13 unmodified lines | ||
| 56 | 56 | #define PCI_DEVICE_ID_LSI_INTRUDER_24 0x00cf |
| 57 | 57 | #define PCI_DEVICE_ID_LSI_CUTLASS_52 0x0052 |
| 58 | 58 | #define PCI_DEVICE_ID_LSI_CUTLASS_53 0x0053 |
| 59 | +#define PCI_DEVICE_ID_LSI_VENTURA 0x0014 | |
| 60 | +#define PCI_DEVICE_ID_LSI_HARPOON 0x0016 | |
| 61 | +#define PCI_DEVICE_ID_LSI_TOMCAT 0x0017 | |
| 62 | +#define PCI_DEVICE_ID_LSI_VENTURA_4PORT 0x001B | |
| 63 | +#define PCI_DEVICE_ID_LSI_CRUSADER_4PORT 0x001C | |
| 59 | 64 | |
| 60 | 65 | /* |
| 61 | 66 | * Intel HBA SSDIDs |
| @@ -100,7 +105,7 @@ · 38 unmodified lines | ||
| 100 | 105 | */ |
| 101 | 106 | |
| 102 | 107 | /* |
| 103 | − * MFI stands for MegaRAID SAS FW Interface. This is just a moniker for | |
| 108 | + * MFI stands for MegaRAID SAS FW Interface. This is just a moniker for | |
| 104 | 109 | * protocol between the software and firmware. Commands are issued using |
| 105 | 110 | * "message frames" |
| 106 | 111 | */ |
| @@ -690,6 +695,18 @@ struct MR_PD_INFO { · 583 unmodified lines | ||
| 690 | 695 | u8 reserved1[512-428]; |
| 691 | 696 | } __packed; |
| 692 | 697 | |
| 698 | +/* | |
| 699 | + * Definition of structure used to expose attributes of VD or JBOD | |
| 700 | + * (this structure is to be filled by firmware when MR_DCMD_DRV_GET_TARGET_PROP | |
| 701 | + * is fired by driver) | |
| 702 | + */ | |
| 703 | +struct MR_TARGET_PROPERTIES { | |
| 704 | + u32 max_io_size_kb; | |
| 705 | + u32 device_qdepth; | |
| 706 | + u32 sector_size; | |
| 707 | + u8 reserved[500]; | |
| 708 | +} __packed; | |
| 709 | + | |
| 693 | 710 | /* |
| 694 | 711 | * defines the physical drive address structure |
| 695 | 712 | */ |
| @@ -728,7 +745,6 @@ struct megasas_pd_list { · 32 unmodified lines | ||
| 728 | 745 | u16 tid; |
| 729 | 746 | u8 driveType; |
| 730 | 747 | u8 driveState; |
| 731 | − u8 interface; | |
| 732 | 748 | } __packed; |
| 733 | 749 | |
| 734 | 750 | /* |
| @@ -1312,7 +1328,55 @@ struct megasas_ctrl_info { · 577 unmodified lines | ||
| 1312 | 1328 | #endif |
| 1313 | 1329 | } adapterOperations3; |
| 1314 | 1330 | |
| 1315 | − u8 pad[0x800-0x7EC]; | |
| 1331 | + struct { | |
| 1332 | +#if defined(__BIG_ENDIAN_BITFIELD) | |
| 1333 | + u8 reserved:7; | |
| 1334 | + /* Indicates whether the CPLD image is part of | |
| 1335 | + * the package and stored in flash | |
| 1336 | + */ | |
| 1337 | + u8 cpld_in_flash:1; | |
| 1338 | +#else | |
| 1339 | + u8 cpld_in_flash:1; | |
| 1340 | + u8 reserved:7; | |
| 1341 | +#endif | |
| 1342 | + u8 reserved1[3]; | |
| 1343 | + /* Null terminated string. Has the version | |
| 1344 | + * information if cpld_in_flash = FALSE | |
| 1345 | + */ | |
| 1346 | + u8 userCodeDefinition[12]; | |
| 1347 | + } cpld; /* Valid only if upgradableCPLD is TRUE */ | |
| 1348 | + | |
| 1349 | + struct { | |
| 1350 | + #if defined(__BIG_ENDIAN_BITFIELD) | |
| 1351 | + u16 reserved:8; | |
| 1352 | + u16 fw_swaps_bbu_vpd_info:1; | |
| 1353 | + u16 support_pd_map_target_id:1; | |
| 1354 | + u16 support_ses_ctrl_in_multipathcfg:1; | |
| 1355 | + u16 image_upload_supported:1; | |
| 1356 | + u16 support_encrypted_mfc:1; | |
| 1357 | + u16 supported_enc_algo:1; | |
| 1358 | + u16 support_ibutton_less:1; | |
| 1359 | + u16 ctrl_info_ext_supported:1; | |
| 1360 | + #else | |
| 1361 | + | |
| 1362 | + u16 ctrl_info_ext_supported:1; | |
| 1363 | + u16 support_ibutton_less:1; | |
| 1364 | + u16 supported_enc_algo:1; | |
| 1365 | + u16 support_encrypted_mfc:1; | |
| 1366 | + u16 image_upload_supported:1; | |
| 1367 | + /* FW supports LUN based association and target port based */ | |
| 1368 | + u16 support_ses_ctrl_in_multipathcfg:1; | |
| 1369 | + /* association for the SES device connected in multipath mode */ | |
| 1370 | + /* FW defines Jbod target Id within MR_PD_CFG_SEQ */ | |
| 1371 | + u16 support_pd_map_target_id:1; | |
| 1372 | + /* FW swaps relevant fields in MR_BBU_VPD_INFO_FIXED to | |
| 1373 | + * provide the data in little endian order | |
| 1374 | + */ | |
| 1375 | + u16 fw_swaps_bbu_vpd_info:1; | |
| 1376 | + u16 reserved:8; | |
| 1377 | + #endif | |
| 1378 | + } adapter_operations4; | |
| 1379 | + u8 pad[0x800 - 0x7FE]; /* 0x7FE pad to 2K for expansion */ | |
| 1316 | 1380 | } __packed; |
| 1317 | 1381 | |
| 1318 | 1382 | /* |
| @@ -1339,12 +1403,15 @@ struct megasas_ctrl_info { · 20 unmodified lines | ||
| 1339 | 1403 | |
| 1340 | 1404 | #define MEGASAS_FW_BUSY 1 |
| 1341 | 1405 | |
| 1342 | −#define VD_EXT_DEBUG 0 | |
| 1406 | +/* Driver's internal Logging levels*/ | |
| 1407 | +#define OCR_LOGS (1 << 0) | |
| 1343 | 1408 | |
| 1344 | 1409 | #define SCAN_PD_CHANNEL 0x1 |
| 1345 | 1410 | #define SCAN_VD_CHANNEL 0x2 |
| 1346 | 1411 | |
| 1347 | 1412 | #define MEGASAS_KDUMP_QUEUE_DEPTH 100 |
| 1413 | +#define MR_LARGE_IO_MIN_SIZE (32 * 1024) | |
| 1414 | +#define MR_R1_LDIO_PIGGYBACK_DEFAULT 4 | |
| 1348 | 1415 | |
| 1349 | 1416 | enum MR_SCSI_CMD_TYPE { |
| 1350 | 1417 | READ_WRITE_LDIO = 0, |
| @@ -1391,7 +1458,7 @@ enum FW_BOOT_CONTEXT { · 40 unmodified lines | ||
| 1391 | 1458 | */ |
| 1392 | 1459 | #define MEGASAS_INT_CMDS 32 |
| 1393 | 1460 | #define MEGASAS_SKINNY_INT_CMDS 5 |
| 1394 | −#define MEGASAS_FUSION_INTERNAL_CMDS 5 | |
| 1461 | +#define MEGASAS_FUSION_INTERNAL_CMDS 8 | |
| 1395 | 1462 | #define MEGASAS_FUSION_IOCTL_CMDS 3 |
| 1396 | 1463 | #define MEGASAS_MFI_IOCTL_CMDS 27 |
| 1397 | 1464 | |
| @@ -1429,13 +1496,19 @@ enum FW_BOOT_CONTEXT { · 31 unmodified lines | ||
| 1429 | 1496 | #define MR_MAX_REPLY_QUEUES_EXT_OFFSET_SHIFT 14 |
| 1430 | 1497 | #define MR_MAX_MSIX_REG_ARRAY 16 |
| 1431 | 1498 | #define MR_RDPQ_MODE_OFFSET 0X00800000 |
| 1499 | + | |
| 1500 | +#define MR_MAX_RAID_MAP_SIZE_OFFSET_SHIFT 16 | |
| 1501 | +#define MR_MAX_RAID_MAP_SIZE_MASK 0x1FF | |
| 1502 | +#define MR_MIN_MAP_SIZE 0x10000 | |
| 1503 | +/* 64k */ | |
| 1504 | + | |
| 1432 | 1505 | #define MR_CAN_HANDLE_SYNC_CACHE_OFFSET 0X01000000 |
| 1433 | 1506 | |
| 1434 | 1507 | /* |
| 1435 | 1508 | * register set for both 1068 and 1078 controllers |
| 1436 | 1509 | * structure extended for 1078 registers |
| 1437 | 1510 | */ |
| 1438 | − | |
| 1511 | + | |
| 1439 | 1512 | struct megasas_register_set { |
| 1440 | 1513 | u32 doorbell; /*0000h*/ |
| 1441 | 1514 | u32 fusion_seq_offset; /*0004h*/ |
| @@ -1471,14 +1544,14 @@ struct megasas_register_set { · 29 unmodified lines | ||
| 1471 | 1544 | u32 outbound_scratch_pad ; /*00B0h*/ |
| 1472 | 1545 | u32 outbound_scratch_pad_2; /*00B4h*/ |
| 1473 | 1546 | u32 outbound_scratch_pad_3; /*00B8h*/ |
| 1547 | + u32 outbound_scratch_pad_4; /*00BCh*/ | |
| 1474 | 1548 | |
| 1475 | − u32 reserved_4; /*00BCh*/ | |
| 1476 | 1549 | |
| 1477 | 1550 | u32 inbound_low_queue_port ; /*00C0h*/ |
| 1478 | 1551 | |
| 1479 | 1552 | u32 inbound_high_queue_port ; /*00C4h*/ |
| 1480 | 1553 | |
| 1481 | − u32 reserved_5; /*00C8h*/ | |
| 1554 | + u32 inbound_single_queue_port; /*00C8h*/ | |
| 1482 | 1555 | u32 res_6[11]; /*CCh*/ |
| 1483 | 1556 | u32 host_diag; |
| 1484 | 1557 | u32 seq_offset; |
| @@ -1544,33 +1617,35 @@ union megasas_sgl_frame { · 59 unmodified lines | ||
| 1544 | 1617 | typedef union _MFI_CAPABILITIES { |
| 1545 | 1618 | struct { |
| 1546 | 1619 | #if defined(__BIG_ENDIAN_BITFIELD) |
| 1547 | − u32 reserved:20; | |
| 1548 | − u32 support_qd_throttling:1; | |
| 1549 | − u32 support_fp_rlbypass:1; | |
| 1550 | − u32 support_vfid_in_ioframe:1; | |
| 1551 | − u32 support_ext_io_size:1; | |
| 1552 | − u32 support_ext_queue_depth:1; | |
| 1553 | − u32 security_protocol_cmds_fw:1; | |
| 1554 | − u32 support_core_affinity:1; | |
| 1555 | − u32 support_ndrive_r1_lb:1; | |
| 1556 | − u32 support_max_255lds:1; | |
| 1557 | − u32 support_fastpath_wb:1; | |
| 1558 | − u32 support_additional_msix:1; | |
| 1559 | − u32 support_fp_remote_lun:1; | |
| 1620 | + u32 reserved:19; | |
| 1621 | + u32 support_pd_map_target_id:1; | |
| 1622 | + u32 support_qd_throttling:1; | |
| 1623 | + u32 support_fp_rlbypass:1; | |
| 1624 | + u32 support_vfid_in_ioframe:1; | |
| 1625 | + u32 support_ext_io_size:1; | |
| 1626 | + u32 support_ext_queue_depth:1; | |
| 1627 | + u32 security_protocol_cmds_fw:1; | |
| 1628 | + u32 support_core_affinity:1; | |
| 1629 | + u32 support_ndrive_r1_lb:1; | |
| 1630 | + u32 support_max_255lds:1; | |
| 1631 | + u32 support_fastpath_wb:1; | |
| 1632 | + u32 support_additional_msix:1; | |
| 1633 | + u32 support_fp_remote_lun:1; | |
| 1560 | 1634 | #else |
| 1561 | − u32 support_fp_remote_lun:1; | |
| 1562 | − u32 support_additional_msix:1; | |
| 1563 | − u32 support_fastpath_wb:1; | |
| 1564 | − u32 support_max_255lds:1; | |
| 1565 | − u32 support_ndrive_r1_lb:1; | |
| 1566 | − u32 support_core_affinity:1; | |
| 1567 | − u32 security_protocol_cmds_fw:1; | |
| 1568 | − u32 support_ext_queue_depth:1; | |
| 1569 | − u32 support_ext_io_size:1; | |
| 1570 | − u32 support_vfid_in_ioframe:1; | |
| 1571 | − u32 support_fp_rlbypass:1; | |
| 1572 | − u32 support_qd_throttling:1; | |
| 1573 | − u32 reserved:20; | |
| 1635 | + u32 support_fp_remote_lun:1; | |
| 1636 | + u32 support_additional_msix:1; | |
| 1637 | + u32 support_fastpath_wb:1; | |
| 1638 | + u32 support_max_255lds:1; | |
| 1639 | + u32 support_ndrive_r1_lb:1; | |
| 1640 | + u32 support_core_affinity:1; | |
| 1641 | + u32 security_protocol_cmds_fw:1; | |
| 1642 | + u32 support_ext_queue_depth:1; | |
| 1643 | + u32 support_ext_io_size:1; | |
| 1644 | + u32 support_vfid_in_ioframe:1; | |
| 1645 | + u32 support_fp_rlbypass:1; | |
| 1646 | + u32 support_qd_throttling:1; | |
| 1647 | + u32 support_pd_map_target_id:1; | |
| 1648 | + u32 reserved:19; | |
| 1574 | 1649 | #endif |
| 1575 | 1650 | } mfi_capabilities; |
| 1576 | 1651 | __le32 reg; |
| @@ -1803,6 +1878,8 @@ union megasas_frame { · 226 unmodified lines | ||
| 1803 | 1878 | struct MR_PRIV_DEVICE { |
| 1804 | 1879 | bool is_tm_capable; |
| 1805 | 1880 | bool tm_busy; |
| 1881 | + atomic_t r1_ldio_hint; | |
| 1882 | + u8 interface_type; | |
| 1806 | 1883 | }; |
| 1807 | 1884 | struct megasas_cmd; |
| 1808 | 1885 | |
| @@ -1994,17 +2071,24 @@ struct MR_DRV_SYSTEM_INFO { · 185 unmodified lines | ||
| 1994 | 2071 | }; |
| 1995 | 2072 | |
| 1996 | 2073 | enum MR_PD_TYPE { |
| 1997 | − UNKNOWN_DRIVE = 0, | |
| 1998 | − PARALLEL_SCSI = 1, | |
| 1999 | − SAS_PD = 2, | |
| 2000 | − SATA_PD = 3, | |
| 2001 | − FC_PD = 4, | |
| 2074 | + UNKNOWN_DRIVE = 0, | |
| 2075 | + PARALLEL_SCSI = 1, | |
| 2076 | + SAS_PD = 2, | |
| 2077 | + SATA_PD = 3, | |
| 2078 | + FC_PD = 4, | |
| 2079 | + NVME_PD = 5, | |
| 2002 | 2080 | }; |
| 2003 | 2081 | |
| 2004 | 2082 | /* JBOD Queue depth definitions */ |
| 2005 | 2083 | #define MEGASAS_SATA_QD 32 |
| 2006 | 2084 | #define MEGASAS_SAS_QD 64 |
| 2007 | 2085 | #define MEGASAS_DEFAULT_PD_QD 64 |
| 2086 | +#define MEGASAS_NVME_QD 32 | |
| 2087 | + | |
| 2088 | +#define MR_DEFAULT_NVME_PAGE_SIZE 4096 | |
| 2089 | +#define MR_DEFAULT_NVME_PAGE_SHIFT 12 | |
| 2090 | +#define MR_DEFAULT_NVME_MDTS_KB 128 | |
| 2091 | +#define MR_NVME_PAGE_SIZE_MASK 0x000000FF | |
| 2008 | 2092 | |
| 2009 | 2093 | struct megasas_instance { |
| 2010 | 2094 | |
| @@ -2022,6 +2106,8 @@ struct megasas_instance { · 11 unmodified lines | ||
| 2022 | 2106 | dma_addr_t hb_host_mem_h; |
| 2023 | 2107 | struct MR_PD_INFO *pd_info; |
| 2024 | 2108 | dma_addr_t pd_info_h; |
| 2109 | + struct MR_TARGET_PROPERTIES *tgt_prop; | |
| 2110 | + dma_addr_t tgt_prop_h; | |
| 2025 | 2111 | |
| 2026 | 2112 | __le32 *reply_queue; |
| 2027 | 2113 | dma_addr_t reply_queue_h; |
| @@ -2039,6 +2125,7 @@ struct megasas_instance { · 11 unmodified lines | ||
| 2039 | 2125 | u32 crash_dump_drv_support; |
| 2040 | 2126 | u32 crash_dump_app_support; |
| 2041 | 2127 | u32 secure_jbod_support; |
| 2128 | + u32 support_morethan256jbod; /* FW support for more than 256 PD/JBOD */ | |
| 2042 | 2129 | bool use_seqnum_jbod_fp; /* Added for PD sequence */ |
| 2043 | 2130 | spinlock_t crashdump_lock; |
| 2044 | 2131 | |
| @@ -2051,6 +2138,7 @@ struct megasas_instance { · 6 unmodified lines | ||
| 2051 | 2138 | |
| 2052 | 2139 | u16 max_num_sge; |
| 2053 | 2140 | u16 max_fw_cmds; |
| 2141 | + u16 max_mpt_cmds; | |
| 2054 | 2142 | u16 max_mfi_cmds; |
| 2055 | 2143 | u16 max_scsi_cmds; |
| 2056 | 2144 | u16 ldio_threshold; |
| @@ -2065,6 +2153,7 @@ struct megasas_instance { · 8 unmodified lines | ||
| 2065 | 2153 | /* used to sync fire the cmd to fw */ |
| 2066 | 2154 | spinlock_t hba_lock; |
| 2067 | 2155 | /* used to synch producer, consumer ptrs in dpc */ |
| 2156 | + spinlock_t stream_lock; | |
| 2068 | 2157 | spinlock_t completion_lock; |
| 2069 | 2158 | struct dma_pool *frame_dma_pool; |
| 2070 | 2159 | struct dma_pool *sense_dma_pool; |
| @@ -2087,6 +2176,11 @@ struct megasas_instance { · 16 unmodified lines | ||
| 2087 | 2176 | atomic_t fw_outstanding; |
| 2088 | 2177 | atomic_t ldio_outstanding; |
| 2089 | 2178 | atomic_t fw_reset_no_pci_access; |
| 2179 | + atomic_t ieee_sgl; | |
| 2180 | + atomic_t prp_sgl; | |
| 2181 | + atomic_t sge_holes_type1; | |
| 2182 | + atomic_t sge_holes_type2; | |
| 2183 | + atomic_t sge_holes_type3; | |
| 2090 | 2184 | |
| 2091 | 2185 | struct megasas_instance_template *instancet; |
| 2092 | 2186 | struct tasklet_struct isr_tasklet; |
| @@ -2142,6 +2236,13 @@ struct megasas_instance { · 49 unmodified lines | ||
| 2142 | 2236 | u8 is_rdpq; |
| 2143 | 2237 | bool dev_handle; |
| 2144 | 2238 | bool fw_sync_cache_support; |
| 2239 | + u32 mfi_frame_size; | |
| 2240 | + bool is_ventura; | |
| 2241 | + bool msix_combined; | |
| 2242 | + u16 max_raid_mapsize; | |
| 2243 | + /* preffered count to send as LDIO irrspective of FP capable.*/ | |
| 2244 | + u8 r1_ldio_hint_default; | |
| 2245 | + u32 nvme_page_size; | |
| 2145 | 2246 | }; |
| 2146 | 2247 | struct MR_LD_VF_MAP { |
| 2147 | 2248 | u32 size; |
| @@ -2230,12 +2331,12 @@ struct megasas_instance_template { · 82 unmodified lines | ||
| 2230 | 2331 | u32 (*init_adapter)(struct megasas_instance *); |
| 2231 | 2332 | u32 (*build_and_issue_cmd) (struct megasas_instance *, |
| 2232 | 2333 | struct scsi_cmnd *); |
| 2233 | − int (*issue_dcmd)(struct megasas_instance *instance, | |
| 2334 | + void (*issue_dcmd)(struct megasas_instance *instance, | |
| 2234 | 2335 | struct megasas_cmd *cmd); |
| 2235 | 2336 | }; |
| 2236 | 2337 | |
| 2237 | −#define MEGASAS_IS_LOGICAL(scp) \ | |
| 2238 | − ((scp->device->channel < MEGASAS_MAX_PD_CHANNELS) ? 0 : 1) | |
| 2338 | +#define MEGASAS_IS_LOGICAL(sdev) \ | |
| 2339 | + ((sdev->channel < MEGASAS_MAX_PD_CHANNELS) ? 0 : 1) | |
| 2239 | 2340 | |
| 2240 | 2341 | #define MEGASAS_DEV_INDEX(scp) \ |
| 2241 | 2342 | (((scp->device->channel % 2) * MEGASAS_MAX_DEV_PER_CHANNEL) + \ |
| @@ -2346,7 +2447,7 @@ MR_BuildRaidContext(struct megasas_instance *instance, · 104 unmodified lines | ||
| 2346 | 2447 | struct IO_REQUEST_INFO *io_info, |
| 2347 | 2448 | struct RAID_CONTEXT *pRAID_Context, |
| 2348 | 2449 | struct MR_DRV_RAID_MAP_ALL *map, u8 **raidLUN); |
| 2349 | −u8 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_DRV_RAID_MAP_ALL *map); | |
| 2450 | +u16 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_DRV_RAID_MAP_ALL *map); | |
| 2350 | 2451 | struct MR_LD_RAID *MR_LdRaidGet(u32 ld, struct MR_DRV_RAID_MAP_ALL *map); |
| 2351 | 2452 | u16 MR_ArPdGet(u32 ar, u32 arm, struct MR_DRV_RAID_MAP_ALL *map); |
| 2352 | 2453 | u16 MR_LdSpanArrayGet(u32 ld, u32 span, struct MR_DRV_RAID_MAP_ALL *map); |
| @@ -2354,13 +2455,16 @@ __le16 MR_PdDevHandleGet(u32 pd, struct MR_DRV_RAID_MAP_ALL *map); · 1 unmodified line | ||
| 2354 | 2455 | u16 MR_GetLDTgtId(u32 ld, struct MR_DRV_RAID_MAP_ALL *map); |
| 2355 | 2456 | |
| 2356 | 2457 | __le16 get_updated_dev_handle(struct megasas_instance *instance, |
| 2357 | − struct LD_LOAD_BALANCE_INFO *lbInfo, struct IO_REQUEST_INFO *in_info); | |
| 2458 | + struct LD_LOAD_BALANCE_INFO *lbInfo, | |
| 2459 | + struct IO_REQUEST_INFO *in_info, | |
| 2460 | + struct MR_DRV_RAID_MAP_ALL *drv_map); | |
| 2358 | 2461 | void mr_update_load_balance_params(struct MR_DRV_RAID_MAP_ALL *map, |
| 2359 | 2462 | struct LD_LOAD_BALANCE_INFO *lbInfo); |
| 2360 | 2463 | int megasas_get_ctrl_info(struct megasas_instance *instance); |
| 2361 | 2464 | /* PD sequence */ |
| 2362 | 2465 | int |
| 2363 | 2466 | megasas_sync_pd_seq_num(struct megasas_instance *instance, bool pend); |
| 2467 | +void megasas_set_dynamic_target_properties(struct scsi_device *sdev); | |
| 2364 | 2468 | int megasas_set_crash_dump_params(struct megasas_instance *instance, |
| 2365 | 2469 | u8 crash_buf_state); |
| 2366 | 2470 | void megasas_free_host_crash_buffer(struct megasas_instance *instance); |
| @@ -2382,4 +2486,7 @@ void megasas_update_sdev_properties(struct scsi_device *sdev); · 15 unmodified lines | ||
| 2382 | 2486 | int megasas_reset_fusion(struct Scsi_Host *shost, int reason); |
| 2383 | 2487 | int megasas_task_abort_fusion(struct scsi_cmnd *scmd); |
| 2384 | 2488 | int megasas_reset_target_fusion(struct scsi_cmnd *scmd); |
| 2489 | +u32 mega_mod64(u64 dividend, u32 divisor); | |
| 2490 | +int megasas_alloc_fusion_context(struct megasas_instance *instance); | |
| 2491 | +void megasas_free_fusion_context(struct megasas_instance *instance); | |
| 2385 | 2492 | #endif /*LSI_MEGARAID_SAS_H */ |
| @@ -43,6 +43,7 @@ · 42 unmodified lines | ||
| 43 | 43 | #include <linux/uio.h> |
| 44 | 44 | #include <linux/slab.h> |
| 45 | 45 | #include <linux/uaccess.h> |
| 46 | +#include <asm/unaligned.h> | |
| 46 | 47 | #include <linux/fs.h> |
| 47 | 48 | #include <linux/compat.h> |
| 48 | 49 | #include <linux/blkdev.h> |
| @@ -116,8 +117,10 @@ static int megasas_ld_list_query(struct megasas_instance *instance, · 67 unmodified lines | ||
| 116 | 117 | static int megasas_issue_init_mfi(struct megasas_instance *instance); |
| 117 | 118 | static int megasas_register_aen(struct megasas_instance *instance, |
| 118 | 119 | u32 seq_num, u32 class_locale_word); |
| 119 | −static int | |
| 120 | −megasas_get_pd_info(struct megasas_instance *instance, u16 device_id); | |
| 120 | +static void megasas_get_pd_info(struct megasas_instance *instance, | |
| 121 | + struct scsi_device *sdev); | |
| 122 | +static int megasas_get_target_prop(struct megasas_instance *instance, | |
| 123 | + struct scsi_device *sdev); | |
| 121 | 124 | /* |
| 122 | 125 | * PCI ID table for all supported controllers |
| 123 | 126 | */ |
| @@ -155,6 +158,12 @@ static struct pci_device_id megasas_pci_table[] = { · 31 unmodified lines | ||
| 155 | 158 | /* Intruder 24 port*/ |
| 156 | 159 | {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_CUTLASS_52)}, |
| 157 | 160 | {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_CUTLASS_53)}, |
| 161 | + /* VENTURA */ | |
| 162 | + {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_VENTURA)}, | |
| 163 | + {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_HARPOON)}, | |
| 164 | + {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_TOMCAT)}, | |
| 165 | + {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_VENTURA_4PORT)}, | |
| 166 | + {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_CRUSADER_4PORT)}, | |
| 158 | 167 | {} |
| 159 | 168 | }; |
| 160 | 169 | |
| @@ -196,12 +205,12 @@ void megasas_fusion_ocr_wq(struct work_struct *work); · 35 unmodified lines | ||
| 196 | 205 | static int megasas_get_ld_vf_affiliation(struct megasas_instance *instance, |
| 197 | 206 | int initial); |
| 198 | 207 | |
| 199 | −int | |
| 208 | +void | |
| 200 | 209 | megasas_issue_dcmd(struct megasas_instance *instance, struct megasas_cmd *cmd) |
| 201 | 210 | { |
| 202 | 211 | instance->instancet->fire_cmd(instance, |
| 203 | 212 | cmd->frame_phys_addr, 0, instance->reg_set); |
| 204 | − return 0; | |
| 213 | + return; | |
| 205 | 214 | } |
| 206 | 215 | |
| 207 | 216 | /** |
| @@ -259,6 +268,8 @@ megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd) · 51 unmodified lines | ||
| 259 | 268 | cmd->scmd = NULL; |
| 260 | 269 | cmd->frame_count = 0; |
| 261 | 270 | cmd->flags = 0; |
| 271 | + memset(cmd->frame, 0, instance->mfi_frame_size); | |
| 272 | + cmd->frame->io.context = cpu_to_le32(cmd->index); | |
| 262 | 273 | if (!fusion && reset_devices) |
| 263 | 274 | cmd->frame->hdr.cmd = MFI_CMD_INVALID; |
| 264 | 275 | list_add(&cmd->list, (&instance->cmd_pool)->next); |
| @@ -989,13 +1000,14 @@ megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd) · 724 unmodified lines | ||
| 989 | 1000 | frame_hdr->cmd_status = MFI_STAT_INVALID_STATUS; |
| 990 | 1001 | frame_hdr->flags |= cpu_to_le16(MFI_FRAME_DONT_POST_IN_REPLY_QUEUE); |
| 991 | 1002 | |
| 992 | − if ((atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR) || | |
| 993 | − (instance->instancet->issue_dcmd(instance, cmd))) { | |
| 1003 | + if (atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR) { | |
| 994 | 1004 | dev_err(&instance->pdev->dev, "Failed from %s %d\n", |
| 995 | 1005 | __func__, __LINE__); |
| 996 | 1006 | return DCMD_NOT_FIRED; |
| 997 | 1007 | } |
| 998 | 1008 | |
| 1009 | + instance->instancet->issue_dcmd(instance, cmd); | |
| 1010 | + | |
| 999 | 1011 | return wait_and_poll(instance, cmd, instance->requestorId ? |
| 1000 | 1012 | MEGASAS_ROUTINE_WAIT_TIME_VF : MFI_IO_TIMEOUT_SECS); |
| 1001 | 1013 | } |
| @@ -1017,13 +1029,14 @@ megasas_issue_blocked_cmd(struct megasas_instance *instance, · 15 unmodified lines | ||
| 1017 | 1029 | int ret = 0; |
| 1018 | 1030 | cmd->cmd_status_drv = MFI_STAT_INVALID_STATUS; |
| 1019 | 1031 | |
| 1020 | − if ((atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR) || | |
| 1021 | − (instance->instancet->issue_dcmd(instance, cmd))) { | |
| 1032 | + if (atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR) { | |
| 1022 | 1033 | dev_err(&instance->pdev->dev, "Failed from %s %d\n", |
| 1023 | 1034 | __func__, __LINE__); |
| 1024 | 1035 | return DCMD_NOT_FIRED; |
| 1025 | 1036 | } |
| 1026 | 1037 | |
| 1038 | + instance->instancet->issue_dcmd(instance, cmd); | |
| 1039 | + | |
| 1027 | 1040 | if (timeout) { |
| 1028 | 1041 | ret = wait_event_timeout(instance->int_cmd_wait_q, |
| 1029 | 1042 | cmd->cmd_status_drv != MFI_STAT_INVALID_STATUS, timeout * HZ); |
| @@ -1081,13 +1094,14 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance, · 51 unmodified lines | ||
| 1081 | 1094 | cmd->sync_cmd = 1; |
| 1082 | 1095 | cmd->cmd_status_drv = MFI_STAT_INVALID_STATUS; |
| 1083 | 1096 | |
| 1084 | − if ((atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR) || | |
| 1085 | − (instance->instancet->issue_dcmd(instance, cmd))) { | |
| 1097 | + if (atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR) { | |
| 1086 | 1098 | dev_err(&instance->pdev->dev, "Failed from %s %d\n", |
| 1087 | 1099 | __func__, __LINE__); |
| 1088 | 1100 | return DCMD_NOT_FIRED; |
| 1089 | 1101 | } |
| 1090 | 1102 | |
| 1103 | + instance->instancet->issue_dcmd(instance, cmd); | |
| 1104 | + | |
| 1091 | 1105 | if (timeout) { |
| 1092 | 1106 | ret = wait_event_timeout(instance->abort_cmd_wait_q, |
| 1093 | 1107 | cmd->cmd_status_drv != MFI_STAT_INVALID_STATUS, timeout * HZ); |
| @@ -1273,7 +1287,7 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, · 179 unmodified lines | ||
| 1273 | 1287 | u16 flags = 0; |
| 1274 | 1288 | struct megasas_pthru_frame *pthru; |
| 1275 | 1289 | |
| 1276 | − is_logical = MEGASAS_IS_LOGICAL(scp); | |
| 1290 | + is_logical = MEGASAS_IS_LOGICAL(scp->device); | |
| 1277 | 1291 | device_id = MEGASAS_DEV_INDEX(scp); |
| 1278 | 1292 | pthru = (struct megasas_pthru_frame *)cmd->frame; |
| 1279 | 1293 | |
| @@ -1513,11 +1527,11 @@ inline int megasas_cmd_type(struct scsi_cmnd *cmd) · 233 unmodified lines | ||
| 1513 | 1527 | case WRITE_6: |
| 1514 | 1528 | case READ_16: |
| 1515 | 1529 | case WRITE_16: |
| 1516 | − ret = (MEGASAS_IS_LOGICAL(cmd)) ? | |
| 1530 | + ret = (MEGASAS_IS_LOGICAL(cmd->device)) ? | |
| 1517 | 1531 | READ_WRITE_LDIO : READ_WRITE_SYSPDIO; |
| 1518 | 1532 | break; |
| 1519 | 1533 | default: |
| 1520 | − ret = (MEGASAS_IS_LOGICAL(cmd)) ? | |
| 1534 | + ret = (MEGASAS_IS_LOGICAL(cmd->device)) ? | |
| 1521 | 1535 | NON_READ_WRITE_LDIO : NON_READ_WRITE_SYSPDIO; |
| 1522 | 1536 | } |
| 1523 | 1537 | return ret; |
| @@ -1537,7 +1551,7 @@ megasas_dump_pending_frames(struct megasas_instance *instance) · 13 unmodified lines | ||
| 1537 | 1551 | struct megasas_io_frame *ldio; |
| 1538 | 1552 | struct megasas_pthru_frame *pthru; |
| 1539 | 1553 | u32 sgcount; |
| 1540 | − u32 max_cmd = instance->max_fw_cmds; | |
| 1554 | + u16 max_cmd = instance->max_fw_cmds; | |
| 1541 | 1555 | |
| 1542 | 1556 | dev_err(&instance->pdev->dev, "[%d]: Dumping Frame Phys Address of all pending cmds in FW\n",instance->host->host_no); |
| 1543 | 1557 | dev_err(&instance->pdev->dev, "[%d]: Total OS Pending cmds : %d\n",instance->host->host_no,atomic_read(&instance->fw_outstanding)); |
| @@ -1662,7 +1676,7 @@ megasas_queue_command(struct Scsi_Host *shost, struct scsi_cmnd *scmd) · 118 unmodified lines | ||
| 1662 | 1676 | /* Check for an mpio path and adjust behavior */ |
| 1663 | 1677 | if (atomic_read(&instance->adprecovery) == MEGASAS_ADPRESET_SM_INFAULT) { |
| 1664 | 1678 | if (megasas_check_mpio_paths(instance, scmd) == |
| 1665 | − (DID_RESET << 16)) { | |
| 1679 | + (DID_REQUEUE << 16)) { | |
| 1666 | 1680 | return SCSI_MLQUEUE_HOST_BUSY; |
| 1667 | 1681 | } else { |
| 1668 | 1682 | scmd->result = DID_NO_CONNECT << 16; |
| @@ -1693,15 +1707,16 @@ megasas_queue_command(struct Scsi_Host *shost, struct scsi_cmnd *scmd) · 24 unmodified lines | ||
| 1693 | 1707 | |
| 1694 | 1708 | scmd->result = 0; |
| 1695 | 1709 | |
| 1696 | − if (MEGASAS_IS_LOGICAL(scmd) && | |
| 1710 | + if (MEGASAS_IS_LOGICAL(scmd->device) && | |
| 1697 | 1711 | (scmd->device->id >= instance->fw_supported_vd_count || |
| 1698 | 1712 | scmd->device->lun)) { |
| 1699 | 1713 | scmd->result = DID_BAD_TARGET << 16; |
| 1700 | 1714 | goto out_done; |
| 1701 | 1715 | } |
| 1702 | 1716 | |
| 1703 | − if ((scmd->cmnd[0] == SYNCHRONIZE_CACHE) && MEGASAS_IS_LOGICAL(scmd) && | |
| 1704 | − (!instance->fw_sync_cache_support)) { | |
| 1717 | + if ((scmd->cmnd[0] == SYNCHRONIZE_CACHE) && | |
| 1718 | + MEGASAS_IS_LOGICAL(scmd->device) && | |
| 1719 | + (!instance->fw_sync_cache_support)) { | |
| 1705 | 1720 | scmd->result = DID_OK << 16; |
| 1706 | 1721 | goto out_done; |
| 1707 | 1722 | } |
| @@ -1728,16 +1743,21 @@ static struct megasas_instance *megasas_lookup_instance(u16 host_no) · 20 unmodified lines | ||
| 1728 | 1743 | } |
| 1729 | 1744 | |
| 1730 | 1745 | /* |
| 1731 | −* megasas_update_sdev_properties - Update sdev structure based on controller's FW capabilities | |
| 1746 | +* megasas_set_dynamic_target_properties - | |
| 1747 | +* Device property set by driver may not be static and it is required to be | |
| 1748 | +* updated after OCR | |
| 1749 | +* | |
| 1750 | +* set tm_capable. | |
| 1751 | +* set dma alignment (only for eedp protection enable vd). | |
| 1732 | 1752 | * |
| 1733 | 1753 | * @sdev: OS provided scsi device |
| 1734 | 1754 | * |
| 1735 | 1755 | * Returns void |
| 1736 | 1756 | */ |
| 1737 | −void megasas_update_sdev_properties(struct scsi_device *sdev) | |
| 1757 | +void megasas_set_dynamic_target_properties(struct scsi_device *sdev) | |
| 1738 | 1758 | { |
| 1739 | − u16 pd_index = 0; | |
| 1740 | − u32 device_id, ld; | |
| 1759 | + u16 pd_index = 0, ld; | |
| 1760 | + u32 device_id; | |
| 1741 | 1761 | struct megasas_instance *instance; |
| 1742 | 1762 | struct fusion_context *fusion; |
| 1743 | 1763 | struct MR_PRIV_DEVICE *mr_device_priv_data; |
| @@ -1749,67 +1769,129 @@ void megasas_update_sdev_properties(struct scsi_device *sdev) · 5 unmodified lines | ||
| 1749 | 1769 | fusion = instance->ctrl_context; |
| 1750 | 1770 | mr_device_priv_data = sdev->hostdata; |
| 1751 | 1771 | |
| 1752 | − if (!fusion) | |
| 1772 | + if (!fusion || !mr_device_priv_data) | |
| 1753 | 1773 | return; |
| 1754 | 1774 | |
| 1755 | − if (sdev->channel < MEGASAS_MAX_PD_CHANNELS && | |
| 1756 | − instance->use_seqnum_jbod_fp) { | |
| 1757 | − pd_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + | |
| 1758 | − sdev->id; | |
| 1759 | − pd_sync = (void *)fusion->pd_seq_sync | |
| 1760 | − [(instance->pd_seq_map_id - 1) & 1]; | |
| 1761 | − mr_device_priv_data->is_tm_capable = | |
| 1762 | − pd_sync->seq[pd_index].capability.tmCapable; | |
| 1763 | − } else { | |
| 1775 | + if (MEGASAS_IS_LOGICAL(sdev)) { | |
| 1764 | 1776 | device_id = ((sdev->channel % 2) * MEGASAS_MAX_DEV_PER_CHANNEL) |
| 1765 | 1777 | + sdev->id; |
| 1766 | 1778 | local_map_ptr = fusion->ld_drv_map[(instance->map_id & 1)]; |
| 1767 | 1779 | ld = MR_TargetIdToLdGet(device_id, local_map_ptr); |
| 1780 | + if (ld >= instance->fw_supported_vd_count) | |
| 1781 | + return; | |
| 1768 | 1782 | raid = MR_LdRaidGet(ld, local_map_ptr); |
| 1769 | 1783 | |
| 1770 | 1784 | if (raid->capability.ldPiMode == MR_PROT_INFO_TYPE_CONTROLLER) |
| 1771 | 1785 | blk_queue_update_dma_alignment(sdev->request_queue, 0x7); |
| 1786 | + | |
| 1772 | 1787 | mr_device_priv_data->is_tm_capable = |
| 1773 | 1788 | raid->capability.tmCapable; |
| 1789 | + } else if (instance->use_seqnum_jbod_fp) { | |
| 1790 | + pd_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + | |
| 1791 | + sdev->id; | |
| 1792 | + pd_sync = (void *)fusion->pd_seq_sync | |
| 1793 | + [(instance->pd_seq_map_id - 1) & 1]; | |
| 1794 | + mr_device_priv_data->is_tm_capable = | |
| 1795 | + pd_sync->seq[pd_index].capability.tmCapable; | |
| 1774 | 1796 | } |
| 1775 | 1797 | } |
| 1776 | 1798 | |
| 1777 | −static void megasas_set_device_queue_depth(struct scsi_device *sdev) | |
| 1799 | +/* | |
| 1800 | + * megasas_set_nvme_device_properties - | |
| 1801 | + * set nomerges=2 | |
| 1802 | + * set virtual page boundary = 4K (current mr_nvme_pg_size is 4K). | |
| 1803 | + * set maximum io transfer = MDTS of NVME device provided by MR firmware. | |
| 1804 | + * | |
| 1805 | + * MR firmware provides value in KB. Caller of this function converts | |
| 1806 | + * kb into bytes. | |
| 1807 | + * | |
| 1808 | + * e.a MDTS=5 means 2^5 * nvme page size. (In case of 4K page size, | |
| 1809 | + * MR firmware provides value 128 as (32 * 4K) = 128K. | |
| 1810 | + * | |
| 1811 | + * @sdev: scsi device | |
| 1812 | + * @max_io_size: maximum io transfer size | |
| 1813 | + * | |
| 1814 | + */ | |
| 1815 | +static inline void | |
| 1816 | +megasas_set_nvme_device_properties(struct scsi_device *sdev, u32 max_io_size) | |
| 1778 | 1817 | { |
| 1779 | − u16 pd_index = 0; | |
| 1780 | − int ret = DCMD_FAILED; | |
| 1781 | 1818 | struct megasas_instance *instance; |
| 1819 | + u32 mr_nvme_pg_size; | |
| 1782 | 1820 | |
| 1783 | − instance = megasas_lookup_instance(sdev->host->host_no); | |
| 1821 | + instance = (struct megasas_instance *)sdev->host->hostdata; | |
| 1822 | + mr_nvme_pg_size = max_t(u32, instance->nvme_page_size, | |
| 1823 | + MR_DEFAULT_NVME_PAGE_SIZE); | |
| 1784 | 1824 | |
| 1785 | − if (sdev->channel < MEGASAS_MAX_PD_CHANNELS) { | |
| 1786 | − pd_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + sdev->id; | |
| 1825 | + blk_queue_max_hw_sectors(sdev->request_queue, (max_io_size / 512)); | |
| 1787 | 1826 | |
| 1788 | − if (instance->pd_info) { | |
| 1789 | − mutex_lock(&instance->hba_mutex); | |
| 1790 | − ret = megasas_get_pd_info(instance, pd_index); | |
| 1791 | − mutex_unlock(&instance->hba_mutex); | |
| 1792 | − } | |
| 1827 | + queue_flag_set_unlocked(QUEUE_FLAG_NOMERGES, sdev->request_queue); | |
| 1828 | + blk_queue_virt_boundary(sdev->request_queue, mr_nvme_pg_size - 1); | |
| 1829 | +} | |
| 1793 | 1830 | |
| 1794 | − if (ret != DCMD_SUCCESS) | |
| 1795 | − return; | |
| 1796 | 1831 | |
| 1797 | − if (instance->pd_list[pd_index].driveState == MR_PD_STATE_SYSTEM) { | |
| 1832 | +/* | |
| 1833 | + * megasas_set_static_target_properties - | |
| 1834 | + * Device property set by driver are static and it is not required to be | |
| 1835 | + * updated after OCR. | |
| 1836 | + * | |
| 1837 | + * set io timeout | |
| 1838 | + * set device queue depth | |
| 1839 | + * set nvme device properties. see - megasas_set_nvme_device_properties | |
| 1840 | + * | |
| 1841 | + * @sdev: scsi device | |
| 1842 | + * @is_target_prop true, if fw provided target properties. | |
| 1843 | + */ | |
| 1844 | +static void megasas_set_static_target_properties(struct scsi_device *sdev, | |
| 1845 | + bool is_target_prop) | |
| 1846 | +{ | |
| 1847 | + u16 target_index = 0; | |
| 1848 | + u8 interface_type; | |
| 1849 | + u32 device_qd = MEGASAS_DEFAULT_CMD_PER_LUN; | |
| 1850 | + u32 max_io_size_kb = MR_DEFAULT_NVME_MDTS_KB; | |
| 1851 | + u32 tgt_device_qd; | |
| 1852 | + struct megasas_instance *instance; | |
| 1853 | + struct MR_PRIV_DEVICE *mr_device_priv_data; | |
| 1798 | 1854 | |
| 1799 | − switch (instance->pd_list[pd_index].interface) { | |
| 1800 | − case SAS_PD: | |
| 1801 | − scsi_change_queue_depth(sdev, MEGASAS_SAS_QD); | |
| 1802 | − break; | |
| 1855 | + instance = megasas_lookup_instance(sdev->host->host_no); | |
| 1856 | + mr_device_priv_data = sdev->hostdata; | |
| 1857 | + interface_type = mr_device_priv_data->interface_type; | |
| 1803 | 1858 | |
| 1804 | − case SATA_PD: | |
| 1805 | − scsi_change_queue_depth(sdev, MEGASAS_SATA_QD); | |
| 1806 | − break; | |
| 1859 | + /* | |
| 1860 | + * The RAID firmware may require extended timeouts. | |
| 1861 | + */ | |
| 1862 | + blk_queue_rq_timeout(sdev->request_queue, scmd_timeout * HZ); | |
| 1807 | 1863 | |
| 1808 | − default: | |
| 1809 | − scsi_change_queue_depth(sdev, MEGASAS_DEFAULT_PD_QD); | |
| 1810 | − } | |
| 1811 | − } | |
| 1864 | + target_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + sdev->id; | |
| 1865 | + | |
| 1866 | + switch (interface_type) { | |
| 1867 | + case SAS_PD: | |
| 1868 | + device_qd = MEGASAS_SAS_QD; | |
| 1869 | + break; | |
| 1870 | + case SATA_PD: | |
| 1871 | + device_qd = MEGASAS_SATA_QD; | |
| 1872 | + break; | |
| 1873 | + case NVME_PD: | |
| 1874 | + device_qd = MEGASAS_NVME_QD; | |
| 1875 | + break; | |
| 1876 | + } | |
| 1877 | + | |
| 1878 | + if (is_target_prop) { | |
| 1879 | + tgt_device_qd = le32_to_cpu(instance->tgt_prop->device_qdepth); | |
| 1880 | + if (tgt_device_qd && | |
| 1881 | + (tgt_device_qd <= instance->host->can_queue)) | |
| 1882 | + device_qd = tgt_device_qd; | |
| 1883 | + | |
| 1884 | + /* max_io_size_kb will be set to non zero for | |
| 1885 | + * nvme based vd and syspd. | |
| 1886 | + */ | |
| 1887 | + max_io_size_kb = le32_to_cpu(instance->tgt_prop->max_io_size_kb); | |
| 1812 | 1888 | } |
| 1889 | + | |
| 1890 | + if (instance->nvme_page_size && max_io_size_kb) | |
| 1891 | + megasas_set_nvme_device_properties(sdev, (max_io_size_kb << 10)); | |
| 1892 | + | |
| 1893 | + scsi_change_queue_depth(sdev, device_qd); | |
| 1894 | + | |
| 1813 | 1895 | } |
| 1814 | 1896 | |
| 1815 | 1897 | |
| @@ -1817,11 +1899,12 @@ static int megasas_slave_configure(struct scsi_device *sdev) · 1 unmodified line | ||
| 1817 | 1899 | { |
| 1818 | 1900 | u16 pd_index = 0; |
| 1819 | 1901 | struct megasas_instance *instance; |
| 1902 | + int ret_target_prop = DCMD_FAILED; | |
| 1903 | + bool is_target_prop = false; | |
| 1820 | 1904 | |
| 1821 | 1905 | instance = megasas_lookup_instance(sdev->host->host_no); |
| 1822 | 1906 | if (instance->pd_list_not_supported) { |
| 1823 | − if (sdev->channel < MEGASAS_MAX_PD_CHANNELS && | |
| 1824 | − sdev->type == TYPE_DISK) { | |
| 1907 | + if (!MEGASAS_IS_LOGICAL(sdev) && sdev->type == TYPE_DISK) { | |
| 1825 | 1908 | pd_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + |
| 1826 | 1909 | sdev->id; |
| 1827 | 1910 | if (instance->pd_list[pd_index].driveState != |
| @@ -1829,14 +1912,25 @@ static int megasas_slave_configure(struct scsi_device *sdev) · 1 unmodified line | ||
| 1829 | 1912 | return -ENXIO; |
| 1830 | 1913 | } |
| 1831 | 1914 | } |
| 1832 | − megasas_set_device_queue_depth(sdev); | |
| 1833 | − megasas_update_sdev_properties(sdev); | |
| 1834 | 1915 | |
| 1835 | − /* | |
| 1836 | − * The RAID firmware may require extended timeouts. | |
| 1916 | + mutex_lock(&instance->hba_mutex); | |
| 1917 | + /* Send DCMD to Firmware and cache the information */ | |
| 1918 | + if ((instance->pd_info) && !MEGASAS_IS_LOGICAL(sdev)) | |
| 1919 | + megasas_get_pd_info(instance, sdev); | |
| 1920 | + | |
| 1921 | + /* Some ventura firmware may not have instance->nvme_page_size set. | |
| 1922 | + * Do not send MR_DCMD_DRV_GET_TARGET_PROP | |
| 1837 | 1923 | */ |
| 1838 | − blk_queue_rq_timeout(sdev->request_queue, | |
| 1839 | − scmd_timeout * HZ); | |
| 1924 | + if ((instance->tgt_prop) && (instance->nvme_page_size)) | |
| 1925 | + ret_target_prop = megasas_get_target_prop(instance, sdev); | |
| 1926 | + | |
| 1927 | + is_target_prop = (ret_target_prop == DCMD_SUCCESS) ? true : false; | |
| 1928 | + megasas_set_static_target_properties(sdev, is_target_prop); | |
| 1929 | + | |
| 1930 | + mutex_unlock(&instance->hba_mutex); | |
| 1931 | + | |
| 1932 | + /* This sdev property may change post OCR */ | |
| 1933 | + megasas_set_dynamic_target_properties(sdev); | |
| 1840 | 1934 | |
| 1841 | 1935 | return 0; |
| 1842 | 1936 | } |
| @@ -1848,7 +1942,7 @@ static int megasas_slave_alloc(struct scsi_device *sdev) · 5 unmodified lines | ||
| 1848 | 1942 | struct MR_PRIV_DEVICE *mr_device_priv_data; |
| 1849 | 1943 | |
| 1850 | 1944 | instance = megasas_lookup_instance(sdev->host->host_no); |
| 1851 | − if (sdev->channel < MEGASAS_MAX_PD_CHANNELS) { | |
| 1945 | + if (!MEGASAS_IS_LOGICAL(sdev)) { | |
| 1852 | 1946 | /* |
| 1853 | 1947 | * Open the OS scan to the SYSTEM PD |
| 1854 | 1948 | */ |
| @@ -2483,7 +2577,7 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance) · 628 unmodified lines | ||
| 2483 | 2577 | struct megasas_cmd, list); |
| 2484 | 2578 | list_del_init(&reset_cmd->list); |
| 2485 | 2579 | if (reset_cmd->scmd) { |
| 2486 | − reset_cmd->scmd->result = DID_RESET << 16; | |
| 2580 | + reset_cmd->scmd->result = DID_REQUEUE << 16; | |
| 2487 | 2581 | dev_notice(&instance->pdev->dev, "%d:%p reset [%02x]\n", |
| 2488 | 2582 | reset_index, reset_cmd, |
| 2489 | 2583 | reset_cmd->scmd->cmnd[0]); |
| @@ -2650,6 +2744,24 @@ blk_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd) · 160 unmodified lines | ||
| 2650 | 2744 | return BLK_EH_RESET_TIMER; |
| 2651 | 2745 | } |
| 2652 | 2746 | |
| 2747 | +/** | |
| 2748 | + * megasas_dump_frame - This function will dump MPT/MFI frame | |
| 2749 | + */ | |
| 2750 | +static inline void | |
| 2751 | +megasas_dump_frame(void *mpi_request, int sz) | |
| 2752 | +{ | |
| 2753 | + int i; | |
| 2754 | + __le32 *mfp = (__le32 *)mpi_request; | |
| 2755 | + | |
| 2756 | + printk(KERN_INFO "IO request frame:\n\t"); | |
| 2757 | + for (i = 0; i < sz / sizeof(__le32); i++) { | |
| 2758 | + if (i && ((i % 8) == 0)) | |
| 2759 | + printk("\n\t"); | |
| 2760 | + printk("%08x ", le32_to_cpu(mfp[i])); | |
| 2761 | + } | |
| 2762 | + printk("\n"); | |
| 2763 | +} | |
| 2764 | + | |
| 2653 | 2765 | /** |
| 2654 | 2766 | * megasas_reset_bus_host - Bus & host reset handler entry point |
| 2655 | 2767 | */ |
| @@ -2660,12 +2772,26 @@ static int megasas_reset_bus_host(struct scsi_cmnd *scmd) · 4 unmodified lines | ||
| 2660 | 2772 | |
| 2661 | 2773 | instance = (struct megasas_instance *)scmd->device->host->hostdata; |
| 2662 | 2774 | |
| 2775 | + scmd_printk(KERN_INFO, scmd, | |
| 2776 | + "Controller reset is requested due to IO timeout\n" | |
| 2777 | + "SCSI command pointer: (%p)\t SCSI host state: %d\t" | |
| 2778 | + " SCSI host busy: %d\t FW outstanding: %d\n", | |
| 2779 | + scmd, scmd->device->host->shost_state, | |
| 2780 | + atomic_read((atomic_t *)&scmd->device->host->host_busy), | |
| 2781 | + atomic_read(&instance->fw_outstanding)); | |
| 2782 | + | |
| 2663 | 2783 | /* |
| 2664 | 2784 | * First wait for all commands to complete |
| 2665 | 2785 | */ |
| 2666 | − if (instance->ctrl_context) | |
| 2667 | − ret = megasas_reset_fusion(scmd->device->host, 1); | |
| 2668 | − else | |
| 2786 | + if (instance->ctrl_context) { | |
| 2787 | + struct megasas_cmd_fusion *cmd; | |
| 2788 | + cmd = (struct megasas_cmd_fusion *)scmd->SCp.ptr; | |
| 2789 | + if (cmd) | |
| 2790 | + megasas_dump_frame(cmd->io_request, | |
| 2791 | + sizeof(struct MPI2_RAID_SCSI_IO_REQUEST)); | |
| 2792 | + ret = megasas_reset_fusion(scmd->device->host, | |
| 2793 | + SCSIIO_TIMEOUT_OCR); | |
| 2794 | + } else | |
| 2669 | 2795 | ret = megasas_generic_reset(scmd); |
| 2670 | 2796 | |
| 2671 | 2797 | return ret; |
| @@ -3343,7 +3469,7 @@ megasas_internal_reset_defer_cmds(struct megasas_instance *instance) · 671 unmodified lines | ||
| 3343 | 3469 | { |
| 3344 | 3470 | struct megasas_cmd *cmd; |
| 3345 | 3471 | int i; |
| 3346 | − u32 max_cmd = instance->max_fw_cmds; | |
| 3472 | + u16 max_cmd = instance->max_fw_cmds; | |
| 3347 | 3473 | u32 defer_index; |
| 3348 | 3474 | unsigned long flags; |
| 3349 | 3475 | |
| @@ -3719,7 +3845,7 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr) · 369 unmodified lines | ||
| 3719 | 3845 | static void megasas_teardown_frame_pool(struct megasas_instance *instance) |
| 3720 | 3846 | { |
| 3721 | 3847 | int i; |
| 3722 | − u32 max_cmd = instance->max_mfi_cmds; | |
| 3848 | + u16 max_cmd = instance->max_mfi_cmds; | |
| 3723 | 3849 | struct megasas_cmd *cmd; |
| 3724 | 3850 | |
| 3725 | 3851 | if (!instance->frame_dma_pool) |
| @@ -3763,9 +3889,8 @@ static void megasas_teardown_frame_pool(struct megasas_instance *instance) · 37 unmodified lines | ||
| 3763 | 3889 | static int megasas_create_frame_pool(struct megasas_instance *instance) |
| 3764 | 3890 | { |
| 3765 | 3891 | int i; |
| 3766 | − u32 max_cmd; | |
| 3892 | + u16 max_cmd; | |
| 3767 | 3893 | u32 sge_sz; |
| 3768 | − u32 total_sz; | |
| 3769 | 3894 | u32 frame_count; |
| 3770 | 3895 | struct megasas_cmd *cmd; |
| 3771 | 3896 | |
| @@ -3793,12 +3918,13 @@ static int megasas_create_frame_pool(struct megasas_instance *instance) · 21 unmodified lines | ||
| 3793 | 3918 | * Total 192 byte (3 MFI frame of 64 byte) |
| 3794 | 3919 | */ |
| 3795 | 3920 | frame_count = instance->ctrl_context ? (3 + 1) : (15 + 1); |
| 3796 | − total_sz = MEGAMFI_FRAME_SIZE * frame_count; | |
| 3921 | + instance->mfi_frame_size = MEGAMFI_FRAME_SIZE * frame_count; | |
| 3797 | 3922 | /* |
| 3798 | 3923 | * Use DMA pool facility provided by PCI layer |
| 3799 | 3924 | */ |
| 3800 | 3925 | instance->frame_dma_pool = pci_pool_create("megasas frame pool", |
| 3801 | − instance->pdev, total_sz, 256, 0); | |
| 3926 | + instance->pdev, instance->mfi_frame_size, | |
| 3927 | + 256, 0); | |
| 3802 | 3928 | |
| 3803 | 3929 | if (!instance->frame_dma_pool) { |
| 3804 | 3930 | dev_printk(KERN_DEBUG, &instance->pdev->dev, "failed to setup frame pool\n"); |
| @@ -3842,7 +3968,7 @@ static int megasas_create_frame_pool(struct megasas_instance *instance) · 37 unmodified lines | ||
| 3842 | 3968 | return -ENOMEM; |
| 3843 | 3969 | } |
| 3844 | 3970 | |
| 3845 | − memset(cmd->frame, 0, total_sz); | |
| 3971 | + memset(cmd->frame, 0, instance->mfi_frame_size); | |
| 3846 | 3972 | cmd->frame->io.context = cpu_to_le32(cmd->index); |
| 3847 | 3973 | cmd->frame->io.pad_0 = 0; |
| 3848 | 3974 | if (!instance->ctrl_context && reset_devices) |
| @@ -3897,7 +4023,7 @@ int megasas_alloc_cmds(struct megasas_instance *instance) · 48 unmodified lines | ||
| 3897 | 4023 | { |
| 3898 | 4024 | int i; |
| 3899 | 4025 | int j; |
| 3900 | − u32 max_cmd; | |
| 4026 | + u16 max_cmd; | |
| 3901 | 4027 | struct megasas_cmd *cmd; |
| 3902 | 4028 | struct fusion_context *fusion; |
| 3903 | 4029 | |
| @@ -3974,18 +4100,22 @@ dcmd_timeout_ocr_possible(struct megasas_instance *instance) { · 70 unmodified lines | ||
| 3974 | 4100 | return INITIATE_OCR; |
| 3975 | 4101 | } |
| 3976 | 4102 | |
| 3977 | −static int | |
| 3978 | −megasas_get_pd_info(struct megasas_instance *instance, u16 device_id) | |
| 4103 | +static void | |
| 4104 | +megasas_get_pd_info(struct megasas_instance *instance, struct scsi_device *sdev) | |
| 3979 | 4105 | { |
| 3980 | 4106 | int ret; |
| 3981 | 4107 | struct megasas_cmd *cmd; |
| 3982 | 4108 | struct megasas_dcmd_frame *dcmd; |
| 3983 | 4109 | |
| 4110 | + struct MR_PRIV_DEVICE *mr_device_priv_data; | |
| 4111 | + u16 device_id = 0; | |
| 4112 | + | |
| 4113 | + device_id = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + sdev->id; | |
| 3984 | 4114 | cmd = megasas_get_cmd(instance); |
| 3985 | 4115 | |
| 3986 | 4116 | if (!cmd) { |
| 3987 | 4117 | dev_err(&instance->pdev->dev, "Failed to get cmd %s\n", __func__); |
| 3988 | − return -ENOMEM; | |
| 4118 | + return; | |
| 3989 | 4119 | } |
| 3990 | 4120 | |
| 3991 | 4121 | dcmd = &cmd->frame->dcmd; |
| @@ -4012,7 +4142,9 @@ megasas_get_pd_info(struct megasas_instance *instance, u16 device_id) · 20 unmodified lines | ||
| 4012 | 4142 | |
| 4013 | 4143 | switch (ret) { |
| 4014 | 4144 | case DCMD_SUCCESS: |
| 4015 | − instance->pd_list[device_id].interface = | |
| 4145 | + mr_device_priv_data = sdev->hostdata; | |
| 4146 | + le16_to_cpus((u16 *)&instance->pd_info->state.ddf.pdType); | |
| 4147 | + mr_device_priv_data->interface_type = | |
| 4016 | 4148 | instance->pd_info->state.ddf.pdType.intf; |
| 4017 | 4149 | break; |
| 4018 | 4150 | |
| @@ -4039,7 +4171,7 @@ megasas_get_pd_info(struct megasas_instance *instance, u16 device_id) · 20 unmodified lines | ||
| 4039 | 4171 | if (ret != DCMD_TIMEOUT) |
| 4040 | 4172 | megasas_return_cmd(instance, cmd); |
| 4041 | 4173 | |
| 4042 | − return ret; | |
| 4174 | + return; | |
| 4043 | 4175 | } |
| 4044 | 4176 | /* |
| 4045 | 4177 | * megasas_get_pd_list_info - Returns FW's pd_list structure |
| @@ -4418,8 +4550,7 @@ megasas_ld_list_query(struct megasas_instance *instance, u8 query_type) · 372 unmodified lines | ||
| 4418 | 4550 | static void megasas_update_ext_vd_details(struct megasas_instance *instance) |
| 4419 | 4551 | { |
| 4420 | 4552 | struct fusion_context *fusion; |
| 4421 | − u32 old_map_sz; | |
| 4422 | − u32 new_map_sz; | |
| 4553 | + u32 ventura_map_sz = 0; | |
| 4423 | 4554 | |
| 4424 | 4555 | fusion = instance->ctrl_context; |
| 4425 | 4556 | /* For MFI based controllers return dummy success */ |
| @@ -4449,21 +4580,27 @@ static void megasas_update_ext_vd_details(struct megasas_instance *instance) · 23 unmodified lines | ||
| 4449 | 4580 | instance->supportmax256vd ? "Extended VD(240 VD)firmware" : |
| 4450 | 4581 | "Legacy(64 VD) firmware"); |
| 4451 | 4582 | |
| 4452 | − old_map_sz = sizeof(struct MR_FW_RAID_MAP) + | |
| 4453 | − (sizeof(struct MR_LD_SPAN_MAP) * | |
| 4454 | − (instance->fw_supported_vd_count - 1)); | |
| 4455 | − new_map_sz = sizeof(struct MR_FW_RAID_MAP_EXT); | |
| 4456 | − fusion->drv_map_sz = sizeof(struct MR_DRV_RAID_MAP) + | |
| 4457 | − (sizeof(struct MR_LD_SPAN_MAP) * | |
| 4458 | − (instance->drv_supported_vd_count - 1)); | |
| 4459 | − | |
| 4460 | − fusion->max_map_sz = max(old_map_sz, new_map_sz); | |
| 4583 | + if (instance->max_raid_mapsize) { | |
| 4584 | + ventura_map_sz = instance->max_raid_mapsize * | |
| 4585 | + MR_MIN_MAP_SIZE; /* 64k */ | |
| 4586 | + fusion->current_map_sz = ventura_map_sz; | |
| 4587 | + fusion->max_map_sz = ventura_map_sz; | |
| 4588 | + } else { | |
| 4589 | + fusion->old_map_sz = sizeof(struct MR_FW_RAID_MAP) + | |
| 4590 | + (sizeof(struct MR_LD_SPAN_MAP) * | |
| 4591 | + (instance->fw_supported_vd_count - 1)); | |
| 4592 | + fusion->new_map_sz = sizeof(struct MR_FW_RAID_MAP_EXT); | |
| 4461 | 4593 | |
| 4594 | + fusion->max_map_sz = | |
| 4595 | + max(fusion->old_map_sz, fusion->new_map_sz); | |
| 4462 | 4596 | |
| 4463 | − if (instance->supportmax256vd) | |
| 4464 | − fusion->current_map_sz = new_map_sz; | |
| 4465 | − else | |
| 4466 | − fusion->current_map_sz = old_map_sz; | |
| 4597 | + if (instance->supportmax256vd) | |
| 4598 | + fusion->current_map_sz = fusion->new_map_sz; | |
| 4599 | + else | |
| 4600 | + fusion->current_map_sz = fusion->old_map_sz; | |
| 4601 | + } | |
| 4602 | + /* irrespective of FW raid maps, driver raid map is constant */ | |
| 4603 | + fusion->drv_map_sz = sizeof(struct MR_DRV_RAID_MAP_ALL); | |
| 4467 | 4604 | } |
| 4468 | 4605 | |
| 4469 | 4606 | /** |
| @@ -4533,6 +4670,7 @@ megasas_get_ctrl_info(struct megasas_instance *instance) · 63 unmodified lines | ||
| 4533 | 4670 | le32_to_cpus((u32 *)&ctrl_info->properties.OnOffProperties); |
| 4534 | 4671 | le32_to_cpus((u32 *)&ctrl_info->adapterOperations2); |
| 4535 | 4672 | le32_to_cpus((u32 *)&ctrl_info->adapterOperations3); |
| 4673 | + le16_to_cpus((u16 *)&ctrl_info->adapter_operations4); | |
| 4536 | 4674 | |
| 4537 | 4675 | /* Update the latest Ext VD info. |
| 4538 | 4676 | * From Init path, store current firmware details. |
| @@ -4542,6 +4680,8 @@ megasas_get_ctrl_info(struct megasas_instance *instance) · 3 unmodified lines | ||
| 4542 | 4680 | megasas_update_ext_vd_details(instance); |
| 4543 | 4681 | instance->use_seqnum_jbod_fp = |
| 4544 | 4682 | ctrl_info->adapterOperations3.useSeqNumJbodFP; |
| 4683 | + instance->support_morethan256jbod = | |
| 4684 | + ctrl_info->adapter_operations4.support_pd_map_target_id; | |
| 4545 | 4685 | |
| 4546 | 4686 | /*Check whether controller is iMR or MR */ |
| 4547 | 4687 | instance->is_imr = (ctrl_info->memory_size ? 0 : 1); |
| @@ -4989,13 +5129,13 @@ skip_alloc: · 441 unmodified lines | ||
| 4989 | 5129 | static int megasas_init_fw(struct megasas_instance *instance) |
| 4990 | 5130 | { |
| 4991 | 5131 | u32 max_sectors_1; |
| 4992 | − u32 max_sectors_2; | |
| 4993 | − u32 tmp_sectors, msix_enable, scratch_pad_2; | |
| 5132 | + u32 max_sectors_2, tmp_sectors, msix_enable; | |
| 5133 | + u32 scratch_pad_2, scratch_pad_3, scratch_pad_4; | |
| 4994 | 5134 | resource_size_t base_addr; |
| 4995 | 5135 | struct megasas_register_set __iomem *reg_set; |
| 4996 | 5136 | struct megasas_ctrl_info *ctrl_info = NULL; |
| 4997 | 5137 | unsigned long bar_list; |
| 4998 | − int i, loop, fw_msix_count = 0; | |
| 5138 | + int i, j, loop, fw_msix_count = 0; | |
| 4999 | 5139 | struct IOV_111 *iovPtr; |
| 5000 | 5140 | struct fusion_context *fusion; |
| 5001 | 5141 | |
| @@ -5020,34 +5160,29 @@ static int megasas_init_fw(struct megasas_instance *instance) · 18 unmodified lines | ||
| 5020 | 5160 | |
| 5021 | 5161 | reg_set = instance->reg_set; |
| 5022 | 5162 | |
| 5023 | − switch (instance->pdev->device) { | |
| 5024 | − case PCI_DEVICE_ID_LSI_FUSION: | |
| 5025 | − case PCI_DEVICE_ID_LSI_PLASMA: | |
| 5026 | − case PCI_DEVICE_ID_LSI_INVADER: | |
| 5027 | − case PCI_DEVICE_ID_LSI_FURY: | |
| 5028 | − case PCI_DEVICE_ID_LSI_INTRUDER: | |
| 5029 | − case PCI_DEVICE_ID_LSI_INTRUDER_24: | |
| 5030 | − case PCI_DEVICE_ID_LSI_CUTLASS_52: | |
| 5031 | − case PCI_DEVICE_ID_LSI_CUTLASS_53: | |
| 5163 | + if (fusion) | |
| 5032 | 5164 | instance->instancet = &megasas_instance_template_fusion; |
| 5033 | − break; | |
| 5034 | − case PCI_DEVICE_ID_LSI_SAS1078R: | |
| 5035 | − case PCI_DEVICE_ID_LSI_SAS1078DE: | |
| 5036 | − instance->instancet = &megasas_instance_template_ppc; | |
| 5037 | − break; | |
| 5038 | − case PCI_DEVICE_ID_LSI_SAS1078GEN2: | |
| 5039 | − case PCI_DEVICE_ID_LSI_SAS0079GEN2: | |
| 5040 | − instance->instancet = &megasas_instance_template_gen2; | |
| 5041 | − break; | |
| 5042 | − case PCI_DEVICE_ID_LSI_SAS0073SKINNY: | |
| 5043 | − case PCI_DEVICE_ID_LSI_SAS0071SKINNY: | |
| 5044 | − instance->instancet = &megasas_instance_template_skinny; | |
| 5045 | − break; | |
| 5046 | − case PCI_DEVICE_ID_LSI_SAS1064R: | |
| 5047 | − case PCI_DEVICE_ID_DELL_PERC5: | |
| 5048 | − default: | |
| 5049 | − instance->instancet = &megasas_instance_template_xscale; | |
| 5050 | − break; | |
| 5165 | + else { | |
| 5166 | + switch (instance->pdev->device) { | |
| 5167 | + case PCI_DEVICE_ID_LSI_SAS1078R: | |
| 5168 | + case PCI_DEVICE_ID_LSI_SAS1078DE: | |
| 5169 | + instance->instancet = &megasas_instance_template_ppc; | |
| 5170 | + break; | |
| 5171 | + case PCI_DEVICE_ID_LSI_SAS1078GEN2: | |
| 5172 | + case PCI_DEVICE_ID_LSI_SAS0079GEN2: | |
| 5173 | + instance->instancet = &megasas_instance_template_gen2; | |
| 5174 | + break; | |
| 5175 | + case PCI_DEVICE_ID_LSI_SAS0073SKINNY: | |
| 5176 | + case PCI_DEVICE_ID_LSI_SAS0071SKINNY: | |
| 5177 | + instance->instancet = &megasas_instance_template_skinny; | |
| 5178 | + break; | |
| 5179 | + case PCI_DEVICE_ID_LSI_SAS1064R: | |
| 5180 | + case PCI_DEVICE_ID_DELL_PERC5: | |
| 5181 | + default: | |
| 5182 | + instance->instancet = &megasas_instance_template_xscale; | |
| 5183 | + instance->pd_list_not_supported = 1; | |
| 5184 | + break; | |
| 5185 | + } | |
| 5051 | 5186 | } |
| 5052 | 5187 | |
| 5053 | 5188 | if (megasas_transition_to_ready(instance, 0)) { |
| @@ -5066,13 +5201,13 @@ static int megasas_init_fw(struct megasas_instance *instance) · 12 unmodified lines | ||
| 5066 | 5201 | goto fail_ready_state; |
| 5067 | 5202 | } |
| 5068 | 5203 | |
| 5069 | − /* | |
| 5070 | − * MSI-X host index 0 is common for all adapter. | |
| 5071 | − * It is used for all MPT based Adapters. | |
| 5072 | − */ | |
| 5073 | − instance->reply_post_host_index_addr[0] = | |
| 5074 | − (u32 __iomem *)((u8 __iomem *)instance->reg_set + | |
| 5075 | − MPI2_REPLY_POST_HOST_INDEX_OFFSET); | |
| 5204 | + if (instance->is_ventura) { | |
| 5205 | + scratch_pad_3 = | |
| 5206 | + readl(&instance->reg_set->outbound_scratch_pad_3); | |
| 5207 | + instance->max_raid_mapsize = ((scratch_pad_3 >> | |
| 5208 | + MR_MAX_RAID_MAP_SIZE_OFFSET_SHIFT) & | |
| 5209 | + MR_MAX_RAID_MAP_SIZE_MASK); | |
| 5210 | + } | |
| 5076 | 5211 | |
| 5077 | 5212 | /* Check if MSI-X is supported while in ready state */ |
| 5078 | 5213 | msix_enable = (instance->instancet->read_fw_status_reg(reg_set) & |
| @@ -5092,6 +5227,9 @@ static int megasas_init_fw(struct megasas_instance *instance) · 13 unmodified lines | ||
| 5092 | 5227 | instance->msix_vectors = ((scratch_pad_2 |
| 5093 | 5228 | & MR_MAX_REPLY_QUEUES_EXT_OFFSET) |
| 5094 | 5229 | >> MR_MAX_REPLY_QUEUES_EXT_OFFSET_SHIFT) + 1; |
| 5230 | + if (instance->msix_vectors > 16) | |
| 5231 | + instance->msix_combined = true; | |
| 5232 | + | |
| 5095 | 5233 | if (rdpq_enable) |
| 5096 | 5234 | instance->is_rdpq = (scratch_pad_2 & MR_RDPQ_MODE_OFFSET) ? |
| 5097 | 5235 | 1 : 0; |
| @@ -5125,6 +5263,20 @@ static int megasas_init_fw(struct megasas_instance *instance) · 27 unmodified lines | ||
| 5125 | 5263 | else |
| 5126 | 5264 | instance->msix_vectors = 0; |
| 5127 | 5265 | } |
| 5266 | + /* | |
| 5267 | + * MSI-X host index 0 is common for all adapter. | |
| 5268 | + * It is used for all MPT based Adapters. | |
| 5269 | + */ | |
| 5270 | + if (instance->msix_combined) { | |
| 5271 | + instance->reply_post_host_index_addr[0] = | |
| 5272 | + (u32 *)((u8 *)instance->reg_set + | |
| 5273 | + MPI2_SUP_REPLY_POST_HOST_INDEX_OFFSET); | |
| 5274 | + } else { | |
| 5275 | + instance->reply_post_host_index_addr[0] = | |
| 5276 | + (u32 *)((u8 *)instance->reg_set + | |
| 5277 | + MPI2_REPLY_POST_HOST_INDEX_OFFSET); | |
| 5278 | + } | |
| 5279 | + | |
| 5128 | 5280 | i = pci_alloc_irq_vectors(instance->pdev, 1, 1, PCI_IRQ_LEGACY); |
| 5129 | 5281 | if (i < 0) |
| 5130 | 5282 | goto fail_setup_irqs; |
| @@ -5155,6 +5307,18 @@ static int megasas_init_fw(struct megasas_instance *instance) · 24 unmodified lines | ||
| 5155 | 5307 | if (instance->instancet->init_adapter(instance)) |
| 5156 | 5308 | goto fail_init_adapter; |
| 5157 | 5309 | |
| 5310 | + if (instance->is_ventura) { | |
| 5311 | + scratch_pad_4 = | |
| 5312 | + readl(&instance->reg_set->outbound_scratch_pad_4); | |
| 5313 | + if ((scratch_pad_4 & MR_NVME_PAGE_SIZE_MASK) >= | |
| 5314 | + MR_DEFAULT_NVME_PAGE_SHIFT) | |
| 5315 | + instance->nvme_page_size = | |
| 5316 | + (1 << (scratch_pad_4 & MR_NVME_PAGE_SIZE_MASK)); | |
| 5317 | + | |
| 5318 | + dev_info(&instance->pdev->dev, | |
| 5319 | + "NVME page size\t: (%d)\n", instance->nvme_page_size); | |
| 5320 | + } | |
| 5321 | + | |
| 5158 | 5322 | if (instance->msix_vectors ? |
| 5159 | 5323 | megasas_setup_irqs_msix(instance, 1) : |
| 5160 | 5324 | megasas_setup_irqs_ioapic(instance)) |
| @@ -5173,13 +5337,43 @@ static int megasas_init_fw(struct megasas_instance *instance) · 12 unmodified lines | ||
| 5173 | 5337 | (MEGASAS_MAX_PD * sizeof(struct megasas_pd_list))); |
| 5174 | 5338 | if (megasas_get_pd_list(instance) < 0) { |
| 5175 | 5339 | dev_err(&instance->pdev->dev, "failed to get PD list\n"); |
| 5176 | − goto fail_get_pd_list; | |
| 5340 | + goto fail_get_ld_pd_list; | |
| 5177 | 5341 | } |
| 5178 | 5342 | |
| 5179 | 5343 | memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS); |
| 5344 | + | |
| 5345 | + /* stream detection initialization */ | |
| 5346 | + if (instance->is_ventura && fusion) { | |
| 5347 | + fusion->stream_detect_by_ld = | |
| 5348 | + kzalloc(sizeof(struct LD_STREAM_DETECT *) | |
| 5349 | + * MAX_LOGICAL_DRIVES_EXT, | |
| 5350 | + GFP_KERNEL); | |
| 5351 | + if (!fusion->stream_detect_by_ld) { | |
| 5352 | + dev_err(&instance->pdev->dev, | |
| 5353 | + "unable to allocate stream detection for pool of LDs\n"); | |
| 5354 | + goto fail_get_ld_pd_list; | |
| 5355 | + } | |
| 5356 | + for (i = 0; i < MAX_LOGICAL_DRIVES_EXT; ++i) { | |
| 5357 | + fusion->stream_detect_by_ld[i] = | |
| 5358 | + kmalloc(sizeof(struct LD_STREAM_DETECT), | |
| 5359 | + GFP_KERNEL); | |
| 5360 | + if (!fusion->stream_detect_by_ld[i]) { | |
| 5361 | + dev_err(&instance->pdev->dev, | |
| 5362 | + "unable to allocate stream detect by LD\n "); | |
| 5363 | + for (j = 0; j < i; ++j) | |
| 5364 | + kfree(fusion->stream_detect_by_ld[j]); | |
| 5365 | + kfree(fusion->stream_detect_by_ld); | |
| 5366 | + fusion->stream_detect_by_ld = NULL; | |
| 5367 | + goto fail_get_ld_pd_list; | |
| 5368 | + } | |
| 5369 | + fusion->stream_detect_by_ld[i]->mru_bit_map | |
| 5370 | + = MR_STREAM_BITMAP; | |
| 5371 | + } | |
| 5372 | + } | |
| 5373 | + | |
| 5180 | 5374 | if (megasas_ld_list_query(instance, |
| 5181 | 5375 | MR_LD_QUERY_TYPE_EXPOSED_TO_HOST)) |
| 5182 | − megasas_get_ld_list(instance); | |
| 5376 | + goto fail_get_ld_pd_list; | |
| 5183 | 5377 | |
| 5184 | 5378 | /* |
| 5185 | 5379 | * Compute the max allowed sectors per IO: The controller info has two |
| @@ -5296,7 +5490,7 @@ static int megasas_init_fw(struct megasas_instance *instance) · 110 unmodified lines | ||
| 5296 | 5490 | |
| 5297 | 5491 | return 0; |
| 5298 | 5492 | |
| 5299 | −fail_get_pd_list: | |
| 5493 | +fail_get_ld_pd_list: | |
| 5300 | 5494 | instance->instancet->disable_intr(instance); |
| 5301 | 5495 | fail_init_adapter: |
| 5302 | 5496 | megasas_destroy_irqs(instance); |
| @@ -5309,9 +5503,11 @@ fail_ready_state: · 6 unmodified lines | ||
| 5309 | 5503 | instance->ctrl_info = NULL; |
| 5310 | 5504 | iounmap(instance->reg_set); |
| 5311 | 5505 | |
| 5312 | − fail_ioremap: | |
| 5506 | +fail_ioremap: | |
| 5313 | 5507 | pci_release_selected_regions(instance->pdev, 1<<instance->bar); |
| 5314 | 5508 | |
| 5509 | + dev_err(&instance->pdev->dev, "Failed from %s %d\n", | |
| 5510 | + __func__, __LINE__); | |
| 5315 | 5511 | return -EINVAL; |
| 5316 | 5512 | } |
| 5317 | 5513 | |
| @@ -5531,6 +5727,98 @@ megasas_register_aen(struct megasas_instance *instance, u32 seq_num, · 213 unmodified lines | ||
| 5531 | 5727 | return 0; |
| 5532 | 5728 | } |
| 5533 | 5729 | |
| 5730 | +/* megasas_get_target_prop - Send DCMD with below details to firmware. | |
| 5731 | + * | |
| 5732 | + * This DCMD will fetch few properties of LD/system PD defined | |
| 5733 | + * in MR_TARGET_DEV_PROPERTIES. eg. Queue Depth, MDTS value. | |
| 5734 | + * | |
| 5735 | + * DCMD send by drivers whenever new target is added to the OS. | |
| 5736 | + * | |
| 5737 | + * dcmd.opcode - MR_DCMD_DEV_GET_TARGET_PROP | |
| 5738 | + * dcmd.mbox.b[0] - DCMD is to be fired for LD or system PD. | |
| 5739 | + * 0 = system PD, 1 = LD. | |
| 5740 | + * dcmd.mbox.s[1] - TargetID for LD/system PD. | |
| 5741 | + * dcmd.sge IN - Pointer to return MR_TARGET_DEV_PROPERTIES. | |
| 5742 | + * | |
| 5743 | + * @instance: Adapter soft state | |
| 5744 | + * @sdev: OS provided scsi device | |
| 5745 | + * | |
| 5746 | + * Returns 0 on success non-zero on failure. | |
| 5747 | + */ | |
| 5748 | +static int | |
| 5749 | +megasas_get_target_prop(struct megasas_instance *instance, | |
| 5750 | + struct scsi_device *sdev) | |
| 5751 | +{ | |
| 5752 | + int ret; | |
| 5753 | + struct megasas_cmd *cmd; | |
| 5754 | + struct megasas_dcmd_frame *dcmd; | |
| 5755 | + u16 targetId = (sdev->channel % 2) + sdev->id; | |
| 5756 | + | |
| 5757 | + cmd = megasas_get_cmd(instance); | |
| 5758 | + | |
| 5759 | + if (!cmd) { | |
| 5760 | + dev_err(&instance->pdev->dev, | |
| 5761 | + "Failed to get cmd %s\n", __func__); | |
| 5762 | + return -ENOMEM; | |
| 5763 | + } | |
| 5764 | + | |
| 5765 | + dcmd = &cmd->frame->dcmd; | |
| 5766 | + | |
| 5767 | + memset(instance->tgt_prop, 0, sizeof(*instance->tgt_prop)); | |
| 5768 | + memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); | |
| 5769 | + dcmd->mbox.b[0] = MEGASAS_IS_LOGICAL(sdev); | |
| 5770 | + | |
| 5771 | + dcmd->mbox.s[1] = cpu_to_le16(targetId); | |
| 5772 | + dcmd->cmd = MFI_CMD_DCMD; | |
| 5773 | + dcmd->cmd_status = 0xFF; | |
| 5774 | + dcmd->sge_count = 1; | |
| 5775 | + dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_READ); | |
| 5776 | + dcmd->timeout = 0; | |
| 5777 | + dcmd->pad_0 = 0; | |
| 5778 | + dcmd->data_xfer_len = | |
| 5779 | + cpu_to_le32(sizeof(struct MR_TARGET_PROPERTIES)); | |
| 5780 | + dcmd->opcode = cpu_to_le32(MR_DCMD_DRV_GET_TARGET_PROP); | |
| 5781 | + dcmd->sgl.sge32[0].phys_addr = | |
| 5782 | + cpu_to_le32(instance->tgt_prop_h); | |
| 5783 | + dcmd->sgl.sge32[0].length = | |
| 5784 | + cpu_to_le32(sizeof(struct MR_TARGET_PROPERTIES)); | |
| 5785 | + | |
| 5786 | + if (instance->ctrl_context && !instance->mask_interrupts) | |
| 5787 | + ret = megasas_issue_blocked_cmd(instance, | |
| 5788 | + cmd, MFI_IO_TIMEOUT_SECS); | |
| 5789 | + else | |
| 5790 | + ret = megasas_issue_polled(instance, cmd); | |
| 5791 | + | |
| 5792 | + switch (ret) { | |
| 5793 | + case DCMD_TIMEOUT: | |
| 5794 | + switch (dcmd_timeout_ocr_possible(instance)) { | |
| 5795 | + case INITIATE_OCR: | |
| 5796 | + cmd->flags |= DRV_DCMD_SKIP_REFIRE; | |
| 5797 | + megasas_reset_fusion(instance->host, | |
| 5798 | + MFI_IO_TIMEOUT_OCR); | |
| 5799 | + break; | |
| 5800 | + case KILL_ADAPTER: | |
| 5801 | + megaraid_sas_kill_hba(instance); | |
| 5802 | + break; | |
| 5803 | + case IGNORE_TIMEOUT: | |
| 5804 | + dev_info(&instance->pdev->dev, | |
| 5805 | + "Ignore DCMD timeout: %s %d\n", | |
| 5806 | + __func__, __LINE__); | |
| 5807 | + break; | |
| 5808 | + } | |
| 5809 | + break; | |
| 5810 | + | |
| 5811 | + default: | |
| 5812 | + megasas_return_cmd(instance, cmd); | |
| 5813 | + } | |
| 5814 | + if (ret != DCMD_SUCCESS) | |
| 5815 | + dev_err(&instance->pdev->dev, | |
| 5816 | + "return from %s %d return value %d\n", | |
| 5817 | + __func__, __LINE__, ret); | |
| 5818 | + | |
| 5819 | + return ret; | |
| 5820 | +} | |
| 5821 | + | |
| 5534 | 5822 | /** |
| 5535 | 5823 | * megasas_start_aen - Subscribes to AEN during driver load time |
| 5536 | 5824 | * @instance: Adapter soft state |
| @@ -5714,6 +6002,12 @@ static int megasas_probe_one(struct pci_dev *pdev, · 177 unmodified lines | ||
| 5714 | 6002 | instance->pdev = pdev; |
| 5715 | 6003 | |
| 5716 | 6004 | switch (instance->pdev->device) { |
| 6005 | + case PCI_DEVICE_ID_LSI_VENTURA: | |
| 6006 | + case PCI_DEVICE_ID_LSI_HARPOON: | |
| 6007 | + case PCI_DEVICE_ID_LSI_TOMCAT: | |
| 6008 | + case PCI_DEVICE_ID_LSI_VENTURA_4PORT: | |
| 6009 | + case PCI_DEVICE_ID_LSI_CRUSADER_4PORT: | |
| 6010 | + instance->is_ventura = true; | |
| 5717 | 6011 | case PCI_DEVICE_ID_LSI_FUSION: |
| 5718 | 6012 | case PCI_DEVICE_ID_LSI_PLASMA: |
| 5719 | 6013 | case PCI_DEVICE_ID_LSI_INVADER: |
| @@ -5723,21 +6017,17 @@ static int megasas_probe_one(struct pci_dev *pdev, · 3 unmodified lines | ||
| 5723 | 6017 | case PCI_DEVICE_ID_LSI_CUTLASS_52: |
| 5724 | 6018 | case PCI_DEVICE_ID_LSI_CUTLASS_53: |
| 5725 | 6019 | { |
| 5726 | − instance->ctrl_context_pages = | |
| 5727 | − get_order(sizeof(struct fusion_context)); | |
| 5728 | − instance->ctrl_context = (void *)__get_free_pages(GFP_KERNEL, | |
| 5729 | − instance->ctrl_context_pages); | |
| 5730 | − if (!instance->ctrl_context) { | |
| 5731 | − dev_printk(KERN_DEBUG, &pdev->dev, "Failed to allocate " | |
| 5732 | − "memory for Fusion context info\n"); | |
| 6020 | + if (megasas_alloc_fusion_context(instance)) { | |
| 6021 | + megasas_free_fusion_context(instance); | |
| 5733 | 6022 | goto fail_alloc_dma_buf; |
| 5734 | 6023 | } |
| 5735 | 6024 | fusion = instance->ctrl_context; |
| 5736 | − memset(fusion, 0, | |
| 5737 | − ((1 << PAGE_SHIFT) << instance->ctrl_context_pages)); | |
| 6025 | + | |
| 5738 | 6026 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) || |
| 5739 | 6027 | (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA)) |
| 5740 | 6028 | fusion->adapter_type = THUNDERBOLT_SERIES; |
| 6029 | + else if (instance->is_ventura) | |
| 6030 | + fusion->adapter_type = VENTURA_SERIES; | |
| 5741 | 6031 | else |
| 5742 | 6032 | fusion->adapter_type = INVADER_SERIES; |
| 5743 | 6033 | } |
| @@ -5799,9 +6089,17 @@ static int megasas_probe_one(struct pci_dev *pdev, · 55 unmodified lines | ||
| 5799 | 6089 | instance->pd_info = pci_alloc_consistent(pdev, |
| 5800 | 6090 | sizeof(struct MR_PD_INFO), &instance->pd_info_h); |
| 5801 | 6091 | |
| 6092 | + instance->pd_info = pci_alloc_consistent(pdev, | |
| 6093 | + sizeof(struct MR_PD_INFO), &instance->pd_info_h); | |
| 6094 | + instance->tgt_prop = pci_alloc_consistent(pdev, | |
| 6095 | + sizeof(struct MR_TARGET_PROPERTIES), &instance->tgt_prop_h); | |
| 6096 | + | |
| 5802 | 6097 | if (!instance->pd_info) |
| 5803 | 6098 | dev_err(&instance->pdev->dev, "Failed to alloc mem for pd_info\n"); |
| 5804 | 6099 | |
| 6100 | + if (!instance->tgt_prop) | |
| 6101 | + dev_err(&instance->pdev->dev, "Failed to alloc mem for tgt_prop\n"); | |
| 6102 | + | |
| 5805 | 6103 | instance->crash_dump_buf = pci_alloc_consistent(pdev, |
| 5806 | 6104 | CRASH_DMA_BUF_SIZE, |
| 5807 | 6105 | &instance->crash_dump_h); |
| @@ -5823,6 +6121,7 @@ static int megasas_probe_one(struct pci_dev *pdev, · 15 unmodified lines | ||
| 5823 | 6121 | |
| 5824 | 6122 | spin_lock_init(&instance->mfi_pool_lock); |
| 5825 | 6123 | spin_lock_init(&instance->hba_lock); |
| 6124 | + spin_lock_init(&instance->stream_lock); | |
| 5826 | 6125 | spin_lock_init(&instance->completion_lock); |
| 5827 | 6126 | |
| 5828 | 6127 | mutex_init(&instance->reset_mutex); |
| @@ -5945,6 +6244,10 @@ fail_alloc_dma_buf: · 116 unmodified lines | ||
| 5945 | 6244 | pci_free_consistent(pdev, sizeof(struct MR_PD_INFO), |
| 5946 | 6245 | instance->pd_info, |
| 5947 | 6246 | instance->pd_info_h); |
| 6247 | + if (instance->tgt_prop) | |
| 6248 | + pci_free_consistent(pdev, sizeof(struct MR_TARGET_PROPERTIES), | |
| 6249 | + instance->tgt_prop, | |
| 6250 | + instance->tgt_prop_h); | |
| 5948 | 6251 | if (instance->producer) |
| 5949 | 6252 | pci_free_consistent(pdev, sizeof(u32), instance->producer, |
| 5950 | 6253 | instance->producer_h); |
| @@ -6217,6 +6520,10 @@ fail_init_mfi: · 266 unmodified lines | ||
| 6217 | 6520 | pci_free_consistent(pdev, sizeof(struct MR_PD_INFO), |
| 6218 | 6521 | instance->pd_info, |
| 6219 | 6522 | instance->pd_info_h); |
| 6523 | + if (instance->tgt_prop) | |
| 6524 | + pci_free_consistent(pdev, sizeof(struct MR_TARGET_PROPERTIES), | |
| 6525 | + instance->tgt_prop, | |
| 6526 | + instance->tgt_prop_h); | |
| 6220 | 6527 | if (instance->producer) |
| 6221 | 6528 | pci_free_consistent(pdev, sizeof(u32), instance->producer, |
| 6222 | 6529 | instance->producer_h); |
| @@ -6330,6 +6637,14 @@ skip_firing_dcmds: · 107 unmodified lines | ||
| 6330 | 6637 | if (instance->msix_vectors) |
| 6331 | 6638 | pci_free_irq_vectors(instance->pdev); |
| 6332 | 6639 | |
| 6640 | + if (instance->is_ventura) { | |
| 6641 | + for (i = 0; i < MAX_LOGICAL_DRIVES_EXT; ++i) | |
| 6642 | + kfree(fusion->stream_detect_by_ld[i]); | |
| 6643 | + kfree(fusion->stream_detect_by_ld); | |
| 6644 | + fusion->stream_detect_by_ld = NULL; | |
| 6645 | + } | |
| 6646 | + | |
| 6647 | + | |
| 6333 | 6648 | if (instance->ctrl_context) { |
| 6334 | 6649 | megasas_release_fusion(instance); |
| 6335 | 6650 | pd_seq_map_sz = sizeof(struct MR_PD_CFG_SEQ_NUM_SYNC) + |
| @@ -6350,8 +6665,7 @@ skip_firing_dcmds: · 14 unmodified lines | ||
| 6350 | 6665 | fusion->pd_seq_sync[i], |
| 6351 | 6666 | fusion->pd_seq_phys[i]); |
| 6352 | 6667 | } |
| 6353 | − free_pages((ulong)instance->ctrl_context, | |
| 6354 | − instance->ctrl_context_pages); | |
| 6668 | + megasas_free_fusion_context(instance); | |
| 6355 | 6669 | } else { |
| 6356 | 6670 | megasas_release_mfi(instance); |
| 6357 | 6671 | pci_free_consistent(pdev, sizeof(u32), |
| @@ -6367,11 +6681,14 @@ skip_firing_dcmds: · 9 unmodified lines | ||
| 6367 | 6681 | if (instance->evt_detail) |
| 6368 | 6682 | pci_free_consistent(pdev, sizeof(struct megasas_evt_detail), |
| 6369 | 6683 | instance->evt_detail, instance->evt_detail_h); |
| 6370 | − | |
| 6371 | 6684 | if (instance->pd_info) |
| 6372 | 6685 | pci_free_consistent(pdev, sizeof(struct MR_PD_INFO), |
| 6373 | 6686 | instance->pd_info, |
| 6374 | 6687 | instance->pd_info_h); |
| 6688 | + if (instance->tgt_prop) | |
| 6689 | + pci_free_consistent(pdev, sizeof(struct MR_TARGET_PROPERTIES), | |
| 6690 | + instance->tgt_prop, | |
| 6691 | + instance->tgt_prop_h); | |
| 6375 | 6692 | if (instance->vf_affiliation) |
| 6376 | 6693 | pci_free_consistent(pdev, (MAX_LOGICAL_DRIVES + 1) * |
| 6377 | 6694 | sizeof(struct MR_LD_VF_AFFILIATION), |
| @@ -6570,6 +6887,13 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, · 192 unmodified lines | ||
| 6570 | 6887 | MFI_FRAME_SGL64 | |
| 6571 | 6888 | MFI_FRAME_SENSE64)); |
| 6572 | 6889 | |
| 6890 | + if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_SHUTDOWN) { | |
| 6891 | + if (megasas_get_ctrl_info(instance) != DCMD_SUCCESS) { | |
| 6892 | + megasas_return_cmd(instance, cmd); | |
| 6893 | + return -1; | |
| 6894 | + } | |
| 6895 | + } | |
| 6896 | + | |
| 6573 | 6897 | if (cmd->frame->dcmd.opcode == MR_DRIVER_SET_APP_CRASHDUMP_MODE) { |
| 6574 | 6898 | error = megasas_set_crash_dump_params_ioctl(cmd); |
| 6575 | 6899 | megasas_return_cmd(instance, cmd); |
| @@ -6678,7 +7002,8 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, · 102 unmodified lines | ||
| 6678 | 7002 | sense_ptr = (unsigned long *) ((unsigned long)ioc->frame.raw + |
| 6679 | 7003 | ioc->sense_off); |
| 6680 | 7004 | |
| 6681 | − if (copy_to_user((void __user *)((unsigned long)(*sense_ptr)), | |
| 7005 | + if (copy_to_user((void __user *)((unsigned long) | |
| 7006 | + get_unaligned((unsigned long *)sense_ptr)), | |
| 6682 | 7007 | sense, ioc->sense_len)) { |
| 6683 | 7008 | dev_err(&instance->pdev->dev, "Failed to copy out to user " |
| 6684 | 7009 | "sense data\n"); |
| @@ -7047,6 +7372,13 @@ megasas_sysfs_set_dbg_lvl(struct device_driver *dd, const char *buf, size_t coun · 362 unmodified lines | ||
| 7047 | 7372 | static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUSR, megasas_sysfs_show_dbg_lvl, |
| 7048 | 7373 | megasas_sysfs_set_dbg_lvl); |
| 7049 | 7374 | |
| 7375 | +static inline void megasas_remove_scsi_device(struct scsi_device *sdev) | |
| 7376 | +{ | |
| 7377 | + sdev_printk(KERN_INFO, sdev, "SCSI device is removed\n"); | |
| 7378 | + scsi_remove_device(sdev); | |
| 7379 | + scsi_device_put(sdev); | |
| 7380 | +} | |
| 7381 | + | |
| 7050 | 7382 | static void |
| 7051 | 7383 | megasas_aen_polling(struct work_struct *work) |
| 7052 | 7384 | { |
| @@ -7151,10 +7483,8 @@ megasas_aen_polling(struct work_struct *work) · 98 unmodified lines | ||
| 7151 | 7483 | else |
| 7152 | 7484 | scsi_device_put(sdev1); |
| 7153 | 7485 | } else { |
| 7154 | − if (sdev1) { | |
| 7155 | − scsi_remove_device(sdev1); | |
| 7156 | − scsi_device_put(sdev1); | |
| 7157 | − } | |
| 7486 | + if (sdev1) | |
| 7487 | + megasas_remove_scsi_device(sdev1); | |
| 7158 | 7488 | } |
| 7159 | 7489 | } |
| 7160 | 7490 | } |
| @@ -7171,10 +7501,8 @@ megasas_aen_polling(struct work_struct *work) · 10 unmodified lines | ||
| 7171 | 7501 | else |
| 7172 | 7502 | scsi_device_put(sdev1); |
| 7173 | 7503 | } else { |
| 7174 | − if (sdev1) { | |
| 7175 | − scsi_remove_device(sdev1); | |
| 7176 | − scsi_device_put(sdev1); | |
| 7177 | − } | |
| 7504 | + if (sdev1) | |
| 7505 | + megasas_remove_scsi_device(sdev1); | |
| 7178 | 7506 | } |
| 7179 | 7507 | } |
| 7180 | 7508 | } |
| @@ -77,7 +77,6 @@ MODULE_PARM_DESC(lb_pending_cmds, "Change raid-1 load balancing outstanding " · 76 unmodified lines | ||
| 77 | 77 | #endif |
| 78 | 78 | #define TRUE 1 |
| 79 | 79 | |
| 80 | −#define SPAN_DEBUG 0 | |
| 81 | 80 | #define SPAN_ROW_SIZE(map, ld, index_) (MR_LdSpanPtrGet(ld, index_, map)->spanRowSize) |
| 82 | 81 | #define SPAN_ROW_DATA_SIZE(map_, ld, index_) (MR_LdSpanPtrGet(ld, index_, map)->spanRowDataSize) |
| 83 | 82 | #define SPAN_INVALID 0xff |
| @@ -155,12 +154,17 @@ __le16 MR_PdDevHandleGet(u32 pd, struct MR_DRV_RAID_MAP_ALL *map) · 71 unmodified lines | ||
| 155 | 154 | return map->raidMap.devHndlInfo[pd].curDevHdl; |
| 156 | 155 | } |
| 157 | 156 | |
| 157 | +static u8 MR_PdInterfaceTypeGet(u32 pd, struct MR_DRV_RAID_MAP_ALL *map) | |
| 158 | +{ | |
| 159 | + return map->raidMap.devHndlInfo[pd].interfaceType; | |
| 160 | +} | |
| 161 | + | |
| 158 | 162 | u16 MR_GetLDTgtId(u32 ld, struct MR_DRV_RAID_MAP_ALL *map) |
| 159 | 163 | { |
| 160 | 164 | return le16_to_cpu(map->raidMap.ldSpanMap[ld].ldRaid.targetId); |
| 161 | 165 | } |
| 162 | 166 | |
| 163 | −u8 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_DRV_RAID_MAP_ALL *map) | |
| 167 | +u16 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_DRV_RAID_MAP_ALL *map) | |
| 164 | 168 | { |
| 165 | 169 | return map->raidMap.ldTgtIdToLd[ldTgtId]; |
| 166 | 170 | } |
| @@ -179,18 +183,108 @@ void MR_PopulateDrvRaidMap(struct megasas_instance *instance) · 12 unmodified lines | ||
| 179 | 183 | struct fusion_context *fusion = instance->ctrl_context; |
| 180 | 184 | struct MR_FW_RAID_MAP_ALL *fw_map_old = NULL; |
| 181 | 185 | struct MR_FW_RAID_MAP *pFwRaidMap = NULL; |
| 182 | − int i; | |
| 186 | + int i, j; | |
| 183 | 187 | u16 ld_count; |
| 188 | + struct MR_FW_RAID_MAP_DYNAMIC *fw_map_dyn; | |
| 189 | + struct MR_FW_RAID_MAP_EXT *fw_map_ext; | |
| 190 | + struct MR_RAID_MAP_DESC_TABLE *desc_table; | |
| 184 | 191 | |
| 185 | 192 | |
| 186 | 193 | struct MR_DRV_RAID_MAP_ALL *drv_map = |
| 187 | 194 | fusion->ld_drv_map[(instance->map_id & 1)]; |
| 188 | 195 | struct MR_DRV_RAID_MAP *pDrvRaidMap = &drv_map->raidMap; |
| 196 | + void *raid_map_data = NULL; | |
| 197 | + | |
| 198 | + memset(drv_map, 0, fusion->drv_map_sz); | |
| 199 | + memset(pDrvRaidMap->ldTgtIdToLd, | |
| 200 | + 0xff, (sizeof(u16) * MAX_LOGICAL_DRIVES_DYN)); | |
| 201 | + | |
| 202 | + if (instance->max_raid_mapsize) { | |
| 203 | + fw_map_dyn = fusion->ld_map[(instance->map_id & 1)]; | |
| 204 | + desc_table = | |
| 205 | + (struct MR_RAID_MAP_DESC_TABLE *)((void *)fw_map_dyn + le32_to_cpu(fw_map_dyn->desc_table_offset)); | |
| 206 | + if (desc_table != fw_map_dyn->raid_map_desc_table) | |
| 207 | + dev_dbg(&instance->pdev->dev, "offsets of desc table are not matching desc %p original %p\n", | |
| 208 | + desc_table, fw_map_dyn->raid_map_desc_table); | |
| 209 | + | |
| 210 | + ld_count = (u16)le16_to_cpu(fw_map_dyn->ld_count); | |
| 211 | + pDrvRaidMap->ldCount = (__le16)cpu_to_le16(ld_count); | |
| 212 | + pDrvRaidMap->fpPdIoTimeoutSec = | |
| 213 | + fw_map_dyn->fp_pd_io_timeout_sec; | |
| 214 | + pDrvRaidMap->totalSize = | |
| 215 | + cpu_to_le32(sizeof(struct MR_DRV_RAID_MAP_ALL)); | |
| 216 | + /* point to actual data starting point*/ | |
| 217 | + raid_map_data = (void *)fw_map_dyn + | |
| 218 | + le32_to_cpu(fw_map_dyn->desc_table_offset) + | |
| 219 | + le32_to_cpu(fw_map_dyn->desc_table_size); | |
| 220 | + | |
| 221 | + for (i = 0; i < le32_to_cpu(fw_map_dyn->desc_table_num_elements); ++i) { | |
| 222 | + switch (le32_to_cpu(desc_table->raid_map_desc_type)) { | |
| 223 | + case RAID_MAP_DESC_TYPE_DEVHDL_INFO: | |
| 224 | + fw_map_dyn->dev_hndl_info = | |
| 225 | + (struct MR_DEV_HANDLE_INFO *)(raid_map_data + le32_to_cpu(desc_table->raid_map_desc_offset)); | |
| 226 | + memcpy(pDrvRaidMap->devHndlInfo, | |
| 227 | + fw_map_dyn->dev_hndl_info, | |
| 228 | + sizeof(struct MR_DEV_HANDLE_INFO) * | |
| 229 | + le32_to_cpu(desc_table->raid_map_desc_elements)); | |
| 230 | + break; | |
| 231 | + case RAID_MAP_DESC_TYPE_TGTID_INFO: | |
| 232 | + fw_map_dyn->ld_tgt_id_to_ld = | |
| 233 | + (u16 *)(raid_map_data + | |
| 234 | + le32_to_cpu(desc_table->raid_map_desc_offset)); | |
| 235 | + for (j = 0; j < le32_to_cpu(desc_table->raid_map_desc_elements); j++) { | |
| 236 | + pDrvRaidMap->ldTgtIdToLd[j] = | |
| 237 | + le16_to_cpu(fw_map_dyn->ld_tgt_id_to_ld[j]); | |
| 238 | + } | |
| 239 | + break; | |
| 240 | + case RAID_MAP_DESC_TYPE_ARRAY_INFO: | |
| 241 | + fw_map_dyn->ar_map_info = | |
| 242 | + (struct MR_ARRAY_INFO *) | |
| 243 | + (raid_map_data + le32_to_cpu(desc_table->raid_map_desc_offset)); | |
| 244 | + memcpy(pDrvRaidMap->arMapInfo, | |
| 245 | + fw_map_dyn->ar_map_info, | |
| 246 | + sizeof(struct MR_ARRAY_INFO) * | |
| 247 | + le32_to_cpu(desc_table->raid_map_desc_elements)); | |
| 248 | + break; | |
| 249 | + case RAID_MAP_DESC_TYPE_SPAN_INFO: | |
| 250 | + fw_map_dyn->ld_span_map = | |
| 251 | + (struct MR_LD_SPAN_MAP *) | |
| 252 | + (raid_map_data + | |
| 253 | + le32_to_cpu(desc_table->raid_map_desc_offset)); | |
| 254 | + memcpy(pDrvRaidMap->ldSpanMap, | |
| 255 | + fw_map_dyn->ld_span_map, | |
| 256 | + sizeof(struct MR_LD_SPAN_MAP) * | |
| 257 | + le32_to_cpu(desc_table->raid_map_desc_elements)); | |
| 258 | + break; | |
| 259 | + default: | |
| 260 | + dev_dbg(&instance->pdev->dev, "wrong number of desctableElements %d\n", | |
| 261 | + fw_map_dyn->desc_table_num_elements); | |
| 262 | + } | |
| 263 | + ++desc_table; | |
| 264 | + } | |
| 265 | + | |
| 266 | + } else if (instance->supportmax256vd) { | |
| 267 | + fw_map_ext = | |
| 268 | + (struct MR_FW_RAID_MAP_EXT *)fusion->ld_map[(instance->map_id & 1)]; | |
| 269 | + ld_count = (u16)le16_to_cpu(fw_map_ext->ldCount); | |
| 270 | + if (ld_count > MAX_LOGICAL_DRIVES_EXT) { | |
| 271 | + dev_dbg(&instance->pdev->dev, "megaraid_sas: LD count exposed in RAID map in not valid\n"); | |
| 272 | + return; | |
| 273 | + } | |
| 274 | + | |
| 275 | + pDrvRaidMap->ldCount = (__le16)cpu_to_le16(ld_count); | |
| 276 | + pDrvRaidMap->fpPdIoTimeoutSec = fw_map_ext->fpPdIoTimeoutSec; | |
| 277 | + for (i = 0; i < (MAX_LOGICAL_DRIVES_EXT); i++) | |
| 278 | + pDrvRaidMap->ldTgtIdToLd[i] = | |
| 279 | + (u16)fw_map_ext->ldTgtIdToLd[i]; | |
| 280 | + memcpy(pDrvRaidMap->ldSpanMap, fw_map_ext->ldSpanMap, | |
| 281 | + sizeof(struct MR_LD_SPAN_MAP) * ld_count); | |
| 282 | + memcpy(pDrvRaidMap->arMapInfo, fw_map_ext->arMapInfo, | |
| 283 | + sizeof(struct MR_ARRAY_INFO) * MAX_API_ARRAYS_EXT); | |
| 284 | + memcpy(pDrvRaidMap->devHndlInfo, fw_map_ext->devHndlInfo, | |
| 285 | + sizeof(struct MR_DEV_HANDLE_INFO) * | |
| 286 | + MAX_RAIDMAP_PHYSICAL_DEVICES); | |
| 189 | 287 | |
| 190 | − if (instance->supportmax256vd) { | |
| 191 | − memcpy(fusion->ld_drv_map[instance->map_id & 1], | |
| 192 | − fusion->ld_map[instance->map_id & 1], | |
| 193 | − fusion->current_map_sz); | |
| 194 | 288 | /* New Raid map will not set totalSize, so keep expected value |
| 195 | 289 | * for legacy code in ValidateMapInfo |
| 196 | 290 | */ |
| @@ -201,50 +295,14 @@ void MR_PopulateDrvRaidMap(struct megasas_instance *instance) · 4 unmodified lines | ||
| 201 | 295 | fusion->ld_map[(instance->map_id & 1)]; |
| 202 | 296 | pFwRaidMap = &fw_map_old->raidMap; |
| 203 | 297 | ld_count = (u16)le32_to_cpu(pFwRaidMap->ldCount); |
| 204 | − | |
| 205 | −#if VD_EXT_DEBUG | |
| 206 | − for (i = 0; i < ld_count; i++) { | |
| 207 | − dev_dbg(&instance->pdev->dev, "(%d) :Index 0x%x " | |
| 208 | − "Target Id 0x%x Seq Num 0x%x Size 0/%llx\n", | |
| 209 | − instance->unique_id, i, | |
| 210 | − fw_map_old->raidMap.ldSpanMap[i].ldRaid.targetId, | |
| 211 | − fw_map_old->raidMap.ldSpanMap[i].ldRaid.seqNum, | |
| 212 | − fw_map_old->raidMap.ldSpanMap[i].ldRaid.size); | |
| 213 | − } | |
| 214 | −#endif | |
| 215 | − | |
| 216 | − memset(drv_map, 0, fusion->drv_map_sz); | |
| 217 | 298 | pDrvRaidMap->totalSize = pFwRaidMap->totalSize; |
| 218 | 299 | pDrvRaidMap->ldCount = (__le16)cpu_to_le16(ld_count); |
| 219 | 300 | pDrvRaidMap->fpPdIoTimeoutSec = pFwRaidMap->fpPdIoTimeoutSec; |
| 220 | 301 | for (i = 0; i < MAX_RAIDMAP_LOGICAL_DRIVES + MAX_RAIDMAP_VIEWS; i++) |
| 221 | 302 | pDrvRaidMap->ldTgtIdToLd[i] = |
| 222 | 303 | (u8)pFwRaidMap->ldTgtIdToLd[i]; |
| 223 | − for (i = (MAX_RAIDMAP_LOGICAL_DRIVES + MAX_RAIDMAP_VIEWS); | |
| 224 | − i < MAX_LOGICAL_DRIVES_EXT; i++) | |
| 225 | − pDrvRaidMap->ldTgtIdToLd[i] = 0xff; | |
| 226 | 304 | for (i = 0; i < ld_count; i++) { |
| 227 | 305 | pDrvRaidMap->ldSpanMap[i] = pFwRaidMap->ldSpanMap[i]; |
| 228 | −#if VD_EXT_DEBUG | |
| 229 | − dev_dbg(&instance->pdev->dev, | |
| 230 | − "pFwRaidMap->ldSpanMap[%d].ldRaid.targetId 0x%x " | |
| 231 | − "pFwRaidMap->ldSpanMap[%d].ldRaid.seqNum 0x%x " | |
| 232 | − "size 0x%x\n", i, i, | |
| 233 | − pFwRaidMap->ldSpanMap[i].ldRaid.targetId, | |
| 234 | − pFwRaidMap->ldSpanMap[i].ldRaid.seqNum, | |
| 235 | − (u32)pFwRaidMap->ldSpanMap[i].ldRaid.rowSize); | |
| 236 | − dev_dbg(&instance->pdev->dev, | |
| 237 | − "pDrvRaidMap->ldSpanMap[%d].ldRaid.targetId 0x%x " | |
| 238 | − "pDrvRaidMap->ldSpanMap[%d].ldRaid.seqNum 0x%x " | |
| 239 | − "size 0x%x\n", i, i, | |
| 240 | − pDrvRaidMap->ldSpanMap[i].ldRaid.targetId, | |
| 241 | − pDrvRaidMap->ldSpanMap[i].ldRaid.seqNum, | |
| 242 | − (u32)pDrvRaidMap->ldSpanMap[i].ldRaid.rowSize); | |
| 243 | − dev_dbg(&instance->pdev->dev, "Driver raid map all %p " | |
| 244 | − "raid map %p LD RAID MAP %p/%p\n", drv_map, | |
| 245 | − pDrvRaidMap, &pFwRaidMap->ldSpanMap[i].ldRaid, | |
| 246 | − &pDrvRaidMap->ldSpanMap[i].ldRaid); | |
| 247 | −#endif | |
| 248 | 306 | } |
| 249 | 307 | memcpy(pDrvRaidMap->arMapInfo, pFwRaidMap->arMapInfo, |
| 250 | 308 | sizeof(struct MR_ARRAY_INFO) * MAX_RAIDMAP_ARRAYS); |
| @@ -265,7 +323,7 @@ u8 MR_ValidateMapInfo(struct megasas_instance *instance) · 14 unmodified lines | ||
| 265 | 323 | struct LD_LOAD_BALANCE_INFO *lbInfo; |
| 266 | 324 | PLD_SPAN_INFO ldSpanInfo; |
| 267 | 325 | struct MR_LD_RAID *raid; |
| 268 | − u16 ldCount, num_lds; | |
| 326 | + u16 num_lds, i; | |
| 269 | 327 | u16 ld; |
| 270 | 328 | u32 expected_size; |
| 271 | 329 | |
| @@ -279,7 +337,9 @@ u8 MR_ValidateMapInfo(struct megasas_instance *instance) · 7 unmodified lines | ||
| 279 | 337 | lbInfo = fusion->load_balance_info; |
| 280 | 338 | ldSpanInfo = fusion->log_to_span; |
| 281 | 339 | |
| 282 | − if (instance->supportmax256vd) | |
| 340 | + if (instance->max_raid_mapsize) | |
| 341 | + expected_size = sizeof(struct MR_DRV_RAID_MAP_ALL); | |
| 342 | + else if (instance->supportmax256vd) | |
| 283 | 343 | expected_size = sizeof(struct MR_FW_RAID_MAP_EXT); |
| 284 | 344 | else |
| 285 | 345 | expected_size = |
| @@ -287,8 +347,10 @@ u8 MR_ValidateMapInfo(struct megasas_instance *instance) · 1 unmodified line | ||
| 287 | 347 | (sizeof(struct MR_LD_SPAN_MAP) * le16_to_cpu(pDrvRaidMap->ldCount))); |
| 288 | 348 | |
| 289 | 349 | if (le32_to_cpu(pDrvRaidMap->totalSize) != expected_size) { |
| 290 | − dev_err(&instance->pdev->dev, "map info structure size 0x%x is not matching with ld count\n", | |
| 291 | − (unsigned int) expected_size); | |
| 350 | + dev_dbg(&instance->pdev->dev, "megasas: map info structure size 0x%x", | |
| 351 | + le32_to_cpu(pDrvRaidMap->totalSize)); | |
| 352 | + dev_dbg(&instance->pdev->dev, "is not matching expected size 0x%x\n", | |
| 353 | + (unsigned int)expected_size); | |
| 292 | 354 | dev_err(&instance->pdev->dev, "megasas: span map %x, pDrvRaidMap->totalSize : %x\n", |
| 293 | 355 | (unsigned int)sizeof(struct MR_LD_SPAN_MAP), |
| 294 | 356 | le32_to_cpu(pDrvRaidMap->totalSize)); |
| @@ -298,15 +360,23 @@ u8 MR_ValidateMapInfo(struct megasas_instance *instance) · 3 unmodified lines | ||
| 298 | 360 | if (instance->UnevenSpanSupport) |
| 299 | 361 | mr_update_span_set(drv_map, ldSpanInfo); |
| 300 | 362 | |
| 301 | − mr_update_load_balance_params(drv_map, lbInfo); | |
| 363 | + if (lbInfo) | |
| 364 | + mr_update_load_balance_params(drv_map, lbInfo); | |
| 302 | 365 | |
| 303 | 366 | num_lds = le16_to_cpu(drv_map->raidMap.ldCount); |
| 304 | 367 | |
| 305 | 368 | /*Convert Raid capability values to CPU arch */ |
| 306 | − for (ldCount = 0; ldCount < num_lds; ldCount++) { | |
| 307 | − ld = MR_TargetIdToLdGet(ldCount, drv_map); | |
| 369 | + for (i = 0; (num_lds > 0) && (i < MAX_LOGICAL_DRIVES_EXT); i++) { | |
| 370 | + ld = MR_TargetIdToLdGet(i, drv_map); | |
| 371 | + | |
| 372 | + /* For non existing VDs, iterate to next VD*/ | |
| 373 | + if (ld >= (MAX_LOGICAL_DRIVES_EXT - 1)) | |
| 374 | + continue; | |
| 375 | + | |
| 308 | 376 | raid = MR_LdRaidGet(ld, drv_map); |
| 309 | 377 | le32_to_cpus((u32 *)&raid->capability); |
| 378 | + | |
| 379 | + num_lds--; | |
| 310 | 380 | } |
| 311 | 381 | |
| 312 | 382 | return 1; |
| @@ -345,91 +415,6 @@ u32 MR_GetSpanBlock(u32 ld, u64 row, u64 *span_blk, · 32 unmodified lines | ||
| 345 | 415 | return SPAN_INVALID; |
| 346 | 416 | } |
| 347 | 417 | |
| 348 | −/* | |
| 349 | −****************************************************************************** | |
| 350 | −* | |
| 351 | −* Function to print info about span set created in driver from FW raid map | |
| 352 | −* | |
| 353 | −* Inputs : | |
| 354 | −* map - LD map | |
| 355 | −* ldSpanInfo - ldSpanInfo per HBA instance | |
| 356 | −*/ | |
| 357 | −#if SPAN_DEBUG | |
| 358 | −static int getSpanInfo(struct MR_DRV_RAID_MAP_ALL *map, | |
| 359 | − PLD_SPAN_INFO ldSpanInfo) | |
| 360 | −{ | |
| 361 | − | |
| 362 | − u8 span; | |
| 363 | − u32 element; | |
| 364 | − struct MR_LD_RAID *raid; | |
| 365 | − LD_SPAN_SET *span_set; | |
| 366 | − struct MR_QUAD_ELEMENT *quad; | |
| 367 | − int ldCount; | |
| 368 | − u16 ld; | |
| 369 | − | |
| 370 | − for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES_EXT; ldCount++) { | |
| 371 | − ld = MR_TargetIdToLdGet(ldCount, map); | |
| 372 | − if (ld >= (MAX_LOGICAL_DRIVES_EXT - 1)) | |
| 373 | − continue; | |
| 374 | − raid = MR_LdRaidGet(ld, map); | |
| 375 | − dev_dbg(&instance->pdev->dev, "LD %x: span_depth=%x\n", | |
| 376 | − ld, raid->spanDepth); | |
| 377 | − for (span = 0; span < raid->spanDepth; span++) | |
| 378 | − dev_dbg(&instance->pdev->dev, "Span=%x," | |
| 379 | − " number of quads=%x\n", span, | |
| 380 | − le32_to_cpu(map->raidMap.ldSpanMap[ld].spanBlock[span]. | |
| 381 | − block_span_info.noElements)); | |
| 382 | − for (element = 0; element < MAX_QUAD_DEPTH; element++) { | |
| 383 | − span_set = &(ldSpanInfo[ld].span_set[element]); | |
| 384 | − if (span_set->span_row_data_width == 0) | |
| 385 | − break; | |
| 386 | − | |
| 387 | − dev_dbg(&instance->pdev->dev, "Span Set %x:" | |
| 388 | − "width=%x, diff=%x\n", element, | |
| 389 | − (unsigned int)span_set->span_row_data_width, | |
| 390 | − (unsigned int)span_set->diff); | |
| 391 | − dev_dbg(&instance->pdev->dev, "logical LBA" | |
| 392 | − "start=0x%08lx, end=0x%08lx\n", | |
| 393 | − (long unsigned int)span_set->log_start_lba, | |
| 394 | − (long unsigned int)span_set->log_end_lba); | |
| 395 | − dev_dbg(&instance->pdev->dev, "span row start=0x%08lx," | |
| 396 | − " end=0x%08lx\n", | |
| 397 | − (long unsigned int)span_set->span_row_start, | |
| 398 | − (long unsigned int)span_set->span_row_end); | |
| 399 | − dev_dbg(&instance->pdev->dev, "data row start=0x%08lx," | |
| 400 | − " end=0x%08lx\n", | |
| 401 | − (long unsigned int)span_set->data_row_start, | |
| 402 | − (long unsigned int)span_set->data_row_end); | |
| 403 | − dev_dbg(&instance->pdev->dev, "data strip start=0x%08lx," | |
| 404 | − " end=0x%08lx\n", | |
| 405 | − (long unsigned int)span_set->data_strip_start, | |
| 406 | − (long unsigned int)span_set->data_strip_end); | |
| 407 | − | |
| 408 | − for (span = 0; span < raid->spanDepth; span++) { | |
| 409 | − if (le32_to_cpu(map->raidMap.ldSpanMap[ld].spanBlock[span]. | |
| 410 | − block_span_info.noElements) >= | |
| 411 | − element + 1) { | |
| 412 | − quad = &map->raidMap.ldSpanMap[ld]. | |
| 413 | − spanBlock[span].block_span_info. | |
| 414 | − quad[element]; | |
| 415 | − dev_dbg(&instance->pdev->dev, "Span=%x," | |
| 416 | − "Quad=%x, diff=%x\n", span, | |
| 417 | − element, le32_to_cpu(quad->diff)); | |
| 418 | − dev_dbg(&instance->pdev->dev, | |
| 419 | − "offset_in_span=0x%08lx\n", | |
| 420 | − (long unsigned int)le64_to_cpu(quad->offsetInSpan)); | |
| 421 | − dev_dbg(&instance->pdev->dev, | |
| 422 | − "logical start=0x%08lx, end=0x%08lx\n", | |
| 423 | − (long unsigned int)le64_to_cpu(quad->logStart), | |
| 424 | − (long unsigned int)le64_to_cpu(quad->logEnd)); | |
| 425 | − } | |
| 426 | − } | |
| 427 | − } | |
| 428 | − } | |
| 429 | − return 0; | |
| 430 | −} | |
| 431 | −#endif | |
| 432 | − | |
| 433 | 418 | /* |
| 434 | 419 | ****************************************************************************** |
| 435 | 420 | * |
| @@ -543,19 +528,7 @@ static u64 get_row_from_strip(struct megasas_instance *instance, · 107 unmodified lines | ||
| 543 | 528 | else |
| 544 | 529 | break; |
| 545 | 530 | } |
| 546 | −#if SPAN_DEBUG | |
| 547 | − dev_info(&instance->pdev->dev, "Strip 0x%llx," | |
| 548 | − "span_set_Strip 0x%llx, span_set_Row 0x%llx" | |
| 549 | − "data width 0x%llx span offset 0x%x\n", strip, | |
| 550 | − (unsigned long long)span_set_Strip, | |
| 551 | − (unsigned long long)span_set_Row, | |
| 552 | − (unsigned long long)span_set->span_row_data_width, | |
| 553 | − span_offset); | |
| 554 | − dev_info(&instance->pdev->dev, "For strip 0x%llx" | |
| 555 | − "row is 0x%llx\n", strip, | |
| 556 | − (unsigned long long) span_set->data_row_start + | |
| 557 | − (unsigned long long) span_set_Row + (span_offset - 1)); | |
| 558 | −#endif | |
| 531 | + | |
| 559 | 532 | retval = (span_set->data_row_start + span_set_Row + |
| 560 | 533 | (span_offset - 1)); |
| 561 | 534 | return retval; |
| @@ -672,11 +645,7 @@ static u32 get_arm_from_strip(struct megasas_instance *instance, · 110 unmodified lines | ||
| 672 | 645 | else |
| 673 | 646 | break; |
| 674 | 647 | } |
| 675 | −#if SPAN_DEBUG | |
| 676 | − dev_info(&instance->pdev->dev, "get_arm_from_strip:" | |
| 677 | − "for ld=0x%x strip=0x%lx arm is 0x%x\n", ld, | |
| 678 | − (long unsigned int)strip, (strip_offset - span_offset)); | |
| 679 | −#endif | |
| 648 | + | |
| 680 | 649 | retval = (strip_offset - span_offset); |
| 681 | 650 | return retval; |
| 682 | 651 | } |
| @@ -737,16 +706,18 @@ static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld, · 54 unmodified lines | ||
| 737 | 706 | struct MR_DRV_RAID_MAP_ALL *map) |
| 738 | 707 | { |
| 739 | 708 | struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map); |
| 740 | − u32 pd, arRef; | |
| 709 | + u32 pd, arRef, r1_alt_pd; | |
| 741 | 710 | u8 physArm, span; |
| 742 | 711 | u64 row; |
| 743 | 712 | u8 retval = TRUE; |
| 744 | 713 | u64 *pdBlock = &io_info->pdBlock; |
| 745 | 714 | __le16 *pDevHandle = &io_info->devHandle; |
| 715 | + u8 *pPdInterface = &io_info->pd_interface; | |
| 746 | 716 | u32 logArm, rowMod, armQ, arm; |
| 747 | 717 | struct fusion_context *fusion; |
| 748 | 718 | |
| 749 | 719 | fusion = instance->ctrl_context; |
| 720 | + *pDevHandle = cpu_to_le16(MR_DEVHANDLE_INVALID); | |
| 750 | 721 | |
| 751 | 722 | /*Get row and span from io_info for Uneven Span IO.*/ |
| 752 | 723 | row = io_info->start_row; |
| @@ -772,27 +743,46 @@ static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld, · 19 unmodified lines | ||
| 772 | 743 | arRef = MR_LdSpanArrayGet(ld, span, map); |
| 773 | 744 | pd = MR_ArPdGet(arRef, physArm, map); |
| 774 | 745 | |
| 775 | − if (pd != MR_PD_INVALID) | |
| 746 | + if (pd != MR_PD_INVALID) { | |
| 776 | 747 | *pDevHandle = MR_PdDevHandleGet(pd, map); |
| 777 | − else { | |
| 778 | − *pDevHandle = cpu_to_le16(MR_PD_INVALID); | |
| 748 | + *pPdInterface = MR_PdInterfaceTypeGet(pd, map); | |
| 749 | + /* get second pd also for raid 1/10 fast path writes*/ | |
| 750 | + if (instance->is_ventura && | |
| 751 | + (raid->level == 1) && | |
| 752 | + !io_info->isRead) { | |
| 753 | + r1_alt_pd = MR_ArPdGet(arRef, physArm + 1, map); | |
| 754 | + if (r1_alt_pd != MR_PD_INVALID) | |
| 755 | + io_info->r1_alt_dev_handle = | |
| 756 | + MR_PdDevHandleGet(r1_alt_pd, map); | |
| 757 | + } | |
| 758 | + } else { | |
| 779 | 759 | if ((raid->level >= 5) && |
| 780 | 760 | ((fusion->adapter_type == THUNDERBOLT_SERIES) || |
| 781 | 761 | ((fusion->adapter_type == INVADER_SERIES) && |
| 782 | 762 | (raid->regTypeReqOnRead != REGION_TYPE_UNUSED)))) |
| 783 | − pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE; | |
| 763 | + pRAID_Context->reg_lock_flags = REGION_TYPE_EXCLUSIVE; | |
| 784 | 764 | else if (raid->level == 1) { |
| 785 | 765 | physArm = physArm + 1; |
| 786 | 766 | pd = MR_ArPdGet(arRef, physArm, map); |
| 787 | − if (pd != MR_PD_INVALID) | |
| 767 | + if (pd != MR_PD_INVALID) { | |
| 788 | 768 | *pDevHandle = MR_PdDevHandleGet(pd, map); |
| 769 | + *pPdInterface = MR_PdInterfaceTypeGet(pd, map); | |
| 770 | + } | |
| 789 | 771 | } |
| 790 | 772 | } |
| 791 | 773 | |
| 792 | 774 | *pdBlock += stripRef + le64_to_cpu(MR_LdSpanPtrGet(ld, span, map)->startBlk); |
| 793 | − pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | | |
| 794 | − physArm; | |
| 795 | − io_info->span_arm = pRAID_Context->spanArm; | |
| 775 | + if (instance->is_ventura) { | |
| 776 | + ((struct RAID_CONTEXT_G35 *)pRAID_Context)->span_arm = | |
| 777 | + (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; | |
| 778 | + io_info->span_arm = | |
| 779 | + (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; | |
| 780 | + } else { | |
| 781 | + pRAID_Context->span_arm = | |
| 782 | + (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; | |
| 783 | + io_info->span_arm = pRAID_Context->span_arm; | |
| 784 | + } | |
| 785 | + io_info->pd_after_lb = pd; | |
| 796 | 786 | return retval; |
| 797 | 787 | } |
| 798 | 788 | |
| @@ -819,16 +809,17 @@ u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow, · 20 unmodified lines | ||
| 819 | 809 | struct MR_DRV_RAID_MAP_ALL *map) |
| 820 | 810 | { |
| 821 | 811 | struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map); |
| 822 | − u32 pd, arRef; | |
| 812 | + u32 pd, arRef, r1_alt_pd; | |
| 823 | 813 | u8 physArm, span; |
| 824 | 814 | u64 row; |
| 825 | 815 | u8 retval = TRUE; |
| 826 | 816 | u64 *pdBlock = &io_info->pdBlock; |
| 827 | 817 | __le16 *pDevHandle = &io_info->devHandle; |
| 818 | + u8 *pPdInterface = &io_info->pd_interface; | |
| 828 | 819 | struct fusion_context *fusion; |
| 829 | 820 | |
| 830 | 821 | fusion = instance->ctrl_context; |
| 831 | − | |
| 822 | + *pDevHandle = cpu_to_le16(MR_DEVHANDLE_INVALID); | |
| 832 | 823 | |
| 833 | 824 | row = mega_div64_32(stripRow, raid->rowDataSize); |
| 834 | 825 | |
| @@ -867,31 +858,49 @@ u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow, · 32 unmodified lines | ||
| 867 | 858 | arRef = MR_LdSpanArrayGet(ld, span, map); |
| 868 | 859 | pd = MR_ArPdGet(arRef, physArm, map); /* Get the pd */ |
| 869 | 860 | |
| 870 | − if (pd != MR_PD_INVALID) | |
| 861 | + if (pd != MR_PD_INVALID) { | |
| 871 | 862 | /* Get dev handle from Pd. */ |
| 872 | 863 | *pDevHandle = MR_PdDevHandleGet(pd, map); |
| 873 | − else { | |
| 874 | − /* set dev handle as invalid. */ | |
| 875 | − *pDevHandle = cpu_to_le16(MR_PD_INVALID); | |
| 864 | + *pPdInterface = MR_PdInterfaceTypeGet(pd, map); | |
| 865 | + /* get second pd also for raid 1/10 fast path writes*/ | |
| 866 | + if (instance->is_ventura && | |
| 867 | + (raid->level == 1) && | |
| 868 | + !io_info->isRead) { | |
| 869 | + r1_alt_pd = MR_ArPdGet(arRef, physArm + 1, map); | |
| 870 | + if (r1_alt_pd != MR_PD_INVALID) | |
| 871 | + io_info->r1_alt_dev_handle = | |
| 872 | + MR_PdDevHandleGet(r1_alt_pd, map); | |
| 873 | + } | |
| 874 | + } else { | |
| 876 | 875 | if ((raid->level >= 5) && |
| 877 | 876 | ((fusion->adapter_type == THUNDERBOLT_SERIES) || |
| 878 | 877 | ((fusion->adapter_type == INVADER_SERIES) && |
| 879 | 878 | (raid->regTypeReqOnRead != REGION_TYPE_UNUSED)))) |
| 880 | − pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE; | |
| 879 | + pRAID_Context->reg_lock_flags = REGION_TYPE_EXCLUSIVE; | |
| 881 | 880 | else if (raid->level == 1) { |
| 882 | 881 | /* Get alternate Pd. */ |
| 883 | 882 | physArm = physArm + 1; |
| 884 | 883 | pd = MR_ArPdGet(arRef, physArm, map); |
| 885 | − if (pd != MR_PD_INVALID) | |
| 884 | + if (pd != MR_PD_INVALID) { | |
| 886 | 885 | /* Get dev handle from Pd */ |
| 887 | 886 | *pDevHandle = MR_PdDevHandleGet(pd, map); |
| 887 | + *pPdInterface = MR_PdInterfaceTypeGet(pd, map); | |
| 888 | + } | |
| 888 | 889 | } |
| 889 | 890 | } |
| 890 | 891 | |
| 891 | 892 | *pdBlock += stripRef + le64_to_cpu(MR_LdSpanPtrGet(ld, span, map)->startBlk); |
| 892 | − pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | | |
| 893 | − physArm; | |
| 894 | − io_info->span_arm = pRAID_Context->spanArm; | |
| 893 | + if (instance->is_ventura) { | |
| 894 | + ((struct RAID_CONTEXT_G35 *)pRAID_Context)->span_arm = | |
| 895 | + (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; | |
| 896 | + io_info->span_arm = | |
| 897 | + (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; | |
| 898 | + } else { | |
| 899 | + pRAID_Context->span_arm = | |
| 900 | + (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; | |
| 901 | + io_info->span_arm = pRAID_Context->span_arm; | |
| 902 | + } | |
| 903 | + io_info->pd_after_lb = pd; | |
| 895 | 904 | return retval; |
| 896 | 905 | } |
| 897 | 906 | |
| @@ -912,7 +921,7 @@ MR_BuildRaidContext(struct megasas_instance *instance, · 14 unmodified lines | ||
| 912 | 921 | { |
| 913 | 922 | struct fusion_context *fusion; |
| 914 | 923 | struct MR_LD_RAID *raid; |
| 915 | − u32 ld, stripSize, stripe_mask; | |
| 924 | + u32 stripSize, stripe_mask; | |
| 916 | 925 | u64 endLba, endStrip, endRow, start_row, start_strip; |
| 917 | 926 | u64 regStart; |
| 918 | 927 | u32 regSize; |
| @@ -924,6 +933,7 @@ MR_BuildRaidContext(struct megasas_instance *instance, · 5 unmodified lines | ||
| 924 | 933 | u8 retval = 0; |
| 925 | 934 | u8 startlba_span = SPAN_INVALID; |
| 926 | 935 | u64 *pdBlock = &io_info->pdBlock; |
| 936 | + u16 ld; | |
| 927 | 937 | |
| 928 | 938 | ldStartBlock = io_info->ldStartBlock; |
| 929 | 939 | numBlocks = io_info->numBlocks; |
| @@ -935,6 +945,8 @@ MR_BuildRaidContext(struct megasas_instance *instance, · 5 unmodified lines | ||
| 935 | 945 | |
| 936 | 946 | ld = MR_TargetIdToLdGet(ldTgtId, map); |
| 937 | 947 | raid = MR_LdRaidGet(ld, map); |
| 948 | + /*check read ahead bit*/ | |
| 949 | + io_info->ra_capable = raid->capability.ra_capable; | |
| 938 | 950 | |
| 939 | 951 | /* |
| 940 | 952 | * if rowDataSize @RAID map and spanRowDataSize @SPAN INFO are zero |
| @@ -996,17 +1008,6 @@ MR_BuildRaidContext(struct megasas_instance *instance, · 55 unmodified lines | ||
| 996 | 1008 | } |
| 997 | 1009 | io_info->start_span = startlba_span; |
| 998 | 1010 | io_info->start_row = start_row; |
| 999 | −#if SPAN_DEBUG | |
| 1000 | − dev_dbg(&instance->pdev->dev, "Check Span number from %s %d" | |
| 1001 | − "for row 0x%llx, start strip 0x%llx end strip 0x%llx" | |
| 1002 | − " span 0x%x\n", __func__, __LINE__, | |
| 1003 | − (unsigned long long)start_row, | |
| 1004 | − (unsigned long long)start_strip, | |
| 1005 | − (unsigned long long)endStrip, startlba_span); | |
| 1006 | − dev_dbg(&instance->pdev->dev, "start_row 0x%llx endRow 0x%llx" | |
| 1007 | − "Start span 0x%x\n", (unsigned long long)start_row, | |
| 1008 | − (unsigned long long)endRow, startlba_span); | |
| 1009 | −#endif | |
| 1010 | 1011 | } else { |
| 1011 | 1012 | start_row = mega_div64_32(start_strip, raid->rowDataSize); |
| 1012 | 1013 | endRow = mega_div64_32(endStrip, raid->rowDataSize); |
| @@ -1093,20 +1094,20 @@ MR_BuildRaidContext(struct megasas_instance *instance, · 80 unmodified lines | ||
| 1093 | 1094 | regSize += stripSize; |
| 1094 | 1095 | } |
| 1095 | 1096 | |
| 1096 | − pRAID_Context->timeoutValue = | |
| 1097 | + pRAID_Context->timeout_value = | |
| 1097 | 1098 | cpu_to_le16(raid->fpIoTimeoutForLd ? |
| 1098 | 1099 | raid->fpIoTimeoutForLd : |
| 1099 | 1100 | map->raidMap.fpPdIoTimeoutSec); |
| 1100 | 1101 | if (fusion->adapter_type == INVADER_SERIES) |
| 1101 | − pRAID_Context->regLockFlags = (isRead) ? | |
| 1102 | + pRAID_Context->reg_lock_flags = (isRead) ? | |
| 1102 | 1103 | raid->regTypeReqOnRead : raid->regTypeReqOnWrite; |
| 1103 | − else | |
| 1104 | − pRAID_Context->regLockFlags = (isRead) ? | |
| 1104 | + else if (!instance->is_ventura) | |
| 1105 | + pRAID_Context->reg_lock_flags = (isRead) ? | |
| 1105 | 1106 | REGION_TYPE_SHARED_READ : raid->regTypeReqOnWrite; |
| 1106 | − pRAID_Context->VirtualDiskTgtId = raid->targetId; | |
| 1107 | − pRAID_Context->regLockRowLBA = cpu_to_le64(regStart); | |
| 1108 | − pRAID_Context->regLockLength = cpu_to_le32(regSize); | |
| 1109 | − pRAID_Context->configSeqNum = raid->seqNum; | |
| 1107 | + pRAID_Context->virtual_disk_tgt_id = raid->targetId; | |
| 1108 | + pRAID_Context->reg_lock_row_lba = cpu_to_le64(regStart); | |
| 1109 | + pRAID_Context->reg_lock_length = cpu_to_le32(regSize); | |
| 1110 | + pRAID_Context->config_seq_num = raid->seqNum; | |
| 1110 | 1111 | /* save pointer to raid->LUN array */ |
| 1111 | 1112 | *raidLUN = raid->LUN; |
| 1112 | 1113 | |
| @@ -1122,7 +1123,7 @@ MR_BuildRaidContext(struct megasas_instance *instance, · 9 unmodified lines | ||
| 1122 | 1123 | ref_in_start_stripe, io_info, |
| 1123 | 1124 | pRAID_Context, map); |
| 1124 | 1125 | /* If IO on an invalid Pd, then FP is not possible.*/ |
| 1125 | − if (io_info->devHandle == cpu_to_le16(MR_PD_INVALID)) | |
| 1126 | + if (io_info->devHandle == MR_DEVHANDLE_INVALID) | |
| 1126 | 1127 | io_info->fpOkForIo = FALSE; |
| 1127 | 1128 | return retval; |
| 1128 | 1129 | } else if (isRead) { |
| @@ -1140,12 +1141,6 @@ MR_BuildRaidContext(struct megasas_instance *instance, · 11 unmodified lines | ||
| 1140 | 1141 | return TRUE; |
| 1141 | 1142 | } |
| 1142 | 1143 | } |
| 1143 | − | |
| 1144 | −#if SPAN_DEBUG | |
| 1145 | − /* Just for testing what arm we get for strip.*/ | |
| 1146 | − if (io_info->IoforUnevenSpan) | |
| 1147 | − get_arm_from_strip(instance, ld, start_strip, map); | |
| 1148 | −#endif | |
| 1149 | 1144 | return TRUE; |
| 1150 | 1145 | } |
| 1151 | 1146 | |
| @@ -1259,10 +1254,6 @@ void mr_update_span_set(struct MR_DRV_RAID_MAP_ALL *map, · 107 unmodified lines | ||
| 1259 | 1254 | break; |
| 1260 | 1255 | } |
| 1261 | 1256 | } |
| 1262 | −#if SPAN_DEBUG | |
| 1263 | − getSpanInfo(map, ldSpanInfo); | |
| 1264 | −#endif | |
| 1265 | − | |
| 1266 | 1257 | } |
| 1267 | 1258 | |
| 1268 | 1259 | void mr_update_load_balance_params(struct MR_DRV_RAID_MAP_ALL *drv_map, |
| @@ -1293,11 +1284,12 @@ void mr_update_load_balance_params(struct MR_DRV_RAID_MAP_ALL *drv_map, · 24 unmodified lines | ||
| 1293 | 1284 | } |
| 1294 | 1285 | |
| 1295 | 1286 | u8 megasas_get_best_arm_pd(struct megasas_instance *instance, |
| 1296 | − struct LD_LOAD_BALANCE_INFO *lbInfo, struct IO_REQUEST_INFO *io_info) | |
| 1287 | + struct LD_LOAD_BALANCE_INFO *lbInfo, | |
| 1288 | + struct IO_REQUEST_INFO *io_info, | |
| 1289 | + struct MR_DRV_RAID_MAP_ALL *drv_map) | |
| 1297 | 1290 | { |
| 1298 | − struct fusion_context *fusion; | |
| 1299 | 1291 | struct MR_LD_RAID *raid; |
| 1300 | − struct MR_DRV_RAID_MAP_ALL *drv_map; | |
| 1292 | + u16 pd1_dev_handle; | |
| 1301 | 1293 | u16 pend0, pend1, ld; |
| 1302 | 1294 | u64 diff0, diff1; |
| 1303 | 1295 | u8 bestArm, pd0, pd1, span, arm; |
| @@ -1310,9 +1302,6 @@ u8 megasas_get_best_arm_pd(struct megasas_instance *instance, · 6 unmodified lines | ||
| 1310 | 1302 | >> RAID_CTX_SPANARM_SPAN_SHIFT); |
| 1311 | 1303 | arm = (io_info->span_arm & RAID_CTX_SPANARM_ARM_MASK); |
| 1312 | 1304 | |
| 1313 | − | |
| 1314 | − fusion = instance->ctrl_context; | |
| 1315 | − drv_map = fusion->ld_drv_map[(instance->map_id & 1)]; | |
| 1316 | 1305 | ld = MR_TargetIdToLdGet(io_info->ldTgtId, drv_map); |
| 1317 | 1306 | raid = MR_LdRaidGet(ld, drv_map); |
| 1318 | 1307 | span_row_size = instance->UnevenSpanSupport ? |
| @@ -1323,47 +1312,52 @@ u8 megasas_get_best_arm_pd(struct megasas_instance *instance, · 4 unmodified lines | ||
| 1323 | 1312 | pd1 = MR_ArPdGet(arRef, (arm + 1) >= span_row_size ? |
| 1324 | 1313 | (arm + 1 - span_row_size) : arm + 1, drv_map); |
| 1325 | 1314 | |
| 1326 | − /* get the pending cmds for the data and mirror arms */ | |
| 1327 | − pend0 = atomic_read(&lbInfo->scsi_pending_cmds[pd0]); | |
| 1328 | − pend1 = atomic_read(&lbInfo->scsi_pending_cmds[pd1]); | |
| 1315 | + /* Get PD1 Dev Handle */ | |
| 1316 | + | |
| 1317 | + pd1_dev_handle = MR_PdDevHandleGet(pd1, drv_map); | |
| 1329 | 1318 | |
| 1330 | − /* Determine the disk whose head is nearer to the req. block */ | |
| 1331 | − diff0 = ABS_DIFF(block, lbInfo->last_accessed_block[pd0]); | |
| 1332 | − diff1 = ABS_DIFF(block, lbInfo->last_accessed_block[pd1]); | |
| 1333 | − bestArm = (diff0 <= diff1 ? arm : arm ^ 1); | |
| 1319 | + if (pd1_dev_handle == MR_DEVHANDLE_INVALID) { | |
| 1320 | + bestArm = arm; | |
| 1321 | + } else { | |
| 1322 | + /* get the pending cmds for the data and mirror arms */ | |
| 1323 | + pend0 = atomic_read(&lbInfo->scsi_pending_cmds[pd0]); | |
| 1324 | + pend1 = atomic_read(&lbInfo->scsi_pending_cmds[pd1]); | |
| 1334 | 1325 | |
| 1335 | − if ((bestArm == arm && pend0 > pend1 + lb_pending_cmds) || | |
| 1336 | − (bestArm != arm && pend1 > pend0 + lb_pending_cmds)) | |
| 1337 | − bestArm ^= 1; | |
| 1326 | + /* Determine the disk whose head is nearer to the req. block */ | |
| 1327 | + diff0 = ABS_DIFF(block, lbInfo->last_accessed_block[pd0]); | |
| 1328 | + diff1 = ABS_DIFF(block, lbInfo->last_accessed_block[pd1]); | |
| 1329 | + bestArm = (diff0 <= diff1 ? arm : arm ^ 1); | |
| 1330 | + | |
| 1331 | + /* Make balance count from 16 to 4 to | |
| 1332 | + * keep driver in sync with Firmware | |
| 1333 | + */ | |
| 1334 | + if ((bestArm == arm && pend0 > pend1 + lb_pending_cmds) || | |
| 1335 | + (bestArm != arm && pend1 > pend0 + lb_pending_cmds)) | |
| 1336 | + bestArm ^= 1; | |
| 1337 | + | |
| 1338 | + /* Update the last accessed block on the correct pd */ | |
| 1339 | + io_info->span_arm = | |
| 1340 | + (span << RAID_CTX_SPANARM_SPAN_SHIFT) | bestArm; | |
| 1341 | + io_info->pd_after_lb = (bestArm == arm) ? pd0 : pd1; | |
| 1342 | + } | |
| 1338 | 1343 | |
| 1339 | − /* Update the last accessed block on the correct pd */ | |
| 1340 | − io_info->pd_after_lb = (bestArm == arm) ? pd0 : pd1; | |
| 1341 | 1344 | lbInfo->last_accessed_block[io_info->pd_after_lb] = block + count - 1; |
| 1342 | − io_info->span_arm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | bestArm; | |
| 1343 | −#if SPAN_DEBUG | |
| 1344 | − if (arm != bestArm) | |
| 1345 | − dev_dbg(&instance->pdev->dev, "LSI Debug R1 Load balance " | |
| 1346 | − "occur - span 0x%x arm 0x%x bestArm 0x%x " | |
| 1347 | − "io_info->span_arm 0x%x\n", | |
| 1348 | − span, arm, bestArm, io_info->span_arm); | |
| 1349 | −#endif | |
| 1350 | 1345 | return io_info->pd_after_lb; |
| 1351 | 1346 | } |
| 1352 | 1347 | |
| 1353 | 1348 | __le16 get_updated_dev_handle(struct megasas_instance *instance, |
| 1354 | − struct LD_LOAD_BALANCE_INFO *lbInfo, struct IO_REQUEST_INFO *io_info) | |
| 1349 | + struct LD_LOAD_BALANCE_INFO *lbInfo, | |
| 1350 | + struct IO_REQUEST_INFO *io_info, | |
| 1351 | + struct MR_DRV_RAID_MAP_ALL *drv_map) | |
| 1355 | 1352 | { |
| 1356 | 1353 | u8 arm_pd; |
| 1357 | 1354 | __le16 devHandle; |
| 1358 | − struct fusion_context *fusion; | |
| 1359 | − struct MR_DRV_RAID_MAP_ALL *drv_map; | |
| 1360 | − | |
| 1361 | − fusion = instance->ctrl_context; | |
| 1362 | − drv_map = fusion->ld_drv_map[(instance->map_id & 1)]; | |
| 1363 | 1355 | |
| 1364 | 1356 | /* get best new arm (PD ID) */ |
| 1365 | − arm_pd = megasas_get_best_arm_pd(instance, lbInfo, io_info); | |
| 1357 | + arm_pd = megasas_get_best_arm_pd(instance, lbInfo, io_info, drv_map); | |
| 1366 | 1358 | devHandle = MR_PdDevHandleGet(arm_pd, drv_map); |
| 1359 | + io_info->pd_interface = MR_PdInterfaceTypeGet(arm_pd, drv_map); | |
| 1367 | 1360 | atomic_inc(&lbInfo->scsi_pending_cmds[arm_pd]); |
| 1361 | + | |
| 1368 | 1362 | return devHandle; |
| 1369 | 1363 | } |
| @@ -47,6 +47,7 @@ · 46 unmodified lines | ||
| 47 | 47 | #include <linux/blkdev.h> |
| 48 | 48 | #include <linux/mutex.h> |
| 49 | 49 | #include <linux/poll.h> |
| 50 | +#include <linux/vmalloc.h> | |
| 50 | 51 | |
| 51 | 52 | #include <scsi/scsi.h> |
| 52 | 53 | #include <scsi/scsi_cmnd.h> |
| @@ -181,32 +182,44 @@ inline void megasas_return_cmd_fusion(struct megasas_instance *instance, · 128 unmodified lines | ||
| 181 | 182 | struct megasas_cmd_fusion *cmd) |
| 182 | 183 | { |
| 183 | 184 | cmd->scmd = NULL; |
| 184 | − memset(cmd->io_request, 0, sizeof(struct MPI2_RAID_SCSI_IO_REQUEST)); | |
| 185 | + memset(cmd->io_request, 0, MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE); | |
| 186 | + cmd->r1_alt_dev_handle = MR_DEVHANDLE_INVALID; | |
| 187 | + cmd->cmd_completed = false; | |
| 185 | 188 | } |
| 186 | 189 | |
| 187 | 190 | /** |
| 188 | 191 | * megasas_fire_cmd_fusion - Sends command to the FW |
| 192 | + * @instance: Adapter soft state | |
| 193 | + * @req_desc: 32bit or 64bit Request descriptor | |
| 194 | + * | |
| 195 | + * Perform PCI Write. Ventura supports 32 bit Descriptor. | |
| 196 | + * Prior to Ventura (12G) MR controller supports 64 bit Descriptor. | |
| 189 | 197 | */ |
| 198 | + | |
| 190 | 199 | static void |
| 191 | 200 | megasas_fire_cmd_fusion(struct megasas_instance *instance, |
| 192 | 201 | union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc) |
| 193 | 202 | { |
| 203 | + if (instance->is_ventura) | |
| 204 | + writel(le32_to_cpu(req_desc->u.low), | |
| 205 | + &instance->reg_set->inbound_single_queue_port); | |
| 206 | + else { | |
| 194 | 207 | #if defined(writeq) && defined(CONFIG_64BIT) |
| 195 | − u64 req_data = (((u64)le32_to_cpu(req_desc->u.high) << 32) | | |
| 196 | − le32_to_cpu(req_desc->u.low)); | |
| 208 | + u64 req_data = (((u64)le32_to_cpu(req_desc->u.high) << 32) | | |
| 209 | + le32_to_cpu(req_desc->u.low)); | |
| 197 | 210 | |
| 198 | − writeq(req_data, &instance->reg_set->inbound_low_queue_port); | |
| 211 | + writeq(req_data, &instance->reg_set->inbound_low_queue_port); | |
| 199 | 212 | #else |
| 200 | − unsigned long flags; | |
| 201 | − | |
| 202 | − spin_lock_irqsave(&instance->hba_lock, flags); | |
| 203 | − writel(le32_to_cpu(req_desc->u.low), | |
| 204 | − &instance->reg_set->inbound_low_queue_port); | |
| 205 | − writel(le32_to_cpu(req_desc->u.high), | |
| 206 | − &instance->reg_set->inbound_high_queue_port); | |
| 207 | − mmiowb(); | |
| 208 | − spin_unlock_irqrestore(&instance->hba_lock, flags); | |
| 213 | + unsigned long flags; | |
| 214 | + spin_lock_irqsave(&instance->hba_lock, flags); | |
| 215 | + writel(le32_to_cpu(req_desc->u.low), | |
| 216 | + &instance->reg_set->inbound_low_queue_port); | |
| 217 | + writel(le32_to_cpu(req_desc->u.high), | |
| 218 | + &instance->reg_set->inbound_high_queue_port); | |
| 219 | + mmiowb(); | |
| 220 | + spin_unlock_irqrestore(&instance->hba_lock, flags); | |
| 209 | 221 | #endif |
| 222 | + } | |
| 210 | 223 | } |
| 211 | 224 | |
| 212 | 225 | /** |
| @@ -229,7 +242,10 @@ megasas_fusion_update_can_queue(struct megasas_instance *instance, int fw_boot_c · 16 unmodified lines | ||
| 229 | 242 | |
| 230 | 243 | reg_set = instance->reg_set; |
| 231 | 244 | |
| 232 | − cur_max_fw_cmds = readl(&instance->reg_set->outbound_scratch_pad_3) & 0x00FFFF; | |
| 245 | + /* ventura FW does not fill outbound_scratch_pad_3 with queue depth */ | |
| 246 | + if (!instance->is_ventura) | |
| 247 | + cur_max_fw_cmds = | |
| 248 | + readl(&instance->reg_set->outbound_scratch_pad_3) & 0x00FFFF; | |
| 233 | 249 | |
| 234 | 250 | if (dual_qdepth_disable || !cur_max_fw_cmds) |
| 235 | 251 | cur_max_fw_cmds = instance->instancet->read_fw_status_reg(reg_set) & 0x00FFFF; |
| @@ -243,7 +259,7 @@ megasas_fusion_update_can_queue(struct megasas_instance *instance, int fw_boot_c · 7 unmodified lines | ||
| 243 | 259 | |
| 244 | 260 | if (fw_boot_context == OCR_CONTEXT) { |
| 245 | 261 | cur_max_fw_cmds = cur_max_fw_cmds - 1; |
| 246 | − if (cur_max_fw_cmds <= instance->max_fw_cmds) { | |
| 262 | + if (cur_max_fw_cmds < instance->max_fw_cmds) { | |
| 247 | 263 | instance->cur_can_queue = |
| 248 | 264 | cur_max_fw_cmds - (MEGASAS_FUSION_INTERNAL_CMDS + |
| 249 | 265 | MEGASAS_FUSION_IOCTL_CMDS); |
| @@ -255,7 +271,8 @@ megasas_fusion_update_can_queue(struct megasas_instance *instance, int fw_boot_c · 5 unmodified lines | ||
| 255 | 271 | instance->ldio_threshold = ldio_threshold; |
| 256 | 272 | |
| 257 | 273 | if (!instance->is_rdpq) |
| 258 | − instance->max_fw_cmds = min_t(u16, instance->max_fw_cmds, 1024); | |
| 274 | + instance->max_fw_cmds = | |
| 275 | + min_t(u16, instance->max_fw_cmds, 1024); | |
| 259 | 276 | |
| 260 | 277 | if (reset_devices) |
| 261 | 278 | instance->max_fw_cmds = min(instance->max_fw_cmds, |
| @@ -271,7 +288,14 @@ megasas_fusion_update_can_queue(struct megasas_instance *instance, int fw_boot_c · 9 unmodified lines | ||
| 271 | 288 | (MEGASAS_FUSION_INTERNAL_CMDS + |
| 272 | 289 | MEGASAS_FUSION_IOCTL_CMDS); |
| 273 | 290 | instance->cur_can_queue = instance->max_scsi_cmds; |
| 291 | + instance->host->can_queue = instance->cur_can_queue; | |
| 274 | 292 | } |
| 293 | + | |
| 294 | + if (instance->is_ventura) | |
| 295 | + instance->max_mpt_cmds = | |
| 296 | + instance->max_fw_cmds * RAID_1_PEER_CMDS; | |
| 297 | + else | |
| 298 | + instance->max_mpt_cmds = instance->max_fw_cmds; | |
| 275 | 299 | } |
| 276 | 300 | /** |
| 277 | 301 | * megasas_free_cmds_fusion - Free all the cmds in the free cmd pool |
| @@ -285,7 +309,7 @@ megasas_free_cmds_fusion(struct megasas_instance *instance) · 7 unmodified lines | ||
| 285 | 309 | struct megasas_cmd_fusion *cmd; |
| 286 | 310 | |
| 287 | 311 | /* SG, Sense */ |
| 288 | − for (i = 0; i < instance->max_fw_cmds; i++) { | |
| 312 | + for (i = 0; i < instance->max_mpt_cmds; i++) { | |
| 289 | 313 | cmd = fusion->cmd_list[i]; |
| 290 | 314 | if (cmd) { |
| 291 | 315 | if (cmd->sg_frame) |
| @@ -329,7 +353,7 @@ megasas_free_cmds_fusion(struct megasas_instance *instance) · 37 unmodified lines | ||
| 329 | 353 | |
| 330 | 354 | |
| 331 | 355 | /* cmd_list */ |
| 332 | − for (i = 0; i < instance->max_fw_cmds; i++) | |
| 356 | + for (i = 0; i < instance->max_mpt_cmds; i++) | |
| 333 | 357 | kfree(fusion->cmd_list[i]); |
| 334 | 358 | |
| 335 | 359 | kfree(fusion->cmd_list); |
| @@ -343,7 +367,7 @@ megasas_free_cmds_fusion(struct megasas_instance *instance) · 7 unmodified lines | ||
| 343 | 367 | static int megasas_create_sg_sense_fusion(struct megasas_instance *instance) |
| 344 | 368 | { |
| 345 | 369 | int i; |
| 346 | − u32 max_cmd; | |
| 370 | + u16 max_cmd; | |
| 347 | 371 | struct fusion_context *fusion; |
| 348 | 372 | struct megasas_cmd_fusion *cmd; |
| 349 | 373 | |
| @@ -353,7 +377,8 @@ static int megasas_create_sg_sense_fusion(struct megasas_instance *instance) · 3 unmodified lines | ||
| 353 | 377 | |
| 354 | 378 | fusion->sg_dma_pool = |
| 355 | 379 | pci_pool_create("mr_sg", instance->pdev, |
| 356 | − instance->max_chain_frame_sz, 4, 0); | |
| 380 | + instance->max_chain_frame_sz, | |
| 381 | + MR_DEFAULT_NVME_PAGE_SIZE, 0); | |
| 357 | 382 | /* SCSI_SENSE_BUFFERSIZE = 96 bytes */ |
| 358 | 383 | fusion->sense_dma_pool = |
| 359 | 384 | pci_pool_create("mr_sense", instance->pdev, |
| @@ -381,33 +406,47 @@ static int megasas_create_sg_sense_fusion(struct megasas_instance *instance) · 21 unmodified lines | ||
| 381 | 406 | return -ENOMEM; |
| 382 | 407 | } |
| 383 | 408 | } |
| 409 | + | |
| 410 | + /* create sense buffer for the raid 1/10 fp */ | |
| 411 | + for (i = max_cmd; i < instance->max_mpt_cmds; i++) { | |
| 412 | + cmd = fusion->cmd_list[i]; | |
| 413 | + cmd->sense = pci_pool_alloc(fusion->sense_dma_pool, | |
| 414 | + GFP_KERNEL, &cmd->sense_phys_addr); | |
| 415 | + if (!cmd->sense) { | |
| 416 | + dev_err(&instance->pdev->dev, | |
| 417 | + "Failed from %s %d\n", __func__, __LINE__); | |
| 418 | + return -ENOMEM; | |
| 419 | + } | |
| 420 | + } | |
| 421 | + | |
| 384 | 422 | return 0; |
| 385 | 423 | } |
| 386 | 424 | |
| 387 | 425 | int |
| 388 | 426 | megasas_alloc_cmdlist_fusion(struct megasas_instance *instance) |
| 389 | 427 | { |
| 390 | − u32 max_cmd, i; | |
| 428 | + u32 max_mpt_cmd, i; | |
| 391 | 429 | struct fusion_context *fusion; |
| 392 | 430 | |
| 393 | 431 | fusion = instance->ctrl_context; |
| 394 | 432 | |
| 395 | − max_cmd = instance->max_fw_cmds; | |
| 433 | + max_mpt_cmd = instance->max_mpt_cmds; | |
| 396 | 434 | |
| 397 | 435 | /* |
| 398 | 436 | * fusion->cmd_list is an array of struct megasas_cmd_fusion pointers. |
| 399 | 437 | * Allocate the dynamic array first and then allocate individual |
| 400 | 438 | * commands. |
| 401 | 439 | */ |
| 402 | − fusion->cmd_list = kzalloc(sizeof(struct megasas_cmd_fusion *) * max_cmd, | |
| 403 | − GFP_KERNEL); | |
| 440 | + fusion->cmd_list = | |
| 441 | + kzalloc(sizeof(struct megasas_cmd_fusion *) * max_mpt_cmd, | |
| 442 | + GFP_KERNEL); | |
| 404 | 443 | if (!fusion->cmd_list) { |
| 405 | 444 | dev_err(&instance->pdev->dev, |
| 406 | 445 | "Failed from %s %d\n", __func__, __LINE__); |
| 407 | 446 | return -ENOMEM; |
| 408 | 447 | } |
| 409 | 448 | |
| 410 | − for (i = 0; i < max_cmd; i++) { | |
| 449 | + for (i = 0; i < max_mpt_cmd; i++) { | |
| 411 | 450 | fusion->cmd_list[i] = kzalloc(sizeof(struct megasas_cmd_fusion), |
| 412 | 451 | GFP_KERNEL); |
| 413 | 452 | if (!fusion->cmd_list[i]) { |
| @@ -539,7 +578,7 @@ megasas_alloc_rdpq_fusion(struct megasas_instance *instance) · 125 unmodified lines | ||
| 539 | 578 | } |
| 540 | 579 | |
| 541 | 580 | fusion->rdpq_virt[i].RDPQBaseAddress = |
| 542 | − fusion->reply_frames_desc_phys[i]; | |
| 581 | + cpu_to_le64(fusion->reply_frames_desc_phys[i]); | |
| 543 | 582 | |
| 544 | 583 | reply_desc = fusion->reply_frames_desc[i]; |
| 545 | 584 | for (j = 0; j < fusion->reply_q_depth; j++, reply_desc++) |
| @@ -642,13 +681,14 @@ megasas_alloc_cmds_fusion(struct megasas_instance *instance) · 96 unmodified lines | ||
| 642 | 681 | */ |
| 643 | 682 | |
| 644 | 683 | /* SMID 0 is reserved. Set SMID/index from 1 */ |
| 645 | − for (i = 0; i < instance->max_fw_cmds; i++) { | |
| 684 | + for (i = 0; i < instance->max_mpt_cmds; i++) { | |
| 646 | 685 | cmd = fusion->cmd_list[i]; |
| 647 | 686 | offset = MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE * i; |
| 648 | 687 | memset(cmd, 0, sizeof(struct megasas_cmd_fusion)); |
| 649 | 688 | cmd->index = i + 1; |
| 650 | 689 | cmd->scmd = NULL; |
| 651 | − cmd->sync_cmd_idx = (i >= instance->max_scsi_cmds) ? | |
| 690 | + cmd->sync_cmd_idx = | |
| 691 | + (i >= instance->max_scsi_cmds && i < instance->max_fw_cmds) ? | |
| 652 | 692 | (i - instance->max_scsi_cmds) : |
| 653 | 693 | (u32)ULONG_MAX; /* Set to Invalid */ |
| 654 | 694 | cmd->instance = instance; |
| @@ -658,6 +698,7 @@ megasas_alloc_cmds_fusion(struct megasas_instance *instance) · 3 unmodified lines | ||
| 658 | 698 | memset(cmd->io_request, 0, |
| 659 | 699 | sizeof(struct MPI2_RAID_SCSI_IO_REQUEST)); |
| 660 | 700 | cmd->io_request_phys_addr = io_req_base_phys + offset; |
| 701 | + cmd->r1_alt_dev_handle = MR_DEVHANDLE_INVALID; | |
| 661 | 702 | } |
| 662 | 703 | |
| 663 | 704 | if (megasas_create_sg_sense_fusion(instance)) |
| @@ -725,6 +766,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) · 61 unmodified lines | ||
| 725 | 766 | const char *sys_info; |
| 726 | 767 | MFI_CAPABILITIES *drv_ops; |
| 727 | 768 | u32 scratch_pad_2; |
| 769 | + unsigned long flags; | |
| 728 | 770 | |
| 729 | 771 | fusion = instance->ctrl_context; |
| 730 | 772 | |
| @@ -781,6 +823,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) · 50 unmodified lines | ||
| 781 | 823 | MPI2_IOCINIT_MSGFLAG_RDPQ_ARRAY_MODE : 0; |
| 782 | 824 | IOCInitMessage->SystemRequestFrameBaseAddress = cpu_to_le64(fusion->io_request_frames_phys); |
| 783 | 825 | IOCInitMessage->HostMSIxVectors = instance->msix_vectors; |
| 826 | + IOCInitMessage->HostPageSize = MR_DEFAULT_NVME_PAGE_SHIFT; | |
| 784 | 827 | init_frame = (struct megasas_init_frame *)cmd->frame; |
| 785 | 828 | memset(init_frame, 0, MEGAMFI_FRAME_SIZE); |
| 786 | 829 | |
| @@ -796,7 +839,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) · 9 unmodified lines | ||
| 796 | 839 | drv_ops = (MFI_CAPABILITIES *) &(init_frame->driver_operations); |
| 797 | 840 | |
| 798 | 841 | /* driver support Extended MSIX */ |
| 799 | − if (fusion->adapter_type == INVADER_SERIES) | |
| 842 | + if (fusion->adapter_type >= INVADER_SERIES) | |
| 800 | 843 | drv_ops->mfi_capabilities.support_additional_msix = 1; |
| 801 | 844 | /* driver supports HA / Remote LUN over Fast Path interface */ |
| 802 | 845 | drv_ops->mfi_capabilities.support_fp_remote_lun = 1; |
| @@ -813,6 +856,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) · 10 unmodified lines | ||
| 813 | 856 | drv_ops->mfi_capabilities.support_ext_queue_depth = 1; |
| 814 | 857 | |
| 815 | 858 | drv_ops->mfi_capabilities.support_qd_throttling = 1; |
| 859 | + drv_ops->mfi_capabilities.support_pd_map_target_id = 1; | |
| 816 | 860 | /* Convert capability to LE32 */ |
| 817 | 861 | cpu_to_le32s((u32 *)&init_frame->driver_operations.mfi_capabilities); |
| 818 | 862 | |
| @@ -850,7 +894,14 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) · 31 unmodified lines | ||
| 850 | 894 | break; |
| 851 | 895 | } |
| 852 | 896 | |
| 853 | − megasas_fire_cmd_fusion(instance, &req_desc); | |
| 897 | + /* For Ventura also IOC INIT required 64 bit Descriptor write. */ | |
| 898 | + spin_lock_irqsave(&instance->hba_lock, flags); | |
| 899 | + writel(le32_to_cpu(req_desc.u.low), | |
| 900 | + &instance->reg_set->inbound_low_queue_port); | |
| 901 | + writel(le32_to_cpu(req_desc.u.high), | |
| 902 | + &instance->reg_set->inbound_high_queue_port); | |
| 903 | + mmiowb(); | |
| 904 | + spin_unlock_irqrestore(&instance->hba_lock, flags); | |
| 854 | 905 | |
| 855 | 906 | wait_and_poll(instance, cmd, MFI_POLL_TIMEOUT_SECS); |
| 856 | 907 | |
| @@ -1009,11 +1060,6 @@ megasas_get_ld_map_info(struct megasas_instance *instance) · 152 unmodified lines | ||
| 1009 | 1060 | |
| 1010 | 1061 | memset(ci, 0, fusion->max_map_sz); |
| 1011 | 1062 | memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); |
| 1012 | −#if VD_EXT_DEBUG | |
| 1013 | − dev_dbg(&instance->pdev->dev, | |
| 1014 | − "%s sending MR_DCMD_LD_MAP_GET_INFO with size %d\n", | |
| 1015 | − __func__, cpu_to_le32(size_map_info)); | |
| 1016 | −#endif | |
| 1017 | 1063 | dcmd->cmd = MFI_CMD_DCMD; |
| 1018 | 1064 | dcmd->cmd_status = 0xFF; |
| 1019 | 1065 | dcmd->sge_count = 1; |
| @@ -1065,10 +1111,11 @@ megasas_get_map_info(struct megasas_instance *instance) · 45 unmodified lines | ||
| 1065 | 1111 | int |
| 1066 | 1112 | megasas_sync_map_info(struct megasas_instance *instance) |
| 1067 | 1113 | { |
| 1068 | − int ret = 0, i; | |
| 1114 | + int i; | |
| 1069 | 1115 | struct megasas_cmd *cmd; |
| 1070 | 1116 | struct megasas_dcmd_frame *dcmd; |
| 1071 | − u32 size_sync_info, num_lds; | |
| 1117 | + u16 num_lds; | |
| 1118 | + u32 size_sync_info; | |
| 1072 | 1119 | struct fusion_context *fusion; |
| 1073 | 1120 | struct MR_LD_TARGET_SYNC *ci = NULL; |
| 1074 | 1121 | struct MR_DRV_RAID_MAP_ALL *map; |
| @@ -1134,7 +1181,7 @@ megasas_sync_map_info(struct megasas_instance *instance) · 59 unmodified lines | ||
| 1134 | 1181 | |
| 1135 | 1182 | instance->instancet->issue_dcmd(instance, cmd); |
| 1136 | 1183 | |
| 1137 | − return ret; | |
| 1184 | + return 0; | |
| 1138 | 1185 | } |
| 1139 | 1186 | |
| 1140 | 1187 | /* |
| @@ -1220,7 +1267,8 @@ megasas_init_adapter_fusion(struct megasas_instance *instance) · 79 unmodified lines | ||
| 1220 | 1267 | { |
| 1221 | 1268 | struct megasas_register_set __iomem *reg_set; |
| 1222 | 1269 | struct fusion_context *fusion; |
| 1223 | − u32 max_cmd, scratch_pad_2; | |
| 1270 | + u16 max_cmd; | |
| 1271 | + u32 scratch_pad_2; | |
| 1224 | 1272 | int i = 0, count; |
| 1225 | 1273 | |
| 1226 | 1274 | fusion = instance->ctrl_context; |
| @@ -1229,13 +1277,6 @@ megasas_init_adapter_fusion(struct megasas_instance *instance) · 2 unmodified lines | ||
| 1229 | 1277 | |
| 1230 | 1278 | megasas_fusion_update_can_queue(instance, PROBE_CONTEXT); |
| 1231 | 1279 | |
| 1232 | − /* | |
| 1233 | − * Reduce the max supported cmds by 1. This is to ensure that the | |
| 1234 | − * reply_q_sz (1 more than the max cmd that driver may send) | |
| 1235 | − * does not exceed max cmds that the FW can support | |
| 1236 | − */ | |
| 1237 | − instance->max_fw_cmds = instance->max_fw_cmds-1; | |
| 1238 | − | |
| 1239 | 1280 | /* |
| 1240 | 1281 | * Only Driver's internal DCMDs and IOCTL DCMDs needs to have MFI frames |
| 1241 | 1282 | */ |
| @@ -1247,12 +1288,12 @@ megasas_init_adapter_fusion(struct megasas_instance *instance) · 5 unmodified lines | ||
| 1247 | 1288 | fusion->reply_q_depth = 2 * (((max_cmd + 1 + 15)/16)*16); |
| 1248 | 1289 | |
| 1249 | 1290 | fusion->request_alloc_sz = |
| 1250 | − sizeof(union MEGASAS_REQUEST_DESCRIPTOR_UNION) *max_cmd; | |
| 1291 | + sizeof(union MEGASAS_REQUEST_DESCRIPTOR_UNION) * instance->max_mpt_cmds; | |
| 1251 | 1292 | fusion->reply_alloc_sz = sizeof(union MPI2_REPLY_DESCRIPTORS_UNION) |
| 1252 | 1293 | *(fusion->reply_q_depth); |
| 1253 | 1294 | fusion->io_frames_alloc_sz = MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE + |
| 1254 | − (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE * | |
| 1255 | − (max_cmd + 1)); /* Extra 1 for SMID 0 */ | |
| 1295 | + (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE | |
| 1296 | + * (instance->max_mpt_cmds + 1)); /* Extra 1 for SMID 0 */ | |
| 1256 | 1297 | |
| 1257 | 1298 | scratch_pad_2 = readl(&instance->reg_set->outbound_scratch_pad_2); |
| 1258 | 1299 | /* If scratch_pad_2 & MEGASAS_MAX_CHAIN_SIZE_UNITS_MASK is set, |
| @@ -1302,7 +1343,7 @@ megasas_init_adapter_fusion(struct megasas_instance *instance) · 43 unmodified lines | ||
| 1302 | 1343 | fusion->last_reply_idx[i] = 0; |
| 1303 | 1344 | |
| 1304 | 1345 | /* |
| 1305 | − * For fusion adapters, 3 commands for IOCTL and 5 commands | |
| 1346 | + * For fusion adapters, 3 commands for IOCTL and 8 commands | |
| 1306 | 1347 | * for driver's internal DCMDs. |
| 1307 | 1348 | */ |
| 1308 | 1349 | instance->max_scsi_cmds = instance->max_fw_cmds - |
| @@ -1331,6 +1372,7 @@ megasas_init_adapter_fusion(struct megasas_instance *instance) · 22 unmodified lines | ||
| 1331 | 1372 | } |
| 1332 | 1373 | |
| 1333 | 1374 | instance->flag_ieee = 1; |
| 1375 | + instance->r1_ldio_hint_default = MR_R1_LDIO_PIGGYBACK_DEFAULT; | |
| 1334 | 1376 | fusion->fast_path_io = 0; |
| 1335 | 1377 | |
| 1336 | 1378 | fusion->drv_map_pages = get_order(fusion->drv_map_sz); |
| @@ -1388,96 +1430,348 @@ fail_alloc_mfi_cmds: · 51 unmodified lines | ||
| 1388 | 1430 | */ |
| 1389 | 1431 | |
| 1390 | 1432 | void |
| 1391 | −map_cmd_status(struct megasas_cmd_fusion *cmd, u8 status, u8 ext_status) | |
| 1433 | +map_cmd_status(struct fusion_context *fusion, | |
| 1434 | + struct scsi_cmnd *scmd, u8 status, u8 ext_status, | |
| 1435 | + u32 data_length, u8 *sense) | |
| 1392 | 1436 | { |
| 1437 | + u8 cmd_type; | |
| 1438 | + int resid; | |
| 1393 | 1439 | |
| 1440 | + cmd_type = megasas_cmd_type(scmd); | |
| 1394 | 1441 | switch (status) { |
| 1395 | 1442 | |
| 1396 | 1443 | case MFI_STAT_OK: |
| 1397 | − cmd->scmd->result = DID_OK << 16; | |
| 1444 | + scmd->result = DID_OK << 16; | |
| 1398 | 1445 | break; |
| 1399 | 1446 | |
| 1400 | 1447 | case MFI_STAT_SCSI_IO_FAILED: |
| 1401 | 1448 | case MFI_STAT_LD_INIT_IN_PROGRESS: |
| 1402 | − cmd->scmd->result = (DID_ERROR << 16) | ext_status; | |
| 1449 | + scmd->result = (DID_ERROR << 16) | ext_status; | |
| 1403 | 1450 | break; |
| 1404 | 1451 | |
| 1405 | 1452 | case MFI_STAT_SCSI_DONE_WITH_ERROR: |
| 1406 | 1453 | |
| 1407 | − cmd->scmd->result = (DID_OK << 16) | ext_status; | |
| 1454 | + scmd->result = (DID_OK << 16) | ext_status; | |
| 1408 | 1455 | if (ext_status == SAM_STAT_CHECK_CONDITION) { |
| 1409 | − memset(cmd->scmd->sense_buffer, 0, | |
| 1456 | + memset(scmd->sense_buffer, 0, | |
| 1410 | 1457 | SCSI_SENSE_BUFFERSIZE); |
| 1411 | − memcpy(cmd->scmd->sense_buffer, cmd->sense, | |
| 1458 | + memcpy(scmd->sense_buffer, sense, | |
| 1412 | 1459 | SCSI_SENSE_BUFFERSIZE); |
| 1413 | − cmd->scmd->result |= DRIVER_SENSE << 24; | |
| 1460 | + scmd->result |= DRIVER_SENSE << 24; | |
| 1414 | 1461 | } |
| 1462 | + | |
| 1463 | + /* | |
| 1464 | + * If the IO request is partially completed, then MR FW will | |
| 1465 | + * update "io_request->DataLength" field with actual number of | |
| 1466 | + * bytes transferred.Driver will set residual bytes count in | |
| 1467 | + * SCSI command structure. | |
| 1468 | + */ | |
| 1469 | + resid = (scsi_bufflen(scmd) - data_length); | |
| 1470 | + scsi_set_resid(scmd, resid); | |
| 1471 | + | |
| 1472 | + if (resid && | |
| 1473 | + ((cmd_type == READ_WRITE_LDIO) || | |
| 1474 | + (cmd_type == READ_WRITE_SYSPDIO))) | |
| 1475 | + scmd_printk(KERN_INFO, scmd, "BRCM Debug mfi stat 0x%x, data len" | |
| 1476 | + " requested/completed 0x%x/0x%x\n", | |
| 1477 | + status, scsi_bufflen(scmd), data_length); | |
| 1415 | 1478 | break; |
| 1416 | 1479 | |
| 1417 | 1480 | case MFI_STAT_LD_OFFLINE: |
| 1418 | 1481 | case MFI_STAT_DEVICE_NOT_FOUND: |
| 1419 | − cmd->scmd->result = DID_BAD_TARGET << 16; | |
| 1482 | + scmd->result = DID_BAD_TARGET << 16; | |
| 1420 | 1483 | break; |
| 1421 | 1484 | case MFI_STAT_CONFIG_SEQ_MISMATCH: |
| 1422 | − cmd->scmd->result = DID_IMM_RETRY << 16; | |
| 1485 | + scmd->result = DID_IMM_RETRY << 16; | |
| 1423 | 1486 | break; |
| 1424 | 1487 | default: |
| 1425 | − dev_printk(KERN_DEBUG, &cmd->instance->pdev->dev, "FW status %#x\n", status); | |
| 1426 | − cmd->scmd->result = DID_ERROR << 16; | |
| 1488 | + scmd->result = DID_ERROR << 16; | |
| 1427 | 1489 | break; |
| 1428 | 1490 | } |
| 1429 | 1491 | } |
| 1430 | 1492 | |
| 1493 | +/** | |
| 1494 | + * megasas_is_prp_possible - | |
| 1495 | + * Checks if native NVMe PRPs can be built for the IO | |
| 1496 | + * | |
| 1497 | + * @instance: Adapter soft state | |
| 1498 | + * @scmd: SCSI command from the mid-layer | |
| 1499 | + * @sge_count: scatter gather element count. | |
| 1500 | + * | |
| 1501 | + * Returns: true: PRPs can be built | |
| 1502 | + * false: IEEE SGLs needs to be built | |
| 1503 | + */ | |
| 1504 | +static bool | |
| 1505 | +megasas_is_prp_possible(struct megasas_instance *instance, | |
| 1506 | + struct scsi_cmnd *scmd, int sge_count) | |
| 1507 | +{ | |
| 1508 | + struct fusion_context *fusion; | |
| 1509 | + int i; | |
| 1510 | + u32 data_length = 0; | |
| 1511 | + struct scatterlist *sg_scmd; | |
| 1512 | + bool build_prp = false; | |
| 1513 | + u32 mr_nvme_pg_size; | |
| 1514 | + | |
| 1515 | + mr_nvme_pg_size = max_t(u32, instance->nvme_page_size, | |
| 1516 | + MR_DEFAULT_NVME_PAGE_SIZE); | |
| 1517 | + fusion = instance->ctrl_context; | |
| 1518 | + data_length = scsi_bufflen(scmd); | |
| 1519 | + sg_scmd = scsi_sglist(scmd); | |
| 1520 | + | |
| 1521 | + /* | |
| 1522 | + * NVMe uses one PRP for each page (or part of a page) | |
| 1523 | + * look at the data length - if 4 pages or less then IEEE is OK | |
| 1524 | + * if > 5 pages then we need to build a native SGL | |
| 1525 | + * if > 4 and <= 5 pages, then check physical address of 1st SG entry | |
| 1526 | + * if this first size in the page is >= the residual beyond 4 pages | |
| 1527 | + * then use IEEE, otherwise use native SGL | |
| 1528 | + */ | |
| 1529 | + | |
| 1530 | + if (data_length > (mr_nvme_pg_size * 5)) { | |
| 1531 | + build_prp = true; | |
| 1532 | + } else if ((data_length > (mr_nvme_pg_size * 4)) && | |
| 1533 | + (data_length <= (mr_nvme_pg_size * 5))) { | |
| 1534 | + /* check if 1st SG entry size is < residual beyond 4 pages */ | |
| 1535 | + if (sg_dma_len(sg_scmd) < (data_length - (mr_nvme_pg_size * 4))) | |
| 1536 | + build_prp = true; | |
| 1537 | + } | |
| 1538 | + | |
| 1539 | +/* | |
| 1540 | + * Below code detects gaps/holes in IO data buffers. | |
| 1541 | + * What does holes/gaps mean? | |
| 1542 | + * Any SGE except first one in a SGL starts at non NVME page size | |
| 1543 | + * aligned address OR Any SGE except last one in a SGL ends at | |
| 1544 | + * non NVME page size boundary. | |
| 1545 | + * | |
| 1546 | + * Driver has already informed block layer by setting boundary rules for | |
| 1547 | + * bio merging done at NVME page size boundary calling kernel API | |
| 1548 | + * blk_queue_virt_boundary inside slave_config. | |
| 1549 | + * Still there is possibility of IO coming with holes to driver because of | |
| 1550 | + * IO merging done by IO scheduler. | |
| 1551 | + * | |
| 1552 | + * With SCSI BLK MQ enabled, there will be no IO with holes as there is no | |
| 1553 | + * IO scheduling so no IO merging. | |
| 1554 | + * | |
| 1555 | + * With SCSI BLK MQ disabled, IO scheduler may attempt to merge IOs and | |
| 1556 | + * then sending IOs with holes. | |
| 1557 | + * | |
| 1558 | + * Though driver can request block layer to disable IO merging by calling- | |
| 1559 | + * queue_flag_set_unlocked(QUEUE_FLAG_NOMERGES, sdev->request_queue) but | |
| 1560 | + * user may tune sysfs parameter- nomerges again to 0 or 1. | |
| 1561 | + * | |
| 1562 | + * If in future IO scheduling is enabled with SCSI BLK MQ, | |
| 1563 | + * this algorithm to detect holes will be required in driver | |
| 1564 | + * for SCSI BLK MQ enabled case as well. | |
| 1565 | + * | |
| 1566 | + * | |
| 1567 | + */ | |
| 1568 | + scsi_for_each_sg(scmd, sg_scmd, sge_count, i) { | |
| 1569 | + if ((i != 0) && (i != (sge_count - 1))) { | |
| 1570 | + if (mega_mod64(sg_dma_len(sg_scmd), mr_nvme_pg_size) || | |
| 1571 | + mega_mod64(sg_dma_address(sg_scmd), | |
| 1572 | + mr_nvme_pg_size)) { | |
| 1573 | + build_prp = false; | |
| 1574 | + atomic_inc(&instance->sge_holes_type1); | |
| 1575 | + break; | |
| 1576 | + } | |
| 1577 | + } | |
| 1578 | + | |
| 1579 | + if ((sge_count > 1) && (i == 0)) { | |
| 1580 | + if ((mega_mod64((sg_dma_address(sg_scmd) + | |
| 1581 | + sg_dma_len(sg_scmd)), | |
| 1582 | + mr_nvme_pg_size))) { | |
| 1583 | + build_prp = false; | |
| 1584 | + atomic_inc(&instance->sge_holes_type2); | |
| 1585 | + break; | |
| 1586 | + } | |
| 1587 | + } | |
| 1588 | + | |
| 1589 | + if ((sge_count > 1) && (i == (sge_count - 1))) { | |
| 1590 | + if (mega_mod64(sg_dma_address(sg_scmd), | |
| 1591 | + mr_nvme_pg_size)) { | |
| 1592 | + build_prp = false; | |
| 1593 | + atomic_inc(&instance->sge_holes_type3); | |
| 1594 | + break; | |
| 1595 | + } | |
| 1596 | + } | |
| 1597 | + } | |
| 1598 | + | |
| 1599 | + return build_prp; | |
| 1600 | +} | |
| 1601 | + | |
| 1602 | +/** | |
| 1603 | + * megasas_make_prp_nvme - | |
| 1604 | + * Prepare PRPs(Physical Region Page)- SGLs specific to NVMe drives only | |
| 1605 | + * | |
| 1606 | + * @instance: Adapter soft state | |
| 1607 | + * @scmd: SCSI command from the mid-layer | |
| 1608 | + * @sgl_ptr: SGL to be filled in | |
| 1609 | + * @cmd: Fusion command frame | |
| 1610 | + * @sge_count: scatter gather element count. | |
| 1611 | + * | |
| 1612 | + * Returns: true: PRPs are built | |
| 1613 | + * false: IEEE SGLs needs to be built | |
| 1614 | + */ | |
| 1615 | +static bool | |
| 1616 | +megasas_make_prp_nvme(struct megasas_instance *instance, struct scsi_cmnd *scmd, | |
| 1617 | + struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr, | |
| 1618 | + struct megasas_cmd_fusion *cmd, int sge_count) | |
| 1619 | +{ | |
| 1620 | + int sge_len, offset, num_prp_in_chain = 0; | |
| 1621 | + struct MPI25_IEEE_SGE_CHAIN64 *main_chain_element, *ptr_first_sgl; | |
| 1622 | + u64 *ptr_sgl; | |
| 1623 | + dma_addr_t ptr_sgl_phys; | |
| 1624 | + u64 sge_addr; | |
| 1625 | + u32 page_mask, page_mask_result; | |
| 1626 | + struct scatterlist *sg_scmd; | |
| 1627 | + u32 first_prp_len; | |
| 1628 | + bool build_prp = false; | |
| 1629 | + int data_len = scsi_bufflen(scmd); | |
| 1630 | + struct fusion_context *fusion; | |
| 1631 | + u32 mr_nvme_pg_size = max_t(u32, instance->nvme_page_size, | |
| 1632 | + MR_DEFAULT_NVME_PAGE_SIZE); | |
| 1633 | + | |
| 1634 | + fusion = instance->ctrl_context; | |
| 1635 | + | |
| 1636 | + build_prp = megasas_is_prp_possible(instance, scmd, sge_count); | |
| 1637 | + | |
| 1638 | + if (!build_prp) | |
| 1639 | + return false; | |
| 1640 | + | |
| 1641 | + /* | |
| 1642 | + * Nvme has a very convoluted prp format. One prp is required | |
| 1643 | + * for each page or partial page. Driver need to split up OS sg_list | |
| 1644 | + * entries if it is longer than one page or cross a page | |
| 1645 | + * boundary. Driver also have to insert a PRP list pointer entry as | |
| 1646 | + * the last entry in each physical page of the PRP list. | |
| 1647 | + * | |
| 1648 | + * NOTE: The first PRP "entry" is actually placed in the first | |
| 1649 | + * SGL entry in the main message as IEEE 64 format. The 2nd | |
| 1650 | + * entry in the main message is the chain element, and the rest | |
| 1651 | + * of the PRP entries are built in the contiguous pcie buffer. | |
| 1652 | + */ | |
| 1653 | + page_mask = mr_nvme_pg_size - 1; | |
| 1654 | + ptr_sgl = (u64 *)cmd->sg_frame; | |
| 1655 | + ptr_sgl_phys = cmd->sg_frame_phys_addr; | |
| 1656 | + memset(ptr_sgl, 0, instance->max_chain_frame_sz); | |
| 1657 | + | |
| 1658 | + /* Build chain frame element which holds all prps except first*/ | |
| 1659 | + main_chain_element = (struct MPI25_IEEE_SGE_CHAIN64 *) | |
| 1660 | + ((u8 *)sgl_ptr + sizeof(struct MPI25_IEEE_SGE_CHAIN64)); | |
| 1661 | + | |
| 1662 | + main_chain_element->Address = cpu_to_le64(ptr_sgl_phys); | |
| 1663 | + main_chain_element->NextChainOffset = 0; | |
| 1664 | + main_chain_element->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT | | |
| 1665 | + IEEE_SGE_FLAGS_SYSTEM_ADDR | | |
| 1666 | + MPI26_IEEE_SGE_FLAGS_NSF_NVME_PRP; | |
| 1667 | + | |
| 1668 | + /* Build first prp, sge need not to be page aligned*/ | |
| 1669 | + ptr_first_sgl = sgl_ptr; | |
| 1670 | + sg_scmd = scsi_sglist(scmd); | |
| 1671 | + sge_addr = sg_dma_address(sg_scmd); | |
| 1672 | + sge_len = sg_dma_len(sg_scmd); | |
| 1673 | + | |
| 1674 | + offset = (u32)(sge_addr & page_mask); | |
| 1675 | + first_prp_len = mr_nvme_pg_size - offset; | |
| 1676 | + | |
| 1677 | + ptr_first_sgl->Address = cpu_to_le64(sge_addr); | |
| 1678 | + ptr_first_sgl->Length = cpu_to_le32(first_prp_len); | |
| 1679 | + | |
| 1680 | + data_len -= first_prp_len; | |
| 1681 | + | |
| 1682 | + if (sge_len > first_prp_len) { | |
| 1683 | + sge_addr += first_prp_len; | |
| 1684 | + sge_len -= first_prp_len; | |
| 1685 | + } else if (sge_len == first_prp_len) { | |
| 1686 | + sg_scmd = sg_next(sg_scmd); | |
| 1687 | + sge_addr = sg_dma_address(sg_scmd); | |
| 1688 | + sge_len = sg_dma_len(sg_scmd); | |
| 1689 | + } | |
| 1690 | + | |
| 1691 | + for (;;) { | |
| 1692 | + offset = (u32)(sge_addr & page_mask); | |
| 1693 | + | |
| 1694 | + /* Put PRP pointer due to page boundary*/ | |
| 1695 | + page_mask_result = (uintptr_t)(ptr_sgl + 1) & page_mask; | |
| 1696 | + if (unlikely(!page_mask_result)) { | |
| 1697 | + scmd_printk(KERN_NOTICE, | |
| 1698 | + scmd, "page boundary ptr_sgl: 0x%p\n", | |
| 1699 | + ptr_sgl); | |
| 1700 | + ptr_sgl_phys += 8; | |
| 1701 | + *ptr_sgl = cpu_to_le64(ptr_sgl_phys); | |
| 1702 | + ptr_sgl++; | |
| 1703 | + num_prp_in_chain++; | |
| 1704 | + } | |
| 1705 | + | |
| 1706 | + *ptr_sgl = cpu_to_le64(sge_addr); | |
| 1707 | + ptr_sgl++; | |
| 1708 | + ptr_sgl_phys += 8; | |
| 1709 | + num_prp_in_chain++; | |
| 1710 | + | |
| 1711 | + sge_addr += mr_nvme_pg_size; | |
| 1712 | + sge_len -= mr_nvme_pg_size; | |
| 1713 | + data_len -= mr_nvme_pg_size; | |
| 1714 | + | |
| 1715 | + if (data_len <= 0) | |
| 1716 | + break; | |
| 1717 | + | |
| 1718 | + if (sge_len > 0) | |
| 1719 | + continue; | |
| 1720 | + | |
| 1721 | + sg_scmd = sg_next(sg_scmd); | |
| 1722 | + sge_addr = sg_dma_address(sg_scmd); | |
| 1723 | + sge_len = sg_dma_len(sg_scmd); | |
| 1724 | + } | |
| 1725 | + | |
| 1726 | + main_chain_element->Length = | |
| 1727 | + cpu_to_le32(num_prp_in_chain * sizeof(u64)); | |
| 1728 | + | |
| 1729 | + atomic_inc(&instance->prp_sgl); | |
| 1730 | + return build_prp; | |
| 1731 | +} | |
| 1732 | + | |
| 1431 | 1733 | /** |
| 1432 | 1734 | * megasas_make_sgl_fusion - Prepares 32-bit SGL |
| 1433 | 1735 | * @instance: Adapter soft state |
| 1434 | 1736 | * @scp: SCSI command from the mid-layer |
| 1435 | 1737 | * @sgl_ptr: SGL to be filled in |
| 1436 | 1738 | * @cmd: cmd we are working on |
| 1739 | + * @sge_count sge count | |
| 1437 | 1740 | * |
| 1438 | − * If successful, this function returns the number of SG elements. | |
| 1439 | 1741 | */ |
| 1440 | −static int | |
| 1742 | +static void | |
| 1441 | 1743 | megasas_make_sgl_fusion(struct megasas_instance *instance, |
| 1442 | 1744 | struct scsi_cmnd *scp, |
| 1443 | 1745 | struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr, |
| 1444 | − struct megasas_cmd_fusion *cmd) | |
| 1746 | + struct megasas_cmd_fusion *cmd, int sge_count) | |
| 1445 | 1747 | { |
| 1446 | − int i, sg_processed, sge_count; | |
| 1748 | + int i, sg_processed; | |
| 1447 | 1749 | struct scatterlist *os_sgl; |
| 1448 | 1750 | struct fusion_context *fusion; |
| 1449 | 1751 | |
| 1450 | 1752 | fusion = instance->ctrl_context; |
| 1451 | 1753 | |
| 1452 | − if (fusion->adapter_type == INVADER_SERIES) { | |
| 1754 | + if (fusion->adapter_type >= INVADER_SERIES) { | |
| 1453 | 1755 | struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr_end = sgl_ptr; |
| 1454 | 1756 | sgl_ptr_end += fusion->max_sge_in_main_msg - 1; |
| 1455 | 1757 | sgl_ptr_end->Flags = 0; |
| 1456 | 1758 | } |
| 1457 | 1759 | |
| 1458 | − sge_count = scsi_dma_map(scp); | |
| 1459 | − | |
| 1460 | − BUG_ON(sge_count < 0); | |
| 1461 | − | |
| 1462 | − if (sge_count > instance->max_num_sge || !sge_count) | |
| 1463 | − return sge_count; | |
| 1464 | − | |
| 1465 | 1760 | scsi_for_each_sg(scp, os_sgl, sge_count, i) { |
| 1466 | 1761 | sgl_ptr->Length = cpu_to_le32(sg_dma_len(os_sgl)); |
| 1467 | 1762 | sgl_ptr->Address = cpu_to_le64(sg_dma_address(os_sgl)); |
| 1468 | 1763 | sgl_ptr->Flags = 0; |
| 1469 | − if (fusion->adapter_type == INVADER_SERIES) | |
| 1764 | + if (fusion->adapter_type >= INVADER_SERIES) | |
| 1470 | 1765 | if (i == sge_count - 1) |
| 1471 | 1766 | sgl_ptr->Flags = IEEE_SGE_FLAGS_END_OF_LIST; |
| 1472 | 1767 | sgl_ptr++; |
| 1473 | − | |
| 1474 | 1768 | sg_processed = i + 1; |
| 1475 | 1769 | |
| 1476 | 1770 | if ((sg_processed == (fusion->max_sge_in_main_msg - 1)) && |
| 1477 | 1771 | (sge_count > fusion->max_sge_in_main_msg)) { |
| 1478 | 1772 | |
| 1479 | 1773 | struct MPI25_IEEE_SGE_CHAIN64 *sg_chain; |
| 1480 | − if (fusion->adapter_type == INVADER_SERIES) { | |
| 1774 | + if (fusion->adapter_type >= INVADER_SERIES) { | |
| 1481 | 1775 | if ((le16_to_cpu(cmd->io_request->IoFlags) & |
| 1482 | 1776 | MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH) != |
| 1483 | 1777 | MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH) |
| @@ -1493,7 +1787,7 @@ megasas_make_sgl_fusion(struct megasas_instance *instance, · 9 unmodified lines | ||
| 1493 | 1787 | sg_chain = sgl_ptr; |
| 1494 | 1788 | /* Prepare chain element */ |
| 1495 | 1789 | sg_chain->NextChainOffset = 0; |
| 1496 | − if (fusion->adapter_type == INVADER_SERIES) | |
| 1790 | + if (fusion->adapter_type >= INVADER_SERIES) | |
| 1497 | 1791 | sg_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT; |
| 1498 | 1792 | else |
| 1499 | 1793 | sg_chain->Flags = |
| @@ -1507,6 +1801,45 @@ megasas_make_sgl_fusion(struct megasas_instance *instance, · 7 unmodified lines | ||
| 1507 | 1801 | memset(sgl_ptr, 0, instance->max_chain_frame_sz); |
| 1508 | 1802 | } |
| 1509 | 1803 | } |
| 1804 | + atomic_inc(&instance->ieee_sgl); | |
| 1805 | +} | |
| 1806 | + | |
| 1807 | +/** | |
| 1808 | + * megasas_make_sgl - Build Scatter Gather List(SGLs) | |
| 1809 | + * @scp: SCSI command pointer | |
| 1810 | + * @instance: Soft instance of controller | |
| 1811 | + * @cmd: Fusion command pointer | |
| 1812 | + * | |
| 1813 | + * This function will build sgls based on device type. | |
| 1814 | + * For nvme drives, there is different way of building sgls in nvme native | |
| 1815 | + * format- PRPs(Physical Region Page). | |
| 1816 | + * | |
| 1817 | + * Returns the number of sg lists actually used, zero if the sg lists | |
| 1818 | + * is NULL, or -ENOMEM if the mapping failed | |
| 1819 | + */ | |
| 1820 | +static | |
| 1821 | +int megasas_make_sgl(struct megasas_instance *instance, struct scsi_cmnd *scp, | |
| 1822 | + struct megasas_cmd_fusion *cmd) | |
| 1823 | +{ | |
| 1824 | + int sge_count; | |
| 1825 | + bool build_prp = false; | |
| 1826 | + struct MPI25_IEEE_SGE_CHAIN64 *sgl_chain64; | |
| 1827 | + | |
| 1828 | + sge_count = scsi_dma_map(scp); | |
| 1829 | + | |
| 1830 | + if ((sge_count > instance->max_num_sge) || (sge_count <= 0)) | |
| 1831 | + return sge_count; | |
| 1832 | + | |
| 1833 | + sgl_chain64 = (struct MPI25_IEEE_SGE_CHAIN64 *)&cmd->io_request->SGL; | |
| 1834 | + if ((le16_to_cpu(cmd->io_request->IoFlags) & | |
| 1835 | + MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH) && | |
| 1836 | + (cmd->pd_interface == NVME_PD)) | |
| 1837 | + build_prp = megasas_make_prp_nvme(instance, scp, sgl_chain64, | |
| 1838 | + cmd, sge_count); | |
| 1839 | + | |
| 1840 | + if (!build_prp) | |
| 1841 | + megasas_make_sgl_fusion(instance, scp, sgl_chain64, | |
| 1842 | + cmd, sge_count); | |
| 1510 | 1843 | |
| 1511 | 1844 | return sge_count; |
| 1512 | 1845 | } |
| @@ -1525,7 +1858,7 @@ megasas_set_pd_lba(struct MPI2_RAID_SCSI_IO_REQUEST *io_request, u8 cdb_len, · 12 unmodified lines | ||
| 1525 | 1858 | struct MR_DRV_RAID_MAP_ALL *local_map_ptr, u32 ref_tag) |
| 1526 | 1859 | { |
| 1527 | 1860 | struct MR_LD_RAID *raid; |
| 1528 | − u32 ld; | |
| 1861 | + u16 ld; | |
| 1529 | 1862 | u64 start_blk = io_info->pdBlock; |
| 1530 | 1863 | u8 *cdb = io_request->CDB.CDB32; |
| 1531 | 1864 | u32 num_blocks = io_info->numBlocks; |
| @@ -1574,6 +1907,7 @@ megasas_set_pd_lba(struct MPI2_RAID_SCSI_IO_REQUEST *io_request, u8 cdb_len, · 42 unmodified lines | ||
| 1574 | 1907 | MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG | |
| 1575 | 1908 | MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP | |
| 1576 | 1909 | MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG | |
| 1910 | + MPI25_SCSIIO_EEDPFLAGS_DO_NOT_DISABLE_MODE | | |
| 1577 | 1911 | MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD); |
| 1578 | 1912 | } else { |
| 1579 | 1913 | io_request->EEDPFlags = cpu_to_le16( |
| @@ -1687,6 +2021,166 @@ megasas_set_pd_lba(struct MPI2_RAID_SCSI_IO_REQUEST *io_request, u8 cdb_len, · 107 unmodified lines | ||
| 1687 | 2021 | } |
| 1688 | 2022 | } |
| 1689 | 2023 | |
| 2024 | +/** | |
| 2025 | + * megasas_stream_detect - stream detection on read and and write IOs | |
| 2026 | + * @instance: Adapter soft state | |
| 2027 | + * @cmd: Command to be prepared | |
| 2028 | + * @io_info: IO Request info | |
| 2029 | + * | |
| 2030 | + */ | |
| 2031 | + | |
| 2032 | +/** stream detection on read and and write IOs */ | |
| 2033 | +static void megasas_stream_detect(struct megasas_instance *instance, | |
| 2034 | + struct megasas_cmd_fusion *cmd, | |
| 2035 | + struct IO_REQUEST_INFO *io_info) | |
| 2036 | +{ | |
| 2037 | + struct fusion_context *fusion = instance->ctrl_context; | |
| 2038 | + u32 device_id = io_info->ldTgtId; | |
| 2039 | + struct LD_STREAM_DETECT *current_ld_sd | |
| 2040 | + = fusion->stream_detect_by_ld[device_id]; | |
| 2041 | + u32 *track_stream = ¤t_ld_sd->mru_bit_map, stream_num; | |
| 2042 | + u32 shifted_values, unshifted_values; | |
| 2043 | + u32 index_value_mask, shifted_values_mask; | |
| 2044 | + int i; | |
| 2045 | + bool is_read_ahead = false; | |
| 2046 | + struct STREAM_DETECT *current_sd; | |
| 2047 | + /* find possible stream */ | |
| 2048 | + for (i = 0; i < MAX_STREAMS_TRACKED; ++i) { | |
| 2049 | + stream_num = (*track_stream >> | |
| 2050 | + (i * BITS_PER_INDEX_STREAM)) & | |
| 2051 | + STREAM_MASK; | |
| 2052 | + current_sd = ¤t_ld_sd->stream_track[stream_num]; | |
| 2053 | + /* if we found a stream, update the raid | |
| 2054 | + * context and also update the mruBitMap | |
| 2055 | + */ | |
| 2056 | + /* boundary condition */ | |
| 2057 | + if ((current_sd->next_seq_lba) && | |
| 2058 | + (io_info->ldStartBlock >= current_sd->next_seq_lba) && | |
| 2059 | + (io_info->ldStartBlock <= (current_sd->next_seq_lba + 32)) && | |
| 2060 | + (current_sd->is_read == io_info->isRead)) { | |
| 2061 | + | |
| 2062 | + if ((io_info->ldStartBlock != current_sd->next_seq_lba) && | |
| 2063 | + ((!io_info->isRead) || (!is_read_ahead))) | |
| 2064 | + /* | |
| 2065 | + * Once the API availible we need to change this. | |
| 2066 | + * At this point we are not allowing any gap | |
| 2067 | + */ | |
| 2068 | + continue; | |
| 2069 | + | |
| 2070 | + SET_STREAM_DETECTED(cmd->io_request->RaidContext.raid_context_g35); | |
| 2071 | + current_sd->next_seq_lba = | |
| 2072 | + io_info->ldStartBlock + io_info->numBlocks; | |
| 2073 | + /* | |
| 2074 | + * update the mruBitMap LRU | |
| 2075 | + */ | |
| 2076 | + shifted_values_mask = | |
| 2077 | + (1 << i * BITS_PER_INDEX_STREAM) - 1; | |
| 2078 | + shifted_values = ((*track_stream & shifted_values_mask) | |
| 2079 | + << BITS_PER_INDEX_STREAM); | |
| 2080 | + index_value_mask = | |
| 2081 | + STREAM_MASK << i * BITS_PER_INDEX_STREAM; | |
| 2082 | + unshifted_values = | |
| 2083 | + *track_stream & ~(shifted_values_mask | | |
| 2084 | + index_value_mask); | |
| 2085 | + *track_stream = | |
| 2086 | + unshifted_values | shifted_values | stream_num; | |
| 2087 | + return; | |
| 2088 | + } | |
| 2089 | + } | |
| 2090 | + /* | |
| 2091 | + * if we did not find any stream, create a new one | |
| 2092 | + * from the least recently used | |
| 2093 | + */ | |
| 2094 | + stream_num = (*track_stream >> | |
| 2095 | + ((MAX_STREAMS_TRACKED - 1) * BITS_PER_INDEX_STREAM)) & | |
| 2096 | + STREAM_MASK; | |
| 2097 | + current_sd = ¤t_ld_sd->stream_track[stream_num]; | |
| 2098 | + current_sd->is_read = io_info->isRead; | |
| 2099 | + current_sd->next_seq_lba = io_info->ldStartBlock + io_info->numBlocks; | |
| 2100 | + *track_stream = (((*track_stream & ZERO_LAST_STREAM) << 4) | stream_num); | |
| 2101 | + return; | |
| 2102 | +} | |
| 2103 | + | |
| 2104 | +/** | |
| 2105 | + * megasas_set_raidflag_cpu_affinity - This function sets the cpu | |
| 2106 | + * affinity (cpu of the controller) and raid_flags in the raid context | |
| 2107 | + * based on IO type. | |
| 2108 | + * | |
| 2109 | + * @praid_context: IO RAID context | |
| 2110 | + * @raid: LD raid map | |
| 2111 | + * @fp_possible: Is fast path possible? | |
| 2112 | + * @is_read: Is read IO? | |
| 2113 | + * | |
| 2114 | + */ | |
| 2115 | +static void | |
| 2116 | +megasas_set_raidflag_cpu_affinity(union RAID_CONTEXT_UNION *praid_context, | |
| 2117 | + struct MR_LD_RAID *raid, bool fp_possible, | |
| 2118 | + u8 is_read, u32 scsi_buff_len) | |
| 2119 | +{ | |
| 2120 | + u8 cpu_sel = MR_RAID_CTX_CPUSEL_0; | |
| 2121 | + struct RAID_CONTEXT_G35 *rctx_g35; | |
| 2122 | + | |
| 2123 | + rctx_g35 = &praid_context->raid_context_g35; | |
| 2124 | + if (fp_possible) { | |
| 2125 | + if (is_read) { | |
| 2126 | + if ((raid->cpuAffinity.pdRead.cpu0) && | |
| 2127 | + (raid->cpuAffinity.pdRead.cpu1)) | |
| 2128 | + cpu_sel = MR_RAID_CTX_CPUSEL_FCFS; | |
| 2129 | + else if (raid->cpuAffinity.pdRead.cpu1) | |
| 2130 | + cpu_sel = MR_RAID_CTX_CPUSEL_1; | |
| 2131 | + } else { | |
| 2132 | + if ((raid->cpuAffinity.pdWrite.cpu0) && | |
| 2133 | + (raid->cpuAffinity.pdWrite.cpu1)) | |
| 2134 | + cpu_sel = MR_RAID_CTX_CPUSEL_FCFS; | |
| 2135 | + else if (raid->cpuAffinity.pdWrite.cpu1) | |
| 2136 | + cpu_sel = MR_RAID_CTX_CPUSEL_1; | |
| 2137 | + /* Fast path cache by pass capable R0/R1 VD */ | |
| 2138 | + if ((raid->level <= 1) && | |
| 2139 | + (raid->capability.fp_cache_bypass_capable)) { | |
| 2140 | + rctx_g35->routing_flags |= | |
| 2141 | + (1 << MR_RAID_CTX_ROUTINGFLAGS_SLD_SHIFT); | |
| 2142 | + rctx_g35->raid_flags = | |
| 2143 | + (MR_RAID_FLAGS_IO_SUB_TYPE_CACHE_BYPASS | |
| 2144 | + << MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT); | |
| 2145 | + } | |
| 2146 | + } | |
| 2147 | + } else { | |
| 2148 | + if (is_read) { | |
| 2149 | + if ((raid->cpuAffinity.ldRead.cpu0) && | |
| 2150 | + (raid->cpuAffinity.ldRead.cpu1)) | |
| 2151 | + cpu_sel = MR_RAID_CTX_CPUSEL_FCFS; | |
| 2152 | + else if (raid->cpuAffinity.ldRead.cpu1) | |
| 2153 | + cpu_sel = MR_RAID_CTX_CPUSEL_1; | |
| 2154 | + } else { | |
| 2155 | + if ((raid->cpuAffinity.ldWrite.cpu0) && | |
| 2156 | + (raid->cpuAffinity.ldWrite.cpu1)) | |
| 2157 | + cpu_sel = MR_RAID_CTX_CPUSEL_FCFS; | |
| 2158 | + else if (raid->cpuAffinity.ldWrite.cpu1) | |
| 2159 | + cpu_sel = MR_RAID_CTX_CPUSEL_1; | |
| 2160 | + | |
| 2161 | + if (is_stream_detected(rctx_g35) && | |
| 2162 | + (raid->level == 5) && | |
| 2163 | + (raid->writeMode == MR_RL_WRITE_THROUGH_MODE) && | |
| 2164 | + (cpu_sel == MR_RAID_CTX_CPUSEL_FCFS)) | |
| 2165 | + cpu_sel = MR_RAID_CTX_CPUSEL_0; | |
| 2166 | + } | |
| 2167 | + } | |
| 2168 | + | |
| 2169 | + rctx_g35->routing_flags |= | |
| 2170 | + (cpu_sel << MR_RAID_CTX_ROUTINGFLAGS_CPUSEL_SHIFT); | |
| 2171 | + | |
| 2172 | + /* Always give priority to MR_RAID_FLAGS_IO_SUB_TYPE_LDIO_BW_LIMIT | |
| 2173 | + * vs MR_RAID_FLAGS_IO_SUB_TYPE_CACHE_BYPASS. | |
| 2174 | + * IO Subtype is not bitmap. | |
| 2175 | + */ | |
| 2176 | + if ((raid->level == 1) && (!is_read)) { | |
| 2177 | + if (scsi_buff_len > MR_LARGE_IO_MIN_SIZE) | |
| 2178 | + praid_context->raid_context_g35.raid_flags = | |
| 2179 | + (MR_RAID_FLAGS_IO_SUB_TYPE_LDIO_BW_LIMIT | |
| 2180 | + << MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT); | |
| 2181 | + } | |
| 2182 | +} | |
| 2183 | + | |
| 1690 | 2184 | /** |
| 1691 | 2185 | * megasas_build_ldio_fusion - Prepares IOs to devices |
| 1692 | 2186 | * @instance: Adapter soft state |
| @@ -1701,29 +2195,36 @@ megasas_build_ldio_fusion(struct megasas_instance *instance, · 8 unmodified lines | ||
| 1701 | 2195 | struct scsi_cmnd *scp, |
| 1702 | 2196 | struct megasas_cmd_fusion *cmd) |
| 1703 | 2197 | { |
| 1704 | − u8 fp_possible; | |
| 2198 | + bool fp_possible; | |
| 2199 | + u16 ld; | |
| 1705 | 2200 | u32 start_lba_lo, start_lba_hi, device_id, datalength = 0; |
| 2201 | + u32 scsi_buff_len; | |
| 1706 | 2202 | struct MPI2_RAID_SCSI_IO_REQUEST *io_request; |
| 1707 | 2203 | union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc; |
| 1708 | 2204 | struct IO_REQUEST_INFO io_info; |
| 1709 | 2205 | struct fusion_context *fusion; |
| 1710 | 2206 | struct MR_DRV_RAID_MAP_ALL *local_map_ptr; |
| 1711 | 2207 | u8 *raidLUN; |
| 2208 | + unsigned long spinlock_flags; | |
| 2209 | + union RAID_CONTEXT_UNION *praid_context; | |
| 2210 | + struct MR_LD_RAID *raid = NULL; | |
| 2211 | + struct MR_PRIV_DEVICE *mrdev_priv; | |
| 1712 | 2212 | |
| 1713 | 2213 | device_id = MEGASAS_DEV_INDEX(scp); |
| 1714 | 2214 | |
| 1715 | 2215 | fusion = instance->ctrl_context; |
| 1716 | 2216 | |
| 1717 | 2217 | io_request = cmd->io_request; |
| 1718 | − io_request->RaidContext.VirtualDiskTgtId = cpu_to_le16(device_id); | |
| 1719 | − io_request->RaidContext.status = 0; | |
| 1720 | − io_request->RaidContext.exStatus = 0; | |
| 2218 | + io_request->RaidContext.raid_context.virtual_disk_tgt_id = | |
| 2219 | + cpu_to_le16(device_id); | |
| 2220 | + io_request->RaidContext.raid_context.status = 0; | |
| 2221 | + io_request->RaidContext.raid_context.ex_status = 0; | |
| 1721 | 2222 | |
| 1722 | 2223 | req_desc = (union MEGASAS_REQUEST_DESCRIPTOR_UNION *)cmd->request_desc; |
| 1723 | 2224 | |
| 1724 | 2225 | start_lba_lo = 0; |
| 1725 | 2226 | start_lba_hi = 0; |
| 1726 | − fp_possible = 0; | |
| 2227 | + fp_possible = false; | |
| 1727 | 2228 | |
| 1728 | 2229 | /* |
| 1729 | 2230 | * 6-byte READ(0x08) or WRITE(0x0A) cdb |
| @@ -1779,22 +2280,27 @@ megasas_build_ldio_fusion(struct megasas_instance *instance, · 49 unmodified lines | ||
| 1779 | 2280 | io_info.ldStartBlock = ((u64)start_lba_hi << 32) | start_lba_lo; |
| 1780 | 2281 | io_info.numBlocks = datalength; |
| 1781 | 2282 | io_info.ldTgtId = device_id; |
| 1782 | − io_request->DataLength = cpu_to_le32(scsi_bufflen(scp)); | |
| 2283 | + io_info.r1_alt_dev_handle = MR_DEVHANDLE_INVALID; | |
| 2284 | + scsi_buff_len = scsi_bufflen(scp); | |
| 2285 | + io_request->DataLength = cpu_to_le32(scsi_buff_len); | |
| 1783 | 2286 | |
| 1784 | 2287 | if (scp->sc_data_direction == PCI_DMA_FROMDEVICE) |
| 1785 | 2288 | io_info.isRead = 1; |
| 1786 | 2289 | |
| 1787 | 2290 | local_map_ptr = fusion->ld_drv_map[(instance->map_id & 1)]; |
| 2291 | + ld = MR_TargetIdToLdGet(device_id, local_map_ptr); | |
| 1788 | 2292 | |
| 1789 | − if ((MR_TargetIdToLdGet(device_id, local_map_ptr) >= | |
| 1790 | − instance->fw_supported_vd_count) || (!fusion->fast_path_io)) { | |
| 1791 | − io_request->RaidContext.regLockFlags = 0; | |
| 1792 | − fp_possible = 0; | |
| 2293 | + if (ld < instance->fw_supported_vd_count) | |
| 2294 | + raid = MR_LdRaidGet(ld, local_map_ptr); | |
| 2295 | + | |
| 2296 | + if (!raid || (!fusion->fast_path_io)) { | |
| 2297 | + io_request->RaidContext.raid_context.reg_lock_flags = 0; | |
| 2298 | + fp_possible = false; | |
| 1793 | 2299 | } else { |
| 1794 | 2300 | if (MR_BuildRaidContext(instance, &io_info, |
| 1795 | − &io_request->RaidContext, | |
| 2301 | + &io_request->RaidContext.raid_context, | |
| 1796 | 2302 | local_map_ptr, &raidLUN)) |
| 1797 | − fp_possible = io_info.fpOkForIo; | |
| 2303 | + fp_possible = (io_info.fpOkForIo > 0) ? true : false; | |
| 1798 | 2304 | } |
| 1799 | 2305 | |
| 1800 | 2306 | /* Use raw_smp_processor_id() for now until cmd->request->cpu is CPU |
| @@ -1803,6 +2309,54 @@ megasas_build_ldio_fusion(struct megasas_instance *instance, · 2 unmodified lines | ||
| 1803 | 2309 | cmd->request_desc->SCSIIO.MSIxIndex = instance->msix_vectors ? |
| 1804 | 2310 | raw_smp_processor_id() % instance->msix_vectors : 0; |
| 1805 | 2311 | |
| 2312 | + praid_context = &io_request->RaidContext; | |
| 2313 | + | |
| 2314 | + if (instance->is_ventura) { | |
| 2315 | + spin_lock_irqsave(&instance->stream_lock, spinlock_flags); | |
| 2316 | + megasas_stream_detect(instance, cmd, &io_info); | |
| 2317 | + spin_unlock_irqrestore(&instance->stream_lock, spinlock_flags); | |
| 2318 | + /* In ventura if stream detected for a read and it is read ahead | |
| 2319 | + * capable make this IO as LDIO | |
| 2320 | + */ | |
| 2321 | + if (is_stream_detected(&io_request->RaidContext.raid_context_g35) && | |
| 2322 | + io_info.isRead && io_info.ra_capable) | |
| 2323 | + fp_possible = false; | |
| 2324 | + | |
| 2325 | + /* FP for Optimal raid level 1. | |
| 2326 | + * All large RAID-1 writes (> 32 KiB, both WT and WB modes) | |
| 2327 | + * are built by the driver as LD I/Os. | |
| 2328 | + * All small RAID-1 WT writes (<= 32 KiB) are built as FP I/Os | |
| 2329 | + * (there is never a reason to process these as buffered writes) | |
| 2330 | + * All small RAID-1 WB writes (<= 32 KiB) are built as FP I/Os | |
| 2331 | + * with the SLD bit asserted. | |
| 2332 | + */ | |
| 2333 | + if (io_info.r1_alt_dev_handle != MR_DEVHANDLE_INVALID) { | |
| 2334 | + mrdev_priv = scp->device->hostdata; | |
| 2335 | + | |
| 2336 | + if (atomic_inc_return(&instance->fw_outstanding) > | |
| 2337 | + (instance->host->can_queue)) { | |
| 2338 | + fp_possible = false; | |
| 2339 | + atomic_dec(&instance->fw_outstanding); | |
| 2340 | + } else if ((scsi_buff_len > MR_LARGE_IO_MIN_SIZE) || | |
| 2341 | + atomic_dec_if_positive(&mrdev_priv->r1_ldio_hint)) { | |
| 2342 | + fp_possible = false; | |
| 2343 | + atomic_dec(&instance->fw_outstanding); | |
| 2344 | + if (scsi_buff_len > MR_LARGE_IO_MIN_SIZE) | |
| 2345 | + atomic_set(&mrdev_priv->r1_ldio_hint, | |
| 2346 | + instance->r1_ldio_hint_default); | |
| 2347 | + } | |
| 2348 | + } | |
| 2349 | + | |
| 2350 | + /* If raid is NULL, set CPU affinity to default CPU0 */ | |
| 2351 | + if (raid) | |
| 2352 | + megasas_set_raidflag_cpu_affinity(praid_context, | |
| 2353 | + raid, fp_possible, io_info.isRead, | |
| 2354 | + scsi_buff_len); | |
| 2355 | + else | |
| 2356 | + praid_context->raid_context_g35.routing_flags |= | |
| 2357 | + (MR_RAID_CTX_CPUSEL_0 << MR_RAID_CTX_ROUTINGFLAGS_CPUSEL_SHIFT); | |
| 2358 | + } | |
| 2359 | + | |
| 1806 | 2360 | if (fp_possible) { |
| 1807 | 2361 | megasas_set_pd_lba(io_request, scp->cmd_len, &io_info, scp, |
| 1808 | 2362 | local_map_ptr, start_lba_lo); |
| @@ -1811,29 +2365,52 @@ megasas_build_ldio_fusion(struct megasas_instance *instance, · 2 unmodified lines | ||
| 1811 | 2365 | (MPI2_REQ_DESCRIPT_FLAGS_FP_IO |
| 1812 | 2366 | << MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); |
| 1813 | 2367 | if (fusion->adapter_type == INVADER_SERIES) { |
| 1814 | − if (io_request->RaidContext.regLockFlags == | |
| 2368 | + if (io_request->RaidContext.raid_context.reg_lock_flags == | |
| 1815 | 2369 | REGION_TYPE_UNUSED) |
| 1816 | 2370 | cmd->request_desc->SCSIIO.RequestFlags = |
| 1817 | 2371 | (MEGASAS_REQ_DESCRIPT_FLAGS_NO_LOCK << |
| 1818 | 2372 | MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); |
| 1819 | − io_request->RaidContext.Type = MPI2_TYPE_CUDA; | |
| 1820 | − io_request->RaidContext.nseg = 0x1; | |
| 2373 | + io_request->RaidContext.raid_context.type | |
| 2374 | + = MPI2_TYPE_CUDA; | |
| 2375 | + io_request->RaidContext.raid_context.nseg = 0x1; | |
| 1821 | 2376 | io_request->IoFlags |= cpu_to_le16(MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH); |
| 1822 | − io_request->RaidContext.regLockFlags |= | |
| 2377 | + io_request->RaidContext.raid_context.reg_lock_flags |= | |
| 1823 | 2378 | (MR_RL_FLAGS_GRANT_DESTINATION_CUDA | |
| 1824 | 2379 | MR_RL_FLAGS_SEQ_NUM_ENABLE); |
| 2380 | + } else if (instance->is_ventura) { | |
| 2381 | + io_request->RaidContext.raid_context_g35.nseg_type |= | |
| 2382 | + (1 << RAID_CONTEXT_NSEG_SHIFT); | |
| 2383 | + io_request->RaidContext.raid_context_g35.nseg_type |= | |
| 2384 | + (MPI2_TYPE_CUDA << RAID_CONTEXT_TYPE_SHIFT); | |
| 2385 | + io_request->RaidContext.raid_context_g35.routing_flags |= | |
| 2386 | + (1 << MR_RAID_CTX_ROUTINGFLAGS_SQN_SHIFT); | |
| 2387 | + io_request->IoFlags |= | |
| 2388 | + cpu_to_le16(MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH); | |
| 1825 | 2389 | } |
| 1826 | − if ((fusion->load_balance_info[device_id].loadBalanceFlag) && | |
| 1827 | − (io_info.isRead)) { | |
| 2390 | + if (fusion->load_balance_info && | |
| 2391 | + (fusion->load_balance_info[device_id].loadBalanceFlag) && | |
| 2392 | + (io_info.isRead)) { | |
| 1828 | 2393 | io_info.devHandle = |
| 1829 | 2394 | get_updated_dev_handle(instance, |
| 1830 | 2395 | &fusion->load_balance_info[device_id], |
| 1831 | − &io_info); | |
| 2396 | + &io_info, local_map_ptr); | |
| 1832 | 2397 | scp->SCp.Status |= MEGASAS_LOAD_BALANCE_FLAG; |
| 1833 | 2398 | cmd->pd_r1_lb = io_info.pd_after_lb; |
| 2399 | + if (instance->is_ventura) | |
| 2400 | + io_request->RaidContext.raid_context_g35.span_arm | |
| 2401 | + = io_info.span_arm; | |
| 2402 | + else | |
| 2403 | + io_request->RaidContext.raid_context.span_arm | |
| 2404 | + = io_info.span_arm; | |
| 2405 | + | |
| 1834 | 2406 | } else |
| 1835 | 2407 | scp->SCp.Status &= ~MEGASAS_LOAD_BALANCE_FLAG; |
| 1836 | 2408 | |
| 2409 | + if (instance->is_ventura) | |
| 2410 | + cmd->r1_alt_dev_handle = io_info.r1_alt_dev_handle; | |
| 2411 | + else | |
| 2412 | + cmd->r1_alt_dev_handle = MR_DEVHANDLE_INVALID; | |
| 2413 | + | |
| 1837 | 2414 | if ((raidLUN[0] == 1) && |
| 1838 | 2415 | (local_map_ptr->raidMap.devHndlInfo[io_info.pd_after_lb].validHandles > 1)) { |
| 1839 | 2416 | instance->dev_handle = !(instance->dev_handle); |
| @@ -1843,28 +2420,39 @@ megasas_build_ldio_fusion(struct megasas_instance *instance, · 3 unmodified lines | ||
| 1843 | 2420 | |
| 1844 | 2421 | cmd->request_desc->SCSIIO.DevHandle = io_info.devHandle; |
| 1845 | 2422 | io_request->DevHandle = io_info.devHandle; |
| 2423 | + cmd->pd_interface = io_info.pd_interface; | |
| 1846 | 2424 | /* populate the LUN field */ |
| 1847 | 2425 | memcpy(io_request->LUN, raidLUN, 8); |
| 1848 | 2426 | } else { |
| 1849 | − io_request->RaidContext.timeoutValue = | |
| 2427 | + io_request->RaidContext.raid_context.timeout_value = | |
| 1850 | 2428 | cpu_to_le16(local_map_ptr->raidMap.fpPdIoTimeoutSec); |
| 1851 | 2429 | cmd->request_desc->SCSIIO.RequestFlags = |
| 1852 | 2430 | (MEGASAS_REQ_DESCRIPT_FLAGS_LD_IO |
| 1853 | 2431 | << MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); |
| 1854 | 2432 | if (fusion->adapter_type == INVADER_SERIES) { |
| 1855 | 2433 | if (io_info.do_fp_rlbypass || |
| 1856 | − (io_request->RaidContext.regLockFlags == REGION_TYPE_UNUSED)) | |
| 2434 | + (io_request->RaidContext.raid_context.reg_lock_flags | |
| 2435 | + == REGION_TYPE_UNUSED)) | |
| 1857 | 2436 | cmd->request_desc->SCSIIO.RequestFlags = |
| 1858 | 2437 | (MEGASAS_REQ_DESCRIPT_FLAGS_NO_LOCK << |
| 1859 | 2438 | MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); |
| 1860 | − io_request->RaidContext.Type = MPI2_TYPE_CUDA; | |
| 1861 | − io_request->RaidContext.regLockFlags |= | |
| 2439 | + io_request->RaidContext.raid_context.type | |
| 2440 | + = MPI2_TYPE_CUDA; | |
| 2441 | + io_request->RaidContext.raid_context.reg_lock_flags |= | |
| 1862 | 2442 | (MR_RL_FLAGS_GRANT_DESTINATION_CPU0 | |
| 1863 | 2443 | MR_RL_FLAGS_SEQ_NUM_ENABLE); |
| 1864 | − io_request->RaidContext.nseg = 0x1; | |
| 2444 | + io_request->RaidContext.raid_context.nseg = 0x1; | |
| 2445 | + } else if (instance->is_ventura) { | |
| 2446 | + io_request->RaidContext.raid_context_g35.routing_flags |= | |
| 2447 | + (1 << MR_RAID_CTX_ROUTINGFLAGS_SQN_SHIFT); | |
| 2448 | + io_request->RaidContext.raid_context_g35.nseg_type |= | |
| 2449 | + (1 << RAID_CONTEXT_NSEG_SHIFT); | |
| 2450 | + io_request->RaidContext.raid_context_g35.nseg_type |= | |
| 2451 | + (MPI2_TYPE_CUDA << RAID_CONTEXT_TYPE_SHIFT); | |
| 1865 | 2452 | } |
| 1866 | 2453 | io_request->Function = MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST; |
| 1867 | 2454 | io_request->DevHandle = cpu_to_le16(device_id); |
| 2455 | + | |
| 1868 | 2456 | } /* Not FP */ |
| 1869 | 2457 | } |
| 1870 | 2458 | |
| @@ -1881,27 +2469,26 @@ static void megasas_build_ld_nonrw_fusion(struct megasas_instance *instance, · 10 unmodified lines | ||
| 1881 | 2469 | { |
| 1882 | 2470 | u32 device_id; |
| 1883 | 2471 | struct MPI2_RAID_SCSI_IO_REQUEST *io_request; |
| 1884 | − u16 pd_index = 0; | |
| 2472 | + u16 ld; | |
| 1885 | 2473 | struct MR_DRV_RAID_MAP_ALL *local_map_ptr; |
| 1886 | 2474 | struct fusion_context *fusion = instance->ctrl_context; |
| 1887 | 2475 | u8 span, physArm; |
| 1888 | 2476 | __le16 devHandle; |
| 1889 | − u32 ld, arRef, pd; | |
| 2477 | + u32 arRef, pd; | |
| 1890 | 2478 | struct MR_LD_RAID *raid; |
| 1891 | 2479 | struct RAID_CONTEXT *pRAID_Context; |
| 1892 | 2480 | u8 fp_possible = 1; |
| 1893 | 2481 | |
| 1894 | 2482 | io_request = cmd->io_request; |
| 1895 | 2483 | device_id = MEGASAS_DEV_INDEX(scmd); |
| 1896 | − pd_index = MEGASAS_PD_INDEX(scmd); | |
| 1897 | 2484 | local_map_ptr = fusion->ld_drv_map[(instance->map_id & 1)]; |
| 1898 | 2485 | io_request->DataLength = cpu_to_le32(scsi_bufflen(scmd)); |
| 1899 | 2486 | /* get RAID_Context pointer */ |
| 1900 | − pRAID_Context = &io_request->RaidContext; | |
| 2487 | + pRAID_Context = &io_request->RaidContext.raid_context; | |
| 1901 | 2488 | /* Check with FW team */ |
| 1902 | − pRAID_Context->VirtualDiskTgtId = cpu_to_le16(device_id); | |
| 1903 | − pRAID_Context->regLockRowLBA = 0; | |
| 1904 | − pRAID_Context->regLockLength = 0; | |
| 2489 | + pRAID_Context->virtual_disk_tgt_id = cpu_to_le16(device_id); | |
| 2490 | + pRAID_Context->reg_lock_row_lba = 0; | |
| 2491 | + pRAID_Context->reg_lock_length = 0; | |
| 1905 | 2492 | |
| 1906 | 2493 | if (fusion->fast_path_io && ( |
| 1907 | 2494 | device_id < instance->fw_supported_vd_count)) { |
| @@ -1909,10 +2496,11 @@ static void megasas_build_ld_nonrw_fusion(struct megasas_instance *instance, · 1 unmodified line | ||
| 1909 | 2496 | ld = MR_TargetIdToLdGet(device_id, local_map_ptr); |
| 1910 | 2497 | if (ld >= instance->fw_supported_vd_count) |
| 1911 | 2498 | fp_possible = 0; |
| 1912 | − | |
| 1913 | − raid = MR_LdRaidGet(ld, local_map_ptr); | |
| 1914 | − if (!(raid->capability.fpNonRWCapable)) | |
| 1915 | − fp_possible = 0; | |
| 2499 | + else { | |
| 2500 | + raid = MR_LdRaidGet(ld, local_map_ptr); | |
| 2501 | + if (!(raid->capability.fpNonRWCapable)) | |
| 2502 | + fp_possible = 0; | |
| 2503 | + } | |
| 1916 | 2504 | } else |
| 1917 | 2505 | fp_possible = 0; |
| 1918 | 2506 | |
| @@ -1920,7 +2508,7 @@ static void megasas_build_ld_nonrw_fusion(struct megasas_instance *instance, · 1 unmodified line | ||
| 1920 | 2508 | io_request->Function = MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST; |
| 1921 | 2509 | io_request->DevHandle = cpu_to_le16(device_id); |
| 1922 | 2510 | io_request->LUN[1] = scmd->device->lun; |
| 1923 | − pRAID_Context->timeoutValue = | |
| 2511 | + pRAID_Context->timeout_value = | |
| 1924 | 2512 | cpu_to_le16 (scmd->request->timeout / HZ); |
| 1925 | 2513 | cmd->request_desc->SCSIIO.RequestFlags = |
| 1926 | 2514 | (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO << |
| @@ -1928,9 +2516,11 @@ static void megasas_build_ld_nonrw_fusion(struct megasas_instance *instance, · 1 unmodified line | ||
| 1928 | 2516 | } else { |
| 1929 | 2517 | |
| 1930 | 2518 | /* set RAID context values */ |
| 1931 | − pRAID_Context->configSeqNum = raid->seqNum; | |
| 1932 | − pRAID_Context->regLockFlags = REGION_TYPE_SHARED_READ; | |
| 1933 | − pRAID_Context->timeoutValue = cpu_to_le16(raid->fpIoTimeoutForLd); | |
| 2519 | + pRAID_Context->config_seq_num = raid->seqNum; | |
| 2520 | + if (!instance->is_ventura) | |
| 2521 | + pRAID_Context->reg_lock_flags = REGION_TYPE_SHARED_READ; | |
| 2522 | + pRAID_Context->timeout_value = | |
| 2523 | + cpu_to_le16(raid->fpIoTimeoutForLd); | |
| 1934 | 2524 | |
| 1935 | 2525 | /* get the DevHandle for the PD (since this is |
| 1936 | 2526 | fpNonRWCapable, this is a single disk RAID0) */ |
| @@ -1965,7 +2555,8 @@ static void megasas_build_ld_nonrw_fusion(struct megasas_instance *instance, · 28 unmodified lines | ||
| 1965 | 2555 | */ |
| 1966 | 2556 | static void |
| 1967 | 2557 | megasas_build_syspd_fusion(struct megasas_instance *instance, |
| 1968 | − struct scsi_cmnd *scmd, struct megasas_cmd_fusion *cmd, u8 fp_possible) | |
| 2558 | + struct scsi_cmnd *scmd, struct megasas_cmd_fusion *cmd, | |
| 2559 | + bool fp_possible) | |
| 1969 | 2560 | { |
| 1970 | 2561 | u32 device_id; |
| 1971 | 2562 | struct MPI2_RAID_SCSI_IO_REQUEST *io_request; |
| @@ -1975,22 +2566,25 @@ megasas_build_syspd_fusion(struct megasas_instance *instance, · 3 unmodified lines | ||
| 1975 | 2566 | struct MR_DRV_RAID_MAP_ALL *local_map_ptr; |
| 1976 | 2567 | struct RAID_CONTEXT *pRAID_Context; |
| 1977 | 2568 | struct MR_PD_CFG_SEQ_NUM_SYNC *pd_sync; |
| 2569 | + struct MR_PRIV_DEVICE *mr_device_priv_data; | |
| 1978 | 2570 | struct fusion_context *fusion = instance->ctrl_context; |
| 1979 | 2571 | pd_sync = (void *)fusion->pd_seq_sync[(instance->pd_seq_map_id - 1) & 1]; |
| 1980 | 2572 | |
| 1981 | 2573 | device_id = MEGASAS_DEV_INDEX(scmd); |
| 1982 | 2574 | pd_index = MEGASAS_PD_INDEX(scmd); |
| 1983 | 2575 | os_timeout_value = scmd->request->timeout / HZ; |
| 2576 | + mr_device_priv_data = scmd->device->hostdata; | |
| 2577 | + cmd->pd_interface = mr_device_priv_data->interface_type; | |
| 1984 | 2578 | |
| 1985 | 2579 | io_request = cmd->io_request; |
| 1986 | 2580 | /* get RAID_Context pointer */ |
| 1987 | − pRAID_Context = &io_request->RaidContext; | |
| 1988 | − pRAID_Context->regLockFlags = 0; | |
| 1989 | − pRAID_Context->regLockRowLBA = 0; | |
| 1990 | − pRAID_Context->regLockLength = 0; | |
| 2581 | + pRAID_Context = &io_request->RaidContext.raid_context; | |
| 2582 | + pRAID_Context->reg_lock_flags = 0; | |
| 2583 | + pRAID_Context->reg_lock_row_lba = 0; | |
| 2584 | + pRAID_Context->reg_lock_length = 0; | |
| 1991 | 2585 | io_request->DataLength = cpu_to_le32(scsi_bufflen(scmd)); |
| 1992 | 2586 | io_request->LUN[1] = scmd->device->lun; |
| 1993 | − pRAID_Context->RAIDFlags = MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD | |
| 2587 | + pRAID_Context->raid_flags = MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD | |
| 1994 | 2588 | << MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT; |
| 1995 | 2589 | |
| 1996 | 2590 | /* If FW supports PD sequence number */ |
| @@ -1999,24 +2593,38 @@ megasas_build_syspd_fusion(struct megasas_instance *instance, · 2 unmodified lines | ||
| 1999 | 2593 | /* TgtId must be incremented by 255 as jbod seq number is index |
| 2000 | 2594 | * below raid map |
| 2001 | 2595 | */ |
| 2002 | − pRAID_Context->VirtualDiskTgtId = | |
| 2003 | − cpu_to_le16(device_id + (MAX_PHYSICAL_DEVICES - 1)); | |
| 2004 | − pRAID_Context->configSeqNum = pd_sync->seq[pd_index].seqNum; | |
| 2596 | + /* More than 256 PD/JBOD support for Ventura */ | |
| 2597 | + if (instance->support_morethan256jbod) | |
| 2598 | + pRAID_Context->virtual_disk_tgt_id = | |
| 2599 | + pd_sync->seq[pd_index].pd_target_id; | |
| 2600 | + else | |
| 2601 | + pRAID_Context->virtual_disk_tgt_id = | |
| 2602 | + cpu_to_le16(device_id + (MAX_PHYSICAL_DEVICES - 1)); | |
| 2603 | + pRAID_Context->config_seq_num = pd_sync->seq[pd_index].seqNum; | |
| 2005 | 2604 | io_request->DevHandle = pd_sync->seq[pd_index].devHandle; |
| 2006 | − pRAID_Context->regLockFlags |= | |
| 2007 | − (MR_RL_FLAGS_SEQ_NUM_ENABLE|MR_RL_FLAGS_GRANT_DESTINATION_CUDA); | |
| 2008 | − pRAID_Context->Type = MPI2_TYPE_CUDA; | |
| 2009 | − pRAID_Context->nseg = 0x1; | |
| 2605 | + if (instance->is_ventura) { | |
| 2606 | + io_request->RaidContext.raid_context_g35.routing_flags |= | |
| 2607 | + (1 << MR_RAID_CTX_ROUTINGFLAGS_SQN_SHIFT); | |
| 2608 | + io_request->RaidContext.raid_context_g35.nseg_type |= | |
| 2609 | + (1 << RAID_CONTEXT_NSEG_SHIFT); | |
| 2610 | + io_request->RaidContext.raid_context_g35.nseg_type |= | |
| 2611 | + (MPI2_TYPE_CUDA << RAID_CONTEXT_TYPE_SHIFT); | |
| 2612 | + } else { | |
| 2613 | + pRAID_Context->type = MPI2_TYPE_CUDA; | |
| 2614 | + pRAID_Context->nseg = 0x1; | |
| 2615 | + pRAID_Context->reg_lock_flags |= | |
| 2616 | + (MR_RL_FLAGS_SEQ_NUM_ENABLE|MR_RL_FLAGS_GRANT_DESTINATION_CUDA); | |
| 2617 | + } | |
| 2010 | 2618 | } else if (fusion->fast_path_io) { |
| 2011 | − pRAID_Context->VirtualDiskTgtId = cpu_to_le16(device_id); | |
| 2012 | − pRAID_Context->configSeqNum = 0; | |
| 2619 | + pRAID_Context->virtual_disk_tgt_id = cpu_to_le16(device_id); | |
| 2620 | + pRAID_Context->config_seq_num = 0; | |
| 2013 | 2621 | local_map_ptr = fusion->ld_drv_map[(instance->map_id & 1)]; |
| 2014 | 2622 | io_request->DevHandle = |
| 2015 | 2623 | local_map_ptr->raidMap.devHndlInfo[device_id].curDevHdl; |
| 2016 | 2624 | } else { |
| 2017 | 2625 | /* Want to send all IO via FW path */ |
| 2018 | − pRAID_Context->VirtualDiskTgtId = cpu_to_le16(device_id); | |
| 2019 | − pRAID_Context->configSeqNum = 0; | |
| 2626 | + pRAID_Context->virtual_disk_tgt_id = cpu_to_le16(device_id); | |
| 2627 | + pRAID_Context->config_seq_num = 0; | |
| 2020 | 2628 | io_request->DevHandle = cpu_to_le16(0xFFFF); |
| 2021 | 2629 | } |
| 2022 | 2630 | |
| @@ -2032,17 +2640,17 @@ megasas_build_syspd_fusion(struct megasas_instance *instance, · 9 unmodified lines | ||
| 2032 | 2640 | cmd->request_desc->SCSIIO.RequestFlags = |
| 2033 | 2641 | (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO << |
| 2034 | 2642 | MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); |
| 2035 | − pRAID_Context->timeoutValue = cpu_to_le16(os_timeout_value); | |
| 2036 | − pRAID_Context->VirtualDiskTgtId = cpu_to_le16(device_id); | |
| 2643 | + pRAID_Context->timeout_value = cpu_to_le16(os_timeout_value); | |
| 2644 | + pRAID_Context->virtual_disk_tgt_id = cpu_to_le16(device_id); | |
| 2037 | 2645 | } else { |
| 2038 | 2646 | /* system pd Fast Path */ |
| 2039 | 2647 | io_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST; |
| 2040 | 2648 | timeout_limit = (scmd->device->type == TYPE_DISK) ? |
| 2041 | 2649 | 255 : 0xFFFF; |
| 2042 | − pRAID_Context->timeoutValue = | |
| 2650 | + pRAID_Context->timeout_value = | |
| 2043 | 2651 | cpu_to_le16((os_timeout_value > timeout_limit) ? |
| 2044 | 2652 | timeout_limit : os_timeout_value); |
| 2045 | − if (fusion->adapter_type == INVADER_SERIES) | |
| 2653 | + if (fusion->adapter_type >= INVADER_SERIES) | |
| 2046 | 2654 | io_request->IoFlags |= |
| 2047 | 2655 | cpu_to_le16(MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH); |
| 2048 | 2656 | |
| @@ -2066,9 +2674,11 @@ megasas_build_io_fusion(struct megasas_instance *instance, · 17 unmodified lines | ||
| 2066 | 2674 | struct scsi_cmnd *scp, |
| 2067 | 2675 | struct megasas_cmd_fusion *cmd) |
| 2068 | 2676 | { |
| 2069 | − u16 sge_count; | |
| 2677 | + int sge_count; | |
| 2070 | 2678 | u8 cmd_type; |
| 2071 | 2679 | struct MPI2_RAID_SCSI_IO_REQUEST *io_request = cmd->io_request; |
| 2680 | + struct MR_PRIV_DEVICE *mr_device_priv_data; | |
| 2681 | + mr_device_priv_data = scp->device->hostdata; | |
| 2072 | 2682 | |
| 2073 | 2683 | /* Zero out some fields so they don't get reused */ |
| 2074 | 2684 | memset(io_request->LUN, 0x0, 8); |
| @@ -2078,9 +2688,9 @@ megasas_build_io_fusion(struct megasas_instance *instance, · 3 unmodified lines | ||
| 2078 | 2688 | io_request->Control = 0; |
| 2079 | 2689 | io_request->EEDPBlockSize = 0; |
| 2080 | 2690 | io_request->ChainOffset = 0; |
| 2081 | − io_request->RaidContext.RAIDFlags = 0; | |
| 2082 | − io_request->RaidContext.Type = 0; | |
| 2083 | − io_request->RaidContext.nseg = 0; | |
| 2691 | + io_request->RaidContext.raid_context.raid_flags = 0; | |
| 2692 | + io_request->RaidContext.raid_context.type = 0; | |
| 2693 | + io_request->RaidContext.raid_context.nseg = 0; | |
| 2084 | 2694 | |
| 2085 | 2695 | memcpy(io_request->CDB.CDB32, scp->cmnd, scp->cmd_len); |
| 2086 | 2696 | /* |
| @@ -2097,12 +2707,14 @@ megasas_build_io_fusion(struct megasas_instance *instance, · 10 unmodified lines | ||
| 2097 | 2707 | megasas_build_ld_nonrw_fusion(instance, scp, cmd); |
| 2098 | 2708 | break; |
| 2099 | 2709 | case READ_WRITE_SYSPDIO: |
| 2710 | + megasas_build_syspd_fusion(instance, scp, cmd, true); | |
| 2711 | + break; | |
| 2100 | 2712 | case NON_READ_WRITE_SYSPDIO: |
| 2101 | − if (instance->secure_jbod_support && | |
| 2102 | − (cmd_type == NON_READ_WRITE_SYSPDIO)) | |
| 2103 | − megasas_build_syspd_fusion(instance, scp, cmd, 0); | |
| 2713 | + if (instance->secure_jbod_support || | |
| 2714 | + mr_device_priv_data->is_tm_capable) | |
| 2715 | + megasas_build_syspd_fusion(instance, scp, cmd, false); | |
| 2104 | 2716 | else |
| 2105 | − megasas_build_syspd_fusion(instance, scp, cmd, 1); | |
| 2717 | + megasas_build_syspd_fusion(instance, scp, cmd, true); | |
| 2106 | 2718 | break; |
| 2107 | 2719 | default: |
| 2108 | 2720 | break; |
| @@ -2112,23 +2724,27 @@ megasas_build_io_fusion(struct megasas_instance *instance, · 3 unmodified lines | ||
| 2112 | 2724 | * Construct SGL |
| 2113 | 2725 | */ |
| 2114 | 2726 | |
| 2115 | − sge_count = | |
| 2116 | − megasas_make_sgl_fusion(instance, scp, | |
| 2117 | − (struct MPI25_IEEE_SGE_CHAIN64 *) | |
| 2118 | − &io_request->SGL, cmd); | |
| 2727 | + sge_count = megasas_make_sgl(instance, scp, cmd); | |
| 2119 | 2728 | |
| 2120 | − if (sge_count > instance->max_num_sge) { | |
| 2121 | − dev_err(&instance->pdev->dev, "Error. sge_count (0x%x) exceeds " | |
| 2122 | − "max (0x%x) allowed\n", sge_count, | |
| 2123 | − instance->max_num_sge); | |
| 2729 | + if (sge_count > instance->max_num_sge || (sge_count < 0)) { | |
| 2730 | + dev_err(&instance->pdev->dev, | |
| 2731 | + "%s %d sge_count (%d) is out of range. Range is: 0-%d\n", | |
| 2732 | + __func__, __LINE__, sge_count, instance->max_num_sge); | |
| 2124 | 2733 | return 1; |
| 2125 | 2734 | } |
| 2126 | 2735 | |
| 2127 | − /* numSGE store lower 8 bit of sge_count. | |
| 2128 | − * numSGEExt store higher 8 bit of sge_count | |
| 2129 | − */ | |
| 2130 | − io_request->RaidContext.numSGE = sge_count; | |
| 2131 | − io_request->RaidContext.numSGEExt = (u8)(sge_count >> 8); | |
| 2736 | + if (instance->is_ventura) { | |
| 2737 | + set_num_sge(&io_request->RaidContext.raid_context_g35, sge_count); | |
| 2738 | + cpu_to_le16s(&io_request->RaidContext.raid_context_g35.routing_flags); | |
| 2739 | + cpu_to_le16s(&io_request->RaidContext.raid_context_g35.nseg_type); | |
| 2740 | + } else { | |
| 2741 | + /* numSGE store lower 8 bit of sge_count. | |
| 2742 | + * numSGEExt store higher 8 bit of sge_count | |
| 2743 | + */ | |
| 2744 | + io_request->RaidContext.raid_context.num_sge = sge_count; | |
| 2745 | + io_request->RaidContext.raid_context.num_sge_ext = | |
| 2746 | + (u8)(sge_count >> 8); | |
| 2747 | + } | |
| 2132 | 2748 | |
| 2133 | 2749 | io_request->SGLFlags = cpu_to_le16(MPI2_SGE_FLAGS_64_BIT_ADDRESSING); |
| 2134 | 2750 | |
| @@ -2149,25 +2765,61 @@ megasas_build_io_fusion(struct megasas_instance *instance, · 14 unmodified lines | ||
| 2149 | 2765 | return 0; |
| 2150 | 2766 | } |
| 2151 | 2767 | |
| 2152 | −union MEGASAS_REQUEST_DESCRIPTOR_UNION * | |
| 2768 | +static union MEGASAS_REQUEST_DESCRIPTOR_UNION * | |
| 2153 | 2769 | megasas_get_request_descriptor(struct megasas_instance *instance, u16 index) |
| 2154 | 2770 | { |
| 2155 | 2771 | u8 *p; |
| 2156 | 2772 | struct fusion_context *fusion; |
| 2157 | 2773 | |
| 2158 | − if (index >= instance->max_fw_cmds) { | |
| 2159 | − dev_err(&instance->pdev->dev, "Invalid SMID (0x%x)request for " | |
| 2160 | − "descriptor for scsi%d\n", index, | |
| 2161 | − instance->host->host_no); | |
| 2162 | − return NULL; | |
| 2163 | − } | |
| 2164 | 2774 | fusion = instance->ctrl_context; |
| 2165 | − p = fusion->req_frames_desc | |
| 2166 | − +sizeof(union MEGASAS_REQUEST_DESCRIPTOR_UNION) *index; | |
| 2775 | + p = fusion->req_frames_desc + | |
| 2776 | + sizeof(union MEGASAS_REQUEST_DESCRIPTOR_UNION) * index; | |
| 2167 | 2777 | |
| 2168 | 2778 | return (union MEGASAS_REQUEST_DESCRIPTOR_UNION *)p; |
| 2169 | 2779 | } |
| 2170 | 2780 | |
| 2781 | + | |
| 2782 | +/* megasas_prepate_secondRaid1_IO | |
| 2783 | + * It prepares the raid 1 second IO | |
| 2784 | + */ | |
| 2785 | +void megasas_prepare_secondRaid1_IO(struct megasas_instance *instance, | |
| 2786 | + struct megasas_cmd_fusion *cmd, | |
| 2787 | + struct megasas_cmd_fusion *r1_cmd) | |
| 2788 | +{ | |
| 2789 | + union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc, *req_desc2 = NULL; | |
| 2790 | + struct fusion_context *fusion; | |
| 2791 | + fusion = instance->ctrl_context; | |
| 2792 | + req_desc = cmd->request_desc; | |
| 2793 | + /* copy the io request frame as well as 8 SGEs data for r1 command*/ | |
| 2794 | + memcpy(r1_cmd->io_request, cmd->io_request, | |
| 2795 | + (sizeof(struct MPI2_RAID_SCSI_IO_REQUEST))); | |
| 2796 | + memcpy(&r1_cmd->io_request->SGL, &cmd->io_request->SGL, | |
| 2797 | + (fusion->max_sge_in_main_msg * sizeof(union MPI2_SGE_IO_UNION))); | |
| 2798 | + /*sense buffer is different for r1 command*/ | |
| 2799 | + r1_cmd->io_request->SenseBufferLowAddress = | |
| 2800 | + cpu_to_le32(r1_cmd->sense_phys_addr); | |
| 2801 | + r1_cmd->scmd = cmd->scmd; | |
| 2802 | + req_desc2 = megasas_get_request_descriptor(instance, | |
| 2803 | + (r1_cmd->index - 1)); | |
| 2804 | + req_desc2->Words = 0; | |
| 2805 | + r1_cmd->request_desc = req_desc2; | |
| 2806 | + req_desc2->SCSIIO.SMID = cpu_to_le16(r1_cmd->index); | |
| 2807 | + req_desc2->SCSIIO.RequestFlags = req_desc->SCSIIO.RequestFlags; | |
| 2808 | + r1_cmd->request_desc->SCSIIO.DevHandle = cmd->r1_alt_dev_handle; | |
| 2809 | + r1_cmd->io_request->DevHandle = cmd->r1_alt_dev_handle; | |
| 2810 | + r1_cmd->r1_alt_dev_handle = cmd->io_request->DevHandle; | |
| 2811 | + cmd->io_request->RaidContext.raid_context_g35.smid.peer_smid = | |
| 2812 | + cpu_to_le16(r1_cmd->index); | |
| 2813 | + r1_cmd->io_request->RaidContext.raid_context_g35.smid.peer_smid = | |
| 2814 | + cpu_to_le16(cmd->index); | |
| 2815 | + /*MSIxIndex of both commands request descriptors should be same*/ | |
| 2816 | + r1_cmd->request_desc->SCSIIO.MSIxIndex = | |
| 2817 | + cmd->request_desc->SCSIIO.MSIxIndex; | |
| 2818 | + /*span arm is different for r1 cmd*/ | |
| 2819 | + r1_cmd->io_request->RaidContext.raid_context_g35.span_arm = | |
| 2820 | + cmd->io_request->RaidContext.raid_context_g35.span_arm + 1; | |
| 2821 | +} | |
| 2822 | + | |
| 2171 | 2823 | /** |
| 2172 | 2824 | * megasas_build_and_issue_cmd_fusion -Main routine for building and |
| 2173 | 2825 | * issuing non IOCTL cmd |
| @@ -2178,7 +2830,7 @@ static u32 · 4 unmodified lines | ||
| 2178 | 2830 | megasas_build_and_issue_cmd_fusion(struct megasas_instance *instance, |
| 2179 | 2831 | struct scsi_cmnd *scmd) |
| 2180 | 2832 | { |
| 2181 | − struct megasas_cmd_fusion *cmd; | |
| 2833 | + struct megasas_cmd_fusion *cmd, *r1_cmd = NULL; | |
| 2182 | 2834 | union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc; |
| 2183 | 2835 | u32 index; |
| 2184 | 2836 | struct fusion_context *fusion; |
| @@ -2193,13 +2845,22 @@ megasas_build_and_issue_cmd_fusion(struct megasas_instance *instance, · 8 unmodified lines | ||
| 2193 | 2845 | return SCSI_MLQUEUE_DEVICE_BUSY; |
| 2194 | 2846 | } |
| 2195 | 2847 | |
| 2848 | + if (atomic_inc_return(&instance->fw_outstanding) > | |
| 2849 | + instance->host->can_queue) { | |
| 2850 | + atomic_dec(&instance->fw_outstanding); | |
| 2851 | + return SCSI_MLQUEUE_HOST_BUSY; | |
| 2852 | + } | |
| 2853 | + | |
| 2196 | 2854 | cmd = megasas_get_cmd_fusion(instance, scmd->request->tag); |
| 2197 | 2855 | |
| 2856 | + if (!cmd) { | |
| 2857 | + atomic_dec(&instance->fw_outstanding); | |
| 2858 | + return SCSI_MLQUEUE_HOST_BUSY; | |
| 2859 | + } | |
| 2860 | + | |
| 2198 | 2861 | index = cmd->index; |
| 2199 | 2862 | |
| 2200 | 2863 | req_desc = megasas_get_request_descriptor(instance, index-1); |
| 2201 | − if (!req_desc) | |
| 2202 | − return SCSI_MLQUEUE_HOST_BUSY; | |
| 2203 | 2864 | |
| 2204 | 2865 | req_desc->Words = 0; |
| 2205 | 2866 | cmd->request_desc = req_desc; |
| @@ -2208,6 +2869,7 @@ megasas_build_and_issue_cmd_fusion(struct megasas_instance *instance, · 2 unmodified lines | ||
| 2208 | 2869 | megasas_return_cmd_fusion(instance, cmd); |
| 2209 | 2870 | dev_err(&instance->pdev->dev, "Error building command\n"); |
| 2210 | 2871 | cmd->request_desc = NULL; |
| 2872 | + atomic_dec(&instance->fw_outstanding); | |
| 2211 | 2873 | return SCSI_MLQUEUE_HOST_BUSY; |
| 2212 | 2874 | } |
| 2213 | 2875 | |
| @@ -2218,17 +2880,91 @@ megasas_build_and_issue_cmd_fusion(struct megasas_instance *instance, · 4 unmodified lines | ||
| 2218 | 2880 | cmd->io_request->ChainOffset != 0xF) |
| 2219 | 2881 | dev_err(&instance->pdev->dev, "The chain offset value is not " |
| 2220 | 2882 | "correct : %x\n", cmd->io_request->ChainOffset); |
| 2883 | + /* | |
| 2884 | + * if it is raid 1/10 fp write capable. | |
| 2885 | + * try to get second command from pool and construct it. | |
| 2886 | + * From FW, it has confirmed that lba values of two PDs | |
| 2887 | + * corresponds to single R1/10 LD are always same | |
| 2888 | + * | |
| 2889 | + */ | |
| 2890 | + /* driver side count always should be less than max_fw_cmds | |
| 2891 | + * to get new command | |
| 2892 | + */ | |
| 2893 | + if (cmd->r1_alt_dev_handle != MR_DEVHANDLE_INVALID) { | |
| 2894 | + r1_cmd = megasas_get_cmd_fusion(instance, | |
| 2895 | + (scmd->request->tag + instance->max_fw_cmds)); | |
| 2896 | + megasas_prepare_secondRaid1_IO(instance, cmd, r1_cmd); | |
| 2897 | + } | |
| 2898 | + | |
| 2221 | 2899 | |
| 2222 | 2900 | /* |
| 2223 | 2901 | * Issue the command to the FW |
| 2224 | 2902 | */ |
| 2225 | − atomic_inc(&instance->fw_outstanding); | |
| 2226 | 2903 | |
| 2227 | 2904 | megasas_fire_cmd_fusion(instance, req_desc); |
| 2228 | 2905 | |
| 2906 | + if (r1_cmd) | |
| 2907 | + megasas_fire_cmd_fusion(instance, r1_cmd->request_desc); | |
| 2908 | + | |
| 2909 | + | |
| 2229 | 2910 | return 0; |
| 2230 | 2911 | } |
| 2231 | 2912 | |
| 2913 | +/** | |
| 2914 | + * megasas_complete_r1_command - | |
| 2915 | + * completes R1 FP write commands which has valid peer smid | |
| 2916 | + * @instance: Adapter soft state | |
| 2917 | + * @cmd_fusion: MPT command frame | |
| 2918 | + * | |
| 2919 | + */ | |
| 2920 | +static inline void | |
| 2921 | +megasas_complete_r1_command(struct megasas_instance *instance, | |
| 2922 | + struct megasas_cmd_fusion *cmd) | |
| 2923 | +{ | |
| 2924 | + u8 *sense, status, ex_status; | |
| 2925 | + u32 data_length; | |
| 2926 | + u16 peer_smid; | |
| 2927 | + struct fusion_context *fusion; | |
| 2928 | + struct megasas_cmd_fusion *r1_cmd = NULL; | |
| 2929 | + struct scsi_cmnd *scmd_local = NULL; | |
| 2930 | + struct RAID_CONTEXT_G35 *rctx_g35; | |
| 2931 | + | |
| 2932 | + rctx_g35 = &cmd->io_request->RaidContext.raid_context_g35; | |
| 2933 | + fusion = instance->ctrl_context; | |
| 2934 | + peer_smid = le16_to_cpu(rctx_g35->smid.peer_smid); | |
| 2935 | + | |
| 2936 | + r1_cmd = fusion->cmd_list[peer_smid - 1]; | |
| 2937 | + scmd_local = cmd->scmd; | |
| 2938 | + status = rctx_g35->status; | |
| 2939 | + ex_status = rctx_g35->ex_status; | |
| 2940 | + data_length = cmd->io_request->DataLength; | |
| 2941 | + sense = cmd->sense; | |
| 2942 | + | |
| 2943 | + cmd->cmd_completed = true; | |
| 2944 | + | |
| 2945 | + /* Check if peer command is completed or not*/ | |
| 2946 | + if (r1_cmd->cmd_completed) { | |
| 2947 | + rctx_g35 = &r1_cmd->io_request->RaidContext.raid_context_g35; | |
| 2948 | + if (rctx_g35->status != MFI_STAT_OK) { | |
| 2949 | + status = rctx_g35->status; | |
| 2950 | + ex_status = rctx_g35->ex_status; | |
| 2951 | + data_length = r1_cmd->io_request->DataLength; | |
| 2952 | + sense = r1_cmd->sense; | |
| 2953 | + } | |
| 2954 | + | |
| 2955 | + megasas_return_cmd_fusion(instance, r1_cmd); | |
| 2956 | + map_cmd_status(fusion, scmd_local, status, ex_status, | |
| 2957 | + le32_to_cpu(data_length), sense); | |
| 2958 | + if (instance->ldio_threshold && | |
| 2959 | + megasas_cmd_type(scmd_local) == READ_WRITE_LDIO) | |
| 2960 | + atomic_dec(&instance->ldio_outstanding); | |
| 2961 | + scmd_local->SCp.ptr = NULL; | |
| 2962 | + megasas_return_cmd_fusion(instance, cmd); | |
| 2963 | + scsi_dma_unmap(scmd_local); | |
| 2964 | + scmd_local->scsi_done(scmd_local); | |
| 2965 | + } | |
| 2966 | +} | |
| 2967 | + | |
| 2232 | 2968 | /** |
| 2233 | 2969 | * complete_cmd_fusion - Completes command |
| 2234 | 2970 | * @instance: Adapter soft state |
| @@ -2244,8 +2980,8 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex) · 9 unmodified lines | ||
| 2244 | 2980 | struct megasas_cmd *cmd_mfi; |
| 2245 | 2981 | struct megasas_cmd_fusion *cmd_fusion; |
| 2246 | 2982 | u16 smid, num_completed; |
| 2247 | − u8 reply_descript_type; | |
| 2248 | − u32 status, extStatus, device_id; | |
| 2983 | + u8 reply_descript_type, *sense, status, extStatus; | |
| 2984 | + u32 device_id, data_length; | |
| 2249 | 2985 | union desc_value d_val; |
| 2250 | 2986 | struct LD_LOAD_BALANCE_INFO *lbinfo; |
| 2251 | 2987 | int threshold_reply_count = 0; |
| @@ -2275,20 +3011,17 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex) · 23 unmodified lines | ||
| 2275 | 3011 | |
| 2276 | 3012 | while (d_val.u.low != cpu_to_le32(UINT_MAX) && |
| 2277 | 3013 | d_val.u.high != cpu_to_le32(UINT_MAX)) { |
| 2278 | − smid = le16_to_cpu(reply_desc->SMID); | |
| 2279 | 3014 | |
| 3015 | + smid = le16_to_cpu(reply_desc->SMID); | |
| 2280 | 3016 | cmd_fusion = fusion->cmd_list[smid - 1]; |
| 2281 | − | |
| 2282 | − scsi_io_req = | |
| 2283 | − (struct MPI2_RAID_SCSI_IO_REQUEST *) | |
| 2284 | − cmd_fusion->io_request; | |
| 2285 | − | |
| 2286 | − if (cmd_fusion->scmd) | |
| 2287 | − cmd_fusion->scmd->SCp.ptr = NULL; | |
| 3017 | + scsi_io_req = (struct MPI2_RAID_SCSI_IO_REQUEST *) | |
| 3018 | + cmd_fusion->io_request; | |
| 2288 | 3019 | |
| 2289 | 3020 | scmd_local = cmd_fusion->scmd; |
| 2290 | − status = scsi_io_req->RaidContext.status; | |
| 2291 | − extStatus = scsi_io_req->RaidContext.exStatus; | |
| 3021 | + status = scsi_io_req->RaidContext.raid_context.status; | |
| 3022 | + extStatus = scsi_io_req->RaidContext.raid_context.ex_status; | |
| 3023 | + sense = cmd_fusion->sense; | |
| 3024 | + data_length = scsi_io_req->DataLength; | |
| 2292 | 3025 | |
| 2293 | 3026 | switch (scsi_io_req->Function) { |
| 2294 | 3027 | case MPI2_FUNCTION_SCSI_TASK_MGMT: |
| @@ -2303,37 +3036,33 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex) · 8 unmodified lines | ||
| 2303 | 3036 | break; |
| 2304 | 3037 | case MPI2_FUNCTION_SCSI_IO_REQUEST: /*Fast Path IO.*/ |
| 2305 | 3038 | /* Update load balancing info */ |
| 2306 | − device_id = MEGASAS_DEV_INDEX(scmd_local); | |
| 2307 | − lbinfo = &fusion->load_balance_info[device_id]; | |
| 2308 | − if (cmd_fusion->scmd->SCp.Status & | |
| 2309 | − MEGASAS_LOAD_BALANCE_FLAG) { | |
| 3039 | + if (fusion->load_balance_info && | |
| 3040 | + (cmd_fusion->scmd->SCp.Status & | |
| 3041 | + MEGASAS_LOAD_BALANCE_FLAG)) { | |
| 3042 | + device_id = MEGASAS_DEV_INDEX(scmd_local); | |
| 3043 | + lbinfo = &fusion->load_balance_info[device_id]; | |
| 2310 | 3044 | atomic_dec(&lbinfo->scsi_pending_cmds[cmd_fusion->pd_r1_lb]); |
| 2311 | − cmd_fusion->scmd->SCp.Status &= | |
| 2312 | − ~MEGASAS_LOAD_BALANCE_FLAG; | |
| 3045 | + cmd_fusion->scmd->SCp.Status &= ~MEGASAS_LOAD_BALANCE_FLAG; | |
| 2313 | 3046 | } |
| 2314 | − if (reply_descript_type == | |
| 2315 | − MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS) { | |
| 2316 | − if (megasas_dbg_lvl == 5) | |
| 2317 | − dev_err(&instance->pdev->dev, "\nFAST Path " | |
| 2318 | − "IO Success\n"); | |
| 2319 | − } | |
| 2320 | − /* Fall thru and complete IO */ | |
| 3047 | + //Fall thru and complete IO | |
| 2321 | 3048 | case MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST: /* LD-IO Path */ |
| 2322 | − /* Map the FW Cmd Status */ | |
| 2323 | − map_cmd_status(cmd_fusion, status, extStatus); | |
| 2324 | − scsi_io_req->RaidContext.status = 0; | |
| 2325 | − scsi_io_req->RaidContext.exStatus = 0; | |
| 2326 | − if (megasas_cmd_type(scmd_local) == READ_WRITE_LDIO) | |
| 2327 | − atomic_dec(&instance->ldio_outstanding); | |
| 2328 | − megasas_return_cmd_fusion(instance, cmd_fusion); | |
| 2329 | − scsi_dma_unmap(scmd_local); | |
| 2330 | − scmd_local->scsi_done(scmd_local); | |
| 2331 | 3049 | atomic_dec(&instance->fw_outstanding); |
| 2332 | − | |
| 3050 | + if (cmd_fusion->r1_alt_dev_handle == MR_DEVHANDLE_INVALID) { | |
| 3051 | + map_cmd_status(fusion, scmd_local, status, | |
| 3052 | + extStatus, le32_to_cpu(data_length), | |
| 3053 | + sense); | |
| 3054 | + if (instance->ldio_threshold && | |
| 3055 | + (megasas_cmd_type(scmd_local) == READ_WRITE_LDIO)) | |
| 3056 | + atomic_dec(&instance->ldio_outstanding); | |
| 3057 | + scmd_local->SCp.ptr = NULL; | |
| 3058 | + megasas_return_cmd_fusion(instance, cmd_fusion); | |
| 3059 | + scsi_dma_unmap(scmd_local); | |
| 3060 | + scmd_local->scsi_done(scmd_local); | |
| 3061 | + } else /* Optimal VD - R1 FP command completion. */ | |
| 3062 | + megasas_complete_r1_command(instance, cmd_fusion); | |
| 2333 | 3063 | break; |
| 2334 | 3064 | case MEGASAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST: /*MFI command */ |
| 2335 | 3065 | cmd_mfi = instance->cmd_list[cmd_fusion->sync_cmd_idx]; |
| 2336 | − | |
| 2337 | 3066 | /* Poll mode. Dummy free. |
| 2338 | 3067 | * In case of Interrupt mode, caller has reverse check. |
| 2339 | 3068 | */ |
| @@ -2376,7 +3105,7 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex) · 36 unmodified lines | ||
| 2376 | 3105 | * pending to be completed |
| 2377 | 3106 | */ |
| 2378 | 3107 | if (threshold_reply_count >= THRESHOLD_REPLY_COUNT) { |
| 2379 | − if (fusion->adapter_type == INVADER_SERIES) | |
| 3108 | + if (instance->msix_combined) | |
| 2380 | 3109 | writel(((MSIxIndex & 0x7) << 24) | |
| 2381 | 3110 | fusion->last_reply_idx[MSIxIndex], |
| 2382 | 3111 | instance->reply_post_host_index_addr[MSIxIndex/8]); |
| @@ -2392,7 +3121,7 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex) · 9 unmodified lines | ||
| 2392 | 3121 | return IRQ_NONE; |
| 2393 | 3122 | |
| 2394 | 3123 | wmb(); |
| 2395 | − if (fusion->adapter_type == INVADER_SERIES) | |
| 3124 | + if (instance->msix_combined) | |
| 2396 | 3125 | writel(((MSIxIndex & 0x7) << 24) | |
| 2397 | 3126 | fusion->last_reply_idx[MSIxIndex], |
| 2398 | 3127 | instance->reply_post_host_index_addr[MSIxIndex/8]); |
| @@ -2404,6 +3133,22 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex) · 5 unmodified lines | ||
| 2404 | 3133 | return IRQ_HANDLED; |
| 2405 | 3134 | } |
| 2406 | 3135 | |
| 3136 | +/** | |
| 3137 | + * megasas_sync_irqs - Synchronizes all IRQs owned by adapter | |
| 3138 | + * @instance: Adapter soft state | |
| 3139 | + */ | |
| 3140 | +void megasas_sync_irqs(unsigned long instance_addr) | |
| 3141 | +{ | |
| 3142 | + u32 count, i; | |
| 3143 | + struct megasas_instance *instance = | |
| 3144 | + (struct megasas_instance *)instance_addr; | |
| 3145 | + | |
| 3146 | + count = instance->msix_vectors > 0 ? instance->msix_vectors : 1; | |
| 3147 | + | |
| 3148 | + for (i = 0; i < count; i++) | |
| 3149 | + synchronize_irq(pci_irq_vector(instance->pdev, i)); | |
| 3150 | +} | |
| 3151 | + | |
| 2407 | 3152 | /** |
| 2408 | 3153 | * megasas_complete_cmd_dpc_fusion - Completes command |
| 2409 | 3154 | * @instance: Adapter soft state |
| @@ -2489,7 +3234,7 @@ irqreturn_t megasas_isr_fusion(int irq, void *devp) · 79 unmodified lines | ||
| 2489 | 3234 | * mfi_cmd: megasas_cmd pointer |
| 2490 | 3235 | * |
| 2491 | 3236 | */ |
| 2492 | −u8 | |
| 3237 | +void | |
| 2493 | 3238 | build_mpt_mfi_pass_thru(struct megasas_instance *instance, |
| 2494 | 3239 | struct megasas_cmd *mfi_cmd) |
| 2495 | 3240 | { |
| @@ -2518,7 +3263,7 @@ build_mpt_mfi_pass_thru(struct megasas_instance *instance, · 22 unmodified lines | ||
| 2518 | 3263 | |
| 2519 | 3264 | io_req = cmd->io_request; |
| 2520 | 3265 | |
| 2521 | − if (fusion->adapter_type == INVADER_SERIES) { | |
| 3266 | + if (fusion->adapter_type >= INVADER_SERIES) { | |
| 2522 | 3267 | struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr_end = |
| 2523 | 3268 | (struct MPI25_IEEE_SGE_CHAIN64 *)&io_req->SGL; |
| 2524 | 3269 | sgl_ptr_end += fusion->max_sge_in_main_msg - 1; |
| @@ -2539,8 +3284,6 @@ build_mpt_mfi_pass_thru(struct megasas_instance *instance, · 14 unmodified lines | ||
| 2539 | 3284 | MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR; |
| 2540 | 3285 | |
| 2541 | 3286 | mpi25_ieee_chain->Length = cpu_to_le32(instance->max_chain_frame_sz); |
| 2542 | − | |
| 2543 | − return 0; | |
| 2544 | 3287 | } |
| 2545 | 3288 | |
| 2546 | 3289 | /** |
| @@ -2552,21 +3295,14 @@ build_mpt_mfi_pass_thru(struct megasas_instance *instance, · 5 unmodified lines | ||
| 2552 | 3295 | union MEGASAS_REQUEST_DESCRIPTOR_UNION * |
| 2553 | 3296 | build_mpt_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd) |
| 2554 | 3297 | { |
| 2555 | − union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc; | |
| 3298 | + union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc = NULL; | |
| 2556 | 3299 | u16 index; |
| 2557 | 3300 | |
| 2558 | − if (build_mpt_mfi_pass_thru(instance, cmd)) { | |
| 2559 | − dev_err(&instance->pdev->dev, "Couldn't build MFI pass thru cmd\n"); | |
| 2560 | − return NULL; | |
| 2561 | − } | |
| 2562 | − | |
| 3301 | + build_mpt_mfi_pass_thru(instance, cmd); | |
| 2563 | 3302 | index = cmd->context.smid; |
| 2564 | 3303 | |
| 2565 | 3304 | req_desc = megasas_get_request_descriptor(instance, index - 1); |
| 2566 | 3305 | |
| 2567 | − if (!req_desc) | |
| 2568 | − return NULL; | |
| 2569 | − | |
| 2570 | 3306 | req_desc->Words = 0; |
| 2571 | 3307 | req_desc->SCSIIO.RequestFlags = (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO << |
| 2572 | 3308 | MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); |
| @@ -2582,21 +3318,16 @@ build_mpt_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd) · 9 unmodified lines | ||
| 2582 | 3318 | * @cmd: mfi cmd pointer |
| 2583 | 3319 | * |
| 2584 | 3320 | */ |
| 2585 | −int | |
| 3321 | +void | |
| 2586 | 3322 | megasas_issue_dcmd_fusion(struct megasas_instance *instance, |
| 2587 | 3323 | struct megasas_cmd *cmd) |
| 2588 | 3324 | { |
| 2589 | 3325 | union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc; |
| 2590 | 3326 | |
| 2591 | 3327 | req_desc = build_mpt_cmd(instance, cmd); |
| 2592 | − if (!req_desc) { | |
| 2593 | − dev_info(&instance->pdev->dev, "Failed from %s %d\n", | |
| 2594 | − __func__, __LINE__); | |
| 2595 | − return DCMD_NOT_FIRED; | |
| 2596 | − } | |
| 2597 | 3328 | |
| 2598 | 3329 | megasas_fire_cmd_fusion(instance, req_desc); |
| 2599 | − return DCMD_SUCCESS; | |
| 3330 | + return; | |
| 2600 | 3331 | } |
| 2601 | 3332 | |
| 2602 | 3333 | /** |
| @@ -2771,6 +3502,14 @@ int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance, · 168 unmodified lines | ||
| 2771 | 3502 | " will reset adapter scsi%d.\n", |
| 2772 | 3503 | instance->host->host_no); |
| 2773 | 3504 | megasas_complete_cmd_dpc_fusion((unsigned long)instance); |
| 3505 | + if (instance->requestorId && reason) { | |
| 3506 | + dev_warn(&instance->pdev->dev, "SR-IOV Found FW in FAULT" | |
| 3507 | + " state while polling during" | |
| 3508 | + " I/O timeout handling for %d\n", | |
| 3509 | + instance->host->host_no); | |
| 3510 | + *convert = 1; | |
| 3511 | + } | |
| 3512 | + | |
| 2774 | 3513 | retval = 1; |
| 2775 | 3514 | goto out; |
| 2776 | 3515 | } |
| @@ -2790,7 +3529,7 @@ int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance, · 13 unmodified lines | ||
| 2790 | 3529 | } |
| 2791 | 3530 | |
| 2792 | 3531 | /* If SR-IOV VF mode & I/O timeout, check for HB timeout */ |
| 2793 | − if (instance->requestorId && reason) { | |
| 3532 | + if (instance->requestorId && (reason == SCSIIO_TIMEOUT_OCR)) { | |
| 2794 | 3533 | if (instance->hb_host_mem->HB.fwCounter != |
| 2795 | 3534 | instance->hb_host_mem->HB.driverCounter) { |
| 2796 | 3535 | instance->hb_host_mem->HB.driverCounter = |
| @@ -3030,12 +3769,6 @@ megasas_issue_tm(struct megasas_instance *instance, u16 device_handle, · 233 unmodified lines | ||
| 3030 | 3769 | |
| 3031 | 3770 | req_desc = megasas_get_request_descriptor(instance, |
| 3032 | 3771 | (cmd_fusion->index - 1)); |
| 3033 | − if (!req_desc) { | |
| 3034 | − dev_err(&instance->pdev->dev, "Failed from %s %d\n", | |
| 3035 | − __func__, __LINE__); | |
| 3036 | − megasas_return_cmd(instance, cmd_mfi); | |
| 3037 | − return -ENOMEM; | |
| 3038 | − } | |
| 3039 | 3772 | |
| 3040 | 3773 | cmd_fusion->request_desc = req_desc; |
| 3041 | 3774 | req_desc->Words = 0; |
| @@ -3092,7 +3825,7 @@ megasas_issue_tm(struct megasas_instance *instance, u16 device_handle, · 50 unmodified lines | ||
| 3092 | 3825 | break; |
| 3093 | 3826 | else { |
| 3094 | 3827 | instance->instancet->disable_intr(instance); |
| 3095 | − msleep(1000); | |
| 3828 | + megasas_sync_irqs((unsigned long)instance); | |
| 3096 | 3829 | megasas_complete_cmd_dpc_fusion |
| 3097 | 3830 | ((unsigned long)instance); |
| 3098 | 3831 | instance->instancet->enable_intr(instance); |
| @@ -3173,13 +3906,13 @@ static u16 megasas_get_tm_devhandle(struct scsi_device *sdev) · 74 unmodified lines | ||
| 3173 | 3906 | instance = (struct megasas_instance *)sdev->host->hostdata; |
| 3174 | 3907 | fusion = instance->ctrl_context; |
| 3175 | 3908 | |
| 3176 | − if (sdev->channel < MEGASAS_MAX_PD_CHANNELS) { | |
| 3909 | + if (!MEGASAS_IS_LOGICAL(sdev)) { | |
| 3177 | 3910 | if (instance->use_seqnum_jbod_fp) { |
| 3178 | − pd_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + | |
| 3179 | − sdev->id; | |
| 3180 | − pd_sync = (void *)fusion->pd_seq_sync | |
| 3181 | − [(instance->pd_seq_map_id - 1) & 1]; | |
| 3182 | − devhandle = pd_sync->seq[pd_index].devHandle; | |
| 3911 | + pd_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) | |
| 3912 | + + sdev->id; | |
| 3913 | + pd_sync = (void *)fusion->pd_seq_sync | |
| 3914 | + [(instance->pd_seq_map_id - 1) & 1]; | |
| 3915 | + devhandle = pd_sync->seq[pd_index].devHandle; | |
| 3183 | 3916 | } else |
| 3184 | 3917 | sdev_printk(KERN_ERR, sdev, "Firmware expose tmCapable" |
| 3185 | 3918 | " without JBOD MAP support from %s %d\n", __func__, __LINE__); |
| @@ -3212,6 +3945,9 @@ int megasas_task_abort_fusion(struct scsi_cmnd *scmd) · 26 unmodified lines | ||
| 3212 | 3945 | instance = (struct megasas_instance *)scmd->device->host->hostdata; |
| 3213 | 3946 | fusion = instance->ctrl_context; |
| 3214 | 3947 | |
| 3948 | + scmd_printk(KERN_INFO, scmd, "task abort called for scmd(%p)\n", scmd); | |
| 3949 | + scsi_print_command(scmd); | |
| 3950 | + | |
| 3215 | 3951 | if (atomic_read(&instance->adprecovery) != MEGASAS_HBA_OPERATIONAL) { |
| 3216 | 3952 | dev_err(&instance->pdev->dev, "Controller is not OPERATIONAL," |
| 3217 | 3953 | "SCSI host:%d\n", instance->host->host_no); |
| @@ -3292,6 +4028,9 @@ int megasas_reset_target_fusion(struct scsi_cmnd *scmd) · 74 unmodified lines | ||
| 3292 | 4028 | instance = (struct megasas_instance *)scmd->device->host->hostdata; |
| 3293 | 4029 | fusion = instance->ctrl_context; |
| 3294 | 4030 | |
| 4031 | + sdev_printk(KERN_INFO, scmd->device, | |
| 4032 | + "target reset called for scmd(%p)\n", scmd); | |
| 4033 | + | |
| 3295 | 4034 | if (atomic_read(&instance->adprecovery) != MEGASAS_HBA_OPERATIONAL) { |
| 3296 | 4035 | dev_err(&instance->pdev->dev, "Controller is not OPERATIONAL," |
| 3297 | 4036 | "SCSI host:%d\n", instance->host->host_no); |
| @@ -3362,7 +4101,7 @@ int megasas_check_mpio_paths(struct megasas_instance *instance, · 64 unmodified lines | ||
| 3362 | 4101 | struct scsi_cmnd *scmd) |
| 3363 | 4102 | { |
| 3364 | 4103 | struct megasas_instance *peer_instance = NULL; |
| 3365 | − int retval = (DID_RESET << 16); | |
| 4104 | + int retval = (DID_REQUEUE << 16); | |
| 3366 | 4105 | |
| 3367 | 4106 | if (instance->peerIsPresent) { |
| 3368 | 4107 | peer_instance = megasas_get_peer_instance(instance); |
| @@ -3377,9 +4116,9 @@ int megasas_check_mpio_paths(struct megasas_instance *instance, · 8 unmodified lines | ||
| 3377 | 4116 | /* Core fusion reset function */ |
| 3378 | 4117 | int megasas_reset_fusion(struct Scsi_Host *shost, int reason) |
| 3379 | 4118 | { |
| 3380 | − int retval = SUCCESS, i, convert = 0; | |
| 4119 | + int retval = SUCCESS, i, j, convert = 0; | |
| 3381 | 4120 | struct megasas_instance *instance; |
| 3382 | − struct megasas_cmd_fusion *cmd_fusion; | |
| 4121 | + struct megasas_cmd_fusion *cmd_fusion, *r1_cmd; | |
| 3383 | 4122 | struct fusion_context *fusion; |
| 3384 | 4123 | u32 abs_state, status_reg, reset_adapter; |
| 3385 | 4124 | u32 io_timeout_in_crash_mode = 0; |
| @@ -3440,7 +4179,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int reason) · 54 unmodified lines | ||
| 3440 | 4179 | set_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags); |
| 3441 | 4180 | atomic_set(&instance->adprecovery, MEGASAS_ADPRESET_SM_POLLING); |
| 3442 | 4181 | instance->instancet->disable_intr(instance); |
| 3443 | − msleep(1000); | |
| 4182 | + megasas_sync_irqs((unsigned long)instance); | |
| 3444 | 4183 | |
| 3445 | 4184 | /* First try waiting for commands to complete */ |
| 3446 | 4185 | if (megasas_wait_for_outstanding_fusion(instance, reason, |
| @@ -3451,23 +4190,40 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int reason) · 4 unmodified lines | ||
| 3451 | 4190 | if (convert) |
| 3452 | 4191 | reason = 0; |
| 3453 | 4192 | |
| 4193 | + if (megasas_dbg_lvl & OCR_LOGS) | |
| 4194 | + dev_info(&instance->pdev->dev, "\nPending SCSI commands:\n"); | |
| 4195 | + | |
| 3454 | 4196 | /* Now return commands back to the OS */ |
| 3455 | 4197 | for (i = 0 ; i < instance->max_scsi_cmds; i++) { |
| 3456 | 4198 | cmd_fusion = fusion->cmd_list[i]; |
| 4199 | + /*check for extra commands issued by driver*/ | |
| 4200 | + if (instance->is_ventura) { | |
| 4201 | + r1_cmd = fusion->cmd_list[i + instance->max_fw_cmds]; | |
| 4202 | + megasas_return_cmd_fusion(instance, r1_cmd); | |
| 4203 | + } | |
| 3457 | 4204 | scmd_local = cmd_fusion->scmd; |
| 3458 | 4205 | if (cmd_fusion->scmd) { |
| 4206 | + if (megasas_dbg_lvl & OCR_LOGS) { | |
| 4207 | + sdev_printk(KERN_INFO, | |
| 4208 | + cmd_fusion->scmd->device, "SMID: 0x%x\n", | |
| 4209 | + cmd_fusion->index); | |
| 4210 | + scsi_print_command(cmd_fusion->scmd); | |
| 4211 | + } | |
| 4212 | + | |
| 3459 | 4213 | scmd_local->result = |
| 3460 | 4214 | megasas_check_mpio_paths(instance, |
| 3461 | 4215 | scmd_local); |
| 3462 | − if (megasas_cmd_type(scmd_local) == READ_WRITE_LDIO) | |
| 4216 | + if (instance->ldio_threshold && | |
| 4217 | + megasas_cmd_type(scmd_local) == READ_WRITE_LDIO) | |
| 3463 | 4218 | atomic_dec(&instance->ldio_outstanding); |
| 3464 | 4219 | megasas_return_cmd_fusion(instance, cmd_fusion); |
| 3465 | 4220 | scsi_dma_unmap(scmd_local); |
| 3466 | 4221 | scmd_local->scsi_done(scmd_local); |
| 3467 | − atomic_dec(&instance->fw_outstanding); | |
| 3468 | 4222 | } |
| 3469 | 4223 | } |
| 3470 | 4224 | |
| 4225 | + atomic_set(&instance->fw_outstanding, 0); | |
| 4226 | + | |
| 3471 | 4227 | status_reg = instance->instancet->read_fw_status_reg( |
| 3472 | 4228 | instance->reg_set); |
| 3473 | 4229 | abs_state = status_reg & MFI_STATE_MASK; |
| @@ -3528,11 +4284,13 @@ transition_to_ready: · 54 unmodified lines | ||
| 3528 | 4284 | __func__, __LINE__); |
| 3529 | 4285 | megaraid_sas_kill_hba(instance); |
| 3530 | 4286 | retval = FAILED; |
| 4287 | + goto out; | |
| 3531 | 4288 | } |
| 3532 | 4289 | /* Reset load balance info */ |
| 3533 | − memset(fusion->load_balance_info, 0, | |
| 3534 | − sizeof(struct LD_LOAD_BALANCE_INFO) | |
| 3535 | − *MAX_LOGICAL_DRIVES_EXT); | |
| 4290 | + if (fusion->load_balance_info) | |
| 4291 | + memset(fusion->load_balance_info, 0, | |
| 4292 | + (sizeof(struct LD_LOAD_BALANCE_INFO) * | |
| 4293 | + MAX_LOGICAL_DRIVES_EXT)); | |
| 3536 | 4294 | |
| 3537 | 4295 | if (!megasas_get_map_info(instance)) |
| 3538 | 4296 | megasas_sync_map_info(instance); |
| @@ -3540,7 +4298,17 @@ transition_to_ready: · 1 unmodified line | ||
| 3540 | 4298 | megasas_setup_jbod_map(instance); |
| 3541 | 4299 | |
| 3542 | 4300 | shost_for_each_device(sdev, shost) |
| 3543 | − megasas_update_sdev_properties(sdev); | |
| 4301 | + megasas_set_dynamic_target_properties(sdev); | |
| 4302 | + | |
| 4303 | + /* reset stream detection array */ | |
| 4304 | + if (instance->is_ventura) { | |
| 4305 | + for (j = 0; j < MAX_LOGICAL_DRIVES_EXT; ++j) { | |
| 4306 | + memset(fusion->stream_detect_by_ld[j], | |
| 4307 | + 0, sizeof(struct LD_STREAM_DETECT)); | |
| 4308 | + fusion->stream_detect_by_ld[j]->mru_bit_map | |
| 4309 | + = MR_STREAM_BITMAP; | |
| 4310 | + } | |
| 4311 | + } | |
| 3544 | 4312 | |
| 3545 | 4313 | clear_bit(MEGASAS_FUSION_IN_RESET, |
| 3546 | 4314 | &instance->reset_flags); |
| @@ -3676,6 +4444,64 @@ void megasas_fusion_ocr_wq(struct work_struct *work) · 129 unmodified lines | ||
| 3676 | 4444 | megasas_reset_fusion(instance->host, 0); |
| 3677 | 4445 | } |
| 3678 | 4446 | |
| 4447 | +/* Allocate fusion context */ | |
| 4448 | +int | |
| 4449 | +megasas_alloc_fusion_context(struct megasas_instance *instance) | |
| 4450 | +{ | |
| 4451 | + struct fusion_context *fusion; | |
| 4452 | + | |
| 4453 | + instance->ctrl_context_pages = get_order(sizeof(struct fusion_context)); | |
| 4454 | + instance->ctrl_context = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, | |
| 4455 | + instance->ctrl_context_pages); | |
| 4456 | + if (!instance->ctrl_context) { | |
| 4457 | + /* fall back to using vmalloc for fusion_context */ | |
| 4458 | + instance->ctrl_context = vzalloc(sizeof(struct fusion_context)); | |
| 4459 | + if (!instance->ctrl_context) { | |
| 4460 | + dev_err(&instance->pdev->dev, "Failed from %s %d\n", __func__, __LINE__); | |
| 4461 | + return -ENOMEM; | |
| 4462 | + } | |
| 4463 | + } | |
| 4464 | + | |
| 4465 | + fusion = instance->ctrl_context; | |
| 4466 | + | |
| 4467 | + fusion->load_balance_info_pages = get_order(MAX_LOGICAL_DRIVES_EXT * | |
| 4468 | + sizeof(struct LD_LOAD_BALANCE_INFO)); | |
| 4469 | + fusion->load_balance_info = | |
| 4470 | + (struct LD_LOAD_BALANCE_INFO *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, | |
| 4471 | + fusion->load_balance_info_pages); | |
| 4472 | + if (!fusion->load_balance_info) { | |
| 4473 | + fusion->load_balance_info = vzalloc(MAX_LOGICAL_DRIVES_EXT * | |
| 4474 | + sizeof(struct LD_LOAD_BALANCE_INFO)); | |
| 4475 | + if (!fusion->load_balance_info) | |
| 4476 | + dev_err(&instance->pdev->dev, "Failed to allocate load_balance_info, " | |
| 4477 | + "continuing without Load Balance support\n"); | |
| 4478 | + } | |
| 4479 | + | |
| 4480 | + return 0; | |
| 4481 | +} | |
| 4482 | + | |
| 4483 | +void | |
| 4484 | +megasas_free_fusion_context(struct megasas_instance *instance) | |
| 4485 | +{ | |
| 4486 | + struct fusion_context *fusion = instance->ctrl_context; | |
| 4487 | + | |
| 4488 | + if (fusion) { | |
| 4489 | + if (fusion->load_balance_info) { | |
| 4490 | + if (is_vmalloc_addr(fusion->load_balance_info)) | |
| 4491 | + vfree(fusion->load_balance_info); | |
| 4492 | + else | |
| 4493 | + free_pages((ulong)fusion->load_balance_info, | |
| 4494 | + fusion->load_balance_info_pages); | |
| 4495 | + } | |
| 4496 | + | |
| 4497 | + if (is_vmalloc_addr(fusion)) | |
| 4498 | + vfree(fusion); | |
| 4499 | + else | |
| 4500 | + free_pages((ulong)fusion, | |
| 4501 | + instance->ctrl_context_pages); | |
| 4502 | + } | |
| 4503 | +} | |
| 4504 | + | |
| 3679 | 4505 | struct megasas_instance_template megasas_instance_template_fusion = { |
| 3680 | 4506 | .enable_intr = megasas_enable_intr_fusion, |
| 3681 | 4507 | .disable_intr = megasas_disable_intr_fusion, |
| @@ -59,6 +59,8 @@ · 58 unmodified lines | ||
| 59 | 59 | #define MR_RL_FLAGS_GRANT_DESTINATION_CPU1 0x10 |
| 60 | 60 | #define MR_RL_FLAGS_GRANT_DESTINATION_CUDA 0x80 |
| 61 | 61 | #define MR_RL_FLAGS_SEQ_NUM_ENABLE 0x8 |
| 62 | +#define MR_RL_WRITE_THROUGH_MODE 0x00 | |
| 63 | +#define MR_RL_WRITE_BACK_MODE 0x01 | |
| 62 | 64 | |
| 63 | 65 | /* T10 PI defines */ |
| 64 | 66 | #define MR_PROT_INFO_TYPE_CONTROLLER 0x8 |
| @@ -81,6 +83,11 @@ · 16 unmodified lines | ||
| 81 | 83 | enum MR_RAID_FLAGS_IO_SUB_TYPE { |
| 82 | 84 | MR_RAID_FLAGS_IO_SUB_TYPE_NONE = 0, |
| 83 | 85 | MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD = 1, |
| 86 | + MR_RAID_FLAGS_IO_SUB_TYPE_RMW_DATA = 2, | |
| 87 | + MR_RAID_FLAGS_IO_SUB_TYPE_RMW_P = 3, | |
| 88 | + MR_RAID_FLAGS_IO_SUB_TYPE_RMW_Q = 4, | |
| 89 | + MR_RAID_FLAGS_IO_SUB_TYPE_CACHE_BYPASS = 6, | |
| 90 | + MR_RAID_FLAGS_IO_SUB_TYPE_LDIO_BW_LIMIT = 7 | |
| 84 | 91 | }; |
| 85 | 92 | |
| 86 | 93 | /* |
| @@ -94,11 +101,13 @@ enum MR_RAID_FLAGS_IO_SUB_TYPE { · 7 unmodified lines | ||
| 94 | 101 | #define MEGASAS_FP_CMD_LEN 16 |
| 95 | 102 | #define MEGASAS_FUSION_IN_RESET 0 |
| 96 | 103 | #define THRESHOLD_REPLY_COUNT 50 |
| 104 | +#define RAID_1_PEER_CMDS 2 | |
| 97 | 105 | #define JBOD_MAPS_COUNT 2 |
| 98 | 106 | |
| 99 | 107 | enum MR_FUSION_ADAPTER_TYPE { |
| 100 | 108 | THUNDERBOLT_SERIES = 0, |
| 101 | 109 | INVADER_SERIES = 1, |
| 110 | + VENTURA_SERIES = 2, | |
| 102 | 111 | }; |
| 103 | 112 | |
| 104 | 113 | /* |
| @@ -108,29 +117,133 @@ enum MR_FUSION_ADAPTER_TYPE { · 3 unmodified lines | ||
| 108 | 117 | |
| 109 | 118 | struct RAID_CONTEXT { |
| 110 | 119 | #if defined(__BIG_ENDIAN_BITFIELD) |
| 111 | − u8 nseg:4; | |
| 112 | − u8 Type:4; | |
| 120 | + u8 nseg:4; | |
| 121 | + u8 type:4; | |
| 113 | 122 | #else |
| 114 | − u8 Type:4; | |
| 115 | − u8 nseg:4; | |
| 123 | + u8 type:4; | |
| 124 | + u8 nseg:4; | |
| 116 | 125 | #endif |
| 117 | − u8 resvd0; | |
| 118 | − __le16 timeoutValue; | |
| 119 | − u8 regLockFlags; | |
| 120 | − u8 resvd1; | |
| 121 | − __le16 VirtualDiskTgtId; | |
| 122 | − __le64 regLockRowLBA; | |
| 123 | − __le32 regLockLength; | |
| 124 | − __le16 nextLMId; | |
| 125 | − u8 exStatus; | |
| 126 | − u8 status; | |
| 127 | − u8 RAIDFlags; | |
| 128 | − u8 numSGE; | |
| 129 | − __le16 configSeqNum; | |
| 130 | − u8 spanArm; | |
| 131 | − u8 priority; | |
| 132 | − u8 numSGEExt; | |
| 133 | − u8 resvd2; | |
| 126 | + u8 resvd0; | |
| 127 | + __le16 timeout_value; | |
| 128 | + u8 reg_lock_flags; | |
| 129 | + u8 resvd1; | |
| 130 | + __le16 virtual_disk_tgt_id; | |
| 131 | + __le64 reg_lock_row_lba; | |
| 132 | + __le32 reg_lock_length; | |
| 133 | + __le16 next_lmid; | |
| 134 | + u8 ex_status; | |
| 135 | + u8 status; | |
| 136 | + u8 raid_flags; | |
| 137 | + u8 num_sge; | |
| 138 | + __le16 config_seq_num; | |
| 139 | + u8 span_arm; | |
| 140 | + u8 priority; | |
| 141 | + u8 num_sge_ext; | |
| 142 | + u8 resvd2; | |
| 143 | +}; | |
| 144 | + | |
| 145 | +/* | |
| 146 | + * Raid Context structure which describes ventura MegaRAID specific | |
| 147 | + * IO Paramenters ,This resides at offset 0x60 where the SGL normally | |
| 148 | + * starts in MPT IO Frames | |
| 149 | + */ | |
| 150 | +struct RAID_CONTEXT_G35 { | |
| 151 | + #define RAID_CONTEXT_NSEG_MASK 0x00F0 | |
| 152 | + #define RAID_CONTEXT_NSEG_SHIFT 4 | |
| 153 | + #define RAID_CONTEXT_TYPE_MASK 0x000F | |
| 154 | + #define RAID_CONTEXT_TYPE_SHIFT 0 | |
| 155 | + u16 nseg_type; | |
| 156 | + u16 timeout_value; /* 0x02 -0x03 */ | |
| 157 | + u16 routing_flags; // 0x04 -0x05 routing flags | |
| 158 | + u16 virtual_disk_tgt_id; /* 0x06 -0x07 */ | |
| 159 | + u64 reg_lock_row_lba; /* 0x08 - 0x0F */ | |
| 160 | + u32 reg_lock_length; /* 0x10 - 0x13 */ | |
| 161 | + union { | |
| 162 | + u16 next_lmid; /* 0x14 - 0x15 */ | |
| 163 | + u16 peer_smid; /* used for the raid 1/10 fp writes */ | |
| 164 | + } smid; | |
| 165 | + u8 ex_status; /* 0x16 : OUT */ | |
| 166 | + u8 status; /* 0x17 status */ | |
| 167 | + u8 raid_flags; /* 0x18 resvd[7:6], ioSubType[5:4], | |
| 168 | + * resvd[3:1], preferredCpu[0] | |
| 169 | + */ | |
| 170 | + u8 span_arm; /* 0x1C span[7:5], arm[4:0] */ | |
| 171 | + u16 config_seq_num; /* 0x1A -0x1B */ | |
| 172 | + union { | |
| 173 | + /* | |
| 174 | + * Bit format: | |
| 175 | + * --------------------------------- | |
| 176 | + * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | | |
| 177 | + * --------------------------------- | |
| 178 | + * Byte0 | numSGE[7]- numSGE[0] | | |
| 179 | + * --------------------------------- | |
| 180 | + * Byte1 |SD | resvd | numSGE 8-11 | | |
| 181 | + * -------------------------------- | |
| 182 | + */ | |
| 183 | + #define NUM_SGE_MASK_LOWER 0xFF | |
| 184 | + #define NUM_SGE_MASK_UPPER 0x0F | |
| 185 | + #define NUM_SGE_SHIFT_UPPER 8 | |
| 186 | + #define STREAM_DETECT_SHIFT 7 | |
| 187 | + #define STREAM_DETECT_MASK 0x80 | |
| 188 | + struct { | |
| 189 | +#if defined(__BIG_ENDIAN_BITFIELD) /* 0x1C - 0x1D */ | |
| 190 | + u16 stream_detected:1; | |
| 191 | + u16 reserved:3; | |
| 192 | + u16 num_sge:12; | |
| 193 | +#else | |
| 194 | + u16 num_sge:12; | |
| 195 | + u16 reserved:3; | |
| 196 | + u16 stream_detected:1; | |
| 197 | +#endif | |
| 198 | + } bits; | |
| 199 | + u8 bytes[2]; | |
| 200 | + } u; | |
| 201 | + u8 resvd2[2]; /* 0x1E-0x1F */ | |
| 202 | +}; | |
| 203 | + | |
| 204 | +#define MR_RAID_CTX_ROUTINGFLAGS_SLD_SHIFT 1 | |
| 205 | +#define MR_RAID_CTX_ROUTINGFLAGS_C2D_SHIFT 2 | |
| 206 | +#define MR_RAID_CTX_ROUTINGFLAGS_FWD_SHIFT 3 | |
| 207 | +#define MR_RAID_CTX_ROUTINGFLAGS_SQN_SHIFT 4 | |
| 208 | +#define MR_RAID_CTX_ROUTINGFLAGS_SBS_SHIFT 5 | |
| 209 | +#define MR_RAID_CTX_ROUTINGFLAGS_RW_SHIFT 6 | |
| 210 | +#define MR_RAID_CTX_ROUTINGFLAGS_LOG_SHIFT 7 | |
| 211 | +#define MR_RAID_CTX_ROUTINGFLAGS_CPUSEL_SHIFT 8 | |
| 212 | +#define MR_RAID_CTX_ROUTINGFLAGS_CPUSEL_MASK 0x0F00 | |
| 213 | +#define MR_RAID_CTX_ROUTINGFLAGS_SETDIVERT_SHIFT 12 | |
| 214 | +#define MR_RAID_CTX_ROUTINGFLAGS_SETDIVERT_MASK 0xF000 | |
| 215 | + | |
| 216 | +static inline void set_num_sge(struct RAID_CONTEXT_G35 *rctx_g35, | |
| 217 | + u16 sge_count) | |
| 218 | +{ | |
| 219 | + rctx_g35->u.bytes[0] = (u8)(sge_count & NUM_SGE_MASK_LOWER); | |
| 220 | + rctx_g35->u.bytes[1] |= (u8)((sge_count >> NUM_SGE_SHIFT_UPPER) | |
| 221 | + & NUM_SGE_MASK_UPPER); | |
| 222 | +} | |
| 223 | + | |
| 224 | +static inline u16 get_num_sge(struct RAID_CONTEXT_G35 *rctx_g35) | |
| 225 | +{ | |
| 226 | + u16 sge_count; | |
| 227 | + | |
| 228 | + sge_count = (u16)(((rctx_g35->u.bytes[1] & NUM_SGE_MASK_UPPER) | |
| 229 | + << NUM_SGE_SHIFT_UPPER) | (rctx_g35->u.bytes[0])); | |
| 230 | + return sge_count; | |
| 231 | +} | |
| 232 | + | |
| 233 | +#define SET_STREAM_DETECTED(rctx_g35) \ | |
| 234 | + (rctx_g35.u.bytes[1] |= STREAM_DETECT_MASK) | |
| 235 | + | |
| 236 | +#define CLEAR_STREAM_DETECTED(rctx_g35) \ | |
| 237 | + (rctx_g35.u.bytes[1] &= ~(STREAM_DETECT_MASK)) | |
| 238 | + | |
| 239 | +static inline bool is_stream_detected(struct RAID_CONTEXT_G35 *rctx_g35) | |
| 240 | +{ | |
| 241 | + return ((rctx_g35->u.bytes[1] & STREAM_DETECT_MASK)); | |
| 242 | +} | |
| 243 | + | |
| 244 | +union RAID_CONTEXT_UNION { | |
| 245 | + struct RAID_CONTEXT raid_context; | |
| 246 | + struct RAID_CONTEXT_G35 raid_context_g35; | |
| 134 | 247 | }; |
| 135 | 248 | |
| 136 | 249 | #define RAID_CTX_SPANARM_ARM_SHIFT (0) |
| @@ -139,6 +252,14 @@ struct RAID_CONTEXT { · 2 unmodified lines | ||
| 139 | 252 | #define RAID_CTX_SPANARM_SPAN_SHIFT (5) |
| 140 | 253 | #define RAID_CTX_SPANARM_SPAN_MASK (0xE0) |
| 141 | 254 | |
| 255 | +/* number of bits per index in U32 TrackStream */ | |
| 256 | +#define BITS_PER_INDEX_STREAM 4 | |
| 257 | +#define INVALID_STREAM_NUM 16 | |
| 258 | +#define MR_STREAM_BITMAP 0x76543210 | |
| 259 | +#define STREAM_MASK ((1 << BITS_PER_INDEX_STREAM) - 1) | |
| 260 | +#define ZERO_LAST_STREAM 0x0fffffff | |
| 261 | +#define MAX_STREAMS_TRACKED 8 | |
| 262 | + | |
| 142 | 263 | /* |
| 143 | 264 | * define region lock types |
| 144 | 265 | */ |
| @@ -175,6 +296,8 @@ enum REGION_TYPE { · 30 unmodified lines | ||
| 175 | 296 | #define MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG (0x0200) |
| 176 | 297 | #define MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD (0x0100) |
| 177 | 298 | #define MPI2_SCSIIO_EEDPFLAGS_INSERT_OP (0x0004) |
| 299 | +/* EEDP escape mode */ | |
| 300 | +#define MPI25_SCSIIO_EEDPFLAGS_DO_NOT_DISABLE_MODE (0x0040) | |
| 178 | 301 | #define MPI2_FUNCTION_SCSI_IO_REQUEST (0x00) /* SCSI IO */ |
| 179 | 302 | #define MPI2_FUNCTION_SCSI_TASK_MGMT (0x01) |
| 180 | 303 | #define MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY (0x03) |
| @@ -407,7 +530,7 @@ struct MPI2_RAID_SCSI_IO_REQUEST { · 226 unmodified lines | ||
| 407 | 530 | u8 LUN[8]; /* 0x34 */ |
| 408 | 531 | __le32 Control; /* 0x3C */ |
| 409 | 532 | union MPI2_SCSI_IO_CDB_UNION CDB; /* 0x40 */ |
| 410 | − struct RAID_CONTEXT RaidContext; /* 0x60 */ | |
| 533 | + union RAID_CONTEXT_UNION RaidContext; /* 0x60 */ | |
| 411 | 534 | union MPI2_SGE_IO_UNION SGL; /* 0x80 */ |
| 412 | 535 | }; |
| 413 | 536 | |
| @@ -563,7 +686,7 @@ struct MPI2_IOC_INIT_REQUEST { · 149 unmodified lines | ||
| 563 | 686 | __le16 HeaderVersion; /* 0x0E */ |
| 564 | 687 | u32 Reserved5; /* 0x10 */ |
| 565 | 688 | __le16 Reserved6; /* 0x14 */ |
| 566 | − u8 Reserved7; /* 0x16 */ | |
| 689 | + u8 HostPageSize; /* 0x16 */ | |
| 567 | 690 | u8 HostMSIxVectors; /* 0x17 */ |
| 568 | 691 | __le16 Reserved8; /* 0x18 */ |
| 569 | 692 | __le16 SystemRequestFrameSize; /* 0x1A */ |
| @@ -579,6 +702,7 @@ struct MPI2_IOC_INIT_REQUEST { · 9 unmodified lines | ||
| 579 | 702 | |
| 580 | 703 | /* mrpriv defines */ |
| 581 | 704 | #define MR_PD_INVALID 0xFFFF |
| 705 | +#define MR_DEVHANDLE_INVALID 0xFFFF | |
| 582 | 706 | #define MAX_SPAN_DEPTH 8 |
| 583 | 707 | #define MAX_QUAD_DEPTH MAX_SPAN_DEPTH |
| 584 | 708 | #define MAX_RAIDMAP_SPAN_DEPTH (MAX_SPAN_DEPTH) |
| @@ -586,16 +710,20 @@ struct MPI2_IOC_INIT_REQUEST { · 1 unmodified line | ||
| 586 | 710 | #define MAX_RAIDMAP_ROW_SIZE (MAX_ROW_SIZE) |
| 587 | 711 | #define MAX_LOGICAL_DRIVES 64 |
| 588 | 712 | #define MAX_LOGICAL_DRIVES_EXT 256 |
| 713 | +#define MAX_LOGICAL_DRIVES_DYN 512 | |
| 589 | 714 | #define MAX_RAIDMAP_LOGICAL_DRIVES (MAX_LOGICAL_DRIVES) |
| 590 | 715 | #define MAX_RAIDMAP_VIEWS (MAX_LOGICAL_DRIVES) |
| 591 | 716 | #define MAX_ARRAYS 128 |
| 592 | 717 | #define MAX_RAIDMAP_ARRAYS (MAX_ARRAYS) |
| 593 | 718 | #define MAX_ARRAYS_EXT 256 |
| 594 | 719 | #define MAX_API_ARRAYS_EXT (MAX_ARRAYS_EXT) |
| 720 | +#define MAX_API_ARRAYS_DYN 512 | |
| 595 | 721 | #define MAX_PHYSICAL_DEVICES 256 |
| 596 | 722 | #define MAX_RAIDMAP_PHYSICAL_DEVICES (MAX_PHYSICAL_DEVICES) |
| 723 | +#define MAX_RAIDMAP_PHYSICAL_DEVICES_DYN 512 | |
| 597 | 724 | #define MR_DCMD_LD_MAP_GET_INFO 0x0300e101 |
| 598 | 725 | #define MR_DCMD_SYSTEM_PD_MAP_GET_INFO 0x0200e102 |
| 726 | +#define MR_DCMD_DRV_GET_TARGET_PROP 0x0200e103 | |
| 599 | 727 | #define MR_DCMD_CTRL_SHARED_HOST_MEM_ALLOC 0x010e8485 /* SR-IOV HB alloc*/ |
| 600 | 728 | #define MR_DCMD_LD_VF_MAP_GET_ALL_LDS_111 0x03200200 |
| 601 | 729 | #define MR_DCMD_LD_VF_MAP_GET_ALL_LDS 0x03150200 |
| @@ -603,7 +731,7 @@ struct MPI2_IOC_INIT_REQUEST { · 1 unmodified line | ||
| 603 | 731 | struct MR_DEV_HANDLE_INFO { |
| 604 | 732 | __le16 curDevHdl; |
| 605 | 733 | u8 validHandles; |
| 606 | − u8 reserved; | |
| 734 | + u8 interfaceType; | |
| 607 | 735 | __le16 devHandle[2]; |
| 608 | 736 | }; |
| 609 | 737 | |
| @@ -640,10 +768,56 @@ struct MR_SPAN_BLOCK_INFO { · 30 unmodified lines | ||
| 640 | 768 | struct MR_SPAN_INFO block_span_info; |
| 641 | 769 | }; |
| 642 | 770 | |
| 771 | +#define MR_RAID_CTX_CPUSEL_0 0 | |
| 772 | +#define MR_RAID_CTX_CPUSEL_1 1 | |
| 773 | +#define MR_RAID_CTX_CPUSEL_2 2 | |
| 774 | +#define MR_RAID_CTX_CPUSEL_3 3 | |
| 775 | +#define MR_RAID_CTX_CPUSEL_FCFS 0xF | |
| 776 | + | |
| 777 | +struct MR_CPU_AFFINITY_MASK { | |
| 778 | + union { | |
| 779 | + struct { | |
| 780 | +#ifndef MFI_BIG_ENDIAN | |
| 781 | + u8 hw_path:1; | |
| 782 | + u8 cpu0:1; | |
| 783 | + u8 cpu1:1; | |
| 784 | + u8 cpu2:1; | |
| 785 | + u8 cpu3:1; | |
| 786 | + u8 reserved:3; | |
| 787 | +#else | |
| 788 | + u8 reserved:3; | |
| 789 | + u8 cpu3:1; | |
| 790 | + u8 cpu2:1; | |
| 791 | + u8 cpu1:1; | |
| 792 | + u8 cpu0:1; | |
| 793 | + u8 hw_path:1; | |
| 794 | +#endif | |
| 795 | + }; | |
| 796 | + u8 core_mask; | |
| 797 | + }; | |
| 798 | +}; | |
| 799 | + | |
| 800 | +struct MR_IO_AFFINITY { | |
| 801 | + union { | |
| 802 | + struct { | |
| 803 | + struct MR_CPU_AFFINITY_MASK pdRead; | |
| 804 | + struct MR_CPU_AFFINITY_MASK pdWrite; | |
| 805 | + struct MR_CPU_AFFINITY_MASK ldRead; | |
| 806 | + struct MR_CPU_AFFINITY_MASK ldWrite; | |
| 807 | + }; | |
| 808 | + u32 word; | |
| 809 | + }; | |
| 810 | + u8 maxCores; /* Total cores + HW Path in ROC */ | |
| 811 | + u8 reserved[3]; | |
| 812 | +}; | |
| 813 | + | |
| 643 | 814 | struct MR_LD_RAID { |
| 644 | 815 | struct { |
| 645 | 816 | #if defined(__BIG_ENDIAN_BITFIELD) |
| 646 | − u32 reserved4:5; | |
| 817 | + u32 reserved4:2; | |
| 818 | + u32 fp_cache_bypass_capable:1; | |
| 819 | + u32 fp_rmw_capable:1; | |
| 820 | + u32 disable_coalescing:1; | |
| 647 | 821 | u32 fpBypassRegionLock:1; |
| 648 | 822 | u32 tmCapable:1; |
| 649 | 823 | u32 fpNonRWCapable:1; |
| @@ -654,11 +828,13 @@ struct MR_LD_RAID { · 4 unmodified lines | ||
| 654 | 828 | u32 encryptionType:8; |
| 655 | 829 | u32 pdPiMode:4; |
| 656 | 830 | u32 ldPiMode:4; |
| 657 | − u32 reserved5:3; | |
| 831 | + u32 reserved5:2; | |
| 832 | + u32 ra_capable:1; | |
| 658 | 833 | u32 fpCapable:1; |
| 659 | 834 | #else |
| 660 | 835 | u32 fpCapable:1; |
| 661 | − u32 reserved5:3; | |
| 836 | + u32 ra_capable:1; | |
| 837 | + u32 reserved5:2; | |
| 662 | 838 | u32 ldPiMode:4; |
| 663 | 839 | u32 pdPiMode:4; |
| 664 | 840 | u32 encryptionType:8; |
| @@ -669,7 +845,10 @@ struct MR_LD_RAID { · 4 unmodified lines | ||
| 669 | 845 | u32 fpNonRWCapable:1; |
| 670 | 846 | u32 tmCapable:1; |
| 671 | 847 | u32 fpBypassRegionLock:1; |
| 672 | − u32 reserved4:5; | |
| 848 | + u32 disable_coalescing:1; | |
| 849 | + u32 fp_rmw_capable:1; | |
| 850 | + u32 fp_cache_bypass_capable:1; | |
| 851 | + u32 reserved4:2; | |
| 673 | 852 | #endif |
| 674 | 853 | } capability; |
| 675 | 854 | __le32 reserved6; |
| @@ -696,7 +875,36 @@ struct MR_LD_RAID { · 20 unmodified lines | ||
| 696 | 875 | |
| 697 | 876 | u8 LUN[8]; /* 0x24 8 byte LUN field used for SCSI IO's */ |
| 698 | 877 | u8 fpIoTimeoutForLd;/*0x2C timeout value used by driver in FP IO*/ |
| 699 | − u8 reserved3[0x80-0x2D]; /* 0x2D */ | |
| 878 | + /* Ox2D This LD accept priority boost of this type */ | |
| 879 | + u8 ld_accept_priority_type; | |
| 880 | + u8 reserved2[2]; /* 0x2E - 0x2F */ | |
| 881 | + /* 0x30 - 0x33, Logical block size for the LD */ | |
| 882 | + u32 logical_block_length; | |
| 883 | + struct { | |
| 884 | +#ifndef MFI_BIG_ENDIAN | |
| 885 | + /* 0x34, P_I_EXPONENT from READ CAPACITY 16 */ | |
| 886 | + u32 ld_pi_exp:4; | |
| 887 | + /* 0x34, LOGICAL BLOCKS PER PHYSICAL | |
| 888 | + * BLOCK EXPONENT from READ CAPACITY 16 | |
| 889 | + */ | |
| 890 | + u32 ld_logical_block_exp:4; | |
| 891 | + u32 reserved1:24; /* 0x34 */ | |
| 892 | +#else | |
| 893 | + u32 reserved1:24; /* 0x34 */ | |
| 894 | + /* 0x34, LOGICAL BLOCKS PER PHYSICAL | |
| 895 | + * BLOCK EXPONENT from READ CAPACITY 16 | |
| 896 | + */ | |
| 897 | + u32 ld_logical_block_exp:4; | |
| 898 | + /* 0x34, P_I_EXPONENT from READ CAPACITY 16 */ | |
| 899 | + u32 ld_pi_exp:4; | |
| 900 | +#endif | |
| 901 | + }; /* 0x34 - 0x37 */ | |
| 902 | + /* 0x38 - 0x3f, This will determine which | |
| 903 | + * core will process LD IO and PD IO. | |
| 904 | + */ | |
| 905 | + struct MR_IO_AFFINITY cpuAffinity; | |
| 906 | + /* Bit definiations are specified by MR_IO_AFFINITY */ | |
| 907 | + u8 reserved3[0x80 - 0x40]; /* 0x40 - 0x7f */ | |
| 700 | 908 | }; |
| 701 | 909 | |
| 702 | 910 | struct MR_LD_SPAN_MAP { |
| @@ -735,6 +943,7 @@ struct IO_REQUEST_INFO { · 32 unmodified lines | ||
| 735 | 943 | u16 ldTgtId; |
| 736 | 944 | u8 isRead; |
| 737 | 945 | __le16 devHandle; |
| 946 | + u8 pd_interface; | |
| 738 | 947 | u64 pdBlock; |
| 739 | 948 | u8 fpOkForIo; |
| 740 | 949 | u8 IoforUnevenSpan; |
| @@ -743,6 +952,8 @@ struct IO_REQUEST_INFO { · 2 unmodified lines | ||
| 743 | 952 | u64 start_row; |
| 744 | 953 | u8 span_arm; /* span[7:5], arm[4:0] */ |
| 745 | 954 | u8 pd_after_lb; |
| 955 | + u16 r1_alt_dev_handle; /* raid 1/10 only */ | |
| 956 | + bool ra_capable; | |
| 746 | 957 | }; |
| 747 | 958 | |
| 748 | 959 | struct MR_LD_TARGET_SYNC { |
| @@ -751,6 +962,91 @@ struct MR_LD_TARGET_SYNC { · 2 unmodified lines | ||
| 751 | 962 | __le16 seqNum; |
| 752 | 963 | }; |
| 753 | 964 | |
| 965 | +/* | |
| 966 | + * RAID Map descriptor Types. | |
| 967 | + * Each element should uniquely idetify one data structure in the RAID map | |
| 968 | + */ | |
| 969 | +enum MR_RAID_MAP_DESC_TYPE { | |
| 970 | + /* MR_DEV_HANDLE_INFO data */ | |
| 971 | + RAID_MAP_DESC_TYPE_DEVHDL_INFO = 0x0, | |
| 972 | + /* target to Ld num Index map */ | |
| 973 | + RAID_MAP_DESC_TYPE_TGTID_INFO = 0x1, | |
| 974 | + /* MR_ARRAY_INFO data */ | |
| 975 | + RAID_MAP_DESC_TYPE_ARRAY_INFO = 0x2, | |
| 976 | + /* MR_LD_SPAN_MAP data */ | |
| 977 | + RAID_MAP_DESC_TYPE_SPAN_INFO = 0x3, | |
| 978 | + RAID_MAP_DESC_TYPE_COUNT, | |
| 979 | +}; | |
| 980 | + | |
| 981 | +/* | |
| 982 | + * This table defines the offset, size and num elements of each descriptor | |
| 983 | + * type in the RAID Map buffer | |
| 984 | + */ | |
| 985 | +struct MR_RAID_MAP_DESC_TABLE { | |
| 986 | + /* Raid map descriptor type */ | |
| 987 | + u32 raid_map_desc_type; | |
| 988 | + /* Offset into the RAID map buffer where | |
| 989 | + * descriptor data is saved | |
| 990 | + */ | |
| 991 | + u32 raid_map_desc_offset; | |
| 992 | + /* total size of the | |
| 993 | + * descriptor buffer | |
| 994 | + */ | |
| 995 | + u32 raid_map_desc_buffer_size; | |
| 996 | + /* Number of elements contained in the | |
| 997 | + * descriptor buffer | |
| 998 | + */ | |
| 999 | + u32 raid_map_desc_elements; | |
| 1000 | +}; | |
| 1001 | + | |
| 1002 | +/* | |
| 1003 | + * Dynamic Raid Map Structure. | |
| 1004 | + */ | |
| 1005 | +struct MR_FW_RAID_MAP_DYNAMIC { | |
| 1006 | + u32 raid_map_size; /* total size of RAID Map structure */ | |
| 1007 | + u32 desc_table_offset;/* Offset of desc table into RAID map*/ | |
| 1008 | + u32 desc_table_size; /* Total Size of desc table */ | |
| 1009 | + /* Total Number of elements in the desc table */ | |
| 1010 | + u32 desc_table_num_elements; | |
| 1011 | + u64 reserved1; | |
| 1012 | + u32 reserved2[3]; /*future use */ | |
| 1013 | + /* timeout value used by driver in FP IOs */ | |
| 1014 | + u8 fp_pd_io_timeout_sec; | |
| 1015 | + u8 reserved3[3]; | |
| 1016 | + /* when this seqNum increments, driver needs to | |
| 1017 | + * release RMW buffers asap | |
| 1018 | + */ | |
| 1019 | + u32 rmw_fp_seq_num; | |
| 1020 | + u16 ld_count; /* count of lds. */ | |
| 1021 | + u16 ar_count; /* count of arrays */ | |
| 1022 | + u16 span_count; /* count of spans */ | |
| 1023 | + u16 reserved4[3]; | |
| 1024 | +/* | |
| 1025 | + * The below structure of pointers is only to be used by the driver. | |
| 1026 | + * This is added in the ,API to reduce the amount of code changes | |
| 1027 | + * needed in the driver to support dynamic RAID map Firmware should | |
| 1028 | + * not update these pointers while preparing the raid map | |
| 1029 | + */ | |
| 1030 | + union { | |
| 1031 | + struct { | |
| 1032 | + struct MR_DEV_HANDLE_INFO *dev_hndl_info; | |
| 1033 | + u16 *ld_tgt_id_to_ld; | |
| 1034 | + struct MR_ARRAY_INFO *ar_map_info; | |
| 1035 | + struct MR_LD_SPAN_MAP *ld_span_map; | |
| 1036 | + }; | |
| 1037 | + u64 ptr_structure_size[RAID_MAP_DESC_TYPE_COUNT]; | |
| 1038 | + }; | |
| 1039 | +/* | |
| 1040 | + * RAID Map descriptor table defines the layout of data in the RAID Map. | |
| 1041 | + * The size of the descriptor table itself could change. | |
| 1042 | + */ | |
| 1043 | + /* Variable Size descriptor Table. */ | |
| 1044 | + struct MR_RAID_MAP_DESC_TABLE | |
| 1045 | + raid_map_desc_table[RAID_MAP_DESC_TYPE_COUNT]; | |
| 1046 | + /* Variable Size buffer containing all data */ | |
| 1047 | + u32 raid_map_desc_data[1]; | |
| 1048 | +}; /* Dynamicaly sized RAID MAp structure */ | |
| 1049 | + | |
| 754 | 1050 | #define IEEE_SGE_FLAGS_ADDR_MASK (0x03) |
| 755 | 1051 | #define IEEE_SGE_FLAGS_SYSTEM_ADDR (0x00) |
| 756 | 1052 | #define IEEE_SGE_FLAGS_IOCDDR_ADDR (0x01) |
| @@ -759,6 +1055,16 @@ struct MR_LD_TARGET_SYNC { · 2 unmodified lines | ||
| 759 | 1055 | #define IEEE_SGE_FLAGS_CHAIN_ELEMENT (0x80) |
| 760 | 1056 | #define IEEE_SGE_FLAGS_END_OF_LIST (0x40) |
| 761 | 1057 | |
| 1058 | +#define MPI2_SGE_FLAGS_SHIFT (0x02) | |
| 1059 | +#define IEEE_SGE_FLAGS_FORMAT_MASK (0xC0) | |
| 1060 | +#define IEEE_SGE_FLAGS_FORMAT_IEEE (0x00) | |
| 1061 | +#define IEEE_SGE_FLAGS_FORMAT_NVME (0x02) | |
| 1062 | + | |
| 1063 | +#define MPI26_IEEE_SGE_FLAGS_NSF_MASK (0x1C) | |
| 1064 | +#define MPI26_IEEE_SGE_FLAGS_NSF_MPI_IEEE (0x00) | |
| 1065 | +#define MPI26_IEEE_SGE_FLAGS_NSF_NVME_PRP (0x08) | |
| 1066 | +#define MPI26_IEEE_SGE_FLAGS_NSF_NVME_SGL (0x10) | |
| 1067 | + | |
| 762 | 1068 | struct megasas_register_set; |
| 763 | 1069 | struct megasas_instance; |
| 764 | 1070 | |
| @@ -795,6 +1101,10 @@ struct megasas_cmd_fusion { · 30 unmodified lines | ||
| 795 | 1101 | u32 index; |
| 796 | 1102 | u8 pd_r1_lb; |
| 797 | 1103 | struct completion done; |
| 1104 | + u8 pd_interface; | |
| 1105 | + u16 r1_alt_dev_handle; /* raid 1/10 only*/ | |
| 1106 | + bool cmd_completed; /* raid 1/10 fp writes status holder */ | |
| 1107 | + | |
| 798 | 1108 | }; |
| 799 | 1109 | |
| 800 | 1110 | struct LD_LOAD_BALANCE_INFO { |
| @@ -856,9 +1166,10 @@ struct MR_DRV_RAID_MAP { · 55 unmodified lines | ||
| 856 | 1166 | __le16 spanCount; |
| 857 | 1167 | __le16 reserve3; |
| 858 | 1168 | |
| 859 | − struct MR_DEV_HANDLE_INFO devHndlInfo[MAX_RAIDMAP_PHYSICAL_DEVICES]; | |
| 860 | − u8 ldTgtIdToLd[MAX_LOGICAL_DRIVES_EXT]; | |
| 861 | − struct MR_ARRAY_INFO arMapInfo[MAX_API_ARRAYS_EXT]; | |
| 1169 | + struct MR_DEV_HANDLE_INFO | |
| 1170 | + devHndlInfo[MAX_RAIDMAP_PHYSICAL_DEVICES_DYN]; | |
| 1171 | + u16 ldTgtIdToLd[MAX_LOGICAL_DRIVES_DYN]; | |
| 1172 | + struct MR_ARRAY_INFO arMapInfo[MAX_API_ARRAYS_DYN]; | |
| 862 | 1173 | struct MR_LD_SPAN_MAP ldSpanMap[1]; |
| 863 | 1174 | |
| 864 | 1175 | }; |
| @@ -870,7 +1181,7 @@ struct MR_DRV_RAID_MAP { · 5 unmodified lines | ||
| 870 | 1181 | struct MR_DRV_RAID_MAP_ALL { |
| 871 | 1182 | |
| 872 | 1183 | struct MR_DRV_RAID_MAP raidMap; |
| 873 | − struct MR_LD_SPAN_MAP ldSpanMap[MAX_LOGICAL_DRIVES_EXT - 1]; | |
| 1184 | + struct MR_LD_SPAN_MAP ldSpanMap[MAX_LOGICAL_DRIVES_DYN - 1]; | |
| 874 | 1185 | } __packed; |
| 875 | 1186 | |
| 876 | 1187 | |
| @@ -919,7 +1230,8 @@ struct MR_PD_CFG_SEQ { · 42 unmodified lines | ||
| 919 | 1230 | u8 reserved:7; |
| 920 | 1231 | #endif |
| 921 | 1232 | } capability; |
| 922 | − u8 reserved[3]; | |
| 1233 | + u8 reserved; | |
| 1234 | + u16 pd_target_id; | |
| 923 | 1235 | } __packed; |
| 924 | 1236 | |
| 925 | 1237 | struct MR_PD_CFG_SEQ_NUM_SYNC { |
| @@ -928,6 +1240,30 @@ struct MR_PD_CFG_SEQ_NUM_SYNC { · 2 unmodified lines | ||
| 928 | 1240 | struct MR_PD_CFG_SEQ seq[1]; |
| 929 | 1241 | } __packed; |
| 930 | 1242 | |
| 1243 | +/* stream detection */ | |
| 1244 | +struct STREAM_DETECT { | |
| 1245 | + u64 next_seq_lba; /* next LBA to match sequential access */ | |
| 1246 | + struct megasas_cmd_fusion *first_cmd_fusion; /* first cmd in group */ | |
| 1247 | + struct megasas_cmd_fusion *last_cmd_fusion; /* last cmd in group */ | |
| 1248 | + u32 count_cmds_in_stream; /* count of host commands in this stream */ | |
| 1249 | + u16 num_sges_in_group; /* total number of SGEs in grouped IOs */ | |
| 1250 | + u8 is_read; /* SCSI OpCode for this stream */ | |
| 1251 | + u8 group_depth; /* total number of host commands in group */ | |
| 1252 | + /* TRUE if cannot add any more commands to this group */ | |
| 1253 | + bool group_flush; | |
| 1254 | + u8 reserved[7]; /* pad to 64-bit alignment */ | |
| 1255 | +}; | |
| 1256 | + | |
| 1257 | +struct LD_STREAM_DETECT { | |
| 1258 | + bool write_back; /* TRUE if WB, FALSE if WT */ | |
| 1259 | + bool fp_write_enabled; | |
| 1260 | + bool members_ssds; | |
| 1261 | + bool fp_cache_bypass_capable; | |
| 1262 | + u32 mru_bit_map; /* bitmap used to track MRU and LRU stream indicies */ | |
| 1263 | + /* this is the array of stream detect structures (one per stream) */ | |
| 1264 | + struct STREAM_DETECT stream_track[MAX_STREAMS_TRACKED]; | |
| 1265 | +}; | |
| 1266 | + | |
| 931 | 1267 | struct MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY { |
| 932 | 1268 | u64 RDPQBaseAddress; |
| 933 | 1269 | u32 Reserved1; |
| @@ -965,7 +1301,7 @@ struct fusion_context { · 31 unmodified lines | ||
| 965 | 1301 | u8 chain_offset_io_request; |
| 966 | 1302 | u8 chain_offset_mfi_pthru; |
| 967 | 1303 | |
| 968 | − struct MR_FW_RAID_MAP_ALL *ld_map[2]; | |
| 1304 | + struct MR_FW_RAID_MAP_DYNAMIC *ld_map[2]; | |
| 969 | 1305 | dma_addr_t ld_map_phys[2]; |
| 970 | 1306 | |
| 971 | 1307 | /*Non dma-able memory. Driver local copy.*/ |
| @@ -973,14 +1309,18 @@ struct fusion_context { · 1 unmodified line | ||
| 973 | 1309 | |
| 974 | 1310 | u32 max_map_sz; |
| 975 | 1311 | u32 current_map_sz; |
| 1312 | + u32 old_map_sz; | |
| 1313 | + u32 new_map_sz; | |
| 976 | 1314 | u32 drv_map_sz; |
| 977 | 1315 | u32 drv_map_pages; |
| 978 | 1316 | struct MR_PD_CFG_SEQ_NUM_SYNC *pd_seq_sync[JBOD_MAPS_COUNT]; |
| 979 | 1317 | dma_addr_t pd_seq_phys[JBOD_MAPS_COUNT]; |
| 980 | 1318 | u8 fast_path_io; |
| 981 | − struct LD_LOAD_BALANCE_INFO load_balance_info[MAX_LOGICAL_DRIVES_EXT]; | |
| 1319 | + struct LD_LOAD_BALANCE_INFO *load_balance_info; | |
| 1320 | + u32 load_balance_info_pages; | |
| 982 | 1321 | LD_SPAN_INFO log_to_span[MAX_LOGICAL_DRIVES_EXT]; |
| 983 | 1322 | u8 adapter_type; |
| 1323 | + struct LD_STREAM_DETECT **stream_detect_by_ld; | |
| 984 | 1324 | }; |
| 985 | 1325 | |
| 986 | 1326 | union desc_value { |
| @@ -624,6 +624,8 @@ typedef struct _MPI26_EVENT_DATA_ACTIVE_CABLE_EXCEPT { · 623 unmodified lines | ||
| 624 | 624 | |
| 625 | 625 | /* defines for ReasonCode field */ |
| 626 | 626 | #define MPI26_EVENT_ACTIVE_CABLE_INSUFFICIENT_POWER (0x00) |
| 627 | +#define MPI26_EVENT_ACTIVE_CABLE_PRESENT (0x01) | |
| 628 | +#define MPI26_EVENT_ACTIVE_CABLE_DEGRADED (0x02) | |
| 627 | 629 | |
| 628 | 630 | /*Hard Reset Received Event data */ |
| 629 | 631 | |
| @@ -1040,6 +1040,25 @@ _base_interrupt(int irq, void *bus_id) · 1039 unmodified lines | ||
| 1040 | 1040 | reply_q->reply_post_free[reply_q->reply_post_host_index]. |
| 1041 | 1041 | Default.ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK; |
| 1042 | 1042 | completed_cmds++; |
| 1043 | + /* Update the reply post host index after continuously | |
| 1044 | + * processing the threshold number of Reply Descriptors. | |
| 1045 | + * So that FW can find enough entries to post the Reply | |
| 1046 | + * Descriptors in the reply descriptor post queue. | |
| 1047 | + */ | |
| 1048 | + if (completed_cmds > ioc->hba_queue_depth/3) { | |
| 1049 | + if (ioc->combined_reply_queue) { | |
| 1050 | + writel(reply_q->reply_post_host_index | | |
| 1051 | + ((msix_index & 7) << | |
| 1052 | + MPI2_RPHI_MSIX_INDEX_SHIFT), | |
| 1053 | + ioc->replyPostRegisterIndex[msix_index/8]); | |
| 1054 | + } else { | |
| 1055 | + writel(reply_q->reply_post_host_index | | |
| 1056 | + (msix_index << | |
| 1057 | + MPI2_RPHI_MSIX_INDEX_SHIFT), | |
| 1058 | + &ioc->chip->ReplyPostHostIndex); | |
| 1059 | + } | |
| 1060 | + completed_cmds = 1; | |
| 1061 | + } | |
| 1043 | 1062 | if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) |
| 1044 | 1063 | goto out; |
| 1045 | 1064 | if (!reply_q->reply_post_host_index) |
| @@ -5522,6 +5541,7 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) · 4476 unmodified lines | ||
| 5522 | 5541 | goto out_free_resources; |
| 5523 | 5542 | |
| 5524 | 5543 | ioc->non_operational_loop = 0; |
| 5544 | + ioc->got_task_abort_from_ioctl = 0; | |
| 5525 | 5545 | return 0; |
| 5526 | 5546 | |
| 5527 | 5547 | out_free_resources: |
| @@ -73,9 +73,9 @@ · 72 unmodified lines | ||
| 73 | 73 | #define MPT3SAS_DRIVER_NAME "mpt3sas" |
| 74 | 74 | #define MPT3SAS_AUTHOR "Avago Technologies <MPT-FusionLinux.pdl@avagotech.com>" |
| 75 | 75 | #define MPT3SAS_DESCRIPTION "LSI MPT Fusion SAS 3.0 Device Driver" |
| 76 | −#define MPT3SAS_DRIVER_VERSION "14.101.00.00" | |
| 77 | −#define MPT3SAS_MAJOR_VERSION 14 | |
| 78 | −#define MPT3SAS_MINOR_VERSION 101 | |
| 76 | +#define MPT3SAS_DRIVER_VERSION "15.100.00.00" | |
| 77 | +#define MPT3SAS_MAJOR_VERSION 15 | |
| 78 | +#define MPT3SAS_MINOR_VERSION 100 | |
| 79 | 79 | #define MPT3SAS_BUILD_VERSION 0 |
| 80 | 80 | #define MPT3SAS_RELEASE_VERSION 00 |
| 81 | 81 | |
| @@ -1000,6 +1000,7 @@ struct MPT3SAS_ADAPTER { · 918 unmodified lines | ||
| 1000 | 1000 | u8 broadcast_aen_busy; |
| 1001 | 1001 | u16 broadcast_aen_pending; |
| 1002 | 1002 | u8 shost_recovery; |
| 1003 | + u8 got_task_abort_from_ioctl; | |
| 1003 | 1004 | |
| 1004 | 1005 | struct mutex reset_in_progress_mutex; |
| 1005 | 1006 | spinlock_t ioc_reset_in_progress_lock; |
| @@ -826,16 +826,18 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, · 825 unmodified lines | ||
| 826 | 826 | "TASK_MGMT: handle(0x%04x), task_type(0x%02x)\n", |
| 827 | 827 | ioc->name, |
| 828 | 828 | le16_to_cpu(tm_request->DevHandle), tm_request->TaskType)); |
| 829 | − | |
| 829 | + ioc->got_task_abort_from_ioctl = 1; | |
| 830 | 830 | if (tm_request->TaskType == |
| 831 | 831 | MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK || |
| 832 | 832 | tm_request->TaskType == |
| 833 | 833 | MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK) { |
| 834 | 834 | if (_ctl_set_task_mid(ioc, &karg, tm_request)) { |
| 835 | 835 | mpt3sas_base_free_smid(ioc, smid); |
| 836 | + ioc->got_task_abort_from_ioctl = 0; | |
| 836 | 837 | goto out; |
| 837 | 838 | } |
| 838 | 839 | } |
| 840 | + ioc->got_task_abort_from_ioctl = 0; | |
| 839 | 841 | |
| 840 | 842 | if (test_bit(device_handle, ioc->device_remove_in_progress)) { |
| 841 | 843 | dtmprintk(ioc, pr_info(MPT3SAS_FMT |
| @@ -1074,6 +1074,26 @@ _scsih_scsi_lookup_get(struct MPT3SAS_ADAPTER *ioc, u16 smid) · 1073 unmodified lines | ||
| 1074 | 1074 | return ioc->scsi_lookup[smid - 1].scmd; |
| 1075 | 1075 | } |
| 1076 | 1076 | |
| 1077 | +/** | |
| 1078 | + * __scsih_scsi_lookup_get_clear - returns scmd entry without | |
| 1079 | + * holding any lock. | |
| 1080 | + * @ioc: per adapter object | |
| 1081 | + * @smid: system request message index | |
| 1082 | + * | |
| 1083 | + * Returns the smid stored scmd pointer. | |
| 1084 | + * Then will dereference the stored scmd pointer. | |
| 1085 | + */ | |
| 1086 | +static inline struct scsi_cmnd * | |
| 1087 | +__scsih_scsi_lookup_get_clear(struct MPT3SAS_ADAPTER *ioc, | |
| 1088 | + u16 smid) | |
| 1089 | +{ | |
| 1090 | + struct scsi_cmnd *scmd = NULL; | |
| 1091 | + | |
| 1092 | + swap(scmd, ioc->scsi_lookup[smid - 1].scmd); | |
| 1093 | + | |
| 1094 | + return scmd; | |
| 1095 | +} | |
| 1096 | + | |
| 1077 | 1097 | /** |
| 1078 | 1098 | * _scsih_scsi_lookup_get_clear - returns scmd entry |
| 1079 | 1099 | * @ioc: per adapter object |
| @@ -1089,8 +1109,7 @@ _scsih_scsi_lookup_get_clear(struct MPT3SAS_ADAPTER *ioc, u16 smid) · 9 unmodified lines | ||
| 1089 | 1109 | struct scsi_cmnd *scmd; |
| 1090 | 1110 | |
| 1091 | 1111 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); |
| 1092 | − scmd = ioc->scsi_lookup[smid - 1].scmd; | |
| 1093 | − ioc->scsi_lookup[smid - 1].scmd = NULL; | |
| 1112 | + scmd = __scsih_scsi_lookup_get_clear(ioc, smid); | |
| 1094 | 1113 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); |
| 1095 | 1114 | |
| 1096 | 1115 | return scmd; |
| @@ -4661,7 +4680,13 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) · 3564 unmodified lines | ||
| 4661 | 4680 | unsigned int sector_sz; |
| 4662 | 4681 | |
| 4663 | 4682 | mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); |
| 4664 | − scmd = _scsih_scsi_lookup_get_clear(ioc, smid); | |
| 4683 | + | |
| 4684 | + if (ioc->broadcast_aen_busy || ioc->pci_error_recovery || | |
| 4685 | + ioc->got_task_abort_from_ioctl) | |
| 4686 | + scmd = _scsih_scsi_lookup_get_clear(ioc, smid); | |
| 4687 | + else | |
| 4688 | + scmd = __scsih_scsi_lookup_get_clear(ioc, smid); | |
| 4689 | + | |
| 4665 | 4690 | if (scmd == NULL) |
| 4666 | 4691 | return 1; |
| 4667 | 4692 | |
| @@ -8044,15 +8069,24 @@ mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index, · 3376 unmodified lines | ||
| 8044 | 8069 | case MPI2_EVENT_ACTIVE_CABLE_EXCEPTION: |
| 8045 | 8070 | ActiveCableEventData = |
| 8046 | 8071 | (Mpi26EventDataActiveCableExcept_t *) mpi_reply->EventData; |
| 8047 | − if (ActiveCableEventData->ReasonCode == | |
| 8048 | − MPI26_EVENT_ACTIVE_CABLE_INSUFFICIENT_POWER) { | |
| 8049 | − pr_info(MPT3SAS_FMT "Currently an active cable with ReceptacleID %d", | |
| 8050 | − ioc->name, ActiveCableEventData->ReceptacleID); | |
| 8051 | − pr_info("cannot be powered and devices connected to this active cable"); | |
| 8052 | − pr_info("will not be seen. This active cable"); | |
| 8053 | − pr_info("requires %d mW of power", | |
| 8054 | − ActiveCableEventData->ActiveCablePowerRequirement); | |
| 8072 | + switch (ActiveCableEventData->ReasonCode) { | |
| 8073 | + case MPI26_EVENT_ACTIVE_CABLE_INSUFFICIENT_POWER: | |
| 8074 | + pr_notice(MPT3SAS_FMT "Receptacle ID %d: This active cable" | |
| 8075 | + " requires %d mW of power\n", ioc->name, | |
| 8076 | + ActiveCableEventData->ReceptacleID, | |
| 8077 | + ActiveCableEventData->ActiveCablePowerRequirement); | |
| 8078 | + pr_notice(MPT3SAS_FMT "Receptacle ID %d: Devices connected" | |
| 8079 | + " to this active cable will not be seen\n", | |
| 8080 | + ioc->name, ActiveCableEventData->ReceptacleID); | |
| 8081 | + break; | |
| 8082 | + | |
| 8083 | + case MPI26_EVENT_ACTIVE_CABLE_DEGRADED: | |
| 8084 | + pr_notice(MPT3SAS_FMT "ReceptacleID %d: This cable", | |
| 8085 | + ioc->name, ActiveCableEventData->ReceptacleID); | |
| 8086 | + pr_notice(" is not running at an optimal speed(12 Gb/s)\n"); | |
| 8087 | + break; | |
| 8055 | 8088 | } |
| 8089 | + | |
| 8056 | 8090 | break; |
| 8057 | 8091 | |
| 8058 | 8092 | default: /* ignore the rest */ |
| @@ -2225,15 +2225,12 @@ static struct scsi_host_template mvumi_template = { · 2224 unmodified lines | ||
| 2225 | 2225 | .name = "Marvell Storage Controller", |
| 2226 | 2226 | .slave_configure = mvumi_slave_configure, |
| 2227 | 2227 | .queuecommand = mvumi_queue_command, |
| 2228 | + .eh_timed_out = mvumi_timed_out, | |
| 2228 | 2229 | .eh_host_reset_handler = mvumi_host_reset, |
| 2229 | 2230 | .bios_param = mvumi_bios_param, |
| 2230 | 2231 | .this_id = -1, |
| 2231 | 2232 | }; |
| 2232 | 2233 | |
| 2233 | −static struct scsi_transport_template mvumi_transport_template = { | |
| 2234 | − .eh_timed_out = mvumi_timed_out, | |
| 2235 | −}; | |
| 2236 | − | |
| 2237 | 2234 | static int mvumi_cfg_hw_reg(struct mvumi_hba *mhba) |
| 2238 | 2235 | { |
| 2239 | 2236 | void *base = NULL; |
| @@ -2451,7 +2448,6 @@ static int mvumi_io_attach(struct mvumi_hba *mhba) · 211 unmodified lines | ||
| 2451 | 2448 | host->cmd_per_lun = (mhba->max_io - 1) ? (mhba->max_io - 1) : 1; |
| 2452 | 2449 | host->max_id = mhba->max_target_id; |
| 2453 | 2450 | host->max_cmd_len = MAX_COMMAND_SIZE; |
| 2454 | − host->transportt = &mvumi_transport_template; | |
| 2455 | 2451 | |
| 2456 | 2452 | ret = scsi_add_host(host, &mhba->pdev->dev); |
| 2457 | 2453 | if (ret) { |
| @@ -888,7 +888,6 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha) · 887 unmodified lines | ||
| 888 | 888 | u32 i = 0, j = 0; |
| 889 | 889 | u32 number_of_intr; |
| 890 | 890 | int flag = 0; |
| 891 | − u32 max_entry; | |
| 892 | 891 | int rc; |
| 893 | 892 | static char intr_drvname[PM8001_MAX_MSIX_VEC][sizeof(DRV_NAME)+3]; |
| 894 | 893 | |
| @@ -900,18 +899,14 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha) · 5 unmodified lines | ||
| 900 | 899 | flag &= ~IRQF_SHARED; |
| 901 | 900 | } |
| 902 | 901 | |
| 903 | − max_entry = sizeof(pm8001_ha->msix_entries) / | |
| 904 | − sizeof(pm8001_ha->msix_entries[0]); | |
| 905 | − for (i = 0; i < max_entry ; i++) | |
| 906 | − pm8001_ha->msix_entries[i].entry = i; | |
| 907 | − rc = pci_enable_msix_exact(pm8001_ha->pdev, pm8001_ha->msix_entries, | |
| 908 | − number_of_intr); | |
| 909 | − pm8001_ha->number_of_intr = number_of_intr; | |
| 910 | − if (rc) | |
| 902 | + rc = pci_alloc_irq_vectors(pm8001_ha->pdev, number_of_intr, | |
| 903 | + number_of_intr, PCI_IRQ_MSIX); | |
| 904 | + if (rc < 0) | |
| 911 | 905 | return rc; |
| 906 | + pm8001_ha->number_of_intr = number_of_intr; | |
| 912 | 907 | |
| 913 | 908 | PM8001_INIT_DBG(pm8001_ha, pm8001_printk( |
| 914 | − "pci_enable_msix_exact request ret:%d no of intr %d\n", | |
| 909 | + "pci_alloc_irq_vectors request ret:%d no of intr %d\n", | |
| 915 | 910 | rc, pm8001_ha->number_of_intr)); |
| 916 | 911 | |
| 917 | 912 | for (i = 0; i < number_of_intr; i++) { |
| @@ -920,15 +915,15 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha) · 2 unmodified lines | ||
| 920 | 915 | pm8001_ha->irq_vector[i].irq_id = i; |
| 921 | 916 | pm8001_ha->irq_vector[i].drv_inst = pm8001_ha; |
| 922 | 917 | |
| 923 | − rc = request_irq(pm8001_ha->msix_entries[i].vector, | |
| 918 | + rc = request_irq(pci_irq_vector(pm8001_ha->pdev, i), | |
| 924 | 919 | pm8001_interrupt_handler_msix, flag, |
| 925 | 920 | intr_drvname[i], &(pm8001_ha->irq_vector[i])); |
| 926 | 921 | if (rc) { |
| 927 | 922 | for (j = 0; j < i; j++) { |
| 928 | − free_irq(pm8001_ha->msix_entries[j].vector, | |
| 923 | + free_irq(pci_irq_vector(pm8001_ha->pdev, i), | |
| 929 | 924 | &(pm8001_ha->irq_vector[i])); |
| 930 | 925 | } |
| 931 | − pci_disable_msix(pm8001_ha->pdev); | |
| 926 | + pci_free_irq_vectors(pm8001_ha->pdev); | |
| 932 | 927 | break; |
| 933 | 928 | } |
| 934 | 929 | } |
| @@ -1102,11 +1097,10 @@ static void pm8001_pci_remove(struct pci_dev *pdev) · 167 unmodified lines | ||
| 1102 | 1097 | |
| 1103 | 1098 | #ifdef PM8001_USE_MSIX |
| 1104 | 1099 | for (i = 0; i < pm8001_ha->number_of_intr; i++) |
| 1105 | − synchronize_irq(pm8001_ha->msix_entries[i].vector); | |
| 1100 | + synchronize_irq(pci_irq_vector(pdev, i)); | |
| 1106 | 1101 | for (i = 0; i < pm8001_ha->number_of_intr; i++) |
| 1107 | − free_irq(pm8001_ha->msix_entries[i].vector, | |
| 1108 | − &(pm8001_ha->irq_vector[i])); | |
| 1109 | − pci_disable_msix(pdev); | |
| 1102 | + free_irq(pci_irq_vector(pdev, i), &pm8001_ha->irq_vector[i]); | |
| 1103 | + pci_free_irq_vectors(pdev); | |
| 1110 | 1104 | #else |
| 1111 | 1105 | free_irq(pm8001_ha->irq, sha); |
| 1112 | 1106 | #endif |
| @@ -1152,11 +1146,10 @@ static int pm8001_pci_suspend(struct pci_dev *pdev, pm_message_t state) · 39 unmodified lines | ||
| 1152 | 1146 | PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha); |
| 1153 | 1147 | #ifdef PM8001_USE_MSIX |
| 1154 | 1148 | for (i = 0; i < pm8001_ha->number_of_intr; i++) |
| 1155 | − synchronize_irq(pm8001_ha->msix_entries[i].vector); | |
| 1149 | + synchronize_irq(pci_irq_vector(pdev, i)); | |
| 1156 | 1150 | for (i = 0; i < pm8001_ha->number_of_intr; i++) |
| 1157 | − free_irq(pm8001_ha->msix_entries[i].vector, | |
| 1158 | − &(pm8001_ha->irq_vector[i])); | |
| 1159 | − pci_disable_msix(pdev); | |
| 1151 | + free_irq(pci_irq_vector(pdev, i), &pm8001_ha->irq_vector[i]); | |
| 1152 | + pci_free_irq_vectors(pdev); | |
| 1160 | 1153 | #else |
| 1161 | 1154 | free_irq(pm8001_ha->irq, sha); |
| 1162 | 1155 | #endif |
| @@ -521,8 +521,6 @@ struct pm8001_hba_info { · 520 unmodified lines | ||
| 521 | 521 | struct pm8001_device *devices; |
| 522 | 522 | struct pm8001_ccb_info *ccb_info; |
| 523 | 523 | #ifdef PM8001_USE_MSIX |
| 524 | − struct msix_entry msix_entries[PM8001_MAX_MSIX_VEC]; | |
| 525 | − /*for msi-x interrupt*/ | |
| 526 | 524 | int number_of_intr;/*will be used in remove()*/ |
| 527 | 525 | #endif |
| 528 | 526 | #ifdef PM8001_USE_TASKLET |
| @@ -4587,16 +4587,14 @@ static void pmcraid_tasklet_function(unsigned long instance) · 4586 unmodified lines | ||
| 4587 | 4587 | static |
| 4588 | 4588 | void pmcraid_unregister_interrupt_handler(struct pmcraid_instance *pinstance) |
| 4589 | 4589 | { |
| 4590 | + struct pci_dev *pdev = pinstance->pdev; | |
| 4590 | 4591 | int i; |
| 4591 | 4592 | |
| 4592 | 4593 | for (i = 0; i < pinstance->num_hrrq; i++) |
| 4593 | − free_irq(pinstance->hrrq_vector[i].vector, | |
| 4594 | − &(pinstance->hrrq_vector[i])); | |
| 4594 | + free_irq(pci_irq_vector(pdev, i), &pinstance->hrrq_vector[i]); | |
| 4595 | 4595 | |
| 4596 | − if (pinstance->interrupt_mode) { | |
| 4597 | − pci_disable_msix(pinstance->pdev); | |
| 4598 | − pinstance->interrupt_mode = 0; | |
| 4599 | − } | |
| 4596 | + pinstance->interrupt_mode = 0; | |
| 4597 | + pci_free_irq_vectors(pdev); | |
| 4600 | 4598 | } |
| 4601 | 4599 | |
| 4602 | 4600 | /** |
| @@ -4609,60 +4607,52 @@ void pmcraid_unregister_interrupt_handler(struct pmcraid_instance *pinstance) · 6 unmodified lines | ||
| 4609 | 4607 | static int |
| 4610 | 4608 | pmcraid_register_interrupt_handler(struct pmcraid_instance *pinstance) |
| 4611 | 4609 | { |
| 4612 | − int rc; | |
| 4613 | 4610 | struct pci_dev *pdev = pinstance->pdev; |
| 4611 | + unsigned int irq_flag = PCI_IRQ_LEGACY, flag; | |
| 4612 | + int num_hrrq, rc, i; | |
| 4613 | + irq_handler_t isr; | |
| 4614 | 4614 | |
| 4615 | − if ((pmcraid_enable_msix) && | |
| 4616 | − (pci_find_capability(pdev, PCI_CAP_ID_MSIX))) { | |
| 4617 | − int num_hrrq = PMCRAID_NUM_MSIX_VECTORS; | |
| 4618 | − struct msix_entry entries[PMCRAID_NUM_MSIX_VECTORS]; | |
| 4619 | − int i; | |
| 4620 | − for (i = 0; i < PMCRAID_NUM_MSIX_VECTORS; i++) | |
| 4621 | − entries[i].entry = i; | |
| 4622 | − | |
| 4623 | − num_hrrq = pci_enable_msix_range(pdev, entries, 1, num_hrrq); | |
| 4624 | − if (num_hrrq < 0) | |
| 4625 | − goto pmcraid_isr_legacy; | |
| 4626 | − | |
| 4627 | − for (i = 0; i < num_hrrq; i++) { | |
| 4628 | − pinstance->hrrq_vector[i].hrrq_id = i; | |
| 4629 | − pinstance->hrrq_vector[i].drv_inst = pinstance; | |
| 4630 | − pinstance->hrrq_vector[i].vector = entries[i].vector; | |
| 4631 | − rc = request_irq(pinstance->hrrq_vector[i].vector, | |
| 4632 | − pmcraid_isr_msix, 0, | |
| 4633 | − PMCRAID_DRIVER_NAME, | |
| 4634 | − &(pinstance->hrrq_vector[i])); | |
| 4635 | − | |
| 4636 | − if (rc) { | |
| 4637 | − int j; | |
| 4638 | − for (j = 0; j < i; j++) | |
| 4639 | − free_irq(entries[j].vector, | |
| 4640 | − &(pinstance->hrrq_vector[j])); | |
| 4641 | − pci_disable_msix(pdev); | |
| 4642 | − goto pmcraid_isr_legacy; | |
| 4643 | − } | |
| 4644 | − } | |
| 4615 | + if (pmcraid_enable_msix) | |
| 4616 | + irq_flag |= PCI_IRQ_MSIX; | |
| 4645 | 4617 | |
| 4646 | − pinstance->num_hrrq = num_hrrq; | |
| 4618 | + num_hrrq = pci_alloc_irq_vectors(pdev, 1, PMCRAID_NUM_MSIX_VECTORS, | |
| 4619 | + irq_flag); | |
| 4620 | + if (num_hrrq < 0) | |
| 4621 | + return num_hrrq; | |
| 4622 | + | |
| 4623 | + if (pdev->msix_enabled) { | |
| 4624 | + flag = 0; | |
| 4625 | + isr = pmcraid_isr_msix; | |
| 4626 | + } else { | |
| 4627 | + flag = IRQF_SHARED; | |
| 4628 | + isr = pmcraid_isr; | |
| 4629 | + } | |
| 4630 | + | |
| 4631 | + for (i = 0; i < num_hrrq; i++) { | |
| 4632 | + struct pmcraid_isr_param *vec = &pinstance->hrrq_vector[i]; | |
| 4633 | + | |
| 4634 | + vec->hrrq_id = i; | |
| 4635 | + vec->drv_inst = pinstance; | |
| 4636 | + rc = request_irq(pci_irq_vector(pdev, i), isr, flag, | |
| 4637 | + PMCRAID_DRIVER_NAME, vec); | |
| 4638 | + if (rc) | |
| 4639 | + goto out_unwind; | |
| 4640 | + } | |
| 4641 | + | |
| 4642 | + pinstance->num_hrrq = num_hrrq; | |
| 4643 | + if (pdev->msix_enabled) { | |
| 4647 | 4644 | pinstance->interrupt_mode = 1; |
| 4648 | 4645 | iowrite32(DOORBELL_INTR_MODE_MSIX, |
| 4649 | 4646 | pinstance->int_regs.host_ioa_interrupt_reg); |
| 4650 | 4647 | ioread32(pinstance->int_regs.host_ioa_interrupt_reg); |
| 4651 | − goto pmcraid_isr_out; | |
| 4652 | 4648 | } |
| 4653 | 4649 | |
| 4654 | −pmcraid_isr_legacy: | |
| 4655 | − /* If MSI-X registration failed fallback to legacy mode, where | |
| 4656 | − * only one hrrq entry will be used | |
| 4657 | − */ | |
| 4658 | − pinstance->hrrq_vector[0].hrrq_id = 0; | |
| 4659 | − pinstance->hrrq_vector[0].drv_inst = pinstance; | |
| 4660 | − pinstance->hrrq_vector[0].vector = pdev->irq; | |
| 4661 | − pinstance->num_hrrq = 1; | |
| 4662 | − | |
| 4663 | − rc = request_irq(pdev->irq, pmcraid_isr, IRQF_SHARED, | |
| 4664 | − PMCRAID_DRIVER_NAME, &pinstance->hrrq_vector[0]); | |
| 4665 | −pmcraid_isr_out: | |
| 4650 | + return 0; | |
| 4651 | + | |
| 4652 | +out_unwind: | |
| 4653 | + while (--i > 0) | |
| 4654 | + free_irq(pci_irq_vector(pdev, i), &pinstance->hrrq_vector[i]); | |
| 4655 | + pci_free_irq_vectors(pdev); | |
| 4666 | 4656 | return rc; |
| 4667 | 4657 | } |
| 4668 | 4658 | |
| @@ -628,7 +628,6 @@ struct pmcraid_interrupts { · 627 unmodified lines | ||
| 628 | 628 | /* ISR parameters LLD allocates (one for each MSI-X if enabled) vectors */ |
| 629 | 629 | struct pmcraid_isr_param { |
| 630 | 630 | struct pmcraid_instance *drv_inst; |
| 631 | − u16 vector; /* allocated msi-x vector */ | |
| 632 | 631 | u8 hrrq_id; /* hrrq entry index */ |
| 633 | 632 | }; |
| 634 | 633 | |
| @@ -52,7 +52,7 @@ qedi_dbg_warn(struct qedi_dbg_ctx *qedi, const char *func, u32 line, · 51 unmodified lines | ||
| 52 | 52 | vaf.va = &va; |
| 53 | 53 | |
| 54 | 54 | if (!(qedi_dbg_log & QEDI_LOG_WARN)) |
| 55 | − return; | |
| 55 | + goto ret; | |
| 56 | 56 | |
| 57 | 57 | if (likely(qedi) && likely(qedi->pdev)) |
| 58 | 58 | pr_warn("[%s]:[%s:%d]:%d: %pV", dev_name(&qedi->pdev->dev), |
| @@ -60,6 +60,7 @@ qedi_dbg_warn(struct qedi_dbg_ctx *qedi, const char *func, u32 line, · 1 unmodified line | ||
| 60 | 60 | else |
| 61 | 61 | pr_warn("[0000:00:00.0]:[%s:%d]: %pV", nfunc, line, &vaf); |
| 62 | 62 | |
| 63 | +ret: | |
| 63 | 64 | va_end(va); |
| 64 | 65 | } |
| 65 | 66 | |
| @@ -80,7 +81,7 @@ qedi_dbg_notice(struct qedi_dbg_ctx *qedi, const char *func, u32 line, · 14 unmodified lines | ||
| 80 | 81 | vaf.va = &va; |
| 81 | 82 | |
| 82 | 83 | if (!(qedi_dbg_log & QEDI_LOG_NOTICE)) |
| 83 | − return; | |
| 84 | + goto ret; | |
| 84 | 85 | |
| 85 | 86 | if (likely(qedi) && likely(qedi->pdev)) |
| 86 | 87 | pr_notice("[%s]:[%s:%d]:%d: %pV", |
| @@ -89,6 +90,7 @@ qedi_dbg_notice(struct qedi_dbg_ctx *qedi, const char *func, u32 line, · 2 unmodified lines | ||
| 89 | 90 | else |
| 90 | 91 | pr_notice("[0000:00:00.0]:[%s:%d]: %pV", nfunc, line, &vaf); |
| 91 | 92 | |
| 93 | +ret: | |
| 92 | 94 | va_end(va); |
| 93 | 95 | } |
| 94 | 96 | |
| @@ -109,7 +111,7 @@ qedi_dbg_info(struct qedi_dbg_ctx *qedi, const char *func, u32 line, · 14 unmodified lines | ||
| 109 | 111 | vaf.va = &va; |
| 110 | 112 | |
| 111 | 113 | if (!(qedi_dbg_log & level)) |
| 112 | − return; | |
| 114 | + goto ret; | |
| 113 | 115 | |
| 114 | 116 | if (likely(qedi) && likely(qedi->pdev)) |
| 115 | 117 | pr_info("[%s]:[%s:%d]:%d: %pV", dev_name(&qedi->pdev->dev), |
| @@ -117,6 +119,7 @@ qedi_dbg_info(struct qedi_dbg_ctx *qedi, const char *func, u32 line, · 1 unmodified line | ||
| 117 | 119 | else |
| 118 | 120 | pr_info("[0000:00:00.0]:[%s:%d]: %pV", nfunc, line, &vaf); |
| 119 | 121 | |
| 122 | +ret: | |
| 120 | 123 | va_end(va); |
| 121 | 124 | } |
| 122 | 125 | |
| @@ -48,6 +48,7 @@ struct scsi_host_template qedi_host_template = { · 47 unmodified lines | ||
| 48 | 48 | .name = "QLogic QEDI 25/40/100Gb iSCSI Initiator Driver", |
| 49 | 49 | .proc_name = QEDI_MODULE_NAME, |
| 50 | 50 | .queuecommand = iscsi_queuecommand, |
| 51 | + .eh_timed_out = iscsi_eh_cmd_timed_out, | |
| 51 | 52 | .eh_abort_handler = iscsi_eh_abort, |
| 52 | 53 | .eh_device_reset_handler = iscsi_eh_device_reset, |
| 53 | 54 | .eh_target_reset_handler = iscsi_eh_recover_target, |
| @@ -453,13 +454,9 @@ static int qedi_iscsi_update_conn(struct qedi_ctx *qedi, · 399 unmodified lines | ||
| 453 | 454 | if (rval) { |
| 454 | 455 | rval = -ENXIO; |
| 455 | 456 | QEDI_ERR(&qedi->dbg_ctx, "Could not update connection\n"); |
| 456 | − goto update_conn_err; | |
| 457 | 457 | } |
| 458 | 458 | |
| 459 | 459 | kfree(conn_info); |
| 460 | − rval = 0; | |
| 461 | − | |
| 462 | −update_conn_err: | |
| 463 | 460 | return rval; |
| 464 | 461 | } |
| 465 | 462 | |
| @@ -2248,7 +2248,7 @@ struct ct_fdmiv2_hba_attr { · 2247 unmodified lines | ||
| 2248 | 2248 | uint32_t num_ports; |
| 2249 | 2249 | uint8_t fabric_name[WWN_SIZE]; |
| 2250 | 2250 | uint8_t bios_name[32]; |
| 2251 | − uint8_t vendor_indentifer[8]; | |
| 2251 | + uint8_t vendor_identifier[8]; | |
| 2252 | 2252 | } a; |
| 2253 | 2253 | }; |
| 2254 | 2254 | |
| @@ -2423,7 +2423,7 @@ struct ct_sns_req { · 168 unmodified lines | ||
| 2423 | 2423 | } rsnn_nn; |
| 2424 | 2424 | |
| 2425 | 2425 | struct { |
| 2426 | − uint8_t hba_indentifier[8]; | |
| 2426 | + uint8_t hba_identifier[8]; | |
| 2427 | 2427 | } ghat; |
| 2428 | 2428 | |
| 2429 | 2429 | struct { |
| @@ -1939,15 +1939,15 @@ qla2x00_fdmiv2_rhba(scsi_qla_host_t *vha) · 1938 unmodified lines | ||
| 1939 | 1939 | /* Vendor Identifier */ |
| 1940 | 1940 | eiter = entries + size; |
| 1941 | 1941 | eiter->type = cpu_to_be16(FDMI_HBA_TYPE_VENDOR_IDENTIFIER); |
| 1942 | − snprintf(eiter->a.vendor_indentifer, sizeof(eiter->a.vendor_indentifer), | |
| 1942 | + snprintf(eiter->a.vendor_identifier, sizeof(eiter->a.vendor_identifier), | |
| 1943 | 1943 | "%s", "QLGC"); |
| 1944 | − alen = strlen(eiter->a.vendor_indentifer); | |
| 1944 | + alen = strlen(eiter->a.vendor_identifier); | |
| 1945 | 1945 | alen += 4 - (alen & 3); |
| 1946 | 1946 | eiter->len = cpu_to_be16(4 + alen); |
| 1947 | 1947 | size += 4 + alen; |
| 1948 | 1948 | |
| 1949 | 1949 | ql_dbg(ql_dbg_disc, vha, 0x20b1, |
| 1950 | − "Vendor Identifier = %s.\n", eiter->a.vendor_indentifer); | |
| 1950 | + "Vendor Identifier = %s.\n", eiter->a.vendor_identifier); | |
| 1951 | 1951 | |
| 1952 | 1952 | /* Update MS request size. */ |
| 1953 | 1953 | qla2x00_update_ms_fdmi_iocb(vha, size + 16); |
| @@ -2997,14 +2997,14 @@ struct qla_init_msix_entry { · 2996 unmodified lines | ||
| 2997 | 2997 | irq_handler_t handler; |
| 2998 | 2998 | }; |
| 2999 | 2999 | |
| 3000 | −static struct qla_init_msix_entry msix_entries[] = { | |
| 3000 | +static const struct qla_init_msix_entry msix_entries[] = { | |
| 3001 | 3001 | { "qla2xxx (default)", qla24xx_msix_default }, |
| 3002 | 3002 | { "qla2xxx (rsp_q)", qla24xx_msix_rsp_q }, |
| 3003 | 3003 | { "qla2xxx (atio_q)", qla83xx_msix_atio_q }, |
| 3004 | 3004 | { "qla2xxx (qpair_multiq)", qla2xxx_msix_rsp_q }, |
| 3005 | 3005 | }; |
| 3006 | 3006 | |
| 3007 | −static struct qla_init_msix_entry qla82xx_msix_entries[] = { | |
| 3007 | +static const struct qla_init_msix_entry qla82xx_msix_entries[] = { | |
| 3008 | 3008 | { "qla2xxx (default)", qla82xx_msix_default }, |
| 3009 | 3009 | { "qla2xxx (rsp_q)", qla82xx_msix_rsp_q }, |
| 3010 | 3010 | }; |
| @@ -3078,7 +3078,7 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp) · 67 unmodified lines | ||
| 3078 | 3078 | qentry->handle = rsp; |
| 3079 | 3079 | rsp->msix = qentry; |
| 3080 | 3080 | scnprintf(qentry->name, sizeof(qentry->name), |
| 3081 | − msix_entries[i].name); | |
| 3081 | + "%s", msix_entries[i].name); | |
| 3082 | 3082 | if (IS_P3P_TYPE(ha)) |
| 3083 | 3083 | ret = request_irq(qentry->vector, |
| 3084 | 3084 | qla82xx_msix_entries[i].handler, |
| @@ -3102,7 +3102,7 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp) · 17 unmodified lines | ||
| 3102 | 3102 | rsp->msix = qentry; |
| 3103 | 3103 | qentry->handle = rsp; |
| 3104 | 3104 | scnprintf(qentry->name, sizeof(qentry->name), |
| 3105 | − msix_entries[QLA_ATIO_VECTOR].name); | |
| 3105 | + "%s", msix_entries[QLA_ATIO_VECTOR].name); | |
| 3106 | 3106 | qentry->in_use = 1; |
| 3107 | 3107 | ret = request_irq(qentry->vector, |
| 3108 | 3108 | msix_entries[QLA_ATIO_VECTOR].handler, |
| @@ -3271,7 +3271,7 @@ free_irqs: · 162 unmodified lines | ||
| 3271 | 3271 | int qla25xx_request_irq(struct qla_hw_data *ha, struct qla_qpair *qpair, |
| 3272 | 3272 | struct qla_msix_entry *msix, int vector_type) |
| 3273 | 3273 | { |
| 3274 | − struct qla_init_msix_entry *intr = &msix_entries[vector_type]; | |
| 3274 | + const struct qla_init_msix_entry *intr = &msix_entries[vector_type]; | |
| 3275 | 3275 | scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); |
| 3276 | 3276 | int ret; |
| 3277 | 3277 | |
| @@ -262,6 +262,7 @@ struct scsi_host_template qla2xxx_driver_template = { · 261 unmodified lines | ||
| 262 | 262 | .name = QLA2XXX_DRIVER_NAME, |
| 263 | 263 | .queuecommand = qla2xxx_queuecommand, |
| 264 | 264 | |
| 265 | + .eh_timed_out = fc_eh_timed_out, | |
| 265 | 266 | .eh_abort_handler = qla2xxx_eh_abort, |
| 266 | 267 | .eh_device_reset_handler = qla2xxx_eh_device_reset, |
| 267 | 268 | .eh_target_reset_handler = qla2xxx_eh_target_reset, |
| @@ -408,9 +408,6 @@ struct qla4_8xxx_legacy_intr_set { · 407 unmodified lines | ||
| 408 | 408 | }; |
| 409 | 409 | |
| 410 | 410 | /* MSI-X Support */ |
| 411 | − | |
| 412 | −#define QLA_MSIX_DEFAULT 0 | |
| 413 | −#define QLA_MSIX_RSP_Q 1 | |
| 414 | 411 | #define QLA_MSIX_ENTRIES 2 |
| 415 | 412 | |
| 416 | 413 | /* |
| @@ -9539,15 +9539,15 @@ exit_host_reset: · 9538 unmodified lines | ||
| 9539 | 9539 | * driver calls the following device driver's callbacks |
| 9540 | 9540 | * |
| 9541 | 9541 | * - Fatal Errors - link_reset |
| 9542 | − * - Non-Fatal Errors - driver's pci_error_detected() which | |
| 9542 | + * - Non-Fatal Errors - driver's error_detected() which | |
| 9543 | 9543 | * returns CAN_RECOVER, NEED_RESET or DISCONNECT. |
| 9544 | 9544 | * |
| 9545 | 9545 | * PCI AER driver calls |
| 9546 | − * CAN_RECOVER - driver's pci_mmio_enabled(), mmio_enabled | |
| 9546 | + * CAN_RECOVER - driver's mmio_enabled(), mmio_enabled() | |
| 9547 | 9547 | * returns RECOVERED or NEED_RESET if fw_hung |
| 9548 | 9548 | * NEED_RESET - driver's slot_reset() |
| 9549 | 9549 | * DISCONNECT - device is dead & cannot recover |
| 9550 | − * RECOVERED - driver's pci_resume() | |
| 9550 | + * RECOVERED - driver's resume() | |
| 9551 | 9551 | */ |
| 9552 | 9552 | static pci_ers_result_t |
| 9553 | 9553 | qla4xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) |
| @@ -125,6 +125,7 @@ static const char *sdebug_version_date = "20160430"; · 124 unmodified lines | ||
| 125 | 125 | #define DEF_OPTS 0 |
| 126 | 126 | #define DEF_OPT_BLKS 1024 |
| 127 | 127 | #define DEF_PHYSBLK_EXP 0 |
| 128 | +#define DEF_OPT_XFERLEN_EXP 0 | |
| 128 | 129 | #define DEF_PTYPE TYPE_DISK |
| 129 | 130 | #define DEF_REMOVABLE false |
| 130 | 131 | #define DEF_SCSI_LEVEL 7 /* INQUIRY, byte2 [6->SPC-4; 7->SPC-5] */ |
| @@ -590,6 +591,7 @@ static int sdebug_num_tgts = DEF_NUM_TGTS; /* targets per host */ · 459 unmodified lines | ||
| 590 | 591 | static int sdebug_opt_blks = DEF_OPT_BLKS; |
| 591 | 592 | static int sdebug_opts = DEF_OPTS; |
| 592 | 593 | static int sdebug_physblk_exp = DEF_PHYSBLK_EXP; |
| 594 | +static int sdebug_opt_xferlen_exp = DEF_OPT_XFERLEN_EXP; | |
| 593 | 595 | static int sdebug_ptype = DEF_PTYPE; /* SCSI peripheral device type */ |
| 594 | 596 | static int sdebug_scsi_level = DEF_SCSI_LEVEL; |
| 595 | 597 | static int sdebug_sector_size = DEF_SECTOR_SIZE; |
| @@ -1205,7 +1207,11 @@ static int inquiry_vpd_b0(unsigned char *arr) · 609 unmodified lines | ||
| 1205 | 1207 | memcpy(arr, vpdb0_data, sizeof(vpdb0_data)); |
| 1206 | 1208 | |
| 1207 | 1209 | /* Optimal transfer length granularity */ |
| 1208 | − gran = 1 << sdebug_physblk_exp; | |
| 1210 | + if (sdebug_opt_xferlen_exp != 0 && | |
| 1211 | + sdebug_physblk_exp < sdebug_opt_xferlen_exp) | |
| 1212 | + gran = 1 << sdebug_opt_xferlen_exp; | |
| 1213 | + else | |
| 1214 | + gran = 1 << sdebug_physblk_exp; | |
| 1209 | 1215 | put_unaligned_be16(gran, arr + 2); |
| 1210 | 1216 | |
| 1211 | 1217 | /* Maximum Transfer Length */ |
| @@ -4161,6 +4167,7 @@ module_param_named(num_tgts, sdebug_num_tgts, int, S_IRUGO | S_IWUSR); · 2949 unmodified lines | ||
| 4161 | 4167 | module_param_named(opt_blks, sdebug_opt_blks, int, S_IRUGO); |
| 4162 | 4168 | module_param_named(opts, sdebug_opts, int, S_IRUGO | S_IWUSR); |
| 4163 | 4169 | module_param_named(physblk_exp, sdebug_physblk_exp, int, S_IRUGO); |
| 4170 | +module_param_named(opt_xferlen_exp, sdebug_opt_xferlen_exp, int, S_IRUGO); | |
| 4164 | 4171 | module_param_named(ptype, sdebug_ptype, int, S_IRUGO | S_IWUSR); |
| 4165 | 4172 | module_param_named(removable, sdebug_removable, bool, S_IRUGO | S_IWUSR); |
| 4166 | 4173 | module_param_named(scsi_level, sdebug_scsi_level, int, S_IRUGO); |
| @@ -4212,6 +4219,7 @@ MODULE_PARM_DESC(num_tgts, "number of targets per host to simulate(def=1)"); · 45 unmodified lines | ||
| 4212 | 4219 | MODULE_PARM_DESC(opt_blks, "optimal transfer length in blocks (def=1024)"); |
| 4213 | 4220 | MODULE_PARM_DESC(opts, "1->noise, 2->medium_err, 4->timeout, 8->recovered_err... (def=0)"); |
| 4214 | 4221 | MODULE_PARM_DESC(physblk_exp, "physical block exponent (def=0)"); |
| 4222 | +MODULE_PARM_DESC(opt_xferlen_exp, "optimal transfer length granularity exponent (def=physblk_exp)"); | |
| 4215 | 4223 | MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])"); |
| 4216 | 4224 | MODULE_PARM_DESC(removable, "claim to have removable media (def=0)"); |
| 4217 | 4225 | MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=7[SPC-5])"); |
| @@ -279,9 +279,7 @@ enum blk_eh_timer_return scsi_times_out(struct request *req) · 278 unmodified lines | ||
| 279 | 279 | if (host->eh_deadline != -1 && !host->last_reset) |
| 280 | 280 | host->last_reset = jiffies; |
| 281 | 281 | |
| 282 | − if (host->transportt->eh_timed_out) | |
| 283 | − rtn = host->transportt->eh_timed_out(scmd); | |
| 284 | − else if (host->hostt->eh_timed_out) | |
| 282 | + if (host->hostt->eh_timed_out) | |
| 285 | 283 | rtn = host->hostt->eh_timed_out(scmd); |
| 286 | 284 | |
| 287 | 285 | if (rtn == BLK_EH_NOT_HANDLED) { |
| @@ -2055,7 +2055,7 @@ static int fc_vport_match(struct attribute_container *cont, · 2054 unmodified lines | ||
| 2055 | 2055 | |
| 2056 | 2056 | |
| 2057 | 2057 | /** |
| 2058 | − * fc_timed_out - FC Transport I/O timeout intercept handler | |
| 2058 | + * fc_eh_timed_out - FC Transport I/O timeout intercept handler | |
| 2059 | 2059 | * @scmd: The SCSI command which timed out |
| 2060 | 2060 | * |
| 2061 | 2061 | * This routine protects against error handlers getting invoked while a |
| @@ -2076,8 +2076,8 @@ static int fc_vport_match(struct attribute_container *cont, · 14 unmodified lines | ||
| 2076 | 2076 | * Notes: |
| 2077 | 2077 | * This routine assumes no locks are held on entry. |
| 2078 | 2078 | */ |
| 2079 | −static enum blk_eh_timer_return | |
| 2080 | −fc_timed_out(struct scsi_cmnd *scmd) | |
| 2079 | +enum blk_eh_timer_return | |
| 2080 | +fc_eh_timed_out(struct scsi_cmnd *scmd) | |
| 2081 | 2081 | { |
| 2082 | 2082 | struct fc_rport *rport = starget_to_rport(scsi_target(scmd->device)); |
| 2083 | 2083 | |
| @@ -2086,6 +2086,7 @@ fc_timed_out(struct scsi_cmnd *scmd) · 2 unmodified lines | ||
| 2086 | 2086 | |
| 2087 | 2087 | return BLK_EH_NOT_HANDLED; |
| 2088 | 2088 | } |
| 2089 | +EXPORT_SYMBOL(fc_eh_timed_out); | |
| 2089 | 2090 | |
| 2090 | 2091 | /* |
| 2091 | 2092 | * Called by fc_user_scan to locate an rport on the shost that |
| @@ -2159,19 +2160,6 @@ fc_user_scan(struct Scsi_Host *shost, uint channel, uint id, u64 lun) · 67 unmodified lines | ||
| 2159 | 2160 | return 0; |
| 2160 | 2161 | } |
| 2161 | 2162 | |
| 2162 | −static int fc_tsk_mgmt_response(struct Scsi_Host *shost, u64 nexus, u64 tm_id, | |
| 2163 | − int result) | |
| 2164 | −{ | |
| 2165 | − struct fc_internal *i = to_fc_internal(shost->transportt); | |
| 2166 | − return i->f->tsk_mgmt_response(shost, nexus, tm_id, result); | |
| 2167 | −} | |
| 2168 | − | |
| 2169 | −static int fc_it_nexus_response(struct Scsi_Host *shost, u64 nexus, int result) | |
| 2170 | −{ | |
| 2171 | − struct fc_internal *i = to_fc_internal(shost->transportt); | |
| 2172 | − return i->f->it_nexus_response(shost, nexus, result); | |
| 2173 | −} | |
| 2174 | − | |
| 2175 | 2163 | struct scsi_transport_template * |
| 2176 | 2164 | fc_attach_transport(struct fc_function_template *ft) |
| 2177 | 2165 | { |
| @@ -2211,14 +2199,8 @@ fc_attach_transport(struct fc_function_template *ft) · 33 unmodified lines | ||
| 2211 | 2199 | /* Transport uses the shost workq for scsi scanning */ |
| 2212 | 2200 | i->t.create_work_queue = 1; |
| 2213 | 2201 | |
| 2214 | − i->t.eh_timed_out = fc_timed_out; | |
| 2215 | − | |
| 2216 | 2202 | i->t.user_scan = fc_user_scan; |
| 2217 | 2203 | |
| 2218 | − /* target-mode drivers' functions */ | |
| 2219 | − i->t.tsk_mgmt_response = fc_tsk_mgmt_response; | |
| 2220 | − i->t.it_nexus_response = fc_it_nexus_response; | |
| 2221 | − | |
| 2222 | 2204 | /* |
| 2223 | 2205 | * Setup SCSI Target Attributes. |
| 2224 | 2206 | */ |
| @@ -591,7 +591,7 @@ EXPORT_SYMBOL(srp_reconnect_rport); · 590 unmodified lines | ||
| 591 | 591 | * Note: This function is called from soft-IRQ context and with the request |
| 592 | 592 | * queue lock held. |
| 593 | 593 | */ |
| 594 | −static enum blk_eh_timer_return srp_timed_out(struct scsi_cmnd *scmd) | |
| 594 | +enum blk_eh_timer_return srp_timed_out(struct scsi_cmnd *scmd) | |
| 595 | 595 | { |
| 596 | 596 | struct scsi_device *sdev = scmd->device; |
| 597 | 597 | struct Scsi_Host *shost = sdev->host; |
| @@ -603,6 +603,7 @@ static enum blk_eh_timer_return srp_timed_out(struct scsi_cmnd *scmd) · 5 unmodified lines | ||
| 603 | 603 | i->f->reset_timer_if_blocked && scsi_device_blocked(sdev) ? |
| 604 | 604 | BLK_EH_RESET_TIMER : BLK_EH_NOT_HANDLED; |
| 605 | 605 | } |
| 606 | +EXPORT_SYMBOL(srp_timed_out); | |
| 606 | 607 | |
| 607 | 608 | static void srp_rport_release(struct device *dev) |
| 608 | 609 | { |
| @@ -793,19 +794,6 @@ void srp_stop_rport_timers(struct srp_rport *rport) · 184 unmodified lines | ||
| 793 | 794 | } |
| 794 | 795 | EXPORT_SYMBOL_GPL(srp_stop_rport_timers); |
| 795 | 796 | |
| 796 | −static int srp_tsk_mgmt_response(struct Scsi_Host *shost, u64 nexus, u64 tm_id, | |
| 797 | − int result) | |
| 798 | −{ | |
| 799 | − struct srp_internal *i = to_srp_internal(shost->transportt); | |
| 800 | − return i->f->tsk_mgmt_response(shost, nexus, tm_id, result); | |
| 801 | −} | |
| 802 | − | |
| 803 | −static int srp_it_nexus_response(struct Scsi_Host *shost, u64 nexus, int result) | |
| 804 | −{ | |
| 805 | − struct srp_internal *i = to_srp_internal(shost->transportt); | |
| 806 | − return i->f->it_nexus_response(shost, nexus, result); | |
| 807 | −} | |
| 808 | − | |
| 809 | 797 | /** |
| 810 | 798 | * srp_attach_transport - instantiate SRP transport template |
| 811 | 799 | * @ft: SRP transport class function template |
| @@ -820,11 +808,6 @@ srp_attach_transport(struct srp_function_template *ft) · 8 unmodified lines | ||
| 820 | 808 | if (!i) |
| 821 | 809 | return NULL; |
| 822 | 810 | |
| 823 | − i->t.eh_timed_out = srp_timed_out; | |
| 824 | − | |
| 825 | − i->t.tsk_mgmt_response = srp_tsk_mgmt_response; | |
| 826 | − i->t.it_nexus_response = srp_it_nexus_response; | |
| 827 | − | |
| 828 | 811 | i->t.host_size = sizeof(struct srp_host_attrs); |
| 829 | 812 | i->t.host_attrs.ac.attrs = &i->host_attrs[0]; |
| 830 | 813 | i->t.host_attrs.ac.class = &srp_host_class.class; |
| @@ -703,7 +703,7 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode) · 702 unmodified lines | ||
| 703 | 703 | |
| 704 | 704 | /** |
| 705 | 705 | * sd_setup_discard_cmnd - unmap blocks on thinly provisioned device |
| 706 | − * @sdp: scsi device to operate one | |
| 706 | + * @sdp: scsi device to operate on | |
| 707 | 707 | * @rq: Request to prepare |
| 708 | 708 | * |
| 709 | 709 | * Will issue either UNMAP or WRITE SAME(16) depending on preference |
| @@ -3226,7 +3226,7 @@ static int sd_probe(struct device *dev) · 2516 unmodified lines | ||
| 3226 | 3226 | * sd_remove - called whenever a scsi disk (previously recognized by |
| 3227 | 3227 | * sd_probe) is detached from the system. It is called (potentially |
| 3228 | 3228 | * multiple times) during sd module unload. |
| 3229 | − * @sdp: pointer to mid level scsi device object | |
| 3229 | + * @dev: pointer to device object | |
| 3230 | 3230 | * |
| 3231 | 3231 | * Note: this function is invoked from the scsi mid-level. |
| 3232 | 3232 | * This function potentially frees up a device name (e.g. /dev/sdc) |
| @@ -299,7 +299,6 @@ struct snic { · 298 unmodified lines | ||
| 299 | 299 | |
| 300 | 300 | /* pci related */ |
| 301 | 301 | struct pci_dev *pdev; |
| 302 | − struct msix_entry msix_entry[SNIC_MSIX_INTR_MAX]; | |
| 303 | 302 | struct snic_msix_entry msix[SNIC_MSIX_INTR_MAX]; |
| 304 | 303 | |
| 305 | 304 | /* io related info */ |
| @@ -93,7 +93,7 @@ snic_free_intr(struct snic *snic) · 92 unmodified lines | ||
| 93 | 93 | /* ONLY interrupt mode MSIX is supported */ |
| 94 | 94 | for (i = 0; i < ARRAY_SIZE(snic->msix); i++) { |
| 95 | 95 | if (snic->msix[i].requested) { |
| 96 | − free_irq(snic->msix_entry[i].vector, | |
| 96 | + free_irq(pci_irq_vector(snic->pdev, i), | |
| 97 | 97 | snic->msix[i].devid); |
| 98 | 98 | } |
| 99 | 99 | } |
| @@ -134,7 +134,7 @@ snic_request_intr(struct snic *snic) · 34 unmodified lines | ||
| 134 | 134 | snic->msix[SNIC_MSIX_ERR_NOTIFY].devid = snic; |
| 135 | 135 | |
| 136 | 136 | for (i = 0; i < ARRAY_SIZE(snic->msix); i++) { |
| 137 | − ret = request_irq(snic->msix_entry[i].vector, | |
| 137 | + ret = request_irq(pci_irq_vector(snic->pdev, i), | |
| 138 | 138 | snic->msix[i].isr, |
| 139 | 139 | 0, |
| 140 | 140 | snic->msix[i].devname, |
| @@ -158,47 +158,37 @@ snic_set_intr_mode(struct snic *snic) · 17 unmodified lines | ||
| 158 | 158 | { |
| 159 | 159 | unsigned int n = ARRAY_SIZE(snic->wq); |
| 160 | 160 | unsigned int m = SNIC_CQ_IO_CMPL_MAX; |
| 161 | − unsigned int i; | |
| 161 | + unsigned int vecs = n + m + 1; | |
| 162 | 162 | |
| 163 | 163 | /* |
| 164 | 164 | * We need n WQs, m CQs, and n+m+1 INTRs |
| 165 | 165 | * (last INTR is used for WQ/CQ errors and notification area |
| 166 | 166 | */ |
| 167 | − | |
| 168 | 167 | BUILD_BUG_ON((ARRAY_SIZE(snic->wq) + SNIC_CQ_IO_CMPL_MAX) > |
| 169 | 168 | ARRAY_SIZE(snic->intr)); |
| 170 | − SNIC_BUG_ON(ARRAY_SIZE(snic->msix_entry) < (n + m + 1)); | |
| 171 | − | |
| 172 | − for (i = 0; i < (n + m + 1); i++) | |
| 173 | − snic->msix_entry[i].entry = i; | |
| 174 | − | |
| 175 | − if (snic->wq_count >= n && snic->cq_count >= (n + m)) { | |
| 176 | − if (!pci_enable_msix(snic->pdev, | |
| 177 | − snic->msix_entry, | |
| 178 | − (n + m + 1))) { | |
| 179 | − snic->wq_count = n; | |
| 180 | − snic->cq_count = n + m; | |
| 181 | − snic->intr_count = n + m + 1; | |
| 182 | − snic->err_intr_offset = SNIC_MSIX_ERR_NOTIFY; | |
| 183 | − | |
| 184 | − SNIC_ISR_DBG(snic->shost, | |
| 185 | − "Using MSI-X Interrupts\n"); | |
| 186 | − svnic_dev_set_intr_mode(snic->vdev, | |
| 187 | − VNIC_DEV_INTR_MODE_MSIX); | |
| 188 | − | |
| 189 | − return 0; | |
| 190 | − } | |
| 191 | − } | |
| 192 | 169 | |
| 193 | − svnic_dev_set_intr_mode(snic->vdev, VNIC_DEV_INTR_MODE_UNKNOWN); | |
| 170 | + if (snic->wq_count < n || snic->cq_count < n + m) | |
| 171 | + goto fail; | |
| 194 | 172 | |
| 173 | + if (pci_alloc_irq_vectors(snic->pdev, vecs, vecs, PCI_IRQ_MSIX) < 0) | |
| 174 | + goto fail; | |
| 175 | + | |
| 176 | + snic->wq_count = n; | |
| 177 | + snic->cq_count = n + m; | |
| 178 | + snic->intr_count = vecs; | |
| 179 | + snic->err_intr_offset = SNIC_MSIX_ERR_NOTIFY; | |
| 180 | + | |
| 181 | + SNIC_ISR_DBG(snic->shost, "Using MSI-X Interrupts\n"); | |
| 182 | + svnic_dev_set_intr_mode(snic->vdev, VNIC_DEV_INTR_MODE_MSIX); | |
| 183 | + return 0; | |
| 184 | +fail: | |
| 185 | + svnic_dev_set_intr_mode(snic->vdev, VNIC_DEV_INTR_MODE_UNKNOWN); | |
| 195 | 186 | return -EINVAL; |
| 196 | 187 | } /* end of snic_set_intr_mode */ |
| 197 | 188 | |
| 198 | 189 | void |
| 199 | 190 | snic_clear_intr_mode(struct snic *snic) |
| 200 | 191 | { |
| 201 | − pci_disable_msix(snic->pdev); | |
| 202 | − | |
| 192 | + pci_free_irq_vectors(snic->pdev); | |
| 203 | 193 | svnic_dev_set_intr_mode(snic->vdev, VNIC_DEV_INTR_MODE_INTX); |
| 204 | 194 | } |
| @@ -136,6 +136,8 @@ struct hv_fc_wwn_packet { · 135 unmodified lines | ||
| 136 | 136 | #define SRB_FLAGS_PORT_DRIVER_RESERVED 0x0F000000 |
| 137 | 137 | #define SRB_FLAGS_CLASS_DRIVER_RESERVED 0xF0000000 |
| 138 | 138 | |
| 139 | +#define SP_UNTAGGED ((unsigned char) ~0) | |
| 140 | +#define SRB_SIMPLE_TAG_REQUEST 0x20 | |
| 139 | 141 | |
| 140 | 142 | /* |
| 141 | 143 | * Platform neutral description of a scsi request - |
| @@ -375,6 +377,7 @@ enum storvsc_request_type { · 233 unmodified lines | ||
| 375 | 377 | #define SRB_STATUS_SUCCESS 0x01 |
| 376 | 378 | #define SRB_STATUS_ABORTED 0x02 |
| 377 | 379 | #define SRB_STATUS_ERROR 0x04 |
| 380 | +#define SRB_STATUS_DATA_OVERRUN 0x12 | |
| 378 | 381 | |
| 379 | 382 | #define SRB_STATUS(status) \ |
| 380 | 383 | (status & ~(SRB_STATUS_AUTOSENSE_VALID | SRB_STATUS_QUEUE_FROZEN)) |
| @@ -458,6 +461,15 @@ struct storvsc_device { · 77 unmodified lines | ||
| 458 | 461 | * Max I/O, the device can support. |
| 459 | 462 | */ |
| 460 | 463 | u32 max_transfer_bytes; |
| 464 | + /* | |
| 465 | + * Number of sub-channels we will open. | |
| 466 | + */ | |
| 467 | + u16 num_sc; | |
| 468 | + struct vmbus_channel **stor_chns; | |
| 469 | + /* | |
| 470 | + * Mask of CPUs bound to subchannels. | |
| 471 | + */ | |
| 472 | + struct cpumask alloced_cpus; | |
| 461 | 473 | /* Used for vsc/vsp channel reset process */ |
| 462 | 474 | struct storvsc_cmd_request init_request; |
| 463 | 475 | struct storvsc_cmd_request reset_request; |
| @@ -635,6 +647,11 @@ static void handle_sc_creation(struct vmbus_channel *new_sc) · 171 unmodified lines | ||
| 635 | 647 | (void *)&props, |
| 636 | 648 | sizeof(struct vmstorage_channel_properties), |
| 637 | 649 | storvsc_on_channel_callback, new_sc); |
| 650 | + | |
| 651 | + if (new_sc->state == CHANNEL_OPENED_STATE) { | |
| 652 | + stor_device->stor_chns[new_sc->target_cpu] = new_sc; | |
| 653 | + cpumask_set_cpu(new_sc->target_cpu, &stor_device->alloced_cpus); | |
| 654 | + } | |
| 638 | 655 | } |
| 639 | 656 | |
| 640 | 657 | static void handle_multichannel_storage(struct hv_device *device, int max_chns) |
| @@ -651,6 +668,7 @@ static void handle_multichannel_storage(struct hv_device *device, int max_chns) · 10 unmodified lines | ||
| 651 | 668 | if (!stor_device) |
| 652 | 669 | return; |
| 653 | 670 | |
| 671 | + stor_device->num_sc = num_sc; | |
| 654 | 672 | request = &stor_device->init_request; |
| 655 | 673 | vstor_packet = &request->vstor_packet; |
| 656 | 674 | |
| @@ -838,6 +856,25 @@ static int storvsc_channel_init(struct hv_device *device, bool is_fc) · 181 unmodified lines | ||
| 838 | 856 | * support multi-channel. |
| 839 | 857 | */ |
| 840 | 858 | max_chns = vstor_packet->storage_channel_properties.max_channel_cnt; |
| 859 | + | |
| 860 | + /* | |
| 861 | + * Allocate state to manage the sub-channels. | |
| 862 | + * We allocate an array based on the numbers of possible CPUs | |
| 863 | + * (Hyper-V does not support cpu online/offline). | |
| 864 | + * This Array will be sparseley populated with unique | |
| 865 | + * channels - primary + sub-channels. | |
| 866 | + * We will however populate all the slots to evenly distribute | |
| 867 | + * the load. | |
| 868 | + */ | |
| 869 | + stor_device->stor_chns = kzalloc(sizeof(void *) * num_possible_cpus(), | |
| 870 | + GFP_KERNEL); | |
| 871 | + if (stor_device->stor_chns == NULL) | |
| 872 | + return -ENOMEM; | |
| 873 | + | |
| 874 | + stor_device->stor_chns[device->channel->target_cpu] = device->channel; | |
| 875 | + cpumask_set_cpu(device->channel->target_cpu, | |
| 876 | + &stor_device->alloced_cpus); | |
| 877 | + | |
| 841 | 878 | if (vmstor_proto_version >= VMSTOR_PROTO_VERSION_WIN8) { |
| 842 | 879 | if (vstor_packet->storage_channel_properties.flags & |
| 843 | 880 | STORAGE_CHANNEL_SUPPORTS_MULTI_CHANNEL) |
| @@ -888,6 +925,13 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb, · 44 unmodified lines | ||
| 888 | 925 | |
| 889 | 926 | switch (SRB_STATUS(vm_srb->srb_status)) { |
| 890 | 927 | case SRB_STATUS_ERROR: |
| 928 | + /* | |
| 929 | + * Let upper layer deal with error when | |
| 930 | + * sense message is present. | |
| 931 | + */ | |
| 932 | + | |
| 933 | + if (vm_srb->srb_status & SRB_STATUS_AUTOSENSE_VALID) | |
| 934 | + break; | |
| 891 | 935 | /* |
| 892 | 936 | * If there is an error; offline the device since all |
| 893 | 937 | * error recovery strategies would have already been |
| @@ -953,6 +997,7 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request, · 59 unmodified lines | ||
| 953 | 997 | struct scsi_cmnd *scmnd = cmd_request->cmd; |
| 954 | 998 | struct scsi_sense_hdr sense_hdr; |
| 955 | 999 | struct vmscsi_request *vm_srb; |
| 1000 | + u32 data_transfer_length; | |
| 956 | 1001 | struct Scsi_Host *host; |
| 957 | 1002 | u32 payload_sz = cmd_request->payload_sz; |
| 958 | 1003 | void *payload = cmd_request->payload; |
| @@ -960,6 +1005,7 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request, · 1 unmodified line | ||
| 960 | 1005 | host = stor_dev->host; |
| 961 | 1006 | |
| 962 | 1007 | vm_srb = &cmd_request->vstor_packet.vm_srb; |
| 1008 | + data_transfer_length = vm_srb->data_transfer_length; | |
| 963 | 1009 | |
| 964 | 1010 | scmnd->result = vm_srb->scsi_status; |
| 965 | 1011 | |
| @@ -973,13 +1019,20 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request, · 7 unmodified lines | ||
| 973 | 1019 | &sense_hdr); |
| 974 | 1020 | } |
| 975 | 1021 | |
| 976 | − if (vm_srb->srb_status != SRB_STATUS_SUCCESS) | |
| 1022 | + if (vm_srb->srb_status != SRB_STATUS_SUCCESS) { | |
| 977 | 1023 | storvsc_handle_error(vm_srb, scmnd, host, sense_hdr.asc, |
| 978 | 1024 | sense_hdr.ascq); |
| 1025 | + /* | |
| 1026 | + * The Windows driver set data_transfer_length on | |
| 1027 | + * SRB_STATUS_DATA_OVERRUN. On other errors, this value | |
| 1028 | + * is untouched. In these cases we set it to 0. | |
| 1029 | + */ | |
| 1030 | + if (vm_srb->srb_status != SRB_STATUS_DATA_OVERRUN) | |
| 1031 | + data_transfer_length = 0; | |
| 1032 | + } | |
| 979 | 1033 | |
| 980 | 1034 | scsi_set_resid(scmnd, |
| 981 | − cmd_request->payload->range.len - | |
| 982 | − vm_srb->data_transfer_length); | |
| 1035 | + cmd_request->payload->range.len - data_transfer_length); | |
| 983 | 1036 | |
| 984 | 1037 | scmnd->scsi_done(scmnd); |
| 985 | 1038 | |
| @@ -1198,17 +1251,64 @@ static int storvsc_dev_remove(struct hv_device *device) · 212 unmodified lines | ||
| 1198 | 1251 | /* Close the channel */ |
| 1199 | 1252 | vmbus_close(device->channel); |
| 1200 | 1253 | |
| 1254 | + kfree(stor_device->stor_chns); | |
| 1201 | 1255 | kfree(stor_device); |
| 1202 | 1256 | return 0; |
| 1203 | 1257 | } |
| 1204 | 1258 | |
| 1259 | +static struct vmbus_channel *get_og_chn(struct storvsc_device *stor_device, | |
| 1260 | + u16 q_num) | |
| 1261 | +{ | |
| 1262 | + u16 slot = 0; | |
| 1263 | + u16 hash_qnum; | |
| 1264 | + struct cpumask alloced_mask; | |
| 1265 | + int num_channels, tgt_cpu; | |
| 1266 | + | |
| 1267 | + if (stor_device->num_sc == 0) | |
| 1268 | + return stor_device->device->channel; | |
| 1269 | + | |
| 1270 | + /* | |
| 1271 | + * Our channel array is sparsley populated and we | |
| 1272 | + * initiated I/O on a processor/hw-q that does not | |
| 1273 | + * currently have a designated channel. Fix this. | |
| 1274 | + * The strategy is simple: | |
| 1275 | + * I. Ensure NUMA locality | |
| 1276 | + * II. Distribute evenly (best effort) | |
| 1277 | + * III. Mapping is persistent. | |
| 1278 | + */ | |
| 1279 | + | |
| 1280 | + cpumask_and(&alloced_mask, &stor_device->alloced_cpus, | |
| 1281 | + cpumask_of_node(cpu_to_node(q_num))); | |
| 1282 | + | |
| 1283 | + num_channels = cpumask_weight(&alloced_mask); | |
| 1284 | + if (num_channels == 0) | |
| 1285 | + return stor_device->device->channel; | |
| 1286 | + | |
| 1287 | + hash_qnum = q_num; | |
| 1288 | + while (hash_qnum >= num_channels) | |
| 1289 | + hash_qnum -= num_channels; | |
| 1290 | + | |
| 1291 | + for_each_cpu(tgt_cpu, &alloced_mask) { | |
| 1292 | + if (slot == hash_qnum) | |
| 1293 | + break; | |
| 1294 | + slot++; | |
| 1295 | + } | |
| 1296 | + | |
| 1297 | + stor_device->stor_chns[q_num] = stor_device->stor_chns[tgt_cpu]; | |
| 1298 | + | |
| 1299 | + return stor_device->stor_chns[q_num]; | |
| 1300 | +} | |
| 1301 | + | |
| 1302 | + | |
| 1205 | 1303 | static int storvsc_do_io(struct hv_device *device, |
| 1206 | − struct storvsc_cmd_request *request) | |
| 1304 | + struct storvsc_cmd_request *request, u16 q_num) | |
| 1207 | 1305 | { |
| 1208 | 1306 | struct storvsc_device *stor_device; |
| 1209 | 1307 | struct vstor_packet *vstor_packet; |
| 1210 | 1308 | struct vmbus_channel *outgoing_channel; |
| 1211 | 1309 | int ret = 0; |
| 1310 | + struct cpumask alloced_mask; | |
| 1311 | + int tgt_cpu; | |
| 1212 | 1312 | |
| 1213 | 1313 | vstor_packet = &request->vstor_packet; |
| 1214 | 1314 | stor_device = get_out_stor_device(device); |
| @@ -1222,7 +1322,26 @@ static int storvsc_do_io(struct hv_device *device, · 7 unmodified lines | ||
| 1222 | 1322 | * Select an an appropriate channel to send the request out. |
| 1223 | 1323 | */ |
| 1224 | 1324 | |
| 1225 | − outgoing_channel = vmbus_get_outgoing_channel(device->channel); | |
| 1325 | + if (stor_device->stor_chns[q_num] != NULL) { | |
| 1326 | + outgoing_channel = stor_device->stor_chns[q_num]; | |
| 1327 | + if (outgoing_channel->target_cpu == smp_processor_id()) { | |
| 1328 | + /* | |
| 1329 | + * Ideally, we want to pick a different channel if | |
| 1330 | + * available on the same NUMA node. | |
| 1331 | + */ | |
| 1332 | + cpumask_and(&alloced_mask, &stor_device->alloced_cpus, | |
| 1333 | + cpumask_of_node(cpu_to_node(q_num))); | |
| 1334 | + for_each_cpu(tgt_cpu, &alloced_mask) { | |
| 1335 | + if (tgt_cpu != outgoing_channel->target_cpu) { | |
| 1336 | + outgoing_channel = | |
| 1337 | + stor_device->stor_chns[tgt_cpu]; | |
| 1338 | + break; | |
| 1339 | + } | |
| 1340 | + } | |
| 1341 | + } | |
| 1342 | + } else { | |
| 1343 | + outgoing_channel = get_og_chn(stor_device, q_num); | |
| 1344 | + } | |
| 1226 | 1345 | |
| 1227 | 1346 | |
| 1228 | 1347 | vstor_packet->flags |= REQUEST_COMPLETION_FLAG; |
| @@ -1267,8 +1386,6 @@ static int storvsc_do_io(struct hv_device *device, · 38 unmodified lines | ||
| 1267 | 1386 | static int storvsc_device_configure(struct scsi_device *sdevice) |
| 1268 | 1387 | { |
| 1269 | 1388 | |
| 1270 | − blk_queue_max_segment_size(sdevice->request_queue, PAGE_SIZE); | |
| 1271 | − | |
| 1272 | 1389 | blk_queue_bounce_limit(sdevice->request_queue, BLK_BOUNCE_ANY); |
| 1273 | 1390 | |
| 1274 | 1391 | blk_queue_rq_timeout(sdevice->request_queue, (storvsc_timeout * HZ)); |
| @@ -1451,6 +1568,13 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) · 176 unmodified lines | ||
| 1451 | 1568 | vm_srb->win8_extension.srb_flags |= |
| 1452 | 1569 | SRB_FLAGS_DISABLE_SYNCH_TRANSFER; |
| 1453 | 1570 | |
| 1571 | + if (scmnd->device->tagged_supported) { | |
| 1572 | + vm_srb->win8_extension.srb_flags |= | |
| 1573 | + (SRB_FLAGS_QUEUE_ACTION_ENABLE | SRB_FLAGS_NO_QUEUE_FREEZE); | |
| 1574 | + vm_srb->win8_extension.queue_tag = SP_UNTAGGED; | |
| 1575 | + vm_srb->win8_extension.queue_action = SRB_SIMPLE_TAG_REQUEST; | |
| 1576 | + } | |
| 1577 | + | |
| 1454 | 1578 | /* Build the SRB */ |
| 1455 | 1579 | switch (scmnd->sc_data_direction) { |
| 1456 | 1580 | case DMA_TO_DEVICE: |
| @@ -1511,20 +1635,14 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) · 54 unmodified lines | ||
| 1511 | 1635 | page_to_pfn(sg_page((cur_sgl))); |
| 1512 | 1636 | cur_sgl = sg_next(cur_sgl); |
| 1513 | 1637 | } |
| 1514 | − | |
| 1515 | − } else if (scsi_sglist(scmnd)) { | |
| 1516 | − payload->range.len = length; | |
| 1517 | − payload->range.offset = | |
| 1518 | − virt_to_phys(scsi_sglist(scmnd)) & (PAGE_SIZE-1); | |
| 1519 | − payload->range.pfn_array[0] = | |
| 1520 | − virt_to_phys(scsi_sglist(scmnd)) >> PAGE_SHIFT; | |
| 1521 | 1638 | } |
| 1522 | 1639 | |
| 1523 | 1640 | cmd_request->payload = payload; |
| 1524 | 1641 | cmd_request->payload_sz = payload_sz; |
| 1525 | 1642 | |
| 1526 | 1643 | /* Invokes the vsc to start an IO */ |
| 1527 | − ret = storvsc_do_io(dev, cmd_request); | |
| 1644 | + ret = storvsc_do_io(dev, cmd_request, get_cpu()); | |
| 1645 | + put_cpu(); | |
| 1528 | 1646 | |
| 1529 | 1647 | if (ret == -EAGAIN) { |
| 1530 | 1648 | /* no more space */ |
| @@ -1550,6 +1668,7 @@ static struct scsi_host_template scsi_driver = { · 19 unmodified lines | ||
| 1550 | 1668 | /* Make sure we dont get a sg segment crosses a page boundary */ |
| 1551 | 1669 | .dma_boundary = PAGE_SIZE-1, |
| 1552 | 1670 | .no_write_same = 1, |
| 1671 | + .track_queue_depth = 1, | |
| 1553 | 1672 | }; |
| 1554 | 1673 | |
| 1555 | 1674 | enum { |
| @@ -1680,6 +1799,11 @@ static int storvsc_probe(struct hv_device *device, · 124 unmodified lines | ||
| 1680 | 1799 | * from the host. |
| 1681 | 1800 | */ |
| 1682 | 1801 | host->sg_tablesize = (stor_device->max_transfer_bytes >> PAGE_SHIFT); |
| 1802 | + /* | |
| 1803 | + * Set the number of HW queues we are supporting. | |
| 1804 | + */ | |
| 1805 | + if (stor_device->num_sc != 0) | |
| 1806 | + host->nr_hw_queues = stor_device->num_sc + 1; | |
| 1683 | 1807 | |
| 1684 | 1808 | /* Register the HBA and start the scsi bus scan */ |
| 1685 | 1809 | ret = scsi_add_host(host, &device->device); |
| @@ -1716,6 +1840,7 @@ err_out2: · 30 unmodified lines | ||
| 1716 | 1840 | goto err_out0; |
| 1717 | 1841 | |
| 1718 | 1842 | err_out1: |
| 1843 | + kfree(stor_device->stor_chns); | |
| 1719 | 1844 | kfree(stor_device); |
| 1720 | 1845 | |
| 1721 | 1846 | err_out0: |
| @@ -1774,11 +1899,6 @@ static int __init storvsc_drv_init(void) · 52 unmodified lines | ||
| 1774 | 1899 | fc_transport_template = fc_attach_transport(&fc_transport_functions); |
| 1775 | 1900 | if (!fc_transport_template) |
| 1776 | 1901 | return -ENODEV; |
| 1777 | − | |
| 1778 | − /* | |
| 1779 | − * Install Hyper-V specific timeout handler. | |
| 1780 | − */ | |
| 1781 | − fc_transport_template->eh_timed_out = storvsc_eh_timed_out; | |
| 1782 | 1902 | #endif |
| 1783 | 1903 | |
| 1784 | 1904 | ret = vmbus_driver_register(&storvsc_drv); |
| @@ -34,7 +34,6 @@ · 33 unmodified lines | ||
| 34 | 34 | #include <asm/dvma.h> |
| 35 | 35 | |
| 36 | 36 | #include <scsi/scsi_host.h> |
| 37 | −#include "sun3_scsi.h" | |
| 38 | 37 | |
| 39 | 38 | /* minimum number of bytes to do dma on */ |
| 40 | 39 | #define DMA_MIN_SIZE 129 |
| @@ -56,11 +55,87 @@ · 15 unmodified lines | ||
| 56 | 55 | #define NCR5380_dma_send_setup sun3scsi_dma_count |
| 57 | 56 | #define NCR5380_dma_residual sun3scsi_dma_residual |
| 58 | 57 | |
| 59 | −#define NCR5380_acquire_dma_irq(instance) (1) | |
| 60 | −#define NCR5380_release_dma_irq(instance) | |
| 61 | − | |
| 62 | 58 | #include "NCR5380.h" |
| 63 | 59 | |
| 60 | +/* dma regs start at regbase + 8, directly after the NCR regs */ | |
| 61 | +struct sun3_dma_regs { | |
| 62 | + unsigned short dma_addr_hi; /* vme only */ | |
| 63 | + unsigned short dma_addr_lo; /* vme only */ | |
| 64 | + unsigned short dma_count_hi; /* vme only */ | |
| 65 | + unsigned short dma_count_lo; /* vme only */ | |
| 66 | + unsigned short udc_data; /* udc dma data reg (obio only) */ | |
| 67 | + unsigned short udc_addr; /* uda dma addr reg (obio only) */ | |
| 68 | + unsigned short fifo_data; /* fifo data reg, | |
| 69 | + * holds extra byte on odd dma reads | |
| 70 | + */ | |
| 71 | + unsigned short fifo_count; | |
| 72 | + unsigned short csr; /* control/status reg */ | |
| 73 | + unsigned short bpack_hi; /* vme only */ | |
| 74 | + unsigned short bpack_lo; /* vme only */ | |
| 75 | + unsigned short ivect; /* vme only */ | |
| 76 | + unsigned short fifo_count_hi; /* vme only */ | |
| 77 | +}; | |
| 78 | + | |
| 79 | +/* ucd chip specific regs - live in dvma space */ | |
| 80 | +struct sun3_udc_regs { | |
| 81 | + unsigned short rsel; /* select regs to load */ | |
| 82 | + unsigned short addr_hi; /* high word of addr */ | |
| 83 | + unsigned short addr_lo; /* low word */ | |
| 84 | + unsigned short count; /* words to be xfer'd */ | |
| 85 | + unsigned short mode_hi; /* high word of channel mode */ | |
| 86 | + unsigned short mode_lo; /* low word of channel mode */ | |
| 87 | +}; | |
| 88 | + | |
| 89 | +/* addresses of the udc registers */ | |
| 90 | +#define UDC_MODE 0x38 | |
| 91 | +#define UDC_CSR 0x2e /* command/status */ | |
| 92 | +#define UDC_CHN_HI 0x26 /* chain high word */ | |
| 93 | +#define UDC_CHN_LO 0x22 /* chain lo word */ | |
| 94 | +#define UDC_CURA_HI 0x1a /* cur reg A high */ | |
| 95 | +#define UDC_CURA_LO 0x0a /* cur reg A low */ | |
| 96 | +#define UDC_CURB_HI 0x12 /* cur reg B high */ | |
| 97 | +#define UDC_CURB_LO 0x02 /* cur reg B low */ | |
| 98 | +#define UDC_MODE_HI 0x56 /* mode reg high */ | |
| 99 | +#define UDC_MODE_LO 0x52 /* mode reg low */ | |
| 100 | +#define UDC_COUNT 0x32 /* words to xfer */ | |
| 101 | + | |
| 102 | +/* some udc commands */ | |
| 103 | +#define UDC_RESET 0 | |
| 104 | +#define UDC_CHN_START 0xa0 /* start chain */ | |
| 105 | +#define UDC_INT_ENABLE 0x32 /* channel 1 int on */ | |
| 106 | + | |
| 107 | +/* udc mode words */ | |
| 108 | +#define UDC_MODE_HIWORD 0x40 | |
| 109 | +#define UDC_MODE_LSEND 0xc2 | |
| 110 | +#define UDC_MODE_LRECV 0xd2 | |
| 111 | + | |
| 112 | +/* udc reg selections */ | |
| 113 | +#define UDC_RSEL_SEND 0x282 | |
| 114 | +#define UDC_RSEL_RECV 0x182 | |
| 115 | + | |
| 116 | +/* bits in csr reg */ | |
| 117 | +#define CSR_DMA_ACTIVE 0x8000 | |
| 118 | +#define CSR_DMA_CONFLICT 0x4000 | |
| 119 | +#define CSR_DMA_BUSERR 0x2000 | |
| 120 | + | |
| 121 | +#define CSR_FIFO_EMPTY 0x400 /* fifo flushed? */ | |
| 122 | +#define CSR_SDB_INT 0x200 /* sbc interrupt pending */ | |
| 123 | +#define CSR_DMA_INT 0x100 /* dma interrupt pending */ | |
| 124 | + | |
| 125 | +#define CSR_LEFT 0xc0 | |
| 126 | +#define CSR_LEFT_3 0xc0 | |
| 127 | +#define CSR_LEFT_2 0x80 | |
| 128 | +#define CSR_LEFT_1 0x40 | |
| 129 | +#define CSR_PACK_ENABLE 0x20 | |
| 130 | + | |
| 131 | +#define CSR_DMA_ENABLE 0x10 | |
| 132 | + | |
| 133 | +#define CSR_SEND 0x8 /* 1 = send 0 = recv */ | |
| 134 | +#define CSR_FIFO 0x2 /* reset fifo */ | |
| 135 | +#define CSR_INTR 0x4 /* interrupt enable */ | |
| 136 | +#define CSR_SCSI 0x1 | |
| 137 | + | |
| 138 | +#define VME_DATA24 0x3d00 | |
| 64 | 139 | |
| 65 | 140 | extern int sun3_map_test(unsigned long, char *); |
| 66 | 141 | |
| @@ -1,102 +0,0 @@ | ||
| 1 | −/* | |
| 2 | − * Sun3 SCSI stuff by Erik Verbruggen (erik@bigmama.xtdnet.nl) | |
| 3 | − * | |
| 4 | − * Sun3 DMA additions by Sam Creasey (sammy@sammy.net) | |
| 5 | − * | |
| 6 | − * Adapted from mac_scsinew.h: | |
| 7 | − */ | |
| 8 | −/* | |
| 9 | − * Cumana Generic NCR5380 driver defines | |
| 10 | − * | |
| 11 | − * Copyright 1993, Drew Eckhardt | |
| 12 | − * Visionary Computing | |
| 13 | − * (Unix and Linux consulting and custom programming) | |
| 14 | − * drew@colorado.edu | |
| 15 | − * +1 (303) 440-4894 | |
| 16 | − */ | |
| 17 | − | |
| 18 | −#ifndef SUN3_SCSI_H | |
| 19 | −#define SUN3_SCSI_H | |
| 20 | − | |
| 21 | −/* additional registers - mainly DMA control regs */ | |
| 22 | −/* these start at regbase + 8 -- directly after the NCR regs */ | |
| 23 | −struct sun3_dma_regs { | |
| 24 | − unsigned short dma_addr_hi; /* vme only */ | |
| 25 | − unsigned short dma_addr_lo; /* vme only */ | |
| 26 | − unsigned short dma_count_hi; /* vme only */ | |
| 27 | − unsigned short dma_count_lo; /* vme only */ | |
| 28 | − unsigned short udc_data; /* udc dma data reg (obio only) */ | |
| 29 | − unsigned short udc_addr; /* uda dma addr reg (obio only) */ | |
| 30 | − unsigned short fifo_data; /* fifo data reg, holds extra byte on | |
| 31 | − odd dma reads */ | |
| 32 | − unsigned short fifo_count; | |
| 33 | − unsigned short csr; /* control/status reg */ | |
| 34 | − unsigned short bpack_hi; /* vme only */ | |
| 35 | − unsigned short bpack_lo; /* vme only */ | |
| 36 | − unsigned short ivect; /* vme only */ | |
| 37 | − unsigned short fifo_count_hi; /* vme only */ | |
| 38 | −}; | |
| 39 | − | |
| 40 | −/* ucd chip specific regs - live in dvma space */ | |
| 41 | −struct sun3_udc_regs { | |
| 42 | − unsigned short rsel; /* select regs to load */ | |
| 43 | − unsigned short addr_hi; /* high word of addr */ | |
| 44 | − unsigned short addr_lo; /* low word */ | |
| 45 | − unsigned short count; /* words to be xfer'd */ | |
| 46 | − unsigned short mode_hi; /* high word of channel mode */ | |
| 47 | − unsigned short mode_lo; /* low word of channel mode */ | |
| 48 | −}; | |
| 49 | − | |
| 50 | −/* addresses of the udc registers */ | |
| 51 | −#define UDC_MODE 0x38 | |
| 52 | −#define UDC_CSR 0x2e /* command/status */ | |
| 53 | −#define UDC_CHN_HI 0x26 /* chain high word */ | |
| 54 | −#define UDC_CHN_LO 0x22 /* chain lo word */ | |
| 55 | −#define UDC_CURA_HI 0x1a /* cur reg A high */ | |
| 56 | −#define UDC_CURA_LO 0x0a /* cur reg A low */ | |
| 57 | −#define UDC_CURB_HI 0x12 /* cur reg B high */ | |
| 58 | −#define UDC_CURB_LO 0x02 /* cur reg B low */ | |
| 59 | −#define UDC_MODE_HI 0x56 /* mode reg high */ | |
| 60 | −#define UDC_MODE_LO 0x52 /* mode reg low */ | |
| 61 | −#define UDC_COUNT 0x32 /* words to xfer */ | |
| 62 | − | |
| 63 | −/* some udc commands */ | |
| 64 | −#define UDC_RESET 0 | |
| 65 | −#define UDC_CHN_START 0xa0 /* start chain */ | |
| 66 | −#define UDC_INT_ENABLE 0x32 /* channel 1 int on */ | |
| 67 | − | |
| 68 | −/* udc mode words */ | |
| 69 | −#define UDC_MODE_HIWORD 0x40 | |
| 70 | −#define UDC_MODE_LSEND 0xc2 | |
| 71 | −#define UDC_MODE_LRECV 0xd2 | |
| 72 | − | |
| 73 | −/* udc reg selections */ | |
| 74 | −#define UDC_RSEL_SEND 0x282 | |
| 75 | −#define UDC_RSEL_RECV 0x182 | |
| 76 | − | |
| 77 | −/* bits in csr reg */ | |
| 78 | −#define CSR_DMA_ACTIVE 0x8000 | |
| 79 | −#define CSR_DMA_CONFLICT 0x4000 | |
| 80 | −#define CSR_DMA_BUSERR 0x2000 | |
| 81 | − | |
| 82 | −#define CSR_FIFO_EMPTY 0x400 /* fifo flushed? */ | |
| 83 | −#define CSR_SDB_INT 0x200 /* sbc interrupt pending */ | |
| 84 | −#define CSR_DMA_INT 0x100 /* dma interrupt pending */ | |
| 85 | − | |
| 86 | −#define CSR_LEFT 0xc0 | |
| 87 | −#define CSR_LEFT_3 0xc0 | |
| 88 | −#define CSR_LEFT_2 0x80 | |
| 89 | −#define CSR_LEFT_1 0x40 | |
| 90 | −#define CSR_PACK_ENABLE 0x20 | |
| 91 | − | |
| 92 | −#define CSR_DMA_ENABLE 0x10 | |
| 93 | − | |
| 94 | −#define CSR_SEND 0x8 /* 1 = send 0 = recv */ | |
| 95 | −#define CSR_FIFO 0x2 /* reset fifo */ | |
| 96 | −#define CSR_INTR 0x4 /* interrupt enable */ | |
| 97 | −#define CSR_SCSI 0x1 | |
| 98 | − | |
| 99 | −#define VME_DATA24 0x3d00 | |
| 100 | − | |
| 101 | −#endif /* SUN3_SCSI_H */ | |
| 102 | − | |
| @@ -1497,17 +1497,21 @@ static void ufs_qcom_print_hw_debug_reg_all(struct ufs_hba *hba, · 1496 unmodified lines | ||
| 1497 | 1497 | |
| 1498 | 1498 | static void ufs_qcom_enable_test_bus(struct ufs_qcom_host *host) |
| 1499 | 1499 | { |
| 1500 | − if (host->dbg_print_en & UFS_QCOM_DBG_PRINT_TEST_BUS_EN) | |
| 1500 | + if (host->dbg_print_en & UFS_QCOM_DBG_PRINT_TEST_BUS_EN) { | |
| 1501 | + ufshcd_rmwl(host->hba, UFS_REG_TEST_BUS_EN, | |
| 1502 | + UFS_REG_TEST_BUS_EN, REG_UFS_CFG1); | |
| 1501 | 1503 | ufshcd_rmwl(host->hba, TEST_BUS_EN, TEST_BUS_EN, REG_UFS_CFG1); |
| 1502 | − else | |
| 1504 | + } else { | |
| 1505 | + ufshcd_rmwl(host->hba, UFS_REG_TEST_BUS_EN, 0, REG_UFS_CFG1); | |
| 1503 | 1506 | ufshcd_rmwl(host->hba, TEST_BUS_EN, 0, REG_UFS_CFG1); |
| 1507 | + } | |
| 1504 | 1508 | } |
| 1505 | 1509 | |
| 1506 | 1510 | static void ufs_qcom_get_default_testbus_cfg(struct ufs_qcom_host *host) |
| 1507 | 1511 | { |
| 1508 | 1512 | /* provide a legal default configuration */ |
| 1509 | − host->testbus.select_major = TSTBUS_UAWM; | |
| 1510 | − host->testbus.select_minor = 1; | |
| 1513 | + host->testbus.select_major = TSTBUS_UNIPRO; | |
| 1514 | + host->testbus.select_minor = 37; | |
| 1511 | 1515 | } |
| 1512 | 1516 | |
| 1513 | 1517 | static bool ufs_qcom_testbus_cfg_is_ok(struct ufs_qcom_host *host) |
| @@ -1524,7 +1528,7 @@ static bool ufs_qcom_testbus_cfg_is_ok(struct ufs_qcom_host *host) · 10 unmodified lines | ||
| 1524 | 1528 | * mappings of select_minor, since there is no harm in |
| 1525 | 1529 | * configuring a non-existent select_minor |
| 1526 | 1530 | */ |
| 1527 | − if (host->testbus.select_minor > 0x1F) { | |
| 1531 | + if (host->testbus.select_minor > 0xFF) { | |
| 1528 | 1532 | dev_err(host->hba->dev, |
| 1529 | 1533 | "%s: 0x%05X is not a legal testbus option\n", |
| 1530 | 1534 | __func__, host->testbus.select_minor); |
| @@ -1593,7 +1597,8 @@ int ufs_qcom_testbus_config(struct ufs_qcom_host *host) · 62 unmodified lines | ||
| 1593 | 1597 | break; |
| 1594 | 1598 | case TSTBUS_UNIPRO: |
| 1595 | 1599 | reg = UFS_UNIPRO_CFG; |
| 1596 | − offset = 1; | |
| 1600 | + offset = 20; | |
| 1601 | + mask = 0xFFF; | |
| 1597 | 1602 | break; |
| 1598 | 1603 | /* |
| 1599 | 1604 | * No need for a default case, since |
| @@ -1612,6 +1617,11 @@ int ufs_qcom_testbus_config(struct ufs_qcom_host *host) · 12 unmodified lines | ||
| 1612 | 1617 | (u32)host->testbus.select_minor << offset, |
| 1613 | 1618 | reg); |
| 1614 | 1619 | ufs_qcom_enable_test_bus(host); |
| 1620 | + /* | |
| 1621 | + * Make sure the test bus configuration is | |
| 1622 | + * committed before returning. | |
| 1623 | + */ | |
| 1624 | + mb(); | |
| 1615 | 1625 | ufshcd_release(host->hba); |
| 1616 | 1626 | pm_runtime_put_sync(host->hba->dev); |
| 1617 | 1627 | |
| @@ -1623,13 +1633,39 @@ static void ufs_qcom_testbus_read(struct ufs_hba *hba) · 5 unmodified lines | ||
| 1623 | 1633 | ufs_qcom_dump_regs(hba, UFS_TEST_BUS, 1, "UFS_TEST_BUS "); |
| 1624 | 1634 | } |
| 1625 | 1635 | |
| 1636 | +static void ufs_qcom_print_unipro_testbus(struct ufs_hba *hba) | |
| 1637 | +{ | |
| 1638 | + struct ufs_qcom_host *host = ufshcd_get_variant(hba); | |
| 1639 | + u32 *testbus = NULL; | |
| 1640 | + int i, nminor = 256, testbus_len = nminor * sizeof(u32); | |
| 1641 | + | |
| 1642 | + testbus = kmalloc(testbus_len, GFP_KERNEL); | |
| 1643 | + if (!testbus) | |
| 1644 | + return; | |
| 1645 | + | |
| 1646 | + host->testbus.select_major = TSTBUS_UNIPRO; | |
| 1647 | + for (i = 0; i < nminor; i++) { | |
| 1648 | + host->testbus.select_minor = i; | |
| 1649 | + ufs_qcom_testbus_config(host); | |
| 1650 | + testbus[i] = ufshcd_readl(hba, UFS_TEST_BUS); | |
| 1651 | + } | |
| 1652 | + print_hex_dump(KERN_ERR, "UNIPRO_TEST_BUS ", DUMP_PREFIX_OFFSET, | |
| 1653 | + 16, 4, testbus, testbus_len, false); | |
| 1654 | + kfree(testbus); | |
| 1655 | +} | |
| 1656 | + | |
| 1626 | 1657 | static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba) |
| 1627 | 1658 | { |
| 1628 | 1659 | ufs_qcom_dump_regs(hba, REG_UFS_SYS1CLK_1US, 16, |
| 1629 | 1660 | "HCI Vendor Specific Registers "); |
| 1630 | 1661 | |
| 1662 | + /* sleep a bit intermittently as we are dumping too much data */ | |
| 1631 | 1663 | ufs_qcom_print_hw_debug_reg_all(hba, NULL, ufs_qcom_dump_regs_wrapper); |
| 1664 | + usleep_range(1000, 1100); | |
| 1632 | 1665 | ufs_qcom_testbus_read(hba); |
| 1666 | + usleep_range(1000, 1100); | |
| 1667 | + ufs_qcom_print_unipro_testbus(hba); | |
| 1668 | + usleep_range(1000, 1100); | |
| 1633 | 1669 | } |
| 1634 | 1670 | |
| 1635 | 1671 | /** |
| @@ -1692,6 +1728,7 @@ static const struct of_device_id ufs_qcom_of_match[] = { · 56 unmodified lines | ||
| 1692 | 1728 | { .compatible = "qcom,ufshc"}, |
| 1693 | 1729 | {}, |
| 1694 | 1730 | }; |
| 1731 | +MODULE_DEVICE_TABLE(of, ufs_qcom_of_match); | |
| 1695 | 1732 | |
| 1696 | 1733 | static const struct dev_pm_ops ufs_qcom_pm_ops = { |
| 1697 | 1734 | .suspend = ufshcd_pltfrm_suspend, |
| @@ -95,6 +95,7 @@ enum { · 94 unmodified lines | ||
| 95 | 95 | #define QUNIPRO_SEL UFS_BIT(0) |
| 96 | 96 | #define TEST_BUS_EN BIT(18) |
| 97 | 97 | #define TEST_BUS_SEL GENMASK(22, 19) |
| 98 | +#define UFS_REG_TEST_BUS_EN BIT(30) | |
| 98 | 99 | |
| 99 | 100 | /* bit definitions for REG_UFS_CFG2 register */ |
| 100 | 101 | #define UAWM_HW_CGC_EN (1 << 0) |
| @@ -523,4 +523,16 @@ struct ufs_dev_info { · 522 unmodified lines | ||
| 523 | 523 | bool is_lu_power_on_wp; |
| 524 | 524 | }; |
| 525 | 525 | |
| 526 | +#define MAX_MODEL_LEN 16 | |
| 527 | +/** | |
| 528 | + * ufs_dev_desc - ufs device details from the device descriptor | |
| 529 | + * | |
| 530 | + * @wmanufacturerid: card details | |
| 531 | + * @model: card model | |
| 532 | + */ | |
| 533 | +struct ufs_dev_desc { | |
| 534 | + u16 wmanufacturerid; | |
| 535 | + char model[MAX_MODEL_LEN + 1]; | |
| 536 | +}; | |
| 537 | + | |
| 526 | 538 | #endif /* End of Header */ |
| @@ -21,41 +21,28 @@ · 20 unmodified lines | ||
| 21 | 21 | #define UFS_ANY_VENDOR 0xFFFF |
| 22 | 22 | #define UFS_ANY_MODEL "ANY_MODEL" |
| 23 | 23 | |
| 24 | −#define MAX_MODEL_LEN 16 | |
| 25 | − | |
| 26 | 24 | #define UFS_VENDOR_TOSHIBA 0x198 |
| 27 | 25 | #define UFS_VENDOR_SAMSUNG 0x1CE |
| 28 | 26 | #define UFS_VENDOR_SKHYNIX 0x1AD |
| 29 | 27 | |
| 30 | −/** | |
| 31 | − * ufs_device_info - ufs device details | |
| 32 | − * @wmanufacturerid: card details | |
| 33 | − * @model: card model | |
| 34 | − */ | |
| 35 | −struct ufs_device_info { | |
| 36 | − u16 wmanufacturerid; | |
| 37 | − char model[MAX_MODEL_LEN + 1]; | |
| 38 | −}; | |
| 39 | − | |
| 40 | 28 | /** |
| 41 | 29 | * ufs_dev_fix - ufs device quirk info |
| 42 | 30 | * @card: ufs card details |
| 43 | 31 | * @quirk: device quirk |
| 44 | 32 | */ |
| 45 | 33 | struct ufs_dev_fix { |
| 46 | − struct ufs_device_info card; | |
| 34 | + struct ufs_dev_desc card; | |
| 47 | 35 | unsigned int quirk; |
| 48 | 36 | }; |
| 49 | 37 | |
| 50 | 38 | #define END_FIX { { 0 }, 0 } |
| 51 | 39 | |
| 52 | 40 | /* add specific device quirk */ |
| 53 | −#define UFS_FIX(_vendor, _model, _quirk) \ | |
| 54 | − { \ | |
| 55 | − .card.wmanufacturerid = (_vendor),\ | |
| 56 | − .card.model = (_model), \ | |
| 57 | − .quirk = (_quirk), \ | |
| 58 | − } | |
| 41 | +#define UFS_FIX(_vendor, _model, _quirk) { \ | |
| 42 | + .card.wmanufacturerid = (_vendor),\ | |
| 43 | + .card.model = (_model), \ | |
| 44 | + .quirk = (_quirk), \ | |
| 45 | +} | |
| 59 | 46 | |
| 60 | 47 | /* |
| 61 | 48 | * If UFS device is having issue in processing LCC (Line Control |
| @@ -144,7 +131,4 @@ struct ufs_dev_fix { · 82 unmodified lines | ||
| 144 | 131 | */ |
| 145 | 132 | #define UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME (1 << 8) |
| 146 | 133 | |
| 147 | −struct ufs_hba; | |
| 148 | −void ufs_advertise_fixup_device(struct ufs_hba *hba); | |
| 149 | − | |
| 150 | 134 | #endif /* UFS_QUIRKS_H_ */ |
| @@ -45,6 +45,9 @@ · 44 unmodified lines | ||
| 45 | 45 | #include "ufs_quirks.h" |
| 46 | 46 | #include "unipro.h" |
| 47 | 47 | |
| 48 | +#define CREATE_TRACE_POINTS | |
| 49 | +#include <trace/events/ufs.h> | |
| 50 | + | |
| 48 | 51 | #define UFSHCD_REQ_SENSE_SIZE 18 |
| 49 | 52 | |
| 50 | 53 | #define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ |
| @@ -94,6 +97,9 @@ · 43 unmodified lines | ||
| 94 | 97 | _ret; \ |
| 95 | 98 | }) |
| 96 | 99 | |
| 100 | +#define ufshcd_hex_dump(prefix_str, buf, len) \ | |
| 101 | +print_hex_dump(KERN_ERR, prefix_str, DUMP_PREFIX_OFFSET, 16, 4, buf, len, false) | |
| 102 | + | |
| 97 | 103 | static u32 ufs_query_desc_max_size[] = { |
| 98 | 104 | QUERY_DESC_DEVICE_MAX_SIZE, |
| 99 | 105 | QUERY_DESC_CONFIGURAION_MAX_SIZE, |
| @@ -185,6 +191,22 @@ ufs_get_pm_lvl_to_link_pwr_state(enum ufs_pm_level lvl) · 85 unmodified lines | ||
| 185 | 191 | return ufs_pm_lvl_states[lvl].link_state; |
| 186 | 192 | } |
| 187 | 193 | |
| 194 | +static inline enum ufs_pm_level | |
| 195 | +ufs_get_desired_pm_lvl_for_dev_link_state(enum ufs_dev_pwr_mode dev_state, | |
| 196 | + enum uic_link_state link_state) | |
| 197 | +{ | |
| 198 | + enum ufs_pm_level lvl; | |
| 199 | + | |
| 200 | + for (lvl = UFS_PM_LVL_0; lvl < UFS_PM_LVL_MAX; lvl++) { | |
| 201 | + if ((ufs_pm_lvl_states[lvl].dev_state == dev_state) && | |
| 202 | + (ufs_pm_lvl_states[lvl].link_state == link_state)) | |
| 203 | + return lvl; | |
| 204 | + } | |
| 205 | + | |
| 206 | + /* if no match found, return the level 0 */ | |
| 207 | + return UFS_PM_LVL_0; | |
| 208 | +} | |
| 209 | + | |
| 188 | 210 | static struct ufs_dev_fix ufs_fixups[] = { |
| 189 | 211 | /* UFS cards deviations table */ |
| 190 | 212 | UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL, |
| @@ -212,6 +234,7 @@ static struct ufs_dev_fix ufs_fixups[] = { · 21 unmodified lines | ||
| 212 | 234 | static void ufshcd_tmc_handler(struct ufs_hba *hba); |
| 213 | 235 | static void ufshcd_async_scan(void *data, async_cookie_t cookie); |
| 214 | 236 | static int ufshcd_reset_and_restore(struct ufs_hba *hba); |
| 237 | +static int ufshcd_eh_host_reset_handler(struct scsi_cmnd *cmd); | |
| 215 | 238 | static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag); |
| 216 | 239 | static void ufshcd_hba_exit(struct ufs_hba *hba); |
| 217 | 240 | static int ufshcd_probe_hba(struct ufs_hba *hba); |
| @@ -223,6 +246,10 @@ static int ufshcd_uic_hibern8_exit(struct ufs_hba *hba); · 5 unmodified lines | ||
| 223 | 246 | static int ufshcd_uic_hibern8_enter(struct ufs_hba *hba); |
| 224 | 247 | static inline void ufshcd_add_delay_before_dme_cmd(struct ufs_hba *hba); |
| 225 | 248 | static int ufshcd_host_reset_and_restore(struct ufs_hba *hba); |
| 249 | +static void ufshcd_resume_clkscaling(struct ufs_hba *hba); | |
| 250 | +static void ufshcd_suspend_clkscaling(struct ufs_hba *hba); | |
| 251 | +static void __ufshcd_suspend_clkscaling(struct ufs_hba *hba); | |
| 252 | +static int ufshcd_scale_clks(struct ufs_hba *hba, bool scale_up); | |
| 226 | 253 | static irqreturn_t ufshcd_intr(int irq, void *__hba); |
| 227 | 254 | static int ufshcd_config_pwr_mode(struct ufs_hba *hba, |
| 228 | 255 | struct ufs_pa_layer_attr *desired_pwr_mode); |
| @@ -267,6 +294,214 @@ static inline void ufshcd_remove_non_printable(char *val) · 38 unmodified lines | ||
| 267 | 294 | *val = ' '; |
| 268 | 295 | } |
| 269 | 296 | |
| 297 | +static void ufshcd_add_command_trace(struct ufs_hba *hba, | |
| 298 | + unsigned int tag, const char *str) | |
| 299 | +{ | |
| 300 | + sector_t lba = -1; | |
| 301 | + u8 opcode = 0; | |
| 302 | + u32 intr, doorbell; | |
| 303 | + struct ufshcd_lrb *lrbp; | |
| 304 | + int transfer_len = -1; | |
| 305 | + | |
| 306 | + if (!trace_ufshcd_command_enabled()) | |
| 307 | + return; | |
| 308 | + | |
| 309 | + lrbp = &hba->lrb[tag]; | |
| 310 | + | |
| 311 | + if (lrbp->cmd) { /* data phase exists */ | |
| 312 | + opcode = (u8)(*lrbp->cmd->cmnd); | |
| 313 | + if ((opcode == READ_10) || (opcode == WRITE_10)) { | |
| 314 | + /* | |
| 315 | + * Currently we only fully trace read(10) and write(10) | |
| 316 | + * commands | |
| 317 | + */ | |
| 318 | + if (lrbp->cmd->request && lrbp->cmd->request->bio) | |
| 319 | + lba = | |
| 320 | + lrbp->cmd->request->bio->bi_iter.bi_sector; | |
| 321 | + transfer_len = be32_to_cpu( | |
| 322 | + lrbp->ucd_req_ptr->sc.exp_data_transfer_len); | |
| 323 | + } | |
| 324 | + } | |
| 325 | + | |
| 326 | + intr = ufshcd_readl(hba, REG_INTERRUPT_STATUS); | |
| 327 | + doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); | |
| 328 | + trace_ufshcd_command(dev_name(hba->dev), str, tag, | |
| 329 | + doorbell, transfer_len, intr, lba, opcode); | |
| 330 | +} | |
| 331 | + | |
| 332 | +static void ufshcd_print_clk_freqs(struct ufs_hba *hba) | |
| 333 | +{ | |
| 334 | + struct ufs_clk_info *clki; | |
| 335 | + struct list_head *head = &hba->clk_list_head; | |
| 336 | + | |
| 337 | + if (!head || list_empty(head)) | |
| 338 | + return; | |
| 339 | + | |
| 340 | + list_for_each_entry(clki, head, list) { | |
| 341 | + if (!IS_ERR_OR_NULL(clki->clk) && clki->min_freq && | |
| 342 | + clki->max_freq) | |
| 343 | + dev_err(hba->dev, "clk: %s, rate: %u\n", | |
| 344 | + clki->name, clki->curr_freq); | |
| 345 | + } | |
| 346 | +} | |
| 347 | + | |
| 348 | +static void ufshcd_print_uic_err_hist(struct ufs_hba *hba, | |
| 349 | + struct ufs_uic_err_reg_hist *err_hist, char *err_name) | |
| 350 | +{ | |
| 351 | + int i; | |
| 352 | + | |
| 353 | + for (i = 0; i < UIC_ERR_REG_HIST_LENGTH; i++) { | |
| 354 | + int p = (i + err_hist->pos - 1) % UIC_ERR_REG_HIST_LENGTH; | |
| 355 | + | |
| 356 | + if (err_hist->reg[p] == 0) | |
| 357 | + continue; | |
| 358 | + dev_err(hba->dev, "%s[%d] = 0x%x at %lld us\n", err_name, i, | |
| 359 | + err_hist->reg[p], ktime_to_us(err_hist->tstamp[p])); | |
| 360 | + } | |
| 361 | +} | |
| 362 | + | |
| 363 | +static void ufshcd_print_host_regs(struct ufs_hba *hba) | |
| 364 | +{ | |
| 365 | + /* | |
| 366 | + * hex_dump reads its data without the readl macro. This might | |
| 367 | + * cause inconsistency issues on some platform, as the printed | |
| 368 | + * values may be from cache and not the most recent value. | |
| 369 | + * To know whether you are looking at an un-cached version verify | |
| 370 | + * that IORESOURCE_MEM flag is on when xxx_get_resource() is invoked | |
| 371 | + * during platform/pci probe function. | |
| 372 | + */ | |
| 373 | + ufshcd_hex_dump("host regs: ", hba->mmio_base, UFSHCI_REG_SPACE_SIZE); | |
| 374 | + dev_err(hba->dev, "hba->ufs_version = 0x%x, hba->capabilities = 0x%x\n", | |
| 375 | + hba->ufs_version, hba->capabilities); | |
| 376 | + dev_err(hba->dev, | |
| 377 | + "hba->outstanding_reqs = 0x%x, hba->outstanding_tasks = 0x%x\n", | |
| 378 | + (u32)hba->outstanding_reqs, (u32)hba->outstanding_tasks); | |
| 379 | + dev_err(hba->dev, | |
| 380 | + "last_hibern8_exit_tstamp at %lld us, hibern8_exit_cnt = %d\n", | |
| 381 | + ktime_to_us(hba->ufs_stats.last_hibern8_exit_tstamp), | |
| 382 | + hba->ufs_stats.hibern8_exit_cnt); | |
| 383 | + | |
| 384 | + ufshcd_print_uic_err_hist(hba, &hba->ufs_stats.pa_err, "pa_err"); | |
| 385 | + ufshcd_print_uic_err_hist(hba, &hba->ufs_stats.dl_err, "dl_err"); | |
| 386 | + ufshcd_print_uic_err_hist(hba, &hba->ufs_stats.nl_err, "nl_err"); | |
| 387 | + ufshcd_print_uic_err_hist(hba, &hba->ufs_stats.tl_err, "tl_err"); | |
| 388 | + ufshcd_print_uic_err_hist(hba, &hba->ufs_stats.dme_err, "dme_err"); | |
| 389 | + | |
| 390 | + ufshcd_print_clk_freqs(hba); | |
| 391 | + | |
| 392 | + if (hba->vops && hba->vops->dbg_register_dump) | |
| 393 | + hba->vops->dbg_register_dump(hba); | |
| 394 | +} | |
| 395 | + | |
| 396 | +static | |
| 397 | +void ufshcd_print_trs(struct ufs_hba *hba, unsigned long bitmap, bool pr_prdt) | |
| 398 | +{ | |
| 399 | + struct ufshcd_lrb *lrbp; | |
| 400 | + int prdt_length; | |
| 401 | + int tag; | |
| 402 | + | |
| 403 | + for_each_set_bit(tag, &bitmap, hba->nutrs) { | |
| 404 | + lrbp = &hba->lrb[tag]; | |
| 405 | + | |
| 406 | + dev_err(hba->dev, "UPIU[%d] - issue time %lld us\n", | |
| 407 | + tag, ktime_to_us(lrbp->issue_time_stamp)); | |
| 408 | + dev_err(hba->dev, | |
| 409 | + "UPIU[%d] - Transfer Request Descriptor phys@0x%llx\n", | |
| 410 | + tag, (u64)lrbp->utrd_dma_addr); | |
| 411 | + | |
| 412 | + ufshcd_hex_dump("UPIU TRD: ", lrbp->utr_descriptor_ptr, | |
| 413 | + sizeof(struct utp_transfer_req_desc)); | |
| 414 | + dev_err(hba->dev, "UPIU[%d] - Request UPIU phys@0x%llx\n", tag, | |
| 415 | + (u64)lrbp->ucd_req_dma_addr); | |
| 416 | + ufshcd_hex_dump("UPIU REQ: ", lrbp->ucd_req_ptr, | |
| 417 | + sizeof(struct utp_upiu_req)); | |
| 418 | + dev_err(hba->dev, "UPIU[%d] - Response UPIU phys@0x%llx\n", tag, | |
| 419 | + (u64)lrbp->ucd_rsp_dma_addr); | |
| 420 | + ufshcd_hex_dump("UPIU RSP: ", lrbp->ucd_rsp_ptr, | |
| 421 | + sizeof(struct utp_upiu_rsp)); | |
| 422 | + | |
| 423 | + prdt_length = le16_to_cpu( | |
| 424 | + lrbp->utr_descriptor_ptr->prd_table_length); | |
| 425 | + dev_err(hba->dev, | |
| 426 | + "UPIU[%d] - PRDT - %d entries phys@0x%llx\n", | |
| 427 | + tag, prdt_length, | |
| 428 | + (u64)lrbp->ucd_prdt_dma_addr); | |
| 429 | + | |
| 430 | + if (pr_prdt) | |
| 431 | + ufshcd_hex_dump("UPIU PRDT: ", lrbp->ucd_prdt_ptr, | |
| 432 | + sizeof(struct ufshcd_sg_entry) * prdt_length); | |
| 433 | + } | |
| 434 | +} | |
| 435 | + | |
| 436 | +static void ufshcd_print_tmrs(struct ufs_hba *hba, unsigned long bitmap) | |
| 437 | +{ | |
| 438 | + struct utp_task_req_desc *tmrdp; | |
| 439 | + int tag; | |
| 440 | + | |
| 441 | + for_each_set_bit(tag, &bitmap, hba->nutmrs) { | |
| 442 | + tmrdp = &hba->utmrdl_base_addr[tag]; | |
| 443 | + dev_err(hba->dev, "TM[%d] - Task Management Header\n", tag); | |
| 444 | + ufshcd_hex_dump("TM TRD: ", &tmrdp->header, | |
| 445 | + sizeof(struct request_desc_header)); | |
| 446 | + dev_err(hba->dev, "TM[%d] - Task Management Request UPIU\n", | |
| 447 | + tag); | |
| 448 | + ufshcd_hex_dump("TM REQ: ", tmrdp->task_req_upiu, | |
| 449 | + sizeof(struct utp_upiu_req)); | |
| 450 | + dev_err(hba->dev, "TM[%d] - Task Management Response UPIU\n", | |
| 451 | + tag); | |
| 452 | + ufshcd_hex_dump("TM RSP: ", tmrdp->task_rsp_upiu, | |
| 453 | + sizeof(struct utp_task_req_desc)); | |
| 454 | + } | |
| 455 | +} | |
| 456 | + | |
| 457 | +static void ufshcd_print_host_state(struct ufs_hba *hba) | |
| 458 | +{ | |
| 459 | + dev_err(hba->dev, "UFS Host state=%d\n", hba->ufshcd_state); | |
| 460 | + dev_err(hba->dev, "lrb in use=0x%lx, outstanding reqs=0x%lx tasks=0x%lx\n", | |
| 461 | + hba->lrb_in_use, hba->outstanding_tasks, hba->outstanding_reqs); | |
| 462 | + dev_err(hba->dev, "saved_err=0x%x, saved_uic_err=0x%x\n", | |
| 463 | + hba->saved_err, hba->saved_uic_err); | |
| 464 | + dev_err(hba->dev, "Device power mode=%d, UIC link state=%d\n", | |
| 465 | + hba->curr_dev_pwr_mode, hba->uic_link_state); | |
| 466 | + dev_err(hba->dev, "PM in progress=%d, sys. suspended=%d\n", | |
| 467 | + hba->pm_op_in_progress, hba->is_sys_suspended); | |
| 468 | + dev_err(hba->dev, "Auto BKOPS=%d, Host self-block=%d\n", | |
| 469 | + hba->auto_bkops_enabled, hba->host->host_self_blocked); | |
| 470 | + dev_err(hba->dev, "Clk gate=%d\n", hba->clk_gating.state); | |
| 471 | + dev_err(hba->dev, "error handling flags=0x%x, req. abort count=%d\n", | |
| 472 | + hba->eh_flags, hba->req_abort_count); | |
| 473 | + dev_err(hba->dev, "Host capabilities=0x%x, caps=0x%x\n", | |
| 474 | + hba->capabilities, hba->caps); | |
| 475 | + dev_err(hba->dev, "quirks=0x%x, dev. quirks=0x%x\n", hba->quirks, | |
| 476 | + hba->dev_quirks); | |
| 477 | +} | |
| 478 | + | |
| 479 | +/** | |
| 480 | + * ufshcd_print_pwr_info - print power params as saved in hba | |
| 481 | + * power info | |
| 482 | + * @hba: per-adapter instance | |
| 483 | + */ | |
| 484 | +static void ufshcd_print_pwr_info(struct ufs_hba *hba) | |
| 485 | +{ | |
| 486 | + static const char * const names[] = { | |
| 487 | + "INVALID MODE", | |
| 488 | + "FAST MODE", | |
| 489 | + "SLOW_MODE", | |
| 490 | + "INVALID MODE", | |
| 491 | + "FASTAUTO_MODE", | |
| 492 | + "SLOWAUTO_MODE", | |
| 493 | + "INVALID MODE", | |
| 494 | + }; | |
| 495 | + | |
| 496 | + dev_err(hba->dev, "%s:[RX, TX]: gear=[%d, %d], lane[%d, %d], pwr[%s, %s], rate = %d\n", | |
| 497 | + __func__, | |
| 498 | + hba->pwr_info.gear_rx, hba->pwr_info.gear_tx, | |
| 499 | + hba->pwr_info.lane_rx, hba->pwr_info.lane_tx, | |
| 500 | + names[hba->pwr_info.pwr_rx], | |
| 501 | + names[hba->pwr_info.pwr_tx], | |
| 502 | + hba->pwr_info.hs_rate); | |
| 503 | +} | |
| 504 | + | |
| 270 | 505 | /* |
| 271 | 506 | * ufshcd_wait_for_register - wait for register value to change |
| 272 | 507 | * @hba - per-adapter interface |
| @@ -605,6 +840,28 @@ static inline int ufshcd_is_hba_active(struct ufs_hba *hba) · 332 unmodified lines | ||
| 605 | 840 | return (ufshcd_readl(hba, REG_CONTROLLER_ENABLE) & 0x1) ? 0 : 1; |
| 606 | 841 | } |
| 607 | 842 | |
| 843 | +static const char *ufschd_uic_link_state_to_string( | |
| 844 | + enum uic_link_state state) | |
| 845 | +{ | |
| 846 | + switch (state) { | |
| 847 | + case UIC_LINK_OFF_STATE: return "OFF"; | |
| 848 | + case UIC_LINK_ACTIVE_STATE: return "ACTIVE"; | |
| 849 | + case UIC_LINK_HIBERN8_STATE: return "HIBERN8"; | |
| 850 | + default: return "UNKNOWN"; | |
| 851 | + } | |
| 852 | +} | |
| 853 | + | |
| 854 | +static const char *ufschd_ufs_dev_pwr_mode_to_string( | |
| 855 | + enum ufs_dev_pwr_mode state) | |
| 856 | +{ | |
| 857 | + switch (state) { | |
| 858 | + case UFS_ACTIVE_PWR_MODE: return "ACTIVE"; | |
| 859 | + case UFS_SLEEP_PWR_MODE: return "SLEEP"; | |
| 860 | + case UFS_POWERDOWN_PWR_MODE: return "POWERDOWN"; | |
| 861 | + default: return "UNKNOWN"; | |
| 862 | + } | |
| 863 | +} | |
| 864 | + | |
| 608 | 865 | u32 ufshcd_get_local_unipro_ver(struct ufs_hba *hba) |
| 609 | 866 | { |
| 610 | 867 | /* HCI version 1.0 and 1.1 supports UniPro 1.41 */ |
| @@ -633,20 +890,523 @@ static bool ufshcd_is_unipro_pa_params_tuning_req(struct ufs_hba *hba) · 22 unmodified lines | ||
| 633 | 890 | return false; |
| 634 | 891 | } |
| 635 | 892 | |
| 893 | +static int ufshcd_scale_clks(struct ufs_hba *hba, bool scale_up) | |
| 894 | +{ | |
| 895 | + int ret = 0; | |
| 896 | + struct ufs_clk_info *clki; | |
| 897 | + struct list_head *head = &hba->clk_list_head; | |
| 898 | + ktime_t start = ktime_get(); | |
| 899 | + bool clk_state_changed = false; | |
| 900 | + | |
| 901 | + if (!head || list_empty(head)) | |
| 902 | + goto out; | |
| 903 | + | |
| 904 | + ret = ufshcd_vops_clk_scale_notify(hba, scale_up, PRE_CHANGE); | |
| 905 | + if (ret) | |
| 906 | + return ret; | |
| 907 | + | |
| 908 | + list_for_each_entry(clki, head, list) { | |
| 909 | + if (!IS_ERR_OR_NULL(clki->clk)) { | |
| 910 | + if (scale_up && clki->max_freq) { | |
| 911 | + if (clki->curr_freq == clki->max_freq) | |
| 912 | + continue; | |
| 913 | + | |
| 914 | + clk_state_changed = true; | |
| 915 | + ret = clk_set_rate(clki->clk, clki->max_freq); | |
| 916 | + if (ret) { | |
| 917 | + dev_err(hba->dev, "%s: %s clk set rate(%dHz) failed, %d\n", | |
| 918 | + __func__, clki->name, | |
| 919 | + clki->max_freq, ret); | |
| 920 | + break; | |
| 921 | + } | |
| 922 | + trace_ufshcd_clk_scaling(dev_name(hba->dev), | |
| 923 | + "scaled up", clki->name, | |
| 924 | + clki->curr_freq, | |
| 925 | + clki->max_freq); | |
| 926 | + | |
| 927 | + clki->curr_freq = clki->max_freq; | |
| 928 | + | |
| 929 | + } else if (!scale_up && clki->min_freq) { | |
| 930 | + if (clki->curr_freq == clki->min_freq) | |
| 931 | + continue; | |
| 932 | + | |
| 933 | + clk_state_changed = true; | |
| 934 | + ret = clk_set_rate(clki->clk, clki->min_freq); | |
| 935 | + if (ret) { | |
| 936 | + dev_err(hba->dev, "%s: %s clk set rate(%dHz) failed, %d\n", | |
| 937 | + __func__, clki->name, | |
| 938 | + clki->min_freq, ret); | |
| 939 | + break; | |
| 940 | + } | |
| 941 | + trace_ufshcd_clk_scaling(dev_name(hba->dev), | |
| 942 | + "scaled down", clki->name, | |
| 943 | + clki->curr_freq, | |
| 944 | + clki->min_freq); | |
| 945 | + clki->curr_freq = clki->min_freq; | |
| 946 | + } | |
| 947 | + } | |
| 948 | + dev_dbg(hba->dev, "%s: clk: %s, rate: %lu\n", __func__, | |
| 949 | + clki->name, clk_get_rate(clki->clk)); | |
| 950 | + } | |
| 951 | + | |
| 952 | + ret = ufshcd_vops_clk_scale_notify(hba, scale_up, POST_CHANGE); | |
| 953 | + | |
| 954 | +out: | |
| 955 | + if (clk_state_changed) | |
| 956 | + trace_ufshcd_profile_clk_scaling(dev_name(hba->dev), | |
| 957 | + (scale_up ? "up" : "down"), | |
| 958 | + ktime_to_us(ktime_sub(ktime_get(), start)), ret); | |
| 959 | + return ret; | |
| 960 | +} | |
| 961 | + | |
| 962 | +/** | |
| 963 | + * ufshcd_is_devfreq_scaling_required - check if scaling is required or not | |
| 964 | + * @hba: per adapter instance | |
| 965 | + * @scale_up: True if scaling up and false if scaling down | |
| 966 | + * | |
| 967 | + * Returns true if scaling is required, false otherwise. | |
| 968 | + */ | |
| 969 | +static bool ufshcd_is_devfreq_scaling_required(struct ufs_hba *hba, | |
| 970 | + bool scale_up) | |
| 971 | +{ | |
| 972 | + struct ufs_clk_info *clki; | |
| 973 | + struct list_head *head = &hba->clk_list_head; | |
| 974 | + | |
| 975 | + if (!head || list_empty(head)) | |
| 976 | + return false; | |
| 977 | + | |
| 978 | + list_for_each_entry(clki, head, list) { | |
| 979 | + if (!IS_ERR_OR_NULL(clki->clk)) { | |
| 980 | + if (scale_up && clki->max_freq) { | |
| 981 | + if (clki->curr_freq == clki->max_freq) | |
| 982 | + continue; | |
| 983 | + return true; | |
| 984 | + } else if (!scale_up && clki->min_freq) { | |
| 985 | + if (clki->curr_freq == clki->min_freq) | |
| 986 | + continue; | |
| 987 | + return true; | |
| 988 | + } | |
| 989 | + } | |
| 990 | + } | |
| 991 | + | |
| 992 | + return false; | |
| 993 | +} | |
| 994 | + | |
| 995 | +static int ufshcd_wait_for_doorbell_clr(struct ufs_hba *hba, | |
| 996 | + u64 wait_timeout_us) | |
| 997 | +{ | |
| 998 | + unsigned long flags; | |
| 999 | + int ret = 0; | |
| 1000 | + u32 tm_doorbell; | |
| 1001 | + u32 tr_doorbell; | |
| 1002 | + bool timeout = false, do_last_check = false; | |
| 1003 | + ktime_t start; | |
| 1004 | + | |
| 1005 | + ufshcd_hold(hba, false); | |
| 1006 | + spin_lock_irqsave(hba->host->host_lock, flags); | |
| 1007 | + /* | |
| 1008 | + * Wait for all the outstanding tasks/transfer requests. | |
| 1009 | + * Verify by checking the doorbell registers are clear. | |
| 1010 | + */ | |
| 1011 | + start = ktime_get(); | |
| 1012 | + do { | |
| 1013 | + if (hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL) { | |
| 1014 | + ret = -EBUSY; | |
| 1015 | + goto out; | |
| 1016 | + } | |
| 1017 | + | |
| 1018 | + tm_doorbell = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL); | |
| 1019 | + tr_doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); | |
| 1020 | + if (!tm_doorbell && !tr_doorbell) { | |
| 1021 | + timeout = false; | |
| 1022 | + break; | |
| 1023 | + } else if (do_last_check) { | |
| 1024 | + break; | |
| 1025 | + } | |
| 1026 | + | |
| 1027 | + spin_unlock_irqrestore(hba->host->host_lock, flags); | |
| 1028 | + schedule(); | |
| 1029 | + if (ktime_to_us(ktime_sub(ktime_get(), start)) > | |
| 1030 | + wait_timeout_us) { | |
| 1031 | + timeout = true; | |
| 1032 | + /* | |
| 1033 | + * We might have scheduled out for long time so make | |
| 1034 | + * sure to check if doorbells are cleared by this time | |
| 1035 | + * or not. | |
| 1036 | + */ | |
| 1037 | + do_last_check = true; | |
| 1038 | + } | |
| 1039 | + spin_lock_irqsave(hba->host->host_lock, flags); | |
| 1040 | + } while (tm_doorbell || tr_doorbell); | |
| 1041 | + | |
| 1042 | + if (timeout) { | |
| 1043 | + dev_err(hba->dev, | |
| 1044 | + "%s: timedout waiting for doorbell to clear (tm=0x%x, tr=0x%x)\n", | |
| 1045 | + __func__, tm_doorbell, tr_doorbell); | |
| 1046 | + ret = -EBUSY; | |
| 1047 | + } | |
| 1048 | +out: | |
| 1049 | + spin_unlock_irqrestore(hba->host->host_lock, flags); | |
| 1050 | + ufshcd_release(hba); | |
| 1051 | + return ret; | |
| 1052 | +} | |
| 1053 | + | |
| 1054 | +/** | |
| 1055 | + * ufshcd_scale_gear - scale up/down UFS gear | |
| 1056 | + * @hba: per adapter instance | |
| 1057 | + * @scale_up: True for scaling up gear and false for scaling down | |
| 1058 | + * | |
| 1059 | + * Returns 0 for success, | |
| 1060 | + * Returns -EBUSY if scaling can't happen at this time | |
| 1061 | + * Returns non-zero for any other errors | |
| 1062 | + */ | |
| 1063 | +static int ufshcd_scale_gear(struct ufs_hba *hba, bool scale_up) | |
| 1064 | +{ | |
| 1065 | + #define UFS_MIN_GEAR_TO_SCALE_DOWN UFS_HS_G1 | |
| 1066 | + int ret = 0; | |
| 1067 | + struct ufs_pa_layer_attr new_pwr_info; | |
| 1068 | + | |
| 1069 | + if (scale_up) { | |
| 1070 | + memcpy(&new_pwr_info, &hba->clk_scaling.saved_pwr_info.info, | |
| 1071 | + sizeof(struct ufs_pa_layer_attr)); | |
| 1072 | + } else { | |
| 1073 | + memcpy(&new_pwr_info, &hba->pwr_info, | |
| 1074 | + sizeof(struct ufs_pa_layer_attr)); | |
| 1075 | + | |
| 1076 | + if (hba->pwr_info.gear_tx > UFS_MIN_GEAR_TO_SCALE_DOWN | |
| 1077 | + || hba->pwr_info.gear_rx > UFS_MIN_GEAR_TO_SCALE_DOWN) { | |
| 1078 | + /* save the current power mode */ | |
| 1079 | + memcpy(&hba->clk_scaling.saved_pwr_info.info, | |
| 1080 | + &hba->pwr_info, | |
| 1081 | + sizeof(struct ufs_pa_layer_attr)); | |
| 1082 | + | |
| 1083 | + /* scale down gear */ | |
| 1084 | + new_pwr_info.gear_tx = UFS_MIN_GEAR_TO_SCALE_DOWN; | |
| 1085 | + new_pwr_info.gear_rx = UFS_MIN_GEAR_TO_SCALE_DOWN; | |
| 1086 | + } | |
| 1087 | + } | |
| 1088 | + | |
| 1089 | + /* check if the power mode needs to be changed or not? */ | |
| 1090 | + ret = ufshcd_change_power_mode(hba, &new_pwr_info); | |
| 1091 | + | |
| 1092 | + if (ret) | |
| 1093 | + dev_err(hba->dev, "%s: failed err %d, old gear: (tx %d rx %d), new gear: (tx %d rx %d)", | |
| 1094 | + __func__, ret, | |
| 1095 | + hba->pwr_info.gear_tx, hba->pwr_info.gear_rx, | |
| 1096 | + new_pwr_info.gear_tx, new_pwr_info.gear_rx); | |
| 1097 | + | |
| 1098 | + return ret; | |
| 1099 | +} | |
| 1100 | + | |
| 1101 | +static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba) | |
| 1102 | +{ | |
| 1103 | + #define DOORBELL_CLR_TOUT_US (1000 * 1000) /* 1 sec */ | |
| 1104 | + int ret = 0; | |
| 1105 | + /* | |
| 1106 | + * make sure that there are no outstanding requests when | |
| 1107 | + * clock scaling is in progress | |
| 1108 | + */ | |
| 1109 | + scsi_block_requests(hba->host); | |
| 1110 | + down_write(&hba->clk_scaling_lock); | |
| 1111 | + if (ufshcd_wait_for_doorbell_clr(hba, DOORBELL_CLR_TOUT_US)) { | |
| 1112 | + ret = -EBUSY; | |
| 1113 | + up_write(&hba->clk_scaling_lock); | |
| 1114 | + scsi_unblock_requests(hba->host); | |
| 1115 | + } | |
| 1116 | + | |
| 1117 | + return ret; | |
| 1118 | +} | |
| 1119 | + | |
| 1120 | +static void ufshcd_clock_scaling_unprepare(struct ufs_hba *hba) | |
| 1121 | +{ | |
| 1122 | + up_write(&hba->clk_scaling_lock); | |
| 1123 | + scsi_unblock_requests(hba->host); | |
| 1124 | +} | |
| 1125 | + | |
| 1126 | +/** | |
| 1127 | + * ufshcd_devfreq_scale - scale up/down UFS clocks and gear | |
| 1128 | + * @hba: per adapter instance | |
| 1129 | + * @scale_up: True for scaling up and false for scalin down | |
| 1130 | + * | |
| 1131 | + * Returns 0 for success, | |
| 1132 | + * Returns -EBUSY if scaling can't happen at this time | |
| 1133 | + * Returns non-zero for any other errors | |
| 1134 | + */ | |
| 1135 | +static int ufshcd_devfreq_scale(struct ufs_hba *hba, bool scale_up) | |
| 1136 | +{ | |
| 1137 | + int ret = 0; | |
| 1138 | + | |
| 1139 | + /* let's not get into low power until clock scaling is completed */ | |
| 1140 | + ufshcd_hold(hba, false); | |
| 1141 | + | |
| 1142 | + ret = ufshcd_clock_scaling_prepare(hba); | |
| 1143 | + if (ret) | |
| 1144 | + return ret; | |
| 1145 | + | |
| 1146 | + /* scale down the gear before scaling down clocks */ | |
| 1147 | + if (!scale_up) { | |
| 1148 | + ret = ufshcd_scale_gear(hba, false); | |
| 1149 | + if (ret) | |
| 1150 | + goto out; | |
| 1151 | + } | |
| 1152 | + | |
| 1153 | + ret = ufshcd_scale_clks(hba, scale_up); | |
| 1154 | + if (ret) { | |
| 1155 | + if (!scale_up) | |
| 1156 | + ufshcd_scale_gear(hba, true); | |
| 1157 | + goto out; | |
| 1158 | + } | |
| 1159 | + | |
| 1160 | + /* scale up the gear after scaling up clocks */ | |
| 1161 | + if (scale_up) { | |
| 1162 | + ret = ufshcd_scale_gear(hba, true); | |
| 1163 | + if (ret) { | |
| 1164 | + ufshcd_scale_clks(hba, false); | |
| 1165 | + goto out; | |
| 1166 | + } | |
| 1167 | + } | |
| 1168 | + | |
| 1169 | + ret = ufshcd_vops_clk_scale_notify(hba, scale_up, POST_CHANGE); | |
| 1170 | + | |
| 1171 | +out: | |
| 1172 | + ufshcd_clock_scaling_unprepare(hba); | |
| 1173 | + ufshcd_release(hba); | |
| 1174 | + return ret; | |
| 1175 | +} | |
| 1176 | + | |
| 1177 | +static void ufshcd_clk_scaling_suspend_work(struct work_struct *work) | |
| 1178 | +{ | |
| 1179 | + struct ufs_hba *hba = container_of(work, struct ufs_hba, | |
| 1180 | + clk_scaling.suspend_work); | |
| 1181 | + unsigned long irq_flags; | |
| 1182 | + | |
| 1183 | + spin_lock_irqsave(hba->host->host_lock, irq_flags); | |
| 1184 | + if (hba->clk_scaling.active_reqs || hba->clk_scaling.is_suspended) { | |
| 1185 | + spin_unlock_irqrestore(hba->host->host_lock, irq_flags); | |
| 1186 | + return; | |
| 1187 | + } | |
| 1188 | + hba->clk_scaling.is_suspended = true; | |
| 1189 | + spin_unlock_irqrestore(hba->host->host_lock, irq_flags); | |
| 1190 | + | |
| 1191 | + __ufshcd_suspend_clkscaling(hba); | |
| 1192 | +} | |
| 1193 | + | |
| 1194 | +static void ufshcd_clk_scaling_resume_work(struct work_struct *work) | |
| 1195 | +{ | |
| 1196 | + struct ufs_hba *hba = container_of(work, struct ufs_hba, | |
| 1197 | + clk_scaling.resume_work); | |
| 1198 | + unsigned long irq_flags; | |
| 1199 | + | |
| 1200 | + spin_lock_irqsave(hba->host->host_lock, irq_flags); | |
| 1201 | + if (!hba->clk_scaling.is_suspended) { | |
| 1202 | + spin_unlock_irqrestore(hba->host->host_lock, irq_flags); | |
| 1203 | + return; | |
| 1204 | + } | |
| 1205 | + hba->clk_scaling.is_suspended = false; | |
| 1206 | + spin_unlock_irqrestore(hba->host->host_lock, irq_flags); | |
| 1207 | + | |
| 1208 | + devfreq_resume_device(hba->devfreq); | |
| 1209 | +} | |
| 1210 | + | |
| 1211 | +static int ufshcd_devfreq_target(struct device *dev, | |
| 1212 | + unsigned long *freq, u32 flags) | |
| 1213 | +{ | |
| 1214 | + int ret = 0; | |
| 1215 | + struct ufs_hba *hba = dev_get_drvdata(dev); | |
| 1216 | + ktime_t start; | |
| 1217 | + bool scale_up, sched_clk_scaling_suspend_work = false; | |
| 1218 | + unsigned long irq_flags; | |
| 1219 | + | |
| 1220 | + if (!ufshcd_is_clkscaling_supported(hba)) | |
| 1221 | + return -EINVAL; | |
| 1222 | + | |
| 1223 | + if ((*freq > 0) && (*freq < UINT_MAX)) { | |
| 1224 | + dev_err(hba->dev, "%s: invalid freq = %lu\n", __func__, *freq); | |
| 1225 | + return -EINVAL; | |
| 1226 | + } | |
| 1227 | + | |
| 1228 | + spin_lock_irqsave(hba->host->host_lock, irq_flags); | |
| 1229 | + if (ufshcd_eh_in_progress(hba)) { | |
| 1230 | + spin_unlock_irqrestore(hba->host->host_lock, irq_flags); | |
| 1231 | + return 0; | |
| 1232 | + } | |
| 1233 | + | |
| 1234 | + if (!hba->clk_scaling.active_reqs) | |
| 1235 | + sched_clk_scaling_suspend_work = true; | |
| 1236 | + | |
| 1237 | + scale_up = (*freq == UINT_MAX) ? true : false; | |
| 1238 | + if (!ufshcd_is_devfreq_scaling_required(hba, scale_up)) { | |
| 1239 | + spin_unlock_irqrestore(hba->host->host_lock, irq_flags); | |
| 1240 | + ret = 0; | |
| 1241 | + goto out; /* no state change required */ | |
| 1242 | + } | |
| 1243 | + spin_unlock_irqrestore(hba->host->host_lock, irq_flags); | |
| 1244 | + | |
| 1245 | + start = ktime_get(); | |
| 1246 | + ret = ufshcd_devfreq_scale(hba, scale_up); | |
| 1247 | + | |
| 1248 | + trace_ufshcd_profile_clk_scaling(dev_name(hba->dev), | |
| 1249 | + (scale_up ? "up" : "down"), | |
| 1250 | + ktime_to_us(ktime_sub(ktime_get(), start)), ret); | |
| 1251 | + | |
| 1252 | +out: | |
| 1253 | + if (sched_clk_scaling_suspend_work) | |
| 1254 | + queue_work(hba->clk_scaling.workq, | |
| 1255 | + &hba->clk_scaling.suspend_work); | |
| 1256 | + | |
| 1257 | + return ret; | |
| 1258 | +} | |
| 1259 | + | |
| 1260 | + | |
| 1261 | +static int ufshcd_devfreq_get_dev_status(struct device *dev, | |
| 1262 | + struct devfreq_dev_status *stat) | |
| 1263 | +{ | |
| 1264 | + struct ufs_hba *hba = dev_get_drvdata(dev); | |
| 1265 | + struct ufs_clk_scaling *scaling = &hba->clk_scaling; | |
| 1266 | + unsigned long flags; | |
| 1267 | + | |
| 1268 | + if (!ufshcd_is_clkscaling_supported(hba)) | |
| 1269 | + return -EINVAL; | |
| 1270 | + | |
| 1271 | + memset(stat, 0, sizeof(*stat)); | |
| 1272 | + | |
| 1273 | + spin_lock_irqsave(hba->host->host_lock, flags); | |
| 1274 | + if (!scaling->window_start_t) | |
| 1275 | + goto start_window; | |
| 1276 | + | |
| 1277 | + if (scaling->is_busy_started) | |
| 1278 | + scaling->tot_busy_t += ktime_to_us(ktime_sub(ktime_get(), | |
| 1279 | + scaling->busy_start_t)); | |
| 1280 | + | |
| 1281 | + stat->total_time = jiffies_to_usecs((long)jiffies - | |
| 1282 | + (long)scaling->window_start_t); | |
| 1283 | + stat->busy_time = scaling->tot_busy_t; | |
| 1284 | +start_window: | |
| 1285 | + scaling->window_start_t = jiffies; | |
| 1286 | + scaling->tot_busy_t = 0; | |
| 1287 | + | |
| 1288 | + if (hba->outstanding_reqs) { | |
| 1289 | + scaling->busy_start_t = ktime_get(); | |
| 1290 | + scaling->is_busy_started = true; | |
| 1291 | + } else { | |
| 1292 | + scaling->busy_start_t = 0; | |
| 1293 | + scaling->is_busy_started = false; | |
| 1294 | + } | |
| 1295 | + spin_unlock_irqrestore(hba->host->host_lock, flags); | |
| 1296 | + return 0; | |
| 1297 | +} | |
| 1298 | + | |
| 1299 | +static struct devfreq_dev_profile ufs_devfreq_profile = { | |
| 1300 | + .polling_ms = 100, | |
| 1301 | + .target = ufshcd_devfreq_target, | |
| 1302 | + .get_dev_status = ufshcd_devfreq_get_dev_status, | |
| 1303 | +}; | |
| 1304 | + | |
| 1305 | +static void __ufshcd_suspend_clkscaling(struct ufs_hba *hba) | |
| 1306 | +{ | |
| 1307 | + unsigned long flags; | |
| 1308 | + | |
| 1309 | + devfreq_suspend_device(hba->devfreq); | |
| 1310 | + spin_lock_irqsave(hba->host->host_lock, flags); | |
| 1311 | + hba->clk_scaling.window_start_t = 0; | |
| 1312 | + spin_unlock_irqrestore(hba->host->host_lock, flags); | |
| 1313 | +} | |
| 1314 | + | |
| 636 | 1315 | static void ufshcd_suspend_clkscaling(struct ufs_hba *hba) |
| 637 | 1316 | { |
| 638 | − if (ufshcd_is_clkscaling_enabled(hba)) { | |
| 639 | − devfreq_suspend_device(hba->devfreq); | |
| 640 | − hba->clk_scaling.window_start_t = 0; | |
| 1317 | + unsigned long flags; | |
| 1318 | + bool suspend = false; | |
| 1319 | + | |
| 1320 | + if (!ufshcd_is_clkscaling_supported(hba)) | |
| 1321 | + return; | |
| 1322 | + | |
| 1323 | + spin_lock_irqsave(hba->host->host_lock, flags); | |
| 1324 | + if (!hba->clk_scaling.is_suspended) { | |
| 1325 | + suspend = true; | |
| 1326 | + hba->clk_scaling.is_suspended = true; | |
| 641 | 1327 | } |
| 1328 | + spin_unlock_irqrestore(hba->host->host_lock, flags); | |
| 1329 | + | |
| 1330 | + if (suspend) | |
| 1331 | + __ufshcd_suspend_clkscaling(hba); | |
| 642 | 1332 | } |
| 643 | 1333 | |
| 644 | 1334 | static void ufshcd_resume_clkscaling(struct ufs_hba *hba) |
| 645 | 1335 | { |
| 646 | − if (ufshcd_is_clkscaling_enabled(hba)) | |
| 1336 | + unsigned long flags; | |
| 1337 | + bool resume = false; | |
| 1338 | + | |
| 1339 | + if (!ufshcd_is_clkscaling_supported(hba)) | |
| 1340 | + return; | |
| 1341 | + | |
| 1342 | + spin_lock_irqsave(hba->host->host_lock, flags); | |
| 1343 | + if (hba->clk_scaling.is_suspended) { | |
| 1344 | + resume = true; | |
| 1345 | + hba->clk_scaling.is_suspended = false; | |
| 1346 | + } | |
| 1347 | + spin_unlock_irqrestore(hba->host->host_lock, flags); | |
| 1348 | + | |
| 1349 | + if (resume) | |
| 647 | 1350 | devfreq_resume_device(hba->devfreq); |
| 648 | 1351 | } |
| 649 | 1352 | |
| 1353 | +static ssize_t ufshcd_clkscale_enable_show(struct device *dev, | |
| 1354 | + struct device_attribute *attr, char *buf) | |
| 1355 | +{ | |
| 1356 | + struct ufs_hba *hba = dev_get_drvdata(dev); | |
| 1357 | + | |
| 1358 | + return snprintf(buf, PAGE_SIZE, "%d\n", hba->clk_scaling.is_allowed); | |
| 1359 | +} | |
| 1360 | + | |
| 1361 | +static ssize_t ufshcd_clkscale_enable_store(struct device *dev, | |
| 1362 | + struct device_attribute *attr, const char *buf, size_t count) | |
| 1363 | +{ | |
| 1364 | + struct ufs_hba *hba = dev_get_drvdata(dev); | |
| 1365 | + u32 value; | |
| 1366 | + int err; | |
| 1367 | + | |
| 1368 | + if (kstrtou32(buf, 0, &value)) | |
| 1369 | + return -EINVAL; | |
| 1370 | + | |
| 1371 | + value = !!value; | |
| 1372 | + if (value == hba->clk_scaling.is_allowed) | |
| 1373 | + goto out; | |
| 1374 | + | |
| 1375 | + pm_runtime_get_sync(hba->dev); | |
| 1376 | + ufshcd_hold(hba, false); | |
| 1377 | + | |
| 1378 | + cancel_work_sync(&hba->clk_scaling.suspend_work); | |
| 1379 | + cancel_work_sync(&hba->clk_scaling.resume_work); | |
| 1380 | + | |
| 1381 | + hba->clk_scaling.is_allowed = value; | |
| 1382 | + | |
| 1383 | + if (value) { | |
| 1384 | + ufshcd_resume_clkscaling(hba); | |
| 1385 | + } else { | |
| 1386 | + ufshcd_suspend_clkscaling(hba); | |
| 1387 | + err = ufshcd_devfreq_scale(hba, true); | |
| 1388 | + if (err) | |
| 1389 | + dev_err(hba->dev, "%s: failed to scale clocks up %d\n", | |
| 1390 | + __func__, err); | |
| 1391 | + } | |
| 1392 | + | |
| 1393 | + ufshcd_release(hba); | |
| 1394 | + pm_runtime_put_sync(hba->dev); | |
| 1395 | +out: | |
| 1396 | + return count; | |
| 1397 | +} | |
| 1398 | + | |
| 1399 | +static void ufshcd_clkscaling_init_sysfs(struct ufs_hba *hba) | |
| 1400 | +{ | |
| 1401 | + hba->clk_scaling.enable_attr.show = ufshcd_clkscale_enable_show; | |
| 1402 | + hba->clk_scaling.enable_attr.store = ufshcd_clkscale_enable_store; | |
| 1403 | + sysfs_attr_init(&hba->clk_scaling.enable_attr.attr); | |
| 1404 | + hba->clk_scaling.enable_attr.attr.name = "clkscale_enable"; | |
| 1405 | + hba->clk_scaling.enable_attr.attr.mode = 0644; | |
| 1406 | + if (device_create_file(hba->dev, &hba->clk_scaling.enable_attr)) | |
| 1407 | + dev_err(hba->dev, "Failed to create sysfs for clkscale_enable\n"); | |
| 1408 | +} | |
| 1409 | + | |
| 650 | 1410 | static void ufshcd_ungate_work(struct work_struct *work) |
| 651 | 1411 | { |
| 652 | 1412 | int ret; |
| @@ -680,7 +1440,6 @@ static void ufshcd_ungate_work(struct work_struct *work) · 27 unmodified lines | ||
| 680 | 1440 | hba->clk_gating.is_suspended = false; |
| 681 | 1441 | } |
| 682 | 1442 | unblock_reqs: |
| 683 | − ufshcd_resume_clkscaling(hba); | |
| 684 | 1443 | scsi_unblock_requests(hba->host); |
| 685 | 1444 | } |
| 686 | 1445 | |
| @@ -727,6 +1486,8 @@ start: · 40 unmodified lines | ||
| 727 | 1486 | case REQ_CLKS_OFF: |
| 728 | 1487 | if (cancel_delayed_work(&hba->clk_gating.gate_work)) { |
| 729 | 1488 | hba->clk_gating.state = CLKS_ON; |
| 1489 | + trace_ufshcd_clk_gating(dev_name(hba->dev), | |
| 1490 | + hba->clk_gating.state); | |
| 730 | 1491 | break; |
| 731 | 1492 | } |
| 732 | 1493 | /* |
| @@ -737,6 +1498,8 @@ start: · 4 unmodified lines | ||
| 737 | 1498 | case CLKS_OFF: |
| 738 | 1499 | scsi_block_requests(hba->host); |
| 739 | 1500 | hba->clk_gating.state = REQ_CLKS_ON; |
| 1501 | + trace_ufshcd_clk_gating(dev_name(hba->dev), | |
| 1502 | + hba->clk_gating.state); | |
| 740 | 1503 | schedule_work(&hba->clk_gating.ungate_work); |
| 741 | 1504 | /* |
| 742 | 1505 | * fall through to check if we should wait for this |
| @@ -781,6 +1544,8 @@ static void ufshcd_gate_work(struct work_struct *work) · 38 unmodified lines | ||
| 781 | 1544 | if (hba->clk_gating.is_suspended || |
| 782 | 1545 | (hba->clk_gating.state == REQ_CLKS_ON)) { |
| 783 | 1546 | hba->clk_gating.state = CLKS_ON; |
| 1547 | + trace_ufshcd_clk_gating(dev_name(hba->dev), | |
| 1548 | + hba->clk_gating.state); | |
| 784 | 1549 | goto rel_lock; |
| 785 | 1550 | } |
| 786 | 1551 | |
| @@ -796,13 +1561,13 @@ static void ufshcd_gate_work(struct work_struct *work) · 9 unmodified lines | ||
| 796 | 1561 | if (ufshcd_can_hibern8_during_gating(hba)) { |
| 797 | 1562 | if (ufshcd_uic_hibern8_enter(hba)) { |
| 798 | 1563 | hba->clk_gating.state = CLKS_ON; |
| 1564 | + trace_ufshcd_clk_gating(dev_name(hba->dev), | |
| 1565 | + hba->clk_gating.state); | |
| 799 | 1566 | goto out; |
| 800 | 1567 | } |
| 801 | 1568 | ufshcd_set_link_hibern8(hba); |
| 802 | 1569 | } |
| 803 | 1570 | |
| 804 | − ufshcd_suspend_clkscaling(hba); | |
| 805 | − | |
| 806 | 1571 | if (!ufshcd_is_link_active(hba)) |
| 807 | 1572 | ufshcd_setup_clocks(hba, false); |
| 808 | 1573 | else |
| @@ -819,9 +1584,11 @@ static void ufshcd_gate_work(struct work_struct *work) · 10 unmodified lines | ||
| 819 | 1584 | * new requests arriving before the current cancel work is done. |
| 820 | 1585 | */ |
| 821 | 1586 | spin_lock_irqsave(hba->host->host_lock, flags); |
| 822 | − if (hba->clk_gating.state == REQ_CLKS_OFF) | |
| 1587 | + if (hba->clk_gating.state == REQ_CLKS_OFF) { | |
| 823 | 1588 | hba->clk_gating.state = CLKS_OFF; |
| 824 | − | |
| 1589 | + trace_ufshcd_clk_gating(dev_name(hba->dev), | |
| 1590 | + hba->clk_gating.state); | |
| 1591 | + } | |
| 825 | 1592 | rel_lock: |
| 826 | 1593 | spin_unlock_irqrestore(hba->host->host_lock, flags); |
| 827 | 1594 | out: |
| @@ -844,6 +1611,7 @@ static void __ufshcd_release(struct ufs_hba *hba) · 16 unmodified lines | ||
| 844 | 1611 | return; |
| 845 | 1612 | |
| 846 | 1613 | hba->clk_gating.state = REQ_CLKS_OFF; |
| 1614 | + trace_ufshcd_clk_gating(dev_name(hba->dev), hba->clk_gating.state); | |
| 847 | 1615 | schedule_delayed_work(&hba->clk_gating.gate_work, |
| 848 | 1616 | msecs_to_jiffies(hba->clk_gating.delay_ms)); |
| 849 | 1617 | } |
| @@ -881,6 +1649,41 @@ static ssize_t ufshcd_clkgate_delay_store(struct device *dev, · 31 unmodified lines | ||
| 881 | 1649 | return count; |
| 882 | 1650 | } |
| 883 | 1651 | |
| 1652 | +static ssize_t ufshcd_clkgate_enable_show(struct device *dev, | |
| 1653 | + struct device_attribute *attr, char *buf) | |
| 1654 | +{ | |
| 1655 | + struct ufs_hba *hba = dev_get_drvdata(dev); | |
| 1656 | + | |
| 1657 | + return snprintf(buf, PAGE_SIZE, "%d\n", hba->clk_gating.is_enabled); | |
| 1658 | +} | |
| 1659 | + | |
| 1660 | +static ssize_t ufshcd_clkgate_enable_store(struct device *dev, | |
| 1661 | + struct device_attribute *attr, const char *buf, size_t count) | |
| 1662 | +{ | |
| 1663 | + struct ufs_hba *hba = dev_get_drvdata(dev); | |
| 1664 | + unsigned long flags; | |
| 1665 | + u32 value; | |
| 1666 | + | |
| 1667 | + if (kstrtou32(buf, 0, &value)) | |
| 1668 | + return -EINVAL; | |
| 1669 | + | |
| 1670 | + value = !!value; | |
| 1671 | + if (value == hba->clk_gating.is_enabled) | |
| 1672 | + goto out; | |
| 1673 | + | |
| 1674 | + if (value) { | |
| 1675 | + ufshcd_release(hba); | |
| 1676 | + } else { | |
| 1677 | + spin_lock_irqsave(hba->host->host_lock, flags); | |
| 1678 | + hba->clk_gating.active_reqs++; | |
| 1679 | + spin_unlock_irqrestore(hba->host->host_lock, flags); | |
| 1680 | + } | |
| 1681 | + | |
| 1682 | + hba->clk_gating.is_enabled = value; | |
| 1683 | +out: | |
| 1684 | + return count; | |
| 1685 | +} | |
| 1686 | + | |
| 884 | 1687 | static void ufshcd_init_clk_gating(struct ufs_hba *hba) |
| 885 | 1688 | { |
| 886 | 1689 | if (!ufshcd_is_clkgating_allowed(hba)) |
| @@ -890,13 +1693,23 @@ static void ufshcd_init_clk_gating(struct ufs_hba *hba) · 3 unmodified lines | ||
| 890 | 1693 | INIT_DELAYED_WORK(&hba->clk_gating.gate_work, ufshcd_gate_work); |
| 891 | 1694 | INIT_WORK(&hba->clk_gating.ungate_work, ufshcd_ungate_work); |
| 892 | 1695 | |
| 1696 | + hba->clk_gating.is_enabled = true; | |
| 1697 | + | |
| 893 | 1698 | hba->clk_gating.delay_attr.show = ufshcd_clkgate_delay_show; |
| 894 | 1699 | hba->clk_gating.delay_attr.store = ufshcd_clkgate_delay_store; |
| 895 | 1700 | sysfs_attr_init(&hba->clk_gating.delay_attr.attr); |
| 896 | 1701 | hba->clk_gating.delay_attr.attr.name = "clkgate_delay_ms"; |
| 897 | − hba->clk_gating.delay_attr.attr.mode = S_IRUGO | S_IWUSR; | |
| 1702 | + hba->clk_gating.delay_attr.attr.mode = 0644; | |
| 898 | 1703 | if (device_create_file(hba->dev, &hba->clk_gating.delay_attr)) |
| 899 | 1704 | dev_err(hba->dev, "Failed to create sysfs for clkgate_delay\n"); |
| 1705 | + | |
1406 more lines aren’t shown here.
This diff is large: its 245 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 158 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 264 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.