1*f92363d1SSreekanth Reddy /* 2*f92363d1SSreekanth Reddy * This module provides common API to set Diagnostic trigger for MPT 3*f92363d1SSreekanth Reddy * (Message Passing Technology) based controllers 4*f92363d1SSreekanth Reddy * 5*f92363d1SSreekanth Reddy * This code is based on drivers/scsi/mpt3sas/mpt3sas_trigger_diag.c 6*f92363d1SSreekanth Reddy * Copyright (C) 2012 LSI Corporation 7*f92363d1SSreekanth Reddy * (mailto:DL-MPTFusionLinux@lsi.com) 8*f92363d1SSreekanth Reddy * 9*f92363d1SSreekanth Reddy * This program is free software; you can redistribute it and/or 10*f92363d1SSreekanth Reddy * modify it under the terms of the GNU General Public License 11*f92363d1SSreekanth Reddy * as published by the Free Software Foundation; either version 2 12*f92363d1SSreekanth Reddy * of the License, or (at your option) any later version. 13*f92363d1SSreekanth Reddy * 14*f92363d1SSreekanth Reddy * This program is distributed in the hope that it will be useful, 15*f92363d1SSreekanth Reddy * but WITHOUT ANY WARRANTY; without even the implied warranty of 16*f92363d1SSreekanth Reddy * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17*f92363d1SSreekanth Reddy * GNU General Public License for more details. 18*f92363d1SSreekanth Reddy * 19*f92363d1SSreekanth Reddy * NO WARRANTY 20*f92363d1SSreekanth Reddy * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR 21*f92363d1SSreekanth Reddy * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT 22*f92363d1SSreekanth Reddy * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, 23*f92363d1SSreekanth Reddy * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is 24*f92363d1SSreekanth Reddy * solely responsible for determining the appropriateness of using and 25*f92363d1SSreekanth Reddy * distributing the Program and assumes all risks associated with its 26*f92363d1SSreekanth Reddy * exercise of rights under this Agreement, including but not limited to 27*f92363d1SSreekanth Reddy * the risks and costs of program errors, damage to or loss of data, 28*f92363d1SSreekanth Reddy * programs or equipment, and unavailability or interruption of operations. 29*f92363d1SSreekanth Reddy 30*f92363d1SSreekanth Reddy * DISCLAIMER OF LIABILITY 31*f92363d1SSreekanth Reddy * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY 32*f92363d1SSreekanth Reddy * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33*f92363d1SSreekanth Reddy * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND 34*f92363d1SSreekanth Reddy * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 35*f92363d1SSreekanth Reddy * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 36*f92363d1SSreekanth Reddy * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED 37*f92363d1SSreekanth Reddy * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES 38*f92363d1SSreekanth Reddy 39*f92363d1SSreekanth Reddy * You should have received a copy of the GNU General Public License 40*f92363d1SSreekanth Reddy * along with this program; if not, write to the Free Software 41*f92363d1SSreekanth Reddy * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 42*f92363d1SSreekanth Reddy * USA. 43*f92363d1SSreekanth Reddy */ 44*f92363d1SSreekanth Reddy 45*f92363d1SSreekanth Reddy #include <linux/version.h> 46*f92363d1SSreekanth Reddy #include <linux/kernel.h> 47*f92363d1SSreekanth Reddy #include <linux/module.h> 48*f92363d1SSreekanth Reddy #include <linux/errno.h> 49*f92363d1SSreekanth Reddy #include <linux/init.h> 50*f92363d1SSreekanth Reddy #include <linux/slab.h> 51*f92363d1SSreekanth Reddy #include <linux/types.h> 52*f92363d1SSreekanth Reddy #include <linux/pci.h> 53*f92363d1SSreekanth Reddy #include <linux/delay.h> 54*f92363d1SSreekanth Reddy #include <linux/compat.h> 55*f92363d1SSreekanth Reddy #include <linux/poll.h> 56*f92363d1SSreekanth Reddy 57*f92363d1SSreekanth Reddy #include <linux/io.h> 58*f92363d1SSreekanth Reddy #include <linux/uaccess.h> 59*f92363d1SSreekanth Reddy 60*f92363d1SSreekanth Reddy #include "mpt3sas_base.h" 61*f92363d1SSreekanth Reddy 62*f92363d1SSreekanth Reddy /** 63*f92363d1SSreekanth Reddy * _mpt3sas_raise_sigio - notifiy app 64*f92363d1SSreekanth Reddy * @ioc: per adapter object 65*f92363d1SSreekanth Reddy * @event_data: 66*f92363d1SSreekanth Reddy */ 67*f92363d1SSreekanth Reddy static void 68*f92363d1SSreekanth Reddy _mpt3sas_raise_sigio(struct MPT3SAS_ADAPTER *ioc, 69*f92363d1SSreekanth Reddy struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data) 70*f92363d1SSreekanth Reddy { 71*f92363d1SSreekanth Reddy Mpi2EventNotificationReply_t *mpi_reply; 72*f92363d1SSreekanth Reddy u16 sz, event_data_sz; 73*f92363d1SSreekanth Reddy unsigned long flags; 74*f92363d1SSreekanth Reddy 75*f92363d1SSreekanth Reddy dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", 76*f92363d1SSreekanth Reddy ioc->name, __func__)); 77*f92363d1SSreekanth Reddy 78*f92363d1SSreekanth Reddy sz = offsetof(Mpi2EventNotificationReply_t, EventData) + 79*f92363d1SSreekanth Reddy sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T) + 4; 80*f92363d1SSreekanth Reddy mpi_reply = kzalloc(sz, GFP_KERNEL); 81*f92363d1SSreekanth Reddy if (!mpi_reply) 82*f92363d1SSreekanth Reddy goto out; 83*f92363d1SSreekanth Reddy mpi_reply->Event = cpu_to_le16(MPI3_EVENT_DIAGNOSTIC_TRIGGER_FIRED); 84*f92363d1SSreekanth Reddy event_data_sz = (sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T) + 4) / 4; 85*f92363d1SSreekanth Reddy mpi_reply->EventDataLength = cpu_to_le16(event_data_sz); 86*f92363d1SSreekanth Reddy memcpy(&mpi_reply->EventData, event_data, 87*f92363d1SSreekanth Reddy sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T)); 88*f92363d1SSreekanth Reddy dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT 89*f92363d1SSreekanth Reddy "%s: add to driver event log\n", 90*f92363d1SSreekanth Reddy ioc->name, __func__)); 91*f92363d1SSreekanth Reddy mpt3sas_ctl_add_to_event_log(ioc, mpi_reply); 92*f92363d1SSreekanth Reddy kfree(mpi_reply); 93*f92363d1SSreekanth Reddy out: 94*f92363d1SSreekanth Reddy 95*f92363d1SSreekanth Reddy /* clearing the diag_trigger_active flag */ 96*f92363d1SSreekanth Reddy spin_lock_irqsave(&ioc->diag_trigger_lock, flags); 97*f92363d1SSreekanth Reddy dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT 98*f92363d1SSreekanth Reddy "%s: clearing diag_trigger_active flag\n", 99*f92363d1SSreekanth Reddy ioc->name, __func__)); 100*f92363d1SSreekanth Reddy ioc->diag_trigger_active = 0; 101*f92363d1SSreekanth Reddy spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 102*f92363d1SSreekanth Reddy 103*f92363d1SSreekanth Reddy dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name, 104*f92363d1SSreekanth Reddy __func__)); 105*f92363d1SSreekanth Reddy } 106*f92363d1SSreekanth Reddy 107*f92363d1SSreekanth Reddy /** 108*f92363d1SSreekanth Reddy * mpt3sas_process_trigger_data - process the event data for the trigger 109*f92363d1SSreekanth Reddy * @ioc: per adapter object 110*f92363d1SSreekanth Reddy * @event_data: 111*f92363d1SSreekanth Reddy */ 112*f92363d1SSreekanth Reddy void 113*f92363d1SSreekanth Reddy mpt3sas_process_trigger_data(struct MPT3SAS_ADAPTER *ioc, 114*f92363d1SSreekanth Reddy struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data) 115*f92363d1SSreekanth Reddy { 116*f92363d1SSreekanth Reddy u8 issue_reset = 0; 117*f92363d1SSreekanth Reddy 118*f92363d1SSreekanth Reddy dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", 119*f92363d1SSreekanth Reddy ioc->name, __func__)); 120*f92363d1SSreekanth Reddy 121*f92363d1SSreekanth Reddy /* release the diag buffer trace */ 122*f92363d1SSreekanth Reddy if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & 123*f92363d1SSreekanth Reddy MPT3_DIAG_BUFFER_IS_RELEASED) == 0) { 124*f92363d1SSreekanth Reddy dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT 125*f92363d1SSreekanth Reddy "%s: release trace diag buffer\n", ioc->name, __func__)); 126*f92363d1SSreekanth Reddy mpt3sas_send_diag_release(ioc, MPI2_DIAG_BUF_TYPE_TRACE, 127*f92363d1SSreekanth Reddy &issue_reset); 128*f92363d1SSreekanth Reddy } 129*f92363d1SSreekanth Reddy 130*f92363d1SSreekanth Reddy _mpt3sas_raise_sigio(ioc, event_data); 131*f92363d1SSreekanth Reddy 132*f92363d1SSreekanth Reddy dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name, 133*f92363d1SSreekanth Reddy __func__)); 134*f92363d1SSreekanth Reddy } 135*f92363d1SSreekanth Reddy 136*f92363d1SSreekanth Reddy /** 137*f92363d1SSreekanth Reddy * mpt3sas_trigger_master - Master trigger handler 138*f92363d1SSreekanth Reddy * @ioc: per adapter object 139*f92363d1SSreekanth Reddy * @trigger_bitmask: 140*f92363d1SSreekanth Reddy * 141*f92363d1SSreekanth Reddy */ 142*f92363d1SSreekanth Reddy void 143*f92363d1SSreekanth Reddy mpt3sas_trigger_master(struct MPT3SAS_ADAPTER *ioc, u32 trigger_bitmask) 144*f92363d1SSreekanth Reddy { 145*f92363d1SSreekanth Reddy struct SL_WH_TRIGGERS_EVENT_DATA_T event_data; 146*f92363d1SSreekanth Reddy unsigned long flags; 147*f92363d1SSreekanth Reddy u8 found_match = 0; 148*f92363d1SSreekanth Reddy 149*f92363d1SSreekanth Reddy spin_lock_irqsave(&ioc->diag_trigger_lock, flags); 150*f92363d1SSreekanth Reddy 151*f92363d1SSreekanth Reddy if (trigger_bitmask & MASTER_TRIGGER_FW_FAULT || 152*f92363d1SSreekanth Reddy trigger_bitmask & MASTER_TRIGGER_ADAPTER_RESET) 153*f92363d1SSreekanth Reddy goto by_pass_checks; 154*f92363d1SSreekanth Reddy 155*f92363d1SSreekanth Reddy /* check to see if trace buffers are currently registered */ 156*f92363d1SSreekanth Reddy if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & 157*f92363d1SSreekanth Reddy MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) { 158*f92363d1SSreekanth Reddy spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 159*f92363d1SSreekanth Reddy return; 160*f92363d1SSreekanth Reddy } 161*f92363d1SSreekanth Reddy 162*f92363d1SSreekanth Reddy /* check to see if trace buffers are currently released */ 163*f92363d1SSreekanth Reddy if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & 164*f92363d1SSreekanth Reddy MPT3_DIAG_BUFFER_IS_RELEASED) { 165*f92363d1SSreekanth Reddy spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 166*f92363d1SSreekanth Reddy return; 167*f92363d1SSreekanth Reddy } 168*f92363d1SSreekanth Reddy 169*f92363d1SSreekanth Reddy by_pass_checks: 170*f92363d1SSreekanth Reddy 171*f92363d1SSreekanth Reddy dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT 172*f92363d1SSreekanth Reddy "%s: enter - trigger_bitmask = 0x%08x\n", 173*f92363d1SSreekanth Reddy ioc->name, __func__, trigger_bitmask)); 174*f92363d1SSreekanth Reddy 175*f92363d1SSreekanth Reddy /* don't send trigger if an trigger is currently active */ 176*f92363d1SSreekanth Reddy if (ioc->diag_trigger_active) { 177*f92363d1SSreekanth Reddy spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 178*f92363d1SSreekanth Reddy goto out; 179*f92363d1SSreekanth Reddy } 180*f92363d1SSreekanth Reddy 181*f92363d1SSreekanth Reddy /* check for the trigger condition */ 182*f92363d1SSreekanth Reddy if (ioc->diag_trigger_master.MasterData & trigger_bitmask) { 183*f92363d1SSreekanth Reddy found_match = 1; 184*f92363d1SSreekanth Reddy ioc->diag_trigger_active = 1; 185*f92363d1SSreekanth Reddy dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT 186*f92363d1SSreekanth Reddy "%s: setting diag_trigger_active flag\n", 187*f92363d1SSreekanth Reddy ioc->name, __func__)); 188*f92363d1SSreekanth Reddy } 189*f92363d1SSreekanth Reddy spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 190*f92363d1SSreekanth Reddy 191*f92363d1SSreekanth Reddy if (!found_match) 192*f92363d1SSreekanth Reddy goto out; 193*f92363d1SSreekanth Reddy 194*f92363d1SSreekanth Reddy memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T)); 195*f92363d1SSreekanth Reddy event_data.trigger_type = MPT3SAS_TRIGGER_MASTER; 196*f92363d1SSreekanth Reddy event_data.u.master.MasterData = trigger_bitmask; 197*f92363d1SSreekanth Reddy 198*f92363d1SSreekanth Reddy if (trigger_bitmask & MASTER_TRIGGER_FW_FAULT || 199*f92363d1SSreekanth Reddy trigger_bitmask & MASTER_TRIGGER_ADAPTER_RESET) 200*f92363d1SSreekanth Reddy _mpt3sas_raise_sigio(ioc, &event_data); 201*f92363d1SSreekanth Reddy else 202*f92363d1SSreekanth Reddy mpt3sas_send_trigger_data_event(ioc, &event_data); 203*f92363d1SSreekanth Reddy 204*f92363d1SSreekanth Reddy out: 205*f92363d1SSreekanth Reddy dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name, 206*f92363d1SSreekanth Reddy __func__)); 207*f92363d1SSreekanth Reddy } 208*f92363d1SSreekanth Reddy 209*f92363d1SSreekanth Reddy /** 210*f92363d1SSreekanth Reddy * mpt3sas_trigger_event - Event trigger handler 211*f92363d1SSreekanth Reddy * @ioc: per adapter object 212*f92363d1SSreekanth Reddy * @event: 213*f92363d1SSreekanth Reddy * @log_entry_qualifier: 214*f92363d1SSreekanth Reddy * 215*f92363d1SSreekanth Reddy */ 216*f92363d1SSreekanth Reddy void 217*f92363d1SSreekanth Reddy mpt3sas_trigger_event(struct MPT3SAS_ADAPTER *ioc, u16 event, 218*f92363d1SSreekanth Reddy u16 log_entry_qualifier) 219*f92363d1SSreekanth Reddy { 220*f92363d1SSreekanth Reddy struct SL_WH_TRIGGERS_EVENT_DATA_T event_data; 221*f92363d1SSreekanth Reddy struct SL_WH_EVENT_TRIGGER_T *event_trigger; 222*f92363d1SSreekanth Reddy int i; 223*f92363d1SSreekanth Reddy unsigned long flags; 224*f92363d1SSreekanth Reddy u8 found_match; 225*f92363d1SSreekanth Reddy 226*f92363d1SSreekanth Reddy spin_lock_irqsave(&ioc->diag_trigger_lock, flags); 227*f92363d1SSreekanth Reddy 228*f92363d1SSreekanth Reddy /* check to see if trace buffers are currently registered */ 229*f92363d1SSreekanth Reddy if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & 230*f92363d1SSreekanth Reddy MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) { 231*f92363d1SSreekanth Reddy spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 232*f92363d1SSreekanth Reddy return; 233*f92363d1SSreekanth Reddy } 234*f92363d1SSreekanth Reddy 235*f92363d1SSreekanth Reddy /* check to see if trace buffers are currently released */ 236*f92363d1SSreekanth Reddy if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & 237*f92363d1SSreekanth Reddy MPT3_DIAG_BUFFER_IS_RELEASED) { 238*f92363d1SSreekanth Reddy spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 239*f92363d1SSreekanth Reddy return; 240*f92363d1SSreekanth Reddy } 241*f92363d1SSreekanth Reddy 242*f92363d1SSreekanth Reddy dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT 243*f92363d1SSreekanth Reddy "%s: enter - event = 0x%04x, log_entry_qualifier = 0x%04x\n", 244*f92363d1SSreekanth Reddy ioc->name, __func__, event, log_entry_qualifier)); 245*f92363d1SSreekanth Reddy 246*f92363d1SSreekanth Reddy /* don't send trigger if an trigger is currently active */ 247*f92363d1SSreekanth Reddy if (ioc->diag_trigger_active) { 248*f92363d1SSreekanth Reddy spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 249*f92363d1SSreekanth Reddy goto out; 250*f92363d1SSreekanth Reddy } 251*f92363d1SSreekanth Reddy 252*f92363d1SSreekanth Reddy /* check for the trigger condition */ 253*f92363d1SSreekanth Reddy event_trigger = ioc->diag_trigger_event.EventTriggerEntry; 254*f92363d1SSreekanth Reddy for (i = 0 , found_match = 0; i < ioc->diag_trigger_event.ValidEntries 255*f92363d1SSreekanth Reddy && !found_match; i++, event_trigger++) { 256*f92363d1SSreekanth Reddy if (event_trigger->EventValue != event) 257*f92363d1SSreekanth Reddy continue; 258*f92363d1SSreekanth Reddy if (event == MPI2_EVENT_LOG_ENTRY_ADDED) { 259*f92363d1SSreekanth Reddy if (event_trigger->LogEntryQualifier == 260*f92363d1SSreekanth Reddy log_entry_qualifier) 261*f92363d1SSreekanth Reddy found_match = 1; 262*f92363d1SSreekanth Reddy continue; 263*f92363d1SSreekanth Reddy } 264*f92363d1SSreekanth Reddy found_match = 1; 265*f92363d1SSreekanth Reddy ioc->diag_trigger_active = 1; 266*f92363d1SSreekanth Reddy dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT 267*f92363d1SSreekanth Reddy "%s: setting diag_trigger_active flag\n", 268*f92363d1SSreekanth Reddy ioc->name, __func__)); 269*f92363d1SSreekanth Reddy } 270*f92363d1SSreekanth Reddy spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 271*f92363d1SSreekanth Reddy 272*f92363d1SSreekanth Reddy if (!found_match) 273*f92363d1SSreekanth Reddy goto out; 274*f92363d1SSreekanth Reddy 275*f92363d1SSreekanth Reddy dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT 276*f92363d1SSreekanth Reddy "%s: setting diag_trigger_active flag\n", 277*f92363d1SSreekanth Reddy ioc->name, __func__)); 278*f92363d1SSreekanth Reddy memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T)); 279*f92363d1SSreekanth Reddy event_data.trigger_type = MPT3SAS_TRIGGER_EVENT; 280*f92363d1SSreekanth Reddy event_data.u.event.EventValue = event; 281*f92363d1SSreekanth Reddy event_data.u.event.LogEntryQualifier = log_entry_qualifier; 282*f92363d1SSreekanth Reddy mpt3sas_send_trigger_data_event(ioc, &event_data); 283*f92363d1SSreekanth Reddy out: 284*f92363d1SSreekanth Reddy dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name, 285*f92363d1SSreekanth Reddy __func__)); 286*f92363d1SSreekanth Reddy } 287*f92363d1SSreekanth Reddy 288*f92363d1SSreekanth Reddy /** 289*f92363d1SSreekanth Reddy * mpt3sas_trigger_scsi - SCSI trigger handler 290*f92363d1SSreekanth Reddy * @ioc: per adapter object 291*f92363d1SSreekanth Reddy * @sense_key: 292*f92363d1SSreekanth Reddy * @asc: 293*f92363d1SSreekanth Reddy * @ascq: 294*f92363d1SSreekanth Reddy * 295*f92363d1SSreekanth Reddy */ 296*f92363d1SSreekanth Reddy void 297*f92363d1SSreekanth Reddy mpt3sas_trigger_scsi(struct MPT3SAS_ADAPTER *ioc, u8 sense_key, u8 asc, 298*f92363d1SSreekanth Reddy u8 ascq) 299*f92363d1SSreekanth Reddy { 300*f92363d1SSreekanth Reddy struct SL_WH_TRIGGERS_EVENT_DATA_T event_data; 301*f92363d1SSreekanth Reddy struct SL_WH_SCSI_TRIGGER_T *scsi_trigger; 302*f92363d1SSreekanth Reddy int i; 303*f92363d1SSreekanth Reddy unsigned long flags; 304*f92363d1SSreekanth Reddy u8 found_match; 305*f92363d1SSreekanth Reddy 306*f92363d1SSreekanth Reddy spin_lock_irqsave(&ioc->diag_trigger_lock, flags); 307*f92363d1SSreekanth Reddy 308*f92363d1SSreekanth Reddy /* check to see if trace buffers are currently registered */ 309*f92363d1SSreekanth Reddy if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & 310*f92363d1SSreekanth Reddy MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) { 311*f92363d1SSreekanth Reddy spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 312*f92363d1SSreekanth Reddy return; 313*f92363d1SSreekanth Reddy } 314*f92363d1SSreekanth Reddy 315*f92363d1SSreekanth Reddy /* check to see if trace buffers are currently released */ 316*f92363d1SSreekanth Reddy if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & 317*f92363d1SSreekanth Reddy MPT3_DIAG_BUFFER_IS_RELEASED) { 318*f92363d1SSreekanth Reddy spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 319*f92363d1SSreekanth Reddy return; 320*f92363d1SSreekanth Reddy } 321*f92363d1SSreekanth Reddy 322*f92363d1SSreekanth Reddy dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT 323*f92363d1SSreekanth Reddy "%s: enter - sense_key = 0x%02x, asc = 0x%02x, ascq = 0x%02x\n", 324*f92363d1SSreekanth Reddy ioc->name, __func__, sense_key, asc, ascq)); 325*f92363d1SSreekanth Reddy 326*f92363d1SSreekanth Reddy /* don't send trigger if an trigger is currently active */ 327*f92363d1SSreekanth Reddy if (ioc->diag_trigger_active) { 328*f92363d1SSreekanth Reddy spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 329*f92363d1SSreekanth Reddy goto out; 330*f92363d1SSreekanth Reddy } 331*f92363d1SSreekanth Reddy 332*f92363d1SSreekanth Reddy /* check for the trigger condition */ 333*f92363d1SSreekanth Reddy scsi_trigger = ioc->diag_trigger_scsi.SCSITriggerEntry; 334*f92363d1SSreekanth Reddy for (i = 0 , found_match = 0; i < ioc->diag_trigger_scsi.ValidEntries 335*f92363d1SSreekanth Reddy && !found_match; i++, scsi_trigger++) { 336*f92363d1SSreekanth Reddy if (scsi_trigger->SenseKey != sense_key) 337*f92363d1SSreekanth Reddy continue; 338*f92363d1SSreekanth Reddy if (!(scsi_trigger->ASC == 0xFF || scsi_trigger->ASC == asc)) 339*f92363d1SSreekanth Reddy continue; 340*f92363d1SSreekanth Reddy if (!(scsi_trigger->ASCQ == 0xFF || scsi_trigger->ASCQ == ascq)) 341*f92363d1SSreekanth Reddy continue; 342*f92363d1SSreekanth Reddy found_match = 1; 343*f92363d1SSreekanth Reddy ioc->diag_trigger_active = 1; 344*f92363d1SSreekanth Reddy } 345*f92363d1SSreekanth Reddy spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 346*f92363d1SSreekanth Reddy 347*f92363d1SSreekanth Reddy if (!found_match) 348*f92363d1SSreekanth Reddy goto out; 349*f92363d1SSreekanth Reddy 350*f92363d1SSreekanth Reddy dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT 351*f92363d1SSreekanth Reddy "%s: setting diag_trigger_active flag\n", 352*f92363d1SSreekanth Reddy ioc->name, __func__)); 353*f92363d1SSreekanth Reddy memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T)); 354*f92363d1SSreekanth Reddy event_data.trigger_type = MPT3SAS_TRIGGER_SCSI; 355*f92363d1SSreekanth Reddy event_data.u.scsi.SenseKey = sense_key; 356*f92363d1SSreekanth Reddy event_data.u.scsi.ASC = asc; 357*f92363d1SSreekanth Reddy event_data.u.scsi.ASCQ = ascq; 358*f92363d1SSreekanth Reddy mpt3sas_send_trigger_data_event(ioc, &event_data); 359*f92363d1SSreekanth Reddy out: 360*f92363d1SSreekanth Reddy dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name, 361*f92363d1SSreekanth Reddy __func__)); 362*f92363d1SSreekanth Reddy } 363*f92363d1SSreekanth Reddy 364*f92363d1SSreekanth Reddy /** 365*f92363d1SSreekanth Reddy * mpt3sas_trigger_mpi - MPI trigger handler 366*f92363d1SSreekanth Reddy * @ioc: per adapter object 367*f92363d1SSreekanth Reddy * @ioc_status: 368*f92363d1SSreekanth Reddy * @loginfo: 369*f92363d1SSreekanth Reddy * 370*f92363d1SSreekanth Reddy */ 371*f92363d1SSreekanth Reddy void 372*f92363d1SSreekanth Reddy mpt3sas_trigger_mpi(struct MPT3SAS_ADAPTER *ioc, u16 ioc_status, u32 loginfo) 373*f92363d1SSreekanth Reddy { 374*f92363d1SSreekanth Reddy struct SL_WH_TRIGGERS_EVENT_DATA_T event_data; 375*f92363d1SSreekanth Reddy struct SL_WH_MPI_TRIGGER_T *mpi_trigger; 376*f92363d1SSreekanth Reddy int i; 377*f92363d1SSreekanth Reddy unsigned long flags; 378*f92363d1SSreekanth Reddy u8 found_match; 379*f92363d1SSreekanth Reddy 380*f92363d1SSreekanth Reddy spin_lock_irqsave(&ioc->diag_trigger_lock, flags); 381*f92363d1SSreekanth Reddy 382*f92363d1SSreekanth Reddy /* check to see if trace buffers are currently registered */ 383*f92363d1SSreekanth Reddy if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & 384*f92363d1SSreekanth Reddy MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) { 385*f92363d1SSreekanth Reddy spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 386*f92363d1SSreekanth Reddy return; 387*f92363d1SSreekanth Reddy } 388*f92363d1SSreekanth Reddy 389*f92363d1SSreekanth Reddy /* check to see if trace buffers are currently released */ 390*f92363d1SSreekanth Reddy if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & 391*f92363d1SSreekanth Reddy MPT3_DIAG_BUFFER_IS_RELEASED) { 392*f92363d1SSreekanth Reddy spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 393*f92363d1SSreekanth Reddy return; 394*f92363d1SSreekanth Reddy } 395*f92363d1SSreekanth Reddy 396*f92363d1SSreekanth Reddy dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT 397*f92363d1SSreekanth Reddy "%s: enter - ioc_status = 0x%04x, loginfo = 0x%08x\n", 398*f92363d1SSreekanth Reddy ioc->name, __func__, ioc_status, loginfo)); 399*f92363d1SSreekanth Reddy 400*f92363d1SSreekanth Reddy /* don't send trigger if an trigger is currently active */ 401*f92363d1SSreekanth Reddy if (ioc->diag_trigger_active) { 402*f92363d1SSreekanth Reddy spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 403*f92363d1SSreekanth Reddy goto out; 404*f92363d1SSreekanth Reddy } 405*f92363d1SSreekanth Reddy 406*f92363d1SSreekanth Reddy /* check for the trigger condition */ 407*f92363d1SSreekanth Reddy mpi_trigger = ioc->diag_trigger_mpi.MPITriggerEntry; 408*f92363d1SSreekanth Reddy for (i = 0 , found_match = 0; i < ioc->diag_trigger_mpi.ValidEntries 409*f92363d1SSreekanth Reddy && !found_match; i++, mpi_trigger++) { 410*f92363d1SSreekanth Reddy if (mpi_trigger->IOCStatus != ioc_status) 411*f92363d1SSreekanth Reddy continue; 412*f92363d1SSreekanth Reddy if (!(mpi_trigger->IocLogInfo == 0xFFFFFFFF || 413*f92363d1SSreekanth Reddy mpi_trigger->IocLogInfo == loginfo)) 414*f92363d1SSreekanth Reddy continue; 415*f92363d1SSreekanth Reddy found_match = 1; 416*f92363d1SSreekanth Reddy ioc->diag_trigger_active = 1; 417*f92363d1SSreekanth Reddy } 418*f92363d1SSreekanth Reddy spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 419*f92363d1SSreekanth Reddy 420*f92363d1SSreekanth Reddy if (!found_match) 421*f92363d1SSreekanth Reddy goto out; 422*f92363d1SSreekanth Reddy 423*f92363d1SSreekanth Reddy dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT 424*f92363d1SSreekanth Reddy "%s: setting diag_trigger_active flag\n", 425*f92363d1SSreekanth Reddy ioc->name, __func__)); 426*f92363d1SSreekanth Reddy memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T)); 427*f92363d1SSreekanth Reddy event_data.trigger_type = MPT3SAS_TRIGGER_MPI; 428*f92363d1SSreekanth Reddy event_data.u.mpi.IOCStatus = ioc_status; 429*f92363d1SSreekanth Reddy event_data.u.mpi.IocLogInfo = loginfo; 430*f92363d1SSreekanth Reddy mpt3sas_send_trigger_data_event(ioc, &event_data); 431*f92363d1SSreekanth Reddy out: 432*f92363d1SSreekanth Reddy dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name, 433*f92363d1SSreekanth Reddy __func__)); 434*f92363d1SSreekanth Reddy } 435