Skip to content

Commit 43ca110

Browse files
sumitsaxena11martinkpetersen
authored andcommitted
scsi: mpi3mr: Add support for PEL commands
Implement driver support for management applications to enable persistent event log (PEL) notifications. Upon receipt of events, the driver will increment a sysfs variable named event_counter. The management application will poll for event_counter value changes and signal the application about events. Link: https://lore.kernel.org/r/20220429211641.642010-6-sumit.saxena@broadcom.com Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com> Signed-off-by: Sumit Saxena <sumit.saxena@broadcom.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent 506bc1a commit 43ca110

File tree

4 files changed

+592
-1
lines changed

4 files changed

+592
-1
lines changed

drivers/scsi/mpi3mr/mpi3mr.h

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
extern spinlock_t mrioc_list_lock;
5454
extern struct list_head mrioc_list;
5555
extern int prot_mask;
56+
extern atomic64_t event_counter;
5657

5758
#define MPI3MR_DRIVER_VERSION "8.0.0.68.0"
5859
#define MPI3MR_DRIVER_RELDATE "10-February-2022"
@@ -91,6 +92,8 @@ extern int prot_mask;
9192
#define MPI3MR_HOSTTAG_INVALID 0xFFFF
9293
#define MPI3MR_HOSTTAG_INITCMDS 1
9394
#define MPI3MR_HOSTTAG_BSG_CMDS 2
95+
#define MPI3MR_HOSTTAG_PEL_ABORT 3
96+
#define MPI3MR_HOSTTAG_PEL_WAIT 4
9497
#define MPI3MR_HOSTTAG_BLK_TMS 5
9598

9699
#define MPI3MR_NUM_DEVRMCMD 16
@@ -152,6 +155,7 @@ extern int prot_mask;
152155

153156
/* Command retry count definitions */
154157
#define MPI3MR_DEV_RMHS_RETRY_COUNT 3
158+
#define MPI3MR_PEL_RETRY_COUNT 3
155159

156160
/* Default target device queue depth */
157161
#define MPI3MR_DEFAULT_SDEV_QD 32
@@ -748,6 +752,16 @@ struct scmd_priv {
748752
* @current_event: Firmware event currently in process
749753
* @driver_info: Driver, Kernel, OS information to firmware
750754
* @change_count: Topology change count
755+
* @pel_enabled: Persistent Event Log(PEL) enabled or not
756+
* @pel_abort_requested: PEL abort is requested or not
757+
* @pel_class: PEL Class identifier
758+
* @pel_locale: PEL Locale identifier
759+
* @pel_cmds: Command tracker for PEL wait command
760+
* @pel_abort_cmd: Command tracker for PEL abort command
761+
* @pel_newest_seqnum: Newest PEL sequenece number
762+
* @pel_seqnum_virt: PEL sequence number virtual address
763+
* @pel_seqnum_dma: PEL sequence number DMA address
764+
* @pel_seqnum_sz: PEL sequenece number size
751765
* @op_reply_q_offset: Operational reply queue offset with MSIx
752766
* @default_qcount: Total Default queues
753767
* @active_poll_qcount: Currently active poll queue count
@@ -894,8 +908,20 @@ struct mpi3mr_ioc {
894908
struct mpi3mr_fwevt *current_event;
895909
struct mpi3_driver_info_layout driver_info;
896910
u16 change_count;
897-
u16 op_reply_q_offset;
898911

912+
u8 pel_enabled;
913+
u8 pel_abort_requested;
914+
u8 pel_class;
915+
u16 pel_locale;
916+
struct mpi3mr_drv_cmd pel_cmds;
917+
struct mpi3mr_drv_cmd pel_abort_cmd;
918+
919+
u32 pel_newest_seqnum;
920+
void *pel_seqnum_virt;
921+
dma_addr_t pel_seqnum_dma;
922+
u32 pel_seqnum_sz;
923+
924+
u16 op_reply_q_offset;
899925
u16 default_qcount;
900926
u16 active_poll_qcount;
901927
u16 requested_poll_qcount;
@@ -918,6 +944,7 @@ struct mpi3mr_ioc {
918944
* @send_ack: Event acknowledgment required or not
919945
* @process_evt: Bottomhalf processing required or not
920946
* @evt_ctx: Event context to send in Ack
947+
* @event_data_size: size of the event data in bytes
921948
* @pending_at_sml: waiting for device add/remove API to complete
922949
* @discard: discard this event
923950
* @ref_count: kref count
@@ -931,6 +958,7 @@ struct mpi3mr_fwevt {
931958
bool send_ack;
932959
bool process_evt;
933960
u32 evt_ctx;
961+
u16 event_data_size;
934962
bool pending_at_sml;
935963
bool discard;
936964
struct kref ref_count;
@@ -1022,5 +1050,11 @@ int mpi3mr_issue_tm(struct mpi3mr_ioc *mrioc, u8 tm_type,
10221050
u8 *resp_code, struct scsi_cmnd *scmd);
10231051
struct mpi3mr_tgt_dev *mpi3mr_get_tgtdev_by_handle(
10241052
struct mpi3mr_ioc *mrioc, u16 handle);
1053+
void mpi3mr_pel_get_seqnum_complete(struct mpi3mr_ioc *mrioc,
1054+
struct mpi3mr_drv_cmd *drv_cmd);
1055+
int mpi3mr_pel_get_seqnum_post(struct mpi3mr_ioc *mrioc,
1056+
struct mpi3mr_drv_cmd *drv_cmd);
1057+
void mpi3mr_app_save_logdata(struct mpi3mr_ioc *mrioc, char *event_data,
1058+
u16 event_data_size);
10251059

10261060
#endif /*MPI3MR_H_INCLUDED*/

drivers/scsi/mpi3mr/mpi3mr_app.c

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,95 @@
1111
#include <linux/bsg-lib.h>
1212
#include <uapi/scsi/scsi_bsg_mpi3mr.h>
1313

14+
/**
15+
* mpi3mr_bsg_pel_abort - sends PEL abort request
16+
* @mrioc: Adapter instance reference
17+
*
18+
* This function sends PEL abort request to the firmware through
19+
* admin request queue.
20+
*
21+
* Return: 0 on success, -1 on failure
22+
*/
23+
static int mpi3mr_bsg_pel_abort(struct mpi3mr_ioc *mrioc)
24+
{
25+
struct mpi3_pel_req_action_abort pel_abort_req;
26+
struct mpi3_pel_reply *pel_reply;
27+
int retval = 0;
28+
u16 pe_log_status;
29+
30+
if (mrioc->reset_in_progress) {
31+
dprint_bsg_err(mrioc, "%s: reset in progress\n", __func__);
32+
return -1;
33+
}
34+
if (mrioc->stop_bsgs) {
35+
dprint_bsg_err(mrioc, "%s: bsgs are blocked\n", __func__);
36+
return -1;
37+
}
38+
39+
memset(&pel_abort_req, 0, sizeof(pel_abort_req));
40+
mutex_lock(&mrioc->pel_abort_cmd.mutex);
41+
if (mrioc->pel_abort_cmd.state & MPI3MR_CMD_PENDING) {
42+
dprint_bsg_err(mrioc, "%s: command is in use\n", __func__);
43+
mutex_unlock(&mrioc->pel_abort_cmd.mutex);
44+
return -1;
45+
}
46+
mrioc->pel_abort_cmd.state = MPI3MR_CMD_PENDING;
47+
mrioc->pel_abort_cmd.is_waiting = 1;
48+
mrioc->pel_abort_cmd.callback = NULL;
49+
pel_abort_req.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_PEL_ABORT);
50+
pel_abort_req.function = MPI3_FUNCTION_PERSISTENT_EVENT_LOG;
51+
pel_abort_req.action = MPI3_PEL_ACTION_ABORT;
52+
pel_abort_req.abort_host_tag = cpu_to_le16(MPI3MR_HOSTTAG_PEL_WAIT);
53+
54+
mrioc->pel_abort_requested = 1;
55+
init_completion(&mrioc->pel_abort_cmd.done);
56+
retval = mpi3mr_admin_request_post(mrioc, &pel_abort_req,
57+
sizeof(pel_abort_req), 0);
58+
if (retval) {
59+
retval = -1;
60+
dprint_bsg_err(mrioc, "%s: admin request post failed\n",
61+
__func__);
62+
mrioc->pel_abort_requested = 0;
63+
goto out_unlock;
64+
}
65+
66+
wait_for_completion_timeout(&mrioc->pel_abort_cmd.done,
67+
(MPI3MR_INTADMCMD_TIMEOUT * HZ));
68+
if (!(mrioc->pel_abort_cmd.state & MPI3MR_CMD_COMPLETE)) {
69+
mrioc->pel_abort_cmd.is_waiting = 0;
70+
dprint_bsg_err(mrioc, "%s: command timedout\n", __func__);
71+
if (!(mrioc->pel_abort_cmd.state & MPI3MR_CMD_RESET))
72+
mpi3mr_soft_reset_handler(mrioc,
73+
MPI3MR_RESET_FROM_PELABORT_TIMEOUT, 1);
74+
retval = -1;
75+
goto out_unlock;
76+
}
77+
if ((mrioc->pel_abort_cmd.ioc_status & MPI3_IOCSTATUS_STATUS_MASK)
78+
!= MPI3_IOCSTATUS_SUCCESS) {
79+
dprint_bsg_err(mrioc,
80+
"%s: command failed, ioc_status(0x%04x) log_info(0x%08x)\n",
81+
__func__, (mrioc->pel_abort_cmd.ioc_status &
82+
MPI3_IOCSTATUS_STATUS_MASK),
83+
mrioc->pel_abort_cmd.ioc_loginfo);
84+
retval = -1;
85+
goto out_unlock;
86+
}
87+
if (mrioc->pel_abort_cmd.state & MPI3MR_CMD_REPLY_VALID) {
88+
pel_reply = (struct mpi3_pel_reply *)mrioc->pel_abort_cmd.reply;
89+
pe_log_status = le16_to_cpu(pel_reply->pe_log_status);
90+
if (pe_log_status != MPI3_PEL_STATUS_SUCCESS) {
91+
dprint_bsg_err(mrioc,
92+
"%s: command failed, pel_status(0x%04x)\n",
93+
__func__, pe_log_status);
94+
retval = -1;
95+
}
96+
}
97+
98+
out_unlock:
99+
mrioc->pel_abort_cmd.state = MPI3MR_CMD_NOTUSED;
100+
mutex_unlock(&mrioc->pel_abort_cmd.mutex);
101+
return retval;
102+
}
14103
/**
15104
* mpi3mr_bsg_verify_adapter - verify adapter number is valid
16105
* @ioc_number: Adapter number
@@ -107,6 +196,87 @@ static long mpi3mr_get_logdata(struct mpi3mr_ioc *mrioc,
107196
return -EINVAL;
108197
}
109198

199+
/**
200+
* mpi3mr_bsg_pel_enable - Handler for PEL enable driver
201+
* @mrioc: Adapter instance reference
202+
* @job: BSG job pointer
203+
*
204+
* This function is the handler for PEL enable driver.
205+
* Validates the application given class and locale and if
206+
* requires aborts the existing PEL wait request and/or issues
207+
* new PEL wait request to the firmware and returns.
208+
*
209+
* Return: 0 on success and proper error codes on failure.
210+
*/
211+
static long mpi3mr_bsg_pel_enable(struct mpi3mr_ioc *mrioc,
212+
struct bsg_job *job)
213+
{
214+
long rval = -EINVAL;
215+
struct mpi3mr_bsg_out_pel_enable pel_enable;
216+
u8 issue_pel_wait;
217+
u8 tmp_class;
218+
u16 tmp_locale;
219+
220+
if (job->request_payload.payload_len != sizeof(pel_enable)) {
221+
dprint_bsg_err(mrioc, "%s: invalid size argument\n",
222+
__func__);
223+
return rval;
224+
}
225+
226+
sg_copy_to_buffer(job->request_payload.sg_list,
227+
job->request_payload.sg_cnt,
228+
&pel_enable, sizeof(pel_enable));
229+
230+
if (pel_enable.pel_class > MPI3_PEL_CLASS_FAULT) {
231+
dprint_bsg_err(mrioc, "%s: out of range class %d sent\n",
232+
__func__, pel_enable.pel_class);
233+
rval = 0;
234+
goto out;
235+
}
236+
if (!mrioc->pel_enabled)
237+
issue_pel_wait = 1;
238+
else {
239+
if ((mrioc->pel_class <= pel_enable.pel_class) &&
240+
!((mrioc->pel_locale & pel_enable.pel_locale) ^
241+
pel_enable.pel_locale)) {
242+
issue_pel_wait = 0;
243+
rval = 0;
244+
} else {
245+
pel_enable.pel_locale |= mrioc->pel_locale;
246+
247+
if (mrioc->pel_class < pel_enable.pel_class)
248+
pel_enable.pel_class = mrioc->pel_class;
249+
250+
rval = mpi3mr_bsg_pel_abort(mrioc);
251+
if (rval) {
252+
dprint_bsg_err(mrioc,
253+
"%s: pel_abort failed, status(%ld)\n",
254+
__func__, rval);
255+
goto out;
256+
}
257+
issue_pel_wait = 1;
258+
}
259+
}
260+
if (issue_pel_wait) {
261+
tmp_class = mrioc->pel_class;
262+
tmp_locale = mrioc->pel_locale;
263+
mrioc->pel_class = pel_enable.pel_class;
264+
mrioc->pel_locale = pel_enable.pel_locale;
265+
mrioc->pel_enabled = 1;
266+
rval = mpi3mr_pel_get_seqnum_post(mrioc, NULL);
267+
if (rval) {
268+
mrioc->pel_class = tmp_class;
269+
mrioc->pel_locale = tmp_locale;
270+
mrioc->pel_enabled = 0;
271+
dprint_bsg_err(mrioc,
272+
"%s: pel get sequence number failed, status(%ld)\n",
273+
__func__, rval);
274+
}
275+
}
276+
277+
out:
278+
return rval;
279+
}
110280
/**
111281
* mpi3mr_get_all_tgt_info - Get all target information
112282
* @mrioc: Adapter instance reference
@@ -372,6 +542,9 @@ static long mpi3mr_bsg_process_drv_cmds(struct bsg_job *job)
372542
case MPI3MR_DRVBSG_OPCODE_GETLOGDATA:
373543
rval = mpi3mr_get_logdata(mrioc, job);
374544
break;
545+
case MPI3MR_DRVBSG_OPCODE_PELENABLE:
546+
rval = mpi3mr_bsg_pel_enable(mrioc, job);
547+
break;
375548
case MPI3MR_DRVBSG_OPCODE_UNKNOWN:
376549
default:
377550
pr_err("%s: unsupported driver command opcode %d\n",
@@ -897,6 +1070,38 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job, unsigned int *reply
8971070
return rval;
8981071
}
8991072

1073+
/**
1074+
* mpi3mr_app_save_logdata - Save Log Data events
1075+
* @mrioc: Adapter instance reference
1076+
* @event_data: event data associated with log data event
1077+
* @event_data_size: event data size to copy
1078+
*
1079+
* If log data event caching is enabled by the applicatiobns,
1080+
* then this function saves the log data in the circular queue
1081+
* and Sends async signal SIGIO to indicate there is an async
1082+
* event from the firmware to the event monitoring applications.
1083+
*
1084+
* Return:Nothing
1085+
*/
1086+
void mpi3mr_app_save_logdata(struct mpi3mr_ioc *mrioc, char *event_data,
1087+
u16 event_data_size)
1088+
{
1089+
u32 index = mrioc->logdata_buf_idx, sz;
1090+
struct mpi3mr_logdata_entry *entry;
1091+
1092+
if (!(mrioc->logdata_buf))
1093+
return;
1094+
1095+
entry = (struct mpi3mr_logdata_entry *)
1096+
(mrioc->logdata_buf + (index * mrioc->logdata_entry_sz));
1097+
entry->valid_entry = 1;
1098+
sz = min(mrioc->logdata_entry_sz, event_data_size);
1099+
memcpy(entry->data, event_data, sz);
1100+
mrioc->logdata_buf_idx =
1101+
((++index) % MPI3MR_BSG_LOGDATA_MAX_ENTRIES);
1102+
atomic64_inc(&event_counter);
1103+
}
1104+
9001105
/**
9011106
* mpi3mr_bsg_request - bsg request entry point
9021107
* @job: BSG job reference

0 commit comments

Comments
 (0)