forked from mirrors/linux
		
	scsi: mpi3mr: Add Event acknowledgment logic
Add Event acknowledgment logic. Link: https://lore.kernel.org/r/20211220141159.16117-19-sreekanth.reddy@broadcom.com Signed-off-by: Sreekanth Reddy <sreekanth.reddy@broadcom.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
		
							parent
							
								
									c5758fc72b
								
							
						
					
					
						commit
						c1af985d27
					
				
					 3 changed files with 224 additions and 12 deletions
				
			
		|  | @ -97,6 +97,10 @@ extern int prot_mask; | ||||||
| 						MPI3MR_NUM_DEVRMCMD - 1) | 						MPI3MR_NUM_DEVRMCMD - 1) | ||||||
| 
 | 
 | ||||||
| #define MPI3MR_INTERNAL_CMDS_RESVD	MPI3MR_HOSTTAG_DEVRMCMD_MAX | #define MPI3MR_INTERNAL_CMDS_RESVD	MPI3MR_HOSTTAG_DEVRMCMD_MAX | ||||||
|  | #define MPI3MR_NUM_EVTACKCMD		4 | ||||||
|  | #define MPI3MR_HOSTTAG_EVTACKCMD_MIN	(MPI3MR_HOSTTAG_DEVRMCMD_MAX + 1) | ||||||
|  | #define MPI3MR_HOSTTAG_EVTACKCMD_MAX	(MPI3MR_HOSTTAG_EVTACKCMD_MIN + \ | ||||||
|  | 					MPI3MR_NUM_EVTACKCMD - 1) | ||||||
| 
 | 
 | ||||||
| /* Reduced resource count definition for crash kernel */ | /* Reduced resource count definition for crash kernel */ | ||||||
| #define MPI3MR_HOST_IOS_KDUMP		128 | #define MPI3MR_HOST_IOS_KDUMP		128 | ||||||
|  | @ -674,11 +678,15 @@ struct scmd_priv { | ||||||
|  * @chain_buf_lock: Chain buffer list lock |  * @chain_buf_lock: Chain buffer list lock | ||||||
|  * @host_tm_cmds: Command tracker for task management commands |  * @host_tm_cmds: Command tracker for task management commands | ||||||
|  * @dev_rmhs_cmds: Command tracker for device removal commands |  * @dev_rmhs_cmds: Command tracker for device removal commands | ||||||
|  |  * @evtack_cmds: Command tracker for event ack commands | ||||||
|  * @devrem_bitmap_sz: Device removal bitmap size |  * @devrem_bitmap_sz: Device removal bitmap size | ||||||
|  * @devrem_bitmap: Device removal bitmap |  * @devrem_bitmap: Device removal bitmap | ||||||
|  * @dev_handle_bitmap_sz: Device handle bitmap size |  * @dev_handle_bitmap_sz: Device handle bitmap size | ||||||
|  * @removepend_bitmap: Remove pending bitmap |  * @removepend_bitmap: Remove pending bitmap | ||||||
|  * @delayed_rmhs_list: Delayed device removal list |  * @delayed_rmhs_list: Delayed device removal list | ||||||
|  |  * @evtack_cmds_bitmap_sz: Event Ack bitmap size | ||||||
|  |  * @evtack_cmds_bitmap: Event Ack bitmap | ||||||
|  |  * @delayed_evtack_cmds_list: Delayed event acknowledgment list | ||||||
|  * @ts_update_counter: Timestamp update counter |  * @ts_update_counter: Timestamp update counter | ||||||
|  * @reset_in_progress: Reset in progress flag |  * @reset_in_progress: Reset in progress flag | ||||||
|  * @unrecoverable: Controller unrecoverable flag |  * @unrecoverable: Controller unrecoverable flag | ||||||
|  | @ -800,11 +808,15 @@ struct mpi3mr_ioc { | ||||||
| 
 | 
 | ||||||
| 	struct mpi3mr_drv_cmd host_tm_cmds; | 	struct mpi3mr_drv_cmd host_tm_cmds; | ||||||
| 	struct mpi3mr_drv_cmd dev_rmhs_cmds[MPI3MR_NUM_DEVRMCMD]; | 	struct mpi3mr_drv_cmd dev_rmhs_cmds[MPI3MR_NUM_DEVRMCMD]; | ||||||
|  | 	struct mpi3mr_drv_cmd evtack_cmds[MPI3MR_NUM_EVTACKCMD]; | ||||||
| 	u16 devrem_bitmap_sz; | 	u16 devrem_bitmap_sz; | ||||||
| 	void *devrem_bitmap; | 	void *devrem_bitmap; | ||||||
| 	u16 dev_handle_bitmap_sz; | 	u16 dev_handle_bitmap_sz; | ||||||
| 	void *removepend_bitmap; | 	void *removepend_bitmap; | ||||||
| 	struct list_head delayed_rmhs_list; | 	struct list_head delayed_rmhs_list; | ||||||
|  | 	u16 evtack_cmds_bitmap_sz; | ||||||
|  | 	void *evtack_cmds_bitmap; | ||||||
|  | 	struct list_head delayed_evtack_cmds_list; | ||||||
| 
 | 
 | ||||||
| 	u32 ts_update_counter; | 	u32 ts_update_counter; | ||||||
| 	u8 reset_in_progress; | 	u8 reset_in_progress; | ||||||
|  | @ -862,6 +874,18 @@ struct delayed_dev_rmhs_node { | ||||||
| 	u8 iou_rc; | 	u8 iou_rc; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * struct delayed_evt_ack_node - Delayed event ack node | ||||||
|  |  * @list: list head | ||||||
|  |  * @event: MPI3 event ID | ||||||
|  |  * @event_ctx: event context | ||||||
|  |  */ | ||||||
|  | struct delayed_evt_ack_node { | ||||||
|  | 	struct list_head list; | ||||||
|  | 	u8 event; | ||||||
|  | 	u32 event_ctx; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| int mpi3mr_setup_resources(struct mpi3mr_ioc *mrioc); | int mpi3mr_setup_resources(struct mpi3mr_ioc *mrioc); | ||||||
| void mpi3mr_cleanup_resources(struct mpi3mr_ioc *mrioc); | void mpi3mr_cleanup_resources(struct mpi3mr_ioc *mrioc); | ||||||
| int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc); | int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc); | ||||||
|  | @ -898,7 +922,7 @@ void mpi3mr_ioc_disable_intr(struct mpi3mr_ioc *mrioc); | ||||||
| void mpi3mr_ioc_enable_intr(struct mpi3mr_ioc *mrioc); | void mpi3mr_ioc_enable_intr(struct mpi3mr_ioc *mrioc); | ||||||
| 
 | 
 | ||||||
| enum mpi3mr_iocstate mpi3mr_get_iocstate(struct mpi3mr_ioc *mrioc); | enum mpi3mr_iocstate mpi3mr_get_iocstate(struct mpi3mr_ioc *mrioc); | ||||||
| int mpi3mr_send_event_ack(struct mpi3mr_ioc *mrioc, u8 event, | int mpi3mr_process_event_ack(struct mpi3mr_ioc *mrioc, u8 event, | ||||||
| 			  u32 event_ctx); | 			  u32 event_ctx); | ||||||
| 
 | 
 | ||||||
| void mpi3mr_wait_for_host_io(struct mpi3mr_ioc *mrioc, u32 timeout); | void mpi3mr_wait_for_host_io(struct mpi3mr_ioc *mrioc, u32 timeout); | ||||||
|  | @ -906,7 +930,7 @@ void mpi3mr_cleanup_fwevt_list(struct mpi3mr_ioc *mrioc); | ||||||
| void mpi3mr_flush_host_io(struct mpi3mr_ioc *mrioc); | void mpi3mr_flush_host_io(struct mpi3mr_ioc *mrioc); | ||||||
| void mpi3mr_invalidate_devhandles(struct mpi3mr_ioc *mrioc); | void mpi3mr_invalidate_devhandles(struct mpi3mr_ioc *mrioc); | ||||||
| void mpi3mr_rfresh_tgtdevs(struct mpi3mr_ioc *mrioc); | void mpi3mr_rfresh_tgtdevs(struct mpi3mr_ioc *mrioc); | ||||||
| void mpi3mr_flush_delayed_rmhs_list(struct mpi3mr_ioc *mrioc); | void mpi3mr_flush_delayed_cmd_lists(struct mpi3mr_ioc *mrioc); | ||||||
| void mpi3mr_check_rh_fault_ioc(struct mpi3mr_ioc *mrioc, u32 reason_code); | void mpi3mr_check_rh_fault_ioc(struct mpi3mr_ioc *mrioc, u32 reason_code); | ||||||
| void mpi3mr_print_fault_info(struct mpi3mr_ioc *mrioc); | void mpi3mr_print_fault_info(struct mpi3mr_ioc *mrioc); | ||||||
| void mpi3mr_check_rh_fault_ioc(struct mpi3mr_ioc *mrioc, u32 reason_code); | void mpi3mr_check_rh_fault_ioc(struct mpi3mr_ioc *mrioc, u32 reason_code); | ||||||
|  |  | ||||||
|  | @ -312,6 +312,12 @@ mpi3mr_get_drv_cmd(struct mpi3mr_ioc *mrioc, u16 host_tag, | ||||||
| 		return &mrioc->dev_rmhs_cmds[idx]; | 		return &mrioc->dev_rmhs_cmds[idx]; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	if (host_tag >= MPI3MR_HOSTTAG_EVTACKCMD_MIN && | ||||||
|  | 	    host_tag <= MPI3MR_HOSTTAG_EVTACKCMD_MAX) { | ||||||
|  | 		idx = host_tag - MPI3MR_HOSTTAG_EVTACKCMD_MIN; | ||||||
|  | 		return &mrioc->evtack_cmds[idx]; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	return NULL; | 	return NULL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -2691,6 +2697,13 @@ static int mpi3mr_alloc_reply_sense_bufs(struct mpi3mr_ioc *mrioc) | ||||||
| 			goto out_failed; | 			goto out_failed; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	for (i = 0; i < MPI3MR_NUM_EVTACKCMD; i++) { | ||||||
|  | 		mrioc->evtack_cmds[i].reply = kzalloc(mrioc->reply_sz, | ||||||
|  | 		    GFP_KERNEL); | ||||||
|  | 		if (!mrioc->evtack_cmds[i].reply) | ||||||
|  | 			goto out_failed; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	mrioc->host_tm_cmds.reply = kzalloc(mrioc->reply_sz, GFP_KERNEL); | 	mrioc->host_tm_cmds.reply = kzalloc(mrioc->reply_sz, GFP_KERNEL); | ||||||
| 	if (!mrioc->host_tm_cmds.reply) | 	if (!mrioc->host_tm_cmds.reply) | ||||||
| 		goto out_failed; | 		goto out_failed; | ||||||
|  | @ -2711,6 +2724,14 @@ static int mpi3mr_alloc_reply_sense_bufs(struct mpi3mr_ioc *mrioc) | ||||||
| 	if (!mrioc->devrem_bitmap) | 	if (!mrioc->devrem_bitmap) | ||||||
| 		goto out_failed; | 		goto out_failed; | ||||||
| 
 | 
 | ||||||
|  | 	mrioc->evtack_cmds_bitmap_sz = MPI3MR_NUM_EVTACKCMD / 8; | ||||||
|  | 	if (MPI3MR_NUM_EVTACKCMD % 8) | ||||||
|  | 		mrioc->evtack_cmds_bitmap_sz++; | ||||||
|  | 	mrioc->evtack_cmds_bitmap = kzalloc(mrioc->evtack_cmds_bitmap_sz, | ||||||
|  | 	    GFP_KERNEL); | ||||||
|  | 	if (!mrioc->evtack_cmds_bitmap) | ||||||
|  | 		goto out_failed; | ||||||
|  | 
 | ||||||
| 	mrioc->num_reply_bufs = mrioc->facts.max_reqs + MPI3MR_NUM_EVT_REPLIES; | 	mrioc->num_reply_bufs = mrioc->facts.max_reqs + MPI3MR_NUM_EVT_REPLIES; | ||||||
| 	mrioc->reply_free_qsz = mrioc->num_reply_bufs + 1; | 	mrioc->reply_free_qsz = mrioc->num_reply_bufs + 1; | ||||||
| 	mrioc->num_sense_bufs = mrioc->facts.max_reqs / MPI3MR_SENSEBUF_FACTOR; | 	mrioc->num_sense_bufs = mrioc->facts.max_reqs / MPI3MR_SENSEBUF_FACTOR; | ||||||
|  | @ -3030,17 +3051,17 @@ static int mpi3mr_issue_event_notification(struct mpi3mr_ioc *mrioc) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * mpi3mr_send_event_ack - Send event acknowledgment |  * mpi3mr_process_event_ack - Process event acknowledgment | ||||||
|  * @mrioc: Adapter instance reference |  * @mrioc: Adapter instance reference | ||||||
|  * @event: MPI3 event ID |  * @event: MPI3 event ID | ||||||
|  * @event_ctx: Event context |  * @event_ctx: event context | ||||||
|  * |  * | ||||||
|  * Send event acknowledgment through admin queue and wait for |  * Send event acknowledgment through admin queue and wait for | ||||||
|  * it to complete. |  * it to complete. | ||||||
|  * |  * | ||||||
|  * Return: 0 on success, non-zero on failures. |  * Return: 0 on success, non-zero on failures. | ||||||
|  */ |  */ | ||||||
| int mpi3mr_send_event_ack(struct mpi3mr_ioc *mrioc, u8 event, | int mpi3mr_process_event_ack(struct mpi3mr_ioc *mrioc, u8 event, | ||||||
| 	u32 event_ctx) | 	u32 event_ctx) | ||||||
| { | { | ||||||
| 	struct mpi3_event_ack_request evtack_req; | 	struct mpi3_event_ack_request evtack_req; | ||||||
|  | @ -3803,8 +3824,13 @@ void mpi3mr_memset_buffers(struct mpi3mr_ioc *mrioc) | ||||||
| 		for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) | 		for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) | ||||||
| 			memset(mrioc->dev_rmhs_cmds[i].reply, 0, | 			memset(mrioc->dev_rmhs_cmds[i].reply, 0, | ||||||
| 			    sizeof(*mrioc->dev_rmhs_cmds[i].reply)); | 			    sizeof(*mrioc->dev_rmhs_cmds[i].reply)); | ||||||
|  | 		for (i = 0; i < MPI3MR_NUM_EVTACKCMD; i++) | ||||||
|  | 			memset(mrioc->evtack_cmds[i].reply, 0, | ||||||
|  | 			    sizeof(*mrioc->evtack_cmds[i].reply)); | ||||||
| 		memset(mrioc->removepend_bitmap, 0, mrioc->dev_handle_bitmap_sz); | 		memset(mrioc->removepend_bitmap, 0, mrioc->dev_handle_bitmap_sz); | ||||||
| 		memset(mrioc->devrem_bitmap, 0, mrioc->devrem_bitmap_sz); | 		memset(mrioc->devrem_bitmap, 0, mrioc->devrem_bitmap_sz); | ||||||
|  | 		memset(mrioc->evtack_cmds_bitmap, 0, | ||||||
|  | 		    mrioc->evtack_cmds_bitmap_sz); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < mrioc->num_queues; i++) { | 	for (i = 0; i < mrioc->num_queues; i++) { | ||||||
|  | @ -3898,12 +3924,20 @@ void mpi3mr_free_mem(struct mpi3mr_ioc *mrioc) | ||||||
| 	kfree(mrioc->host_tm_cmds.reply); | 	kfree(mrioc->host_tm_cmds.reply); | ||||||
| 	mrioc->host_tm_cmds.reply = NULL; | 	mrioc->host_tm_cmds.reply = NULL; | ||||||
| 
 | 
 | ||||||
|  | 	for (i = 0; i < MPI3MR_NUM_EVTACKCMD; i++) { | ||||||
|  | 		kfree(mrioc->evtack_cmds[i].reply); | ||||||
|  | 		mrioc->evtack_cmds[i].reply = NULL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	kfree(mrioc->removepend_bitmap); | 	kfree(mrioc->removepend_bitmap); | ||||||
| 	mrioc->removepend_bitmap = NULL; | 	mrioc->removepend_bitmap = NULL; | ||||||
| 
 | 
 | ||||||
| 	kfree(mrioc->devrem_bitmap); | 	kfree(mrioc->devrem_bitmap); | ||||||
| 	mrioc->devrem_bitmap = NULL; | 	mrioc->devrem_bitmap = NULL; | ||||||
| 
 | 
 | ||||||
|  | 	kfree(mrioc->evtack_cmds_bitmap); | ||||||
|  | 	mrioc->evtack_cmds_bitmap = NULL; | ||||||
|  | 
 | ||||||
| 	kfree(mrioc->chain_bitmap); | 	kfree(mrioc->chain_bitmap); | ||||||
| 	mrioc->chain_bitmap = NULL; | 	mrioc->chain_bitmap = NULL; | ||||||
| 
 | 
 | ||||||
|  | @ -4079,6 +4113,11 @@ static void mpi3mr_flush_drv_cmds(struct mpi3mr_ioc *mrioc) | ||||||
| 		cmdptr = &mrioc->dev_rmhs_cmds[i]; | 		cmdptr = &mrioc->dev_rmhs_cmds[i]; | ||||||
| 		mpi3mr_drv_cmd_comp_reset(mrioc, cmdptr); | 		mpi3mr_drv_cmd_comp_reset(mrioc, cmdptr); | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < MPI3MR_NUM_EVTACKCMD; i++) { | ||||||
|  | 		cmdptr = &mrioc->evtack_cmds[i]; | ||||||
|  | 		mpi3mr_drv_cmd_comp_reset(mrioc, cmdptr); | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  | @ -4176,10 +4215,11 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc, | ||||||
| 		goto out; | 		goto out; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	mpi3mr_flush_delayed_rmhs_list(mrioc); | 	mpi3mr_flush_delayed_cmd_lists(mrioc); | ||||||
| 	mpi3mr_flush_drv_cmds(mrioc); | 	mpi3mr_flush_drv_cmds(mrioc); | ||||||
| 	memset(mrioc->devrem_bitmap, 0, mrioc->devrem_bitmap_sz); | 	memset(mrioc->devrem_bitmap, 0, mrioc->devrem_bitmap_sz); | ||||||
| 	memset(mrioc->removepend_bitmap, 0, mrioc->dev_handle_bitmap_sz); | 	memset(mrioc->removepend_bitmap, 0, mrioc->dev_handle_bitmap_sz); | ||||||
|  | 	memset(mrioc->evtack_cmds_bitmap, 0, mrioc->evtack_cmds_bitmap_sz); | ||||||
| 	mpi3mr_cleanup_fwevt_list(mrioc); | 	mpi3mr_cleanup_fwevt_list(mrioc); | ||||||
| 	mpi3mr_flush_host_io(mrioc); | 	mpi3mr_flush_host_io(mrioc); | ||||||
| 	mpi3mr_invalidate_devhandles(mrioc); | 	mpi3mr_invalidate_devhandles(mrioc); | ||||||
|  |  | ||||||
|  | @ -34,6 +34,9 @@ MODULE_PARM_DESC(logging_level, | ||||||
| 	" bits for enabling additional logging info (default=0)"); | 	" bits for enabling additional logging info (default=0)"); | ||||||
| 
 | 
 | ||||||
| /* Forward declarations*/ | /* Forward declarations*/ | ||||||
|  | static void mpi3mr_send_event_ack(struct mpi3mr_ioc *mrioc, u8 event, | ||||||
|  | 	struct mpi3mr_drv_cmd *cmdparam, u32 event_ctx); | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * mpi3mr_host_tag_for_scmd - Get host tag for a scmd |  * mpi3mr_host_tag_for_scmd - Get host tag for a scmd | ||||||
|  * @mrioc: Adapter instance reference |  * @mrioc: Adapter instance reference | ||||||
|  | @ -1336,7 +1339,7 @@ static void mpi3mr_fwevt_bh(struct mpi3mr_ioc *mrioc, | ||||||
| 
 | 
 | ||||||
| evt_ack: | evt_ack: | ||||||
| 	if (fwevt->send_ack) | 	if (fwevt->send_ack) | ||||||
| 		mpi3mr_send_event_ack(mrioc, fwevt->event_id, | 		mpi3mr_process_event_ack(mrioc, fwevt->event_id, | ||||||
| 		    fwevt->evt_ctx); | 		    fwevt->evt_ctx); | ||||||
| out: | out: | ||||||
| 	/* Put fwevt reference count to neutralize kref_init increment */ | 	/* Put fwevt reference count to neutralize kref_init increment */ | ||||||
|  | @ -1400,24 +1403,33 @@ static int mpi3mr_create_tgtdev(struct mpi3mr_ioc *mrioc, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * mpi3mr_flush_delayed_rmhs_list - Flush pending commands |  * mpi3mr_flush_delayed_cmd_lists - Flush pending commands | ||||||
|  * @mrioc: Adapter instance reference |  * @mrioc: Adapter instance reference | ||||||
|  * |  * | ||||||
|  * Flush pending commands in the delayed removal handshake list |  * Flush pending commands in the delayed lists due to a | ||||||
|  * due to a controller reset or driver removal as a cleanup. |  * controller reset or driver removal as a cleanup. | ||||||
|  * |  * | ||||||
|  * Return: Nothing |  * Return: Nothing | ||||||
|  */ |  */ | ||||||
| void mpi3mr_flush_delayed_rmhs_list(struct mpi3mr_ioc *mrioc) | void mpi3mr_flush_delayed_cmd_lists(struct mpi3mr_ioc *mrioc) | ||||||
| { | { | ||||||
| 	struct delayed_dev_rmhs_node *_rmhs_node; | 	struct delayed_dev_rmhs_node *_rmhs_node; | ||||||
|  | 	struct delayed_evt_ack_node *_evtack_node; | ||||||
| 
 | 
 | ||||||
|  | 	dprint_reset(mrioc, "flushing delayed dev_remove_hs commands\n"); | ||||||
| 	while (!list_empty(&mrioc->delayed_rmhs_list)) { | 	while (!list_empty(&mrioc->delayed_rmhs_list)) { | ||||||
| 		_rmhs_node = list_entry(mrioc->delayed_rmhs_list.next, | 		_rmhs_node = list_entry(mrioc->delayed_rmhs_list.next, | ||||||
| 		    struct delayed_dev_rmhs_node, list); | 		    struct delayed_dev_rmhs_node, list); | ||||||
| 		list_del(&_rmhs_node->list); | 		list_del(&_rmhs_node->list); | ||||||
| 		kfree(_rmhs_node); | 		kfree(_rmhs_node); | ||||||
| 	} | 	} | ||||||
|  | 	dprint_reset(mrioc, "flushing delayed event ack commands\n"); | ||||||
|  | 	while (!list_empty(&mrioc->delayed_evtack_cmds_list)) { | ||||||
|  | 		_evtack_node = list_entry(mrioc->delayed_evtack_cmds_list.next, | ||||||
|  | 		    struct delayed_evt_ack_node, list); | ||||||
|  | 		list_del(&_evtack_node->list); | ||||||
|  | 		kfree(_evtack_node); | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  | @ -1633,6 +1645,141 @@ static void mpi3mr_dev_rmhs_send_tm(struct mpi3mr_ioc *mrioc, u16 handle, | ||||||
| 	clear_bit(cmd_idx, mrioc->devrem_bitmap); | 	clear_bit(cmd_idx, mrioc->devrem_bitmap); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * mpi3mr_complete_evt_ack - event ack request completion | ||||||
|  |  * @mrioc: Adapter instance reference | ||||||
|  |  * @drv_cmd: Internal command tracker | ||||||
|  |  * | ||||||
|  |  * This is the completion handler for non blocking event | ||||||
|  |  * acknowledgment sent to the firmware and this will issue any | ||||||
|  |  * pending event acknowledgment request. | ||||||
|  |  * | ||||||
|  |  * Return: Nothing | ||||||
|  |  */ | ||||||
|  | static void mpi3mr_complete_evt_ack(struct mpi3mr_ioc *mrioc, | ||||||
|  | 	struct mpi3mr_drv_cmd *drv_cmd) | ||||||
|  | { | ||||||
|  | 	u16 cmd_idx = drv_cmd->host_tag - MPI3MR_HOSTTAG_EVTACKCMD_MIN; | ||||||
|  | 	struct delayed_evt_ack_node *delayed_evtack = NULL; | ||||||
|  | 
 | ||||||
|  | 	if (drv_cmd->ioc_status != MPI3_IOCSTATUS_SUCCESS) { | ||||||
|  | 		dprint_event_th(mrioc, | ||||||
|  | 		    "immediate event ack failed with ioc_status(0x%04x) log_info(0x%08x)\n", | ||||||
|  | 		    (drv_cmd->ioc_status & MPI3_IOCSTATUS_STATUS_MASK), | ||||||
|  | 		    drv_cmd->ioc_loginfo); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!list_empty(&mrioc->delayed_evtack_cmds_list)) { | ||||||
|  | 		delayed_evtack = | ||||||
|  | 			list_entry(mrioc->delayed_evtack_cmds_list.next, | ||||||
|  | 			    struct delayed_evt_ack_node, list); | ||||||
|  | 		mpi3mr_send_event_ack(mrioc, delayed_evtack->event, drv_cmd, | ||||||
|  | 		    delayed_evtack->event_ctx); | ||||||
|  | 		list_del(&delayed_evtack->list); | ||||||
|  | 		kfree(delayed_evtack); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	drv_cmd->state = MPI3MR_CMD_NOTUSED; | ||||||
|  | 	drv_cmd->callback = NULL; | ||||||
|  | 	clear_bit(cmd_idx, mrioc->evtack_cmds_bitmap); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * mpi3mr_send_event_ack - Issue event acknwoledgment request | ||||||
|  |  * @mrioc: Adapter instance reference | ||||||
|  |  * @event: MPI3 event id | ||||||
|  |  * @cmdparam: Internal command tracker | ||||||
|  |  * @event_ctx: event context | ||||||
|  |  * | ||||||
|  |  * Issues event acknowledgment request to the firmware if there | ||||||
|  |  * is a free command to send the event ack else it to a pend | ||||||
|  |  * list so that it will be processed on a completion of a prior | ||||||
|  |  * event acknowledgment . | ||||||
|  |  * | ||||||
|  |  * Return: Nothing | ||||||
|  |  */ | ||||||
|  | static void mpi3mr_send_event_ack(struct mpi3mr_ioc *mrioc, u8 event, | ||||||
|  | 	struct mpi3mr_drv_cmd *cmdparam, u32 event_ctx) | ||||||
|  | { | ||||||
|  | 	struct mpi3_event_ack_request evtack_req; | ||||||
|  | 	int retval = 0; | ||||||
|  | 	u8 retrycount = 5; | ||||||
|  | 	u16 cmd_idx = MPI3MR_NUM_EVTACKCMD; | ||||||
|  | 	struct mpi3mr_drv_cmd *drv_cmd = cmdparam; | ||||||
|  | 	struct delayed_evt_ack_node *delayed_evtack = NULL; | ||||||
|  | 
 | ||||||
|  | 	if (drv_cmd) { | ||||||
|  | 		dprint_event_th(mrioc, | ||||||
|  | 		    "sending delayed event ack in the top half for event(0x%02x), event_ctx(0x%08x)\n", | ||||||
|  | 		    event, event_ctx); | ||||||
|  | 		goto issue_cmd; | ||||||
|  | 	} | ||||||
|  | 	dprint_event_th(mrioc, | ||||||
|  | 	    "sending event ack in the top half for event(0x%02x), event_ctx(0x%08x)\n", | ||||||
|  | 	    event, event_ctx); | ||||||
|  | 	do { | ||||||
|  | 		cmd_idx = find_first_zero_bit(mrioc->evtack_cmds_bitmap, | ||||||
|  | 		    MPI3MR_NUM_EVTACKCMD); | ||||||
|  | 		if (cmd_idx < MPI3MR_NUM_EVTACKCMD) { | ||||||
|  | 			if (!test_and_set_bit(cmd_idx, | ||||||
|  | 			    mrioc->evtack_cmds_bitmap)) | ||||||
|  | 				break; | ||||||
|  | 			cmd_idx = MPI3MR_NUM_EVTACKCMD; | ||||||
|  | 		} | ||||||
|  | 	} while (retrycount--); | ||||||
|  | 
 | ||||||
|  | 	if (cmd_idx >= MPI3MR_NUM_EVTACKCMD) { | ||||||
|  | 		delayed_evtack = kzalloc(sizeof(*delayed_evtack), | ||||||
|  | 		    GFP_ATOMIC); | ||||||
|  | 		if (!delayed_evtack) | ||||||
|  | 			return; | ||||||
|  | 		INIT_LIST_HEAD(&delayed_evtack->list); | ||||||
|  | 		delayed_evtack->event = event; | ||||||
|  | 		delayed_evtack->event_ctx = event_ctx; | ||||||
|  | 		list_add_tail(&delayed_evtack->list, | ||||||
|  | 		    &mrioc->delayed_evtack_cmds_list); | ||||||
|  | 		dprint_event_th(mrioc, | ||||||
|  | 		    "event ack in the top half for event(0x%02x), event_ctx(0x%08x) is postponed\n", | ||||||
|  | 		    event, event_ctx); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	drv_cmd = &mrioc->evtack_cmds[cmd_idx]; | ||||||
|  | 
 | ||||||
|  | issue_cmd: | ||||||
|  | 	cmd_idx = drv_cmd->host_tag - MPI3MR_HOSTTAG_EVTACKCMD_MIN; | ||||||
|  | 
 | ||||||
|  | 	memset(&evtack_req, 0, sizeof(evtack_req)); | ||||||
|  | 	if (drv_cmd->state & MPI3MR_CMD_PENDING) { | ||||||
|  | 		dprint_event_th(mrioc, | ||||||
|  | 		    "sending event ack failed due to command in use\n"); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 	drv_cmd->state = MPI3MR_CMD_PENDING; | ||||||
|  | 	drv_cmd->is_waiting = 0; | ||||||
|  | 	drv_cmd->callback = mpi3mr_complete_evt_ack; | ||||||
|  | 	evtack_req.host_tag = cpu_to_le16(drv_cmd->host_tag); | ||||||
|  | 	evtack_req.function = MPI3_FUNCTION_EVENT_ACK; | ||||||
|  | 	evtack_req.event = event; | ||||||
|  | 	evtack_req.event_context = cpu_to_le32(event_ctx); | ||||||
|  | 	retval = mpi3mr_admin_request_post(mrioc, &evtack_req, | ||||||
|  | 	    sizeof(evtack_req), 1); | ||||||
|  | 	if (retval) { | ||||||
|  | 		dprint_event_th(mrioc, | ||||||
|  | 		    "posting event ack request is failed\n"); | ||||||
|  | 		goto out_failed; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	dprint_event_th(mrioc, | ||||||
|  | 	    "event ack in the top half for event(0x%02x), event_ctx(0x%08x) is posted\n", | ||||||
|  | 	    event, event_ctx); | ||||||
|  | out: | ||||||
|  | 	return; | ||||||
|  | out_failed: | ||||||
|  | 	drv_cmd->state = MPI3MR_CMD_NOTUSED; | ||||||
|  | 	drv_cmd->callback = NULL; | ||||||
|  | 	clear_bit(cmd_idx, mrioc->evtack_cmds_bitmap); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * mpi3mr_pcietopochg_evt_th - PCIETopologyChange evt tophalf |  * mpi3mr_pcietopochg_evt_th - PCIETopologyChange evt tophalf | ||||||
|  * @mrioc: Adapter instance reference |  * @mrioc: Adapter instance reference | ||||||
|  | @ -3773,6 +3920,7 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id) | ||||||
| 	INIT_LIST_HEAD(&mrioc->fwevt_list); | 	INIT_LIST_HEAD(&mrioc->fwevt_list); | ||||||
| 	INIT_LIST_HEAD(&mrioc->tgtdev_list); | 	INIT_LIST_HEAD(&mrioc->tgtdev_list); | ||||||
| 	INIT_LIST_HEAD(&mrioc->delayed_rmhs_list); | 	INIT_LIST_HEAD(&mrioc->delayed_rmhs_list); | ||||||
|  | 	INIT_LIST_HEAD(&mrioc->delayed_evtack_cmds_list); | ||||||
| 
 | 
 | ||||||
| 	mutex_init(&mrioc->reset_mutex); | 	mutex_init(&mrioc->reset_mutex); | ||||||
| 	mpi3mr_init_drv_cmd(&mrioc->init_cmds, MPI3MR_HOSTTAG_INITCMDS); | 	mpi3mr_init_drv_cmd(&mrioc->init_cmds, MPI3MR_HOSTTAG_INITCMDS); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Sreekanth Reddy
						Sreekanth Reddy