Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge patch series "mpi3mr: Few Enhancements and minor fixes"

Ranjan Kumar <ranjan.kumar@broadcom.com> says:

Few Enhancements and minor fixes of mpi3mr driver.

Link: https://lore.kernel.org/r/20250129100850.25430-1-ranjan.kumar@broadcom.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

+281 -23
+1
drivers/scsi/mpi3mr/mpi/mpi30_tool.h
··· 9 9 #define MPI3_DIAG_BUFFER_TYPE_FW (0x02) 10 10 #define MPI3_DIAG_BUFFER_ACTION_RELEASE (0x01) 11 11 12 + #define MPI3_DIAG_BUFFER_POST_MSGFLAGS_SEGMENTED (0x01) 12 13 struct mpi3_diag_buffer_post_request { 13 14 __le16 host_tag; 14 15 u8 ioc_use_only02;
+28 -3
drivers/scsi/mpi3mr/mpi3mr.h
··· 56 56 extern int prot_mask; 57 57 extern atomic64_t event_counter; 58 58 59 - #define MPI3MR_DRIVER_VERSION "8.12.0.3.50" 60 - #define MPI3MR_DRIVER_RELDATE "11-November-2024" 59 + #define MPI3MR_DRIVER_VERSION "8.12.1.0.50" 60 + #define MPI3MR_DRIVER_RELDATE "28-January-2025" 61 61 62 62 #define MPI3MR_DRIVER_NAME "mpi3mr" 63 63 #define MPI3MR_DRIVER_LICENSE "GPL" ··· 80 80 81 81 /* Admin queue management definitions */ 82 82 #define MPI3MR_ADMIN_REQ_Q_SIZE (2 * MPI3MR_PAGE_SIZE_4K) 83 - #define MPI3MR_ADMIN_REPLY_Q_SIZE (4 * MPI3MR_PAGE_SIZE_4K) 83 + #define MPI3MR_ADMIN_REPLY_Q_SIZE (8 * MPI3MR_PAGE_SIZE_4K) 84 84 #define MPI3MR_ADMIN_REQ_FRAME_SZ 128 85 85 #define MPI3MR_ADMIN_REPLY_FRAME_SZ 16 86 86 87 87 /* Operational queue management definitions */ 88 88 #define MPI3MR_OP_REQ_Q_QD 512 89 89 #define MPI3MR_OP_REP_Q_QD 1024 90 + #define MPI3MR_OP_REP_Q_QD2K 2048 90 91 #define MPI3MR_OP_REP_Q_QD4K 4096 91 92 #define MPI3MR_OP_REQ_Q_SEG_SIZE 4096 92 93 #define MPI3MR_OP_REP_Q_SEG_SIZE 4096 ··· 329 328 #define MPI3MR_RESET_REASON_OSTYPE_SHIFT 28 330 329 #define MPI3MR_RESET_REASON_IOCNUM_SHIFT 20 331 330 331 + 332 332 /* Queue type definitions */ 333 333 enum queue_type { 334 334 MPI3MR_DEFAULT_QUEUE = 0, ··· 389 387 u16 max_msix_vectors; 390 388 u8 personality; 391 389 u8 dma_mask; 390 + bool max_req_limit; 392 391 u8 protocol_flags; 393 392 u8 sge_mod_mask; 394 393 u8 sge_mod_value; ··· 459 456 * @enable_irq_poll: Flag to indicate polling is enabled 460 457 * @in_use: Queue is handled by poll/ISR 461 458 * @qtype: Type of queue (types defined in enum queue_type) 459 + * @qfull_watermark: Watermark defined in reply queue to avoid 460 + * reply queue full 462 461 */ 463 462 struct op_reply_qinfo { 464 463 u16 ci; ··· 476 471 bool enable_irq_poll; 477 472 atomic_t in_use; 478 473 enum queue_type qtype; 474 + u16 qfull_watermark; 479 475 }; 480 476 481 477 /** ··· 934 928 * @size: Buffer size 935 929 * @addr: Virtual address 936 930 * @dma_addr: Buffer DMA address 931 + * @is_segmented: The buffer is segmented or not 932 + * @disabled_after_reset: The buffer is disabled after reset 937 933 */ 938 934 struct diag_buffer_desc { 939 935 u8 type; ··· 945 937 u32 size; 946 938 void *addr; 947 939 dma_addr_t dma_addr; 940 + bool is_segmented; 941 + bool disabled_after_reset; 948 942 }; 949 943 950 944 /** ··· 1100 1090 * @ts_update_interval: Timestamp update interval 1101 1091 * @reset_in_progress: Reset in progress flag 1102 1092 * @unrecoverable: Controller unrecoverable flag 1093 + * @io_admin_reset_sync: Manage state of I/O ops during an admin reset process 1103 1094 * @prev_reset_result: Result of previous reset 1104 1095 * @reset_mutex: Controller reset mutex 1105 1096 * @reset_waitq: Controller reset wait queue ··· 1164 1153 * @snapdump_trigger_active: Snapdump trigger active flag 1165 1154 * @pci_err_recovery: PCI error recovery in progress 1166 1155 * @block_on_pci_err: Block IO during PCI error recovery 1156 + * @reply_qfull_count: Occurences of reply queue full avoidance kicking-in 1157 + * @prevent_reply_qfull: Enable reply queue prevention 1158 + * @seg_tb_support: Segmented trace buffer support 1159 + * @num_tb_segs: Number of Segments in Trace buffer 1160 + * @trace_buf_pool: DMA pool for Segmented trace buffer segments 1161 + * @trace_buf: Trace buffer segments memory descriptor 1167 1162 */ 1168 1163 struct mpi3mr_ioc { 1169 1164 struct list_head list; ··· 1293 1276 u16 ts_update_interval; 1294 1277 u8 reset_in_progress; 1295 1278 u8 unrecoverable; 1279 + u8 io_admin_reset_sync; 1296 1280 int prev_reset_result; 1297 1281 struct mutex reset_mutex; 1298 1282 wait_queue_head_t reset_waitq; ··· 1369 1351 bool fw_release_trigger_active; 1370 1352 bool pci_err_recovery; 1371 1353 bool block_on_pci_err; 1354 + atomic_t reply_qfull_count; 1355 + bool prevent_reply_qfull; 1356 + bool seg_tb_support; 1357 + u32 num_tb_segs; 1358 + struct dma_pool *trace_buf_pool; 1359 + struct segments *trace_buf; 1360 + 1372 1361 }; 1373 1362 1374 1363 /**
+119 -9
drivers/scsi/mpi3mr/mpi3mr_app.c
··· 12 12 #include <uapi/scsi/scsi_bsg_mpi3mr.h> 13 13 14 14 /** 15 - * mpi3mr_alloc_trace_buffer: Allocate trace buffer 15 + * mpi3mr_alloc_trace_buffer: Allocate segmented trace buffer 16 16 * @mrioc: Adapter instance reference 17 17 * @trace_size: Trace buffer size 18 18 * 19 - * Allocate trace buffer 19 + * Allocate either segmented memory pools or contiguous buffer 20 + * based on the controller capability for the host trace 21 + * buffer. 22 + * 20 23 * Return: 0 on success, non-zero on failure. 21 24 */ 22 25 static int mpi3mr_alloc_trace_buffer(struct mpi3mr_ioc *mrioc, u32 trace_size) 23 26 { 24 27 struct diag_buffer_desc *diag_buffer = &mrioc->diag_buffers[0]; 28 + int i, sz; 29 + u64 *diag_buffer_list = NULL; 30 + dma_addr_t diag_buffer_list_dma; 31 + u32 seg_count; 25 32 26 - diag_buffer->addr = dma_alloc_coherent(&mrioc->pdev->dev, 27 - trace_size, &diag_buffer->dma_addr, GFP_KERNEL); 28 - if (diag_buffer->addr) { 29 - dprint_init(mrioc, "trace diag buffer is allocated successfully\n"); 33 + if (mrioc->seg_tb_support) { 34 + seg_count = (trace_size) / MPI3MR_PAGE_SIZE_4K; 35 + trace_size = seg_count * MPI3MR_PAGE_SIZE_4K; 36 + 37 + diag_buffer_list = dma_alloc_coherent(&mrioc->pdev->dev, 38 + sizeof(u64) * seg_count, 39 + &diag_buffer_list_dma, GFP_KERNEL); 40 + if (!diag_buffer_list) 41 + return -1; 42 + 43 + mrioc->num_tb_segs = seg_count; 44 + 45 + sz = sizeof(struct segments) * seg_count; 46 + mrioc->trace_buf = kzalloc(sz, GFP_KERNEL); 47 + if (!mrioc->trace_buf) 48 + goto trace_buf_failed; 49 + 50 + mrioc->trace_buf_pool = dma_pool_create("trace_buf pool", 51 + &mrioc->pdev->dev, MPI3MR_PAGE_SIZE_4K, MPI3MR_PAGE_SIZE_4K, 52 + 0); 53 + if (!mrioc->trace_buf_pool) { 54 + ioc_err(mrioc, "trace buf pool: dma_pool_create failed\n"); 55 + goto trace_buf_pool_failed; 56 + } 57 + 58 + for (i = 0; i < seg_count; i++) { 59 + mrioc->trace_buf[i].segment = 60 + dma_pool_zalloc(mrioc->trace_buf_pool, GFP_KERNEL, 61 + &mrioc->trace_buf[i].segment_dma); 62 + diag_buffer_list[i] = 63 + (u64) mrioc->trace_buf[i].segment_dma; 64 + if (!diag_buffer_list[i]) 65 + goto tb_seg_alloc_failed; 66 + } 67 + 68 + diag_buffer->addr = diag_buffer_list; 69 + diag_buffer->dma_addr = diag_buffer_list_dma; 70 + diag_buffer->is_segmented = true; 71 + 72 + dprint_init(mrioc, "segmented trace diag buffer\n" 73 + "is allocated successfully seg_count:%d\n", seg_count); 30 74 return 0; 75 + } else { 76 + diag_buffer->addr = dma_alloc_coherent(&mrioc->pdev->dev, 77 + trace_size, &diag_buffer->dma_addr, GFP_KERNEL); 78 + if (diag_buffer->addr) { 79 + dprint_init(mrioc, "trace diag buffer is allocated successfully\n"); 80 + return 0; 81 + } 82 + return -1; 31 83 } 84 + 85 + tb_seg_alloc_failed: 86 + if (mrioc->trace_buf_pool) { 87 + for (i = 0; i < mrioc->num_tb_segs; i++) { 88 + if (mrioc->trace_buf[i].segment) { 89 + dma_pool_free(mrioc->trace_buf_pool, 90 + mrioc->trace_buf[i].segment, 91 + mrioc->trace_buf[i].segment_dma); 92 + mrioc->trace_buf[i].segment = NULL; 93 + } 94 + mrioc->trace_buf[i].segment = NULL; 95 + } 96 + dma_pool_destroy(mrioc->trace_buf_pool); 97 + mrioc->trace_buf_pool = NULL; 98 + } 99 + trace_buf_pool_failed: 100 + kfree(mrioc->trace_buf); 101 + mrioc->trace_buf = NULL; 102 + trace_buf_failed: 103 + if (diag_buffer_list) 104 + dma_free_coherent(&mrioc->pdev->dev, 105 + sizeof(u64) * mrioc->num_tb_segs, 106 + diag_buffer_list, diag_buffer_list_dma); 32 107 return -1; 33 108 } 34 109 ··· 175 100 dprint_init(mrioc, 176 101 "trying to allocate trace diag buffer of size = %dKB\n", 177 102 trace_size / 1024); 178 - if (get_order(trace_size) > MAX_PAGE_ORDER || 103 + if ((!mrioc->seg_tb_support && (get_order(trace_size) > MAX_PAGE_ORDER)) || 179 104 mpi3mr_alloc_trace_buffer(mrioc, trace_size)) { 105 + 180 106 retry = true; 181 107 trace_size -= trace_dec_size; 182 108 dprint_init(mrioc, "trace diag buffer allocation failed\n" ··· 237 161 u8 prev_status; 238 162 int retval = 0; 239 163 164 + if (diag_buffer->disabled_after_reset) { 165 + dprint_bsg_err(mrioc, "%s: skiping diag buffer posting\n" 166 + "as it is disabled after reset\n", __func__); 167 + return -1; 168 + } 169 + 240 170 memset(&diag_buf_post_req, 0, sizeof(diag_buf_post_req)); 241 171 mutex_lock(&mrioc->init_cmds.mutex); 242 172 if (mrioc->init_cmds.state & MPI3MR_CMD_PENDING) { ··· 259 177 diag_buf_post_req.address = le64_to_cpu(diag_buffer->dma_addr); 260 178 diag_buf_post_req.length = le32_to_cpu(diag_buffer->size); 261 179 262 - dprint_bsg_info(mrioc, "%s: posting diag buffer type %d\n", __func__, 263 - diag_buffer->type); 180 + if (diag_buffer->is_segmented) 181 + diag_buf_post_req.msg_flags |= MPI3_DIAG_BUFFER_POST_MSGFLAGS_SEGMENTED; 182 + 183 + dprint_bsg_info(mrioc, "%s: posting diag buffer type %d segmented:%d\n", __func__, 184 + diag_buffer->type, diag_buffer->is_segmented); 185 + 264 186 prev_status = diag_buffer->status; 265 187 diag_buffer->status = MPI3MR_HDB_BUFSTATUS_POSTED_UNPAUSED; 266 188 init_completion(&mrioc->init_cmds.done); ··· 3147 3061 static DEVICE_ATTR_RO(reply_queue_count); 3148 3062 3149 3063 /** 3064 + * reply_qfull_count_show - Show reply qfull count 3065 + * @dev: class device 3066 + * @attr: Device attributes 3067 + * @buf: Buffer to copy 3068 + * 3069 + * Retrieves the current value of the reply_qfull_count from the mrioc structure and 3070 + * formats it as a string for display. 3071 + * 3072 + * Return: sysfs_emit() return 3073 + */ 3074 + static ssize_t 3075 + reply_qfull_count_show(struct device *dev, struct device_attribute *attr, 3076 + char *buf) 3077 + { 3078 + struct Scsi_Host *shost = class_to_shost(dev); 3079 + struct mpi3mr_ioc *mrioc = shost_priv(shost); 3080 + 3081 + return sysfs_emit(buf, "%u\n", atomic_read(&mrioc->reply_qfull_count)); 3082 + } 3083 + 3084 + static DEVICE_ATTR_RO(reply_qfull_count); 3085 + 3086 + /** 3150 3087 * logging_level_show - Show controller debug level 3151 3088 * @dev: class device 3152 3089 * @attr: Device attributes ··· 3261 3152 &dev_attr_fw_queue_depth.attr, 3262 3153 &dev_attr_op_req_q_count.attr, 3263 3154 &dev_attr_reply_queue_count.attr, 3155 + &dev_attr_reply_qfull_count.attr, 3264 3156 &dev_attr_logging_level.attr, 3265 3157 &dev_attr_adp_state.attr, 3266 3158 NULL,
+133 -11
drivers/scsi/mpi3mr/mpi3mr_fw.c
··· 17 17 struct mpi3_ioc_facts_data *facts_data); 18 18 static void mpi3mr_pel_wait_complete(struct mpi3mr_ioc *mrioc, 19 19 struct mpi3mr_drv_cmd *drv_cmd); 20 - 20 + static int mpi3mr_check_op_admin_proc(struct mpi3mr_ioc *mrioc); 21 21 static int poll_queues; 22 22 module_param(poll_queues, int, 0444); 23 23 MODULE_PARM_DESC(poll_queues, "Number of queues for io_uring poll mode. (Range 1 - 126)"); ··· 459 459 } 460 460 461 461 do { 462 - if (mrioc->unrecoverable) 462 + if (mrioc->unrecoverable || mrioc->io_admin_reset_sync) 463 463 break; 464 464 465 465 mrioc->admin_req_ci = le16_to_cpu(reply_desc->request_queue_ci); ··· 554 554 } 555 555 556 556 do { 557 - if (mrioc->unrecoverable) 557 + if (mrioc->unrecoverable || mrioc->io_admin_reset_sync) 558 558 break; 559 559 560 560 req_q_idx = le16_to_cpu(reply_desc->request_queue_id) - 1; ··· 1302 1302 (ioc_config & MPI3_SYSIF_IOC_CONFIG_ENABLE_IOC))) 1303 1303 retval = 0; 1304 1304 1305 - ioc_info(mrioc, "Base IOC Sts/Config after %s MUR is (0x%x)/(0x%x)\n", 1305 + ioc_info(mrioc, "Base IOC Sts/Config after %s MUR is (0x%08x)/(0x%08x)\n", 1306 1306 (!retval) ? "successful" : "failed", ioc_status, ioc_config); 1307 1307 return retval; 1308 1308 } ··· 1354 1354 "critical error: multipath capability is enabled at the\n" 1355 1355 "\tcontroller while sas transport support is enabled at the\n" 1356 1356 "\tdriver, please reboot the system or reload the driver\n"); 1357 + 1358 + if (mrioc->seg_tb_support) { 1359 + if (!(mrioc->facts.ioc_capabilities & 1360 + MPI3_IOCFACTS_CAPABILITY_SEG_DIAG_TRACE_SUPPORTED)) { 1361 + ioc_err(mrioc, 1362 + "critical error: previously enabled segmented trace\n" 1363 + " buffer capability is disabled after reset. Please\n" 1364 + " update the firmware or reboot the system or\n" 1365 + " reload the driver to enable trace diag buffer\n"); 1366 + mrioc->diag_buffers[0].disabled_after_reset = true; 1367 + } else 1368 + mrioc->diag_buffers[0].disabled_after_reset = false; 1369 + } 1357 1370 1358 1371 if (mrioc->facts.max_devhandle > mrioc->dev_handle_bitmap_bits) { 1359 1372 removepend_bitmap = bitmap_zalloc(mrioc->facts.max_devhandle, ··· 1730 1717 ioc_config = readl(&mrioc->sysif_regs->ioc_configuration); 1731 1718 ioc_status = readl(&mrioc->sysif_regs->ioc_status); 1732 1719 ioc_info(mrioc, 1733 - "ioc_status/ioc_onfig after %s reset is (0x%x)/(0x%x)\n", 1720 + "ioc_status/ioc_config after %s reset is (0x%08x)/(0x%08x)\n", 1734 1721 (!retval)?"successful":"failed", ioc_status, 1735 1722 ioc_config); 1736 1723 if (retval) ··· 2117 2104 } 2118 2105 2119 2106 reply_qid = qidx + 1; 2120 - op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD; 2121 - if ((mrioc->pdev->device == MPI3_MFGPAGE_DEVID_SAS4116) && 2122 - !mrioc->pdev->revision) 2123 - op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD4K; 2107 + 2108 + if (mrioc->pdev->device == MPI3_MFGPAGE_DEVID_SAS4116) { 2109 + if (mrioc->pdev->revision) 2110 + op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD; 2111 + else 2112 + op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD4K; 2113 + } else 2114 + op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD2K; 2115 + 2124 2116 op_reply_q->ci = 0; 2125 2117 op_reply_q->ephase = 1; 2126 2118 atomic_set(&op_reply_q->pend_ios, 0); 2127 2119 atomic_set(&op_reply_q->in_use, 0); 2128 2120 op_reply_q->enable_irq_poll = false; 2121 + op_reply_q->qfull_watermark = 2122 + op_reply_q->num_replies - (MPI3MR_THRESHOLD_REPLY_COUNT * 2); 2129 2123 2130 2124 if (!op_reply_q->q_segments) { 2131 2125 retval = mpi3mr_alloc_op_reply_q_segments(mrioc, qidx); ··· 2436 2416 void *segment_base_addr; 2437 2417 u16 req_sz = mrioc->facts.op_req_sz; 2438 2418 struct segments *segments = op_req_q->q_segments; 2419 + struct op_reply_qinfo *op_reply_q = NULL; 2439 2420 2440 2421 reply_qidx = op_req_q->reply_qid - 1; 2422 + op_reply_q = mrioc->op_reply_qinfo + reply_qidx; 2441 2423 2442 2424 if (mrioc->unrecoverable) 2443 2425 return -EFAULT; ··· 2466 2444 } 2467 2445 if (mrioc->pci_err_recovery) { 2468 2446 ioc_err(mrioc, "operational request queue submission failed due to pci error recovery in progress\n"); 2447 + retval = -EAGAIN; 2448 + goto out; 2449 + } 2450 + 2451 + /* Reply queue is nearing to get full, push back IOs to SML */ 2452 + if ((mrioc->prevent_reply_qfull == true) && 2453 + (atomic_read(&op_reply_q->pend_ios) > 2454 + (op_reply_q->qfull_watermark))) { 2455 + atomic_inc(&mrioc->reply_qfull_count); 2469 2456 retval = -EAGAIN; 2470 2457 goto out; 2471 2458 } ··· 3119 3088 mrioc->facts.max_msix_vectors = le16_to_cpu(facts_data->max_msix_vectors); 3120 3089 mrioc->facts.personality = (facts_flags & 3121 3090 MPI3_IOCFACTS_FLAGS_PERSONALITY_MASK); 3091 + mrioc->facts.dma_mask = (facts_flags & 3092 + MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_MASK) >> 3093 + MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_SHIFT; 3122 3094 mrioc->facts.dma_mask = (facts_flags & 3123 3095 MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_MASK) >> 3124 3096 MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_SHIFT; ··· 4248 4214 mrioc->shost->transportt = mpi3mr_transport_template; 4249 4215 } 4250 4216 4217 + if (mrioc->facts.max_req_limit) 4218 + mrioc->prevent_reply_qfull = true; 4219 + 4220 + if (mrioc->facts.ioc_capabilities & 4221 + MPI3_IOCFACTS_CAPABILITY_SEG_DIAG_TRACE_SUPPORTED) 4222 + mrioc->seg_tb_support = true; 4223 + 4251 4224 mrioc->reply_sz = mrioc->facts.reply_sz; 4252 4225 4253 4226 retval = mpi3mr_check_reset_dma_mask(mrioc); ··· 4411 4370 goto out_failed_noretry; 4412 4371 } 4413 4372 4373 + mrioc->io_admin_reset_sync = 0; 4414 4374 if (is_resume || mrioc->block_on_pci_err) { 4415 4375 dprint_reset(mrioc, "setting up single ISR\n"); 4416 4376 retval = mpi3mr_setup_isr(mrioc, 1); ··· 4713 4671 */ 4714 4672 void mpi3mr_free_mem(struct mpi3mr_ioc *mrioc) 4715 4673 { 4716 - u16 i; 4674 + u16 i, j; 4717 4675 struct mpi3mr_intr_info *intr_info; 4718 4676 struct diag_buffer_desc *diag_buffer; 4719 4677 ··· 4848 4806 4849 4807 for (i = 0; i < MPI3MR_MAX_NUM_HDB; i++) { 4850 4808 diag_buffer = &mrioc->diag_buffers[i]; 4809 + if ((i == 0) && mrioc->seg_tb_support) { 4810 + if (mrioc->trace_buf_pool) { 4811 + for (j = 0; j < mrioc->num_tb_segs; j++) { 4812 + if (mrioc->trace_buf[j].segment) { 4813 + dma_pool_free(mrioc->trace_buf_pool, 4814 + mrioc->trace_buf[j].segment, 4815 + mrioc->trace_buf[j].segment_dma); 4816 + mrioc->trace_buf[j].segment = NULL; 4817 + } 4818 + 4819 + mrioc->trace_buf[j].segment = NULL; 4820 + } 4821 + dma_pool_destroy(mrioc->trace_buf_pool); 4822 + mrioc->trace_buf_pool = NULL; 4823 + } 4824 + 4825 + kfree(mrioc->trace_buf); 4826 + mrioc->trace_buf = NULL; 4827 + diag_buffer->size = sizeof(u64) * mrioc->num_tb_segs; 4828 + } 4851 4829 if (diag_buffer->addr) { 4852 4830 dma_free_coherent(&mrioc->pdev->dev, 4853 4831 diag_buffer->size, diag_buffer->addr, ··· 4945 4883 } 4946 4884 4947 4885 ioc_info(mrioc, 4948 - "Base IOC Sts/Config after %s shutdown is (0x%x)/(0x%x)\n", 4886 + "Base IOC Sts/Config after %s shutdown is (0x%08x)/(0x%08x)\n", 4949 4887 (!retval) ? "successful" : "failed", ioc_status, 4950 4888 ioc_config); 4951 4889 } ··· 5291 5229 } 5292 5230 5293 5231 /** 5232 + * mpi3mr_check_op_admin_proc - 5233 + * @mrioc: Adapter instance reference 5234 + * 5235 + * Check if any of the operation reply queues 5236 + * or the admin reply queue are currently in use. 5237 + * If any queue is in use, this function waits for 5238 + * a maximum of 10 seconds for them to become available. 5239 + * 5240 + * Return: 0 on success, non-zero on failure. 5241 + */ 5242 + static int mpi3mr_check_op_admin_proc(struct mpi3mr_ioc *mrioc) 5243 + { 5244 + 5245 + u16 timeout = 10 * 10; 5246 + u16 elapsed_time = 0; 5247 + bool op_admin_in_use = false; 5248 + 5249 + do { 5250 + op_admin_in_use = false; 5251 + 5252 + /* Check admin_reply queue first to exit early */ 5253 + if (atomic_read(&mrioc->admin_reply_q_in_use) == 1) 5254 + op_admin_in_use = true; 5255 + else { 5256 + /* Check op_reply queues */ 5257 + int i; 5258 + 5259 + for (i = 0; i < mrioc->num_queues; i++) { 5260 + if (atomic_read(&mrioc->op_reply_qinfo[i].in_use) == 1) { 5261 + op_admin_in_use = true; 5262 + break; 5263 + } 5264 + } 5265 + } 5266 + 5267 + if (!op_admin_in_use) 5268 + break; 5269 + 5270 + msleep(100); 5271 + 5272 + } while (++elapsed_time < timeout); 5273 + 5274 + if (op_admin_in_use) 5275 + return 1; 5276 + 5277 + return 0; 5278 + } 5279 + 5280 + /** 5294 5281 * mpi3mr_soft_reset_handler - Reset the controller 5295 5282 * @mrioc: Adapter instance reference 5296 5283 * @reset_reason: Reset reason code ··· 5419 5308 mpi3mr_wait_for_host_io(mrioc, MPI3MR_RESET_HOST_IOWAIT_TIMEOUT); 5420 5309 5421 5310 mpi3mr_ioc_disable_intr(mrioc); 5311 + mrioc->io_admin_reset_sync = 1; 5422 5312 5423 5313 if (snapdump) { 5424 5314 mpi3mr_set_diagsave(mrioc); ··· 5447 5335 ioc_err(mrioc, "Failed to issue soft reset to the ioc\n"); 5448 5336 goto out; 5449 5337 } 5338 + 5339 + retval = mpi3mr_check_op_admin_proc(mrioc); 5340 + if (retval) { 5341 + ioc_err(mrioc, "Soft reset failed due to an Admin or I/O queue polling\n" 5342 + "thread still processing replies even after a 10 second\n" 5343 + "timeout. Marking the controller as unrecoverable!\n"); 5344 + 5345 + goto out; 5346 + } 5347 + 5450 5348 if (mrioc->num_io_throttle_group != 5451 5349 mrioc->facts.max_io_throttle_group) { 5452 5350 ioc_err(mrioc,