0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046 #include <linux/kernel.h>
0047 #include <linux/module.h>
0048 #include <linux/errno.h>
0049 #include <linux/init.h>
0050 #include <linux/slab.h>
0051 #include <linux/types.h>
0052 #include <linux/pci.h>
0053 #include <linux/delay.h>
0054 #include <linux/compat.h>
0055 #include <linux/poll.h>
0056
0057 #include <linux/io.h>
0058 #include <linux/uaccess.h>
0059
0060 #include "mpt3sas_base.h"
0061
0062
0063
0064
0065
0066
0067 static void
0068 _mpt3sas_raise_sigio(struct MPT3SAS_ADAPTER *ioc,
0069 struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data)
0070 {
0071 Mpi2EventNotificationReply_t *mpi_reply;
0072 u16 sz, event_data_sz;
0073 unsigned long flags;
0074
0075 dTriggerDiagPrintk(ioc, ioc_info(ioc, "%s: enter\n", __func__));
0076
0077 sz = offsetof(Mpi2EventNotificationReply_t, EventData) +
0078 sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T) + 4;
0079 mpi_reply = kzalloc(sz, GFP_KERNEL);
0080 if (!mpi_reply)
0081 goto out;
0082 mpi_reply->Event = cpu_to_le16(MPI3_EVENT_DIAGNOSTIC_TRIGGER_FIRED);
0083 event_data_sz = (sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T) + 4) / 4;
0084 mpi_reply->EventDataLength = cpu_to_le16(event_data_sz);
0085 memcpy(&mpi_reply->EventData, event_data,
0086 sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T));
0087 dTriggerDiagPrintk(ioc,
0088 ioc_info(ioc, "%s: add to driver event log\n",
0089 __func__));
0090 mpt3sas_ctl_add_to_event_log(ioc, mpi_reply);
0091 kfree(mpi_reply);
0092 out:
0093
0094
0095 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
0096 dTriggerDiagPrintk(ioc,
0097 ioc_info(ioc, "%s: clearing diag_trigger_active flag\n",
0098 __func__));
0099 ioc->diag_trigger_active = 0;
0100 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
0101
0102 dTriggerDiagPrintk(ioc, ioc_info(ioc, "%s: exit\n",
0103 __func__));
0104 }
0105
0106
0107
0108
0109
0110
0111 void
0112 mpt3sas_process_trigger_data(struct MPT3SAS_ADAPTER *ioc,
0113 struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data)
0114 {
0115 u8 issue_reset = 0;
0116 u32 *trig_data = (u32 *)&event_data->u.master;
0117
0118 dTriggerDiagPrintk(ioc, ioc_info(ioc, "%s: enter\n", __func__));
0119
0120
0121 if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
0122 MPT3_DIAG_BUFFER_IS_RELEASED) == 0) {
0123
0124
0125
0126
0127 ioc_info(ioc,
0128 "%s: Releasing the trace buffer. Trigger_Type 0x%08x, Data[0] 0x%08x, Data[1] 0x%08x\n",
0129 __func__, event_data->trigger_type,
0130 trig_data[0], trig_data[1]);
0131 mpt3sas_send_diag_release(ioc, MPI2_DIAG_BUF_TYPE_TRACE,
0132 &issue_reset);
0133 }
0134
0135 ioc->htb_rel.buffer_rel_condition = MPT3_DIAG_BUFFER_REL_TRIGGER;
0136 if (event_data) {
0137 ioc->htb_rel.trigger_type = event_data->trigger_type;
0138 switch (event_data->trigger_type) {
0139 case MPT3SAS_TRIGGER_SCSI:
0140 memcpy(&ioc->htb_rel.trigger_info_dwords,
0141 &event_data->u.scsi,
0142 sizeof(struct SL_WH_SCSI_TRIGGER_T));
0143 break;
0144 case MPT3SAS_TRIGGER_MPI:
0145 memcpy(&ioc->htb_rel.trigger_info_dwords,
0146 &event_data->u.mpi,
0147 sizeof(struct SL_WH_MPI_TRIGGER_T));
0148 break;
0149 case MPT3SAS_TRIGGER_MASTER:
0150 ioc->htb_rel.trigger_info_dwords[0] =
0151 event_data->u.master.MasterData;
0152 break;
0153 case MPT3SAS_TRIGGER_EVENT:
0154 memcpy(&ioc->htb_rel.trigger_info_dwords,
0155 &event_data->u.event,
0156 sizeof(struct SL_WH_EVENT_TRIGGER_T));
0157 break;
0158 default:
0159 ioc_err(ioc, "%d - Is not a valid Trigger type\n",
0160 event_data->trigger_type);
0161 break;
0162 }
0163 }
0164 _mpt3sas_raise_sigio(ioc, event_data);
0165
0166 dTriggerDiagPrintk(ioc, ioc_info(ioc, "%s: exit\n",
0167 __func__));
0168 }
0169
0170
0171
0172
0173
0174
0175
0176 void
0177 mpt3sas_trigger_master(struct MPT3SAS_ADAPTER *ioc, u32 trigger_bitmask)
0178 {
0179 struct SL_WH_TRIGGERS_EVENT_DATA_T event_data;
0180 unsigned long flags;
0181 u8 found_match = 0;
0182
0183 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
0184
0185 if (trigger_bitmask & MASTER_TRIGGER_FW_FAULT ||
0186 trigger_bitmask & MASTER_TRIGGER_ADAPTER_RESET)
0187 goto by_pass_checks;
0188
0189
0190 if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
0191 MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
0192 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
0193 return;
0194 }
0195
0196
0197 if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
0198 MPT3_DIAG_BUFFER_IS_RELEASED) {
0199 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
0200 return;
0201 }
0202
0203 by_pass_checks:
0204
0205 dTriggerDiagPrintk(ioc,
0206 ioc_info(ioc, "%s: enter - trigger_bitmask = 0x%08x\n",
0207 __func__, trigger_bitmask));
0208
0209
0210 if (ioc->diag_trigger_active) {
0211 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
0212 goto out;
0213 }
0214
0215
0216 if (ioc->diag_trigger_master.MasterData & trigger_bitmask) {
0217 found_match = 1;
0218 ioc->diag_trigger_active = 1;
0219 dTriggerDiagPrintk(ioc,
0220 ioc_info(ioc, "%s: setting diag_trigger_active flag\n",
0221 __func__));
0222 }
0223 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
0224
0225 if (!found_match)
0226 goto out;
0227
0228 memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T));
0229 event_data.trigger_type = MPT3SAS_TRIGGER_MASTER;
0230 event_data.u.master.MasterData = trigger_bitmask;
0231
0232 if (trigger_bitmask & MASTER_TRIGGER_FW_FAULT ||
0233 trigger_bitmask & MASTER_TRIGGER_ADAPTER_RESET) {
0234 ioc->htb_rel.trigger_type = MPT3SAS_TRIGGER_MASTER;
0235 ioc->htb_rel.trigger_info_dwords[0] = trigger_bitmask;
0236 if (ioc->reset_from_user)
0237 ioc->htb_rel.trigger_info_dwords[1] =
0238 MPT_DIAG_RESET_ISSUED_BY_USER;
0239 _mpt3sas_raise_sigio(ioc, &event_data);
0240 } else
0241 mpt3sas_send_trigger_data_event(ioc, &event_data);
0242
0243 out:
0244 dTriggerDiagPrintk(ioc, ioc_info(ioc, "%s: exit\n",
0245 __func__));
0246 }
0247
0248
0249
0250
0251
0252
0253
0254
0255 void
0256 mpt3sas_trigger_event(struct MPT3SAS_ADAPTER *ioc, u16 event,
0257 u16 log_entry_qualifier)
0258 {
0259 struct SL_WH_TRIGGERS_EVENT_DATA_T event_data;
0260 struct SL_WH_EVENT_TRIGGER_T *event_trigger;
0261 int i;
0262 unsigned long flags;
0263 u8 found_match;
0264
0265 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
0266
0267
0268 if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
0269 MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
0270 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
0271 return;
0272 }
0273
0274
0275 if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
0276 MPT3_DIAG_BUFFER_IS_RELEASED) {
0277 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
0278 return;
0279 }
0280
0281 dTriggerDiagPrintk(ioc,
0282 ioc_info(ioc, "%s: enter - event = 0x%04x, log_entry_qualifier = 0x%04x\n",
0283 __func__, event, log_entry_qualifier));
0284
0285
0286 if (ioc->diag_trigger_active) {
0287 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
0288 goto out;
0289 }
0290
0291
0292 event_trigger = ioc->diag_trigger_event.EventTriggerEntry;
0293 for (i = 0 , found_match = 0; i < ioc->diag_trigger_event.ValidEntries
0294 && !found_match; i++, event_trigger++) {
0295 if (event_trigger->EventValue != event)
0296 continue;
0297 if (event == MPI2_EVENT_LOG_ENTRY_ADDED) {
0298 if (event_trigger->LogEntryQualifier ==
0299 log_entry_qualifier)
0300 found_match = 1;
0301 continue;
0302 }
0303 found_match = 1;
0304 ioc->diag_trigger_active = 1;
0305 dTriggerDiagPrintk(ioc,
0306 ioc_info(ioc, "%s: setting diag_trigger_active flag\n",
0307 __func__));
0308 }
0309 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
0310
0311 if (!found_match)
0312 goto out;
0313
0314 dTriggerDiagPrintk(ioc,
0315 ioc_info(ioc, "%s: setting diag_trigger_active flag\n",
0316 __func__));
0317 memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T));
0318 event_data.trigger_type = MPT3SAS_TRIGGER_EVENT;
0319 event_data.u.event.EventValue = event;
0320 event_data.u.event.LogEntryQualifier = log_entry_qualifier;
0321 mpt3sas_send_trigger_data_event(ioc, &event_data);
0322 out:
0323 dTriggerDiagPrintk(ioc, ioc_info(ioc, "%s: exit\n",
0324 __func__));
0325 }
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335 void
0336 mpt3sas_trigger_scsi(struct MPT3SAS_ADAPTER *ioc, u8 sense_key, u8 asc,
0337 u8 ascq)
0338 {
0339 struct SL_WH_TRIGGERS_EVENT_DATA_T event_data;
0340 struct SL_WH_SCSI_TRIGGER_T *scsi_trigger;
0341 int i;
0342 unsigned long flags;
0343 u8 found_match;
0344
0345 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
0346
0347
0348 if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
0349 MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
0350 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
0351 return;
0352 }
0353
0354
0355 if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
0356 MPT3_DIAG_BUFFER_IS_RELEASED) {
0357 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
0358 return;
0359 }
0360
0361 dTriggerDiagPrintk(ioc,
0362 ioc_info(ioc, "%s: enter - sense_key = 0x%02x, asc = 0x%02x, ascq = 0x%02x\n",
0363 __func__, sense_key, asc, ascq));
0364
0365
0366 if (ioc->diag_trigger_active) {
0367 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
0368 goto out;
0369 }
0370
0371
0372 scsi_trigger = ioc->diag_trigger_scsi.SCSITriggerEntry;
0373 for (i = 0 , found_match = 0; i < ioc->diag_trigger_scsi.ValidEntries
0374 && !found_match; i++, scsi_trigger++) {
0375 if (scsi_trigger->SenseKey != sense_key)
0376 continue;
0377 if (!(scsi_trigger->ASC == 0xFF || scsi_trigger->ASC == asc))
0378 continue;
0379 if (!(scsi_trigger->ASCQ == 0xFF || scsi_trigger->ASCQ == ascq))
0380 continue;
0381 found_match = 1;
0382 ioc->diag_trigger_active = 1;
0383 }
0384 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
0385
0386 if (!found_match)
0387 goto out;
0388
0389 dTriggerDiagPrintk(ioc,
0390 ioc_info(ioc, "%s: setting diag_trigger_active flag\n",
0391 __func__));
0392 memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T));
0393 event_data.trigger_type = MPT3SAS_TRIGGER_SCSI;
0394 event_data.u.scsi.SenseKey = sense_key;
0395 event_data.u.scsi.ASC = asc;
0396 event_data.u.scsi.ASCQ = ascq;
0397 mpt3sas_send_trigger_data_event(ioc, &event_data);
0398 out:
0399 dTriggerDiagPrintk(ioc, ioc_info(ioc, "%s: exit\n",
0400 __func__));
0401 }
0402
0403
0404
0405
0406
0407
0408
0409
0410 void
0411 mpt3sas_trigger_mpi(struct MPT3SAS_ADAPTER *ioc, u16 ioc_status, u32 loginfo)
0412 {
0413 struct SL_WH_TRIGGERS_EVENT_DATA_T event_data;
0414 struct SL_WH_MPI_TRIGGER_T *mpi_trigger;
0415 int i;
0416 unsigned long flags;
0417 u8 found_match;
0418
0419 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
0420
0421
0422 if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
0423 MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
0424 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
0425 return;
0426 }
0427
0428
0429 if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
0430 MPT3_DIAG_BUFFER_IS_RELEASED) {
0431 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
0432 return;
0433 }
0434
0435 dTriggerDiagPrintk(ioc,
0436 ioc_info(ioc, "%s: enter - ioc_status = 0x%04x, loginfo = 0x%08x\n",
0437 __func__, ioc_status, loginfo));
0438
0439
0440 if (ioc->diag_trigger_active) {
0441 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
0442 goto out;
0443 }
0444
0445
0446 mpi_trigger = ioc->diag_trigger_mpi.MPITriggerEntry;
0447 for (i = 0 , found_match = 0; i < ioc->diag_trigger_mpi.ValidEntries
0448 && !found_match; i++, mpi_trigger++) {
0449 if (mpi_trigger->IOCStatus != ioc_status)
0450 continue;
0451 if (!(mpi_trigger->IocLogInfo == 0xFFFFFFFF ||
0452 mpi_trigger->IocLogInfo == loginfo))
0453 continue;
0454 found_match = 1;
0455 ioc->diag_trigger_active = 1;
0456 }
0457 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
0458
0459 if (!found_match)
0460 goto out;
0461
0462 dTriggerDiagPrintk(ioc,
0463 ioc_info(ioc, "%s: setting diag_trigger_active flag\n",
0464 __func__));
0465 memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T));
0466 event_data.trigger_type = MPT3SAS_TRIGGER_MPI;
0467 event_data.u.mpi.IOCStatus = ioc_status;
0468 event_data.u.mpi.IocLogInfo = loginfo;
0469 mpt3sas_send_trigger_data_event(ioc, &event_data);
0470 out:
0471 dTriggerDiagPrintk(ioc, ioc_info(ioc, "%s: exit\n",
0472 __func__));
0473 }