18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * This module provides common API to set Diagnostic trigger for MPT 38c2ecf20Sopenharmony_ci * (Message Passing Technology) based controllers 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * This code is based on drivers/scsi/mpt3sas/mpt3sas_trigger_diag.c 68c2ecf20Sopenharmony_ci * Copyright (C) 2012-2014 LSI Corporation 78c2ecf20Sopenharmony_ci * Copyright (C) 2013-2014 Avago Technologies 88c2ecf20Sopenharmony_ci * (mailto: MPT-FusionLinux.pdl@avagotech.com) 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or 118c2ecf20Sopenharmony_ci * modify it under the terms of the GNU General Public License 128c2ecf20Sopenharmony_ci * as published by the Free Software Foundation; either version 2 138c2ecf20Sopenharmony_ci * of the License, or (at your option) any later version. 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * This program is distributed in the hope that it will be useful, 168c2ecf20Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 178c2ecf20Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 188c2ecf20Sopenharmony_ci * GNU General Public License for more details. 198c2ecf20Sopenharmony_ci * 208c2ecf20Sopenharmony_ci * NO WARRANTY 218c2ecf20Sopenharmony_ci * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR 228c2ecf20Sopenharmony_ci * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT 238c2ecf20Sopenharmony_ci * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, 248c2ecf20Sopenharmony_ci * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is 258c2ecf20Sopenharmony_ci * solely responsible for determining the appropriateness of using and 268c2ecf20Sopenharmony_ci * distributing the Program and assumes all risks associated with its 278c2ecf20Sopenharmony_ci * exercise of rights under this Agreement, including but not limited to 288c2ecf20Sopenharmony_ci * the risks and costs of program errors, damage to or loss of data, 298c2ecf20Sopenharmony_ci * programs or equipment, and unavailability or interruption of operations. 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci * DISCLAIMER OF LIABILITY 328c2ecf20Sopenharmony_ci * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY 338c2ecf20Sopenharmony_ci * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 348c2ecf20Sopenharmony_ci * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND 358c2ecf20Sopenharmony_ci * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 368c2ecf20Sopenharmony_ci * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 378c2ecf20Sopenharmony_ci * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED 388c2ecf20Sopenharmony_ci * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci * You should have received a copy of the GNU General Public License 418c2ecf20Sopenharmony_ci * along with this program; if not, write to the Free Software 428c2ecf20Sopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 438c2ecf20Sopenharmony_ci * USA. 448c2ecf20Sopenharmony_ci */ 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci#include <linux/kernel.h> 478c2ecf20Sopenharmony_ci#include <linux/module.h> 488c2ecf20Sopenharmony_ci#include <linux/errno.h> 498c2ecf20Sopenharmony_ci#include <linux/init.h> 508c2ecf20Sopenharmony_ci#include <linux/slab.h> 518c2ecf20Sopenharmony_ci#include <linux/types.h> 528c2ecf20Sopenharmony_ci#include <linux/pci.h> 538c2ecf20Sopenharmony_ci#include <linux/delay.h> 548c2ecf20Sopenharmony_ci#include <linux/compat.h> 558c2ecf20Sopenharmony_ci#include <linux/poll.h> 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci#include <linux/io.h> 588c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci#include "mpt3sas_base.h" 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci/** 638c2ecf20Sopenharmony_ci * _mpt3sas_raise_sigio - notifiy app 648c2ecf20Sopenharmony_ci * @ioc: per adapter object 658c2ecf20Sopenharmony_ci * @event_data: ? 668c2ecf20Sopenharmony_ci */ 678c2ecf20Sopenharmony_cistatic void 688c2ecf20Sopenharmony_ci_mpt3sas_raise_sigio(struct MPT3SAS_ADAPTER *ioc, 698c2ecf20Sopenharmony_ci struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data) 708c2ecf20Sopenharmony_ci{ 718c2ecf20Sopenharmony_ci Mpi2EventNotificationReply_t *mpi_reply; 728c2ecf20Sopenharmony_ci u16 sz, event_data_sz; 738c2ecf20Sopenharmony_ci unsigned long flags; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci dTriggerDiagPrintk(ioc, ioc_info(ioc, "%s: enter\n", __func__)); 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci sz = offsetof(Mpi2EventNotificationReply_t, EventData) + 788c2ecf20Sopenharmony_ci sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T) + 4; 798c2ecf20Sopenharmony_ci mpi_reply = kzalloc(sz, GFP_KERNEL); 808c2ecf20Sopenharmony_ci if (!mpi_reply) 818c2ecf20Sopenharmony_ci goto out; 828c2ecf20Sopenharmony_ci mpi_reply->Event = cpu_to_le16(MPI3_EVENT_DIAGNOSTIC_TRIGGER_FIRED); 838c2ecf20Sopenharmony_ci event_data_sz = (sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T) + 4) / 4; 848c2ecf20Sopenharmony_ci mpi_reply->EventDataLength = cpu_to_le16(event_data_sz); 858c2ecf20Sopenharmony_ci memcpy(&mpi_reply->EventData, event_data, 868c2ecf20Sopenharmony_ci sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T)); 878c2ecf20Sopenharmony_ci dTriggerDiagPrintk(ioc, 888c2ecf20Sopenharmony_ci ioc_info(ioc, "%s: add to driver event log\n", 898c2ecf20Sopenharmony_ci __func__)); 908c2ecf20Sopenharmony_ci mpt3sas_ctl_add_to_event_log(ioc, mpi_reply); 918c2ecf20Sopenharmony_ci kfree(mpi_reply); 928c2ecf20Sopenharmony_ci out: 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci /* clearing the diag_trigger_active flag */ 958c2ecf20Sopenharmony_ci spin_lock_irqsave(&ioc->diag_trigger_lock, flags); 968c2ecf20Sopenharmony_ci dTriggerDiagPrintk(ioc, 978c2ecf20Sopenharmony_ci ioc_info(ioc, "%s: clearing diag_trigger_active flag\n", 988c2ecf20Sopenharmony_ci __func__)); 998c2ecf20Sopenharmony_ci ioc->diag_trigger_active = 0; 1008c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci dTriggerDiagPrintk(ioc, ioc_info(ioc, "%s: exit\n", 1038c2ecf20Sopenharmony_ci __func__)); 1048c2ecf20Sopenharmony_ci} 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci/** 1078c2ecf20Sopenharmony_ci * mpt3sas_process_trigger_data - process the event data for the trigger 1088c2ecf20Sopenharmony_ci * @ioc: per adapter object 1098c2ecf20Sopenharmony_ci * @event_data: ? 1108c2ecf20Sopenharmony_ci */ 1118c2ecf20Sopenharmony_civoid 1128c2ecf20Sopenharmony_cimpt3sas_process_trigger_data(struct MPT3SAS_ADAPTER *ioc, 1138c2ecf20Sopenharmony_ci struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data) 1148c2ecf20Sopenharmony_ci{ 1158c2ecf20Sopenharmony_ci u8 issue_reset = 0; 1168c2ecf20Sopenharmony_ci u32 *trig_data = (u32 *)&event_data->u.master; 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci dTriggerDiagPrintk(ioc, ioc_info(ioc, "%s: enter\n", __func__)); 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci /* release the diag buffer trace */ 1218c2ecf20Sopenharmony_ci if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & 1228c2ecf20Sopenharmony_ci MPT3_DIAG_BUFFER_IS_RELEASED) == 0) { 1238c2ecf20Sopenharmony_ci /* 1248c2ecf20Sopenharmony_ci * add a log message so that user knows which event caused 1258c2ecf20Sopenharmony_ci * the release 1268c2ecf20Sopenharmony_ci */ 1278c2ecf20Sopenharmony_ci ioc_info(ioc, 1288c2ecf20Sopenharmony_ci "%s: Releasing the trace buffer. Trigger_Type 0x%08x, Data[0] 0x%08x, Data[1] 0x%08x\n", 1298c2ecf20Sopenharmony_ci __func__, event_data->trigger_type, 1308c2ecf20Sopenharmony_ci trig_data[0], trig_data[1]); 1318c2ecf20Sopenharmony_ci mpt3sas_send_diag_release(ioc, MPI2_DIAG_BUF_TYPE_TRACE, 1328c2ecf20Sopenharmony_ci &issue_reset); 1338c2ecf20Sopenharmony_ci } 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci _mpt3sas_raise_sigio(ioc, event_data); 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci dTriggerDiagPrintk(ioc, ioc_info(ioc, "%s: exit\n", 1388c2ecf20Sopenharmony_ci __func__)); 1398c2ecf20Sopenharmony_ci} 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci/** 1428c2ecf20Sopenharmony_ci * mpt3sas_trigger_master - Master trigger handler 1438c2ecf20Sopenharmony_ci * @ioc: per adapter object 1448c2ecf20Sopenharmony_ci * @trigger_bitmask: 1458c2ecf20Sopenharmony_ci * 1468c2ecf20Sopenharmony_ci */ 1478c2ecf20Sopenharmony_civoid 1488c2ecf20Sopenharmony_cimpt3sas_trigger_master(struct MPT3SAS_ADAPTER *ioc, u32 trigger_bitmask) 1498c2ecf20Sopenharmony_ci{ 1508c2ecf20Sopenharmony_ci struct SL_WH_TRIGGERS_EVENT_DATA_T event_data; 1518c2ecf20Sopenharmony_ci unsigned long flags; 1528c2ecf20Sopenharmony_ci u8 found_match = 0; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci spin_lock_irqsave(&ioc->diag_trigger_lock, flags); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci if (trigger_bitmask & MASTER_TRIGGER_FW_FAULT || 1578c2ecf20Sopenharmony_ci trigger_bitmask & MASTER_TRIGGER_ADAPTER_RESET) 1588c2ecf20Sopenharmony_ci goto by_pass_checks; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci /* check to see if trace buffers are currently registered */ 1618c2ecf20Sopenharmony_ci if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & 1628c2ecf20Sopenharmony_ci MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) { 1638c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 1648c2ecf20Sopenharmony_ci return; 1658c2ecf20Sopenharmony_ci } 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci /* check to see if trace buffers are currently released */ 1688c2ecf20Sopenharmony_ci if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & 1698c2ecf20Sopenharmony_ci MPT3_DIAG_BUFFER_IS_RELEASED) { 1708c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 1718c2ecf20Sopenharmony_ci return; 1728c2ecf20Sopenharmony_ci } 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci by_pass_checks: 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci dTriggerDiagPrintk(ioc, 1778c2ecf20Sopenharmony_ci ioc_info(ioc, "%s: enter - trigger_bitmask = 0x%08x\n", 1788c2ecf20Sopenharmony_ci __func__, trigger_bitmask)); 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci /* don't send trigger if an trigger is currently active */ 1818c2ecf20Sopenharmony_ci if (ioc->diag_trigger_active) { 1828c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 1838c2ecf20Sopenharmony_ci goto out; 1848c2ecf20Sopenharmony_ci } 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci /* check for the trigger condition */ 1878c2ecf20Sopenharmony_ci if (ioc->diag_trigger_master.MasterData & trigger_bitmask) { 1888c2ecf20Sopenharmony_ci found_match = 1; 1898c2ecf20Sopenharmony_ci ioc->diag_trigger_active = 1; 1908c2ecf20Sopenharmony_ci dTriggerDiagPrintk(ioc, 1918c2ecf20Sopenharmony_ci ioc_info(ioc, "%s: setting diag_trigger_active flag\n", 1928c2ecf20Sopenharmony_ci __func__)); 1938c2ecf20Sopenharmony_ci } 1948c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci if (!found_match) 1978c2ecf20Sopenharmony_ci goto out; 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T)); 2008c2ecf20Sopenharmony_ci event_data.trigger_type = MPT3SAS_TRIGGER_MASTER; 2018c2ecf20Sopenharmony_ci event_data.u.master.MasterData = trigger_bitmask; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci if (trigger_bitmask & MASTER_TRIGGER_FW_FAULT || 2048c2ecf20Sopenharmony_ci trigger_bitmask & MASTER_TRIGGER_ADAPTER_RESET) 2058c2ecf20Sopenharmony_ci _mpt3sas_raise_sigio(ioc, &event_data); 2068c2ecf20Sopenharmony_ci else 2078c2ecf20Sopenharmony_ci mpt3sas_send_trigger_data_event(ioc, &event_data); 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci out: 2108c2ecf20Sopenharmony_ci dTriggerDiagPrintk(ioc, ioc_info(ioc, "%s: exit\n", 2118c2ecf20Sopenharmony_ci __func__)); 2128c2ecf20Sopenharmony_ci} 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci/** 2158c2ecf20Sopenharmony_ci * mpt3sas_trigger_event - Event trigger handler 2168c2ecf20Sopenharmony_ci * @ioc: per adapter object 2178c2ecf20Sopenharmony_ci * @event: ? 2188c2ecf20Sopenharmony_ci * @log_entry_qualifier: ? 2198c2ecf20Sopenharmony_ci * 2208c2ecf20Sopenharmony_ci */ 2218c2ecf20Sopenharmony_civoid 2228c2ecf20Sopenharmony_cimpt3sas_trigger_event(struct MPT3SAS_ADAPTER *ioc, u16 event, 2238c2ecf20Sopenharmony_ci u16 log_entry_qualifier) 2248c2ecf20Sopenharmony_ci{ 2258c2ecf20Sopenharmony_ci struct SL_WH_TRIGGERS_EVENT_DATA_T event_data; 2268c2ecf20Sopenharmony_ci struct SL_WH_EVENT_TRIGGER_T *event_trigger; 2278c2ecf20Sopenharmony_ci int i; 2288c2ecf20Sopenharmony_ci unsigned long flags; 2298c2ecf20Sopenharmony_ci u8 found_match; 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci spin_lock_irqsave(&ioc->diag_trigger_lock, flags); 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci /* check to see if trace buffers are currently registered */ 2348c2ecf20Sopenharmony_ci if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & 2358c2ecf20Sopenharmony_ci MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) { 2368c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 2378c2ecf20Sopenharmony_ci return; 2388c2ecf20Sopenharmony_ci } 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci /* check to see if trace buffers are currently released */ 2418c2ecf20Sopenharmony_ci if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & 2428c2ecf20Sopenharmony_ci MPT3_DIAG_BUFFER_IS_RELEASED) { 2438c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 2448c2ecf20Sopenharmony_ci return; 2458c2ecf20Sopenharmony_ci } 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci dTriggerDiagPrintk(ioc, 2488c2ecf20Sopenharmony_ci ioc_info(ioc, "%s: enter - event = 0x%04x, log_entry_qualifier = 0x%04x\n", 2498c2ecf20Sopenharmony_ci __func__, event, log_entry_qualifier)); 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci /* don't send trigger if an trigger is currently active */ 2528c2ecf20Sopenharmony_ci if (ioc->diag_trigger_active) { 2538c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 2548c2ecf20Sopenharmony_ci goto out; 2558c2ecf20Sopenharmony_ci } 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci /* check for the trigger condition */ 2588c2ecf20Sopenharmony_ci event_trigger = ioc->diag_trigger_event.EventTriggerEntry; 2598c2ecf20Sopenharmony_ci for (i = 0 , found_match = 0; i < ioc->diag_trigger_event.ValidEntries 2608c2ecf20Sopenharmony_ci && !found_match; i++, event_trigger++) { 2618c2ecf20Sopenharmony_ci if (event_trigger->EventValue != event) 2628c2ecf20Sopenharmony_ci continue; 2638c2ecf20Sopenharmony_ci if (event == MPI2_EVENT_LOG_ENTRY_ADDED) { 2648c2ecf20Sopenharmony_ci if (event_trigger->LogEntryQualifier == 2658c2ecf20Sopenharmony_ci log_entry_qualifier) 2668c2ecf20Sopenharmony_ci found_match = 1; 2678c2ecf20Sopenharmony_ci continue; 2688c2ecf20Sopenharmony_ci } 2698c2ecf20Sopenharmony_ci found_match = 1; 2708c2ecf20Sopenharmony_ci ioc->diag_trigger_active = 1; 2718c2ecf20Sopenharmony_ci dTriggerDiagPrintk(ioc, 2728c2ecf20Sopenharmony_ci ioc_info(ioc, "%s: setting diag_trigger_active flag\n", 2738c2ecf20Sopenharmony_ci __func__)); 2748c2ecf20Sopenharmony_ci } 2758c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci if (!found_match) 2788c2ecf20Sopenharmony_ci goto out; 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci dTriggerDiagPrintk(ioc, 2818c2ecf20Sopenharmony_ci ioc_info(ioc, "%s: setting diag_trigger_active flag\n", 2828c2ecf20Sopenharmony_ci __func__)); 2838c2ecf20Sopenharmony_ci memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T)); 2848c2ecf20Sopenharmony_ci event_data.trigger_type = MPT3SAS_TRIGGER_EVENT; 2858c2ecf20Sopenharmony_ci event_data.u.event.EventValue = event; 2868c2ecf20Sopenharmony_ci event_data.u.event.LogEntryQualifier = log_entry_qualifier; 2878c2ecf20Sopenharmony_ci mpt3sas_send_trigger_data_event(ioc, &event_data); 2888c2ecf20Sopenharmony_ci out: 2898c2ecf20Sopenharmony_ci dTriggerDiagPrintk(ioc, ioc_info(ioc, "%s: exit\n", 2908c2ecf20Sopenharmony_ci __func__)); 2918c2ecf20Sopenharmony_ci} 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci/** 2948c2ecf20Sopenharmony_ci * mpt3sas_trigger_scsi - SCSI trigger handler 2958c2ecf20Sopenharmony_ci * @ioc: per adapter object 2968c2ecf20Sopenharmony_ci * @sense_key: ? 2978c2ecf20Sopenharmony_ci * @asc: ? 2988c2ecf20Sopenharmony_ci * @ascq: ? 2998c2ecf20Sopenharmony_ci * 3008c2ecf20Sopenharmony_ci */ 3018c2ecf20Sopenharmony_civoid 3028c2ecf20Sopenharmony_cimpt3sas_trigger_scsi(struct MPT3SAS_ADAPTER *ioc, u8 sense_key, u8 asc, 3038c2ecf20Sopenharmony_ci u8 ascq) 3048c2ecf20Sopenharmony_ci{ 3058c2ecf20Sopenharmony_ci struct SL_WH_TRIGGERS_EVENT_DATA_T event_data; 3068c2ecf20Sopenharmony_ci struct SL_WH_SCSI_TRIGGER_T *scsi_trigger; 3078c2ecf20Sopenharmony_ci int i; 3088c2ecf20Sopenharmony_ci unsigned long flags; 3098c2ecf20Sopenharmony_ci u8 found_match; 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci spin_lock_irqsave(&ioc->diag_trigger_lock, flags); 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci /* check to see if trace buffers are currently registered */ 3148c2ecf20Sopenharmony_ci if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & 3158c2ecf20Sopenharmony_ci MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) { 3168c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 3178c2ecf20Sopenharmony_ci return; 3188c2ecf20Sopenharmony_ci } 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci /* check to see if trace buffers are currently released */ 3218c2ecf20Sopenharmony_ci if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & 3228c2ecf20Sopenharmony_ci MPT3_DIAG_BUFFER_IS_RELEASED) { 3238c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 3248c2ecf20Sopenharmony_ci return; 3258c2ecf20Sopenharmony_ci } 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci dTriggerDiagPrintk(ioc, 3288c2ecf20Sopenharmony_ci ioc_info(ioc, "%s: enter - sense_key = 0x%02x, asc = 0x%02x, ascq = 0x%02x\n", 3298c2ecf20Sopenharmony_ci __func__, sense_key, asc, ascq)); 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci /* don't send trigger if an trigger is currently active */ 3328c2ecf20Sopenharmony_ci if (ioc->diag_trigger_active) { 3338c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 3348c2ecf20Sopenharmony_ci goto out; 3358c2ecf20Sopenharmony_ci } 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci /* check for the trigger condition */ 3388c2ecf20Sopenharmony_ci scsi_trigger = ioc->diag_trigger_scsi.SCSITriggerEntry; 3398c2ecf20Sopenharmony_ci for (i = 0 , found_match = 0; i < ioc->diag_trigger_scsi.ValidEntries 3408c2ecf20Sopenharmony_ci && !found_match; i++, scsi_trigger++) { 3418c2ecf20Sopenharmony_ci if (scsi_trigger->SenseKey != sense_key) 3428c2ecf20Sopenharmony_ci continue; 3438c2ecf20Sopenharmony_ci if (!(scsi_trigger->ASC == 0xFF || scsi_trigger->ASC == asc)) 3448c2ecf20Sopenharmony_ci continue; 3458c2ecf20Sopenharmony_ci if (!(scsi_trigger->ASCQ == 0xFF || scsi_trigger->ASCQ == ascq)) 3468c2ecf20Sopenharmony_ci continue; 3478c2ecf20Sopenharmony_ci found_match = 1; 3488c2ecf20Sopenharmony_ci ioc->diag_trigger_active = 1; 3498c2ecf20Sopenharmony_ci } 3508c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci if (!found_match) 3538c2ecf20Sopenharmony_ci goto out; 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci dTriggerDiagPrintk(ioc, 3568c2ecf20Sopenharmony_ci ioc_info(ioc, "%s: setting diag_trigger_active flag\n", 3578c2ecf20Sopenharmony_ci __func__)); 3588c2ecf20Sopenharmony_ci memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T)); 3598c2ecf20Sopenharmony_ci event_data.trigger_type = MPT3SAS_TRIGGER_SCSI; 3608c2ecf20Sopenharmony_ci event_data.u.scsi.SenseKey = sense_key; 3618c2ecf20Sopenharmony_ci event_data.u.scsi.ASC = asc; 3628c2ecf20Sopenharmony_ci event_data.u.scsi.ASCQ = ascq; 3638c2ecf20Sopenharmony_ci mpt3sas_send_trigger_data_event(ioc, &event_data); 3648c2ecf20Sopenharmony_ci out: 3658c2ecf20Sopenharmony_ci dTriggerDiagPrintk(ioc, ioc_info(ioc, "%s: exit\n", 3668c2ecf20Sopenharmony_ci __func__)); 3678c2ecf20Sopenharmony_ci} 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci/** 3708c2ecf20Sopenharmony_ci * mpt3sas_trigger_mpi - MPI trigger handler 3718c2ecf20Sopenharmony_ci * @ioc: per adapter object 3728c2ecf20Sopenharmony_ci * @ioc_status: ? 3738c2ecf20Sopenharmony_ci * @loginfo: ? 3748c2ecf20Sopenharmony_ci * 3758c2ecf20Sopenharmony_ci */ 3768c2ecf20Sopenharmony_civoid 3778c2ecf20Sopenharmony_cimpt3sas_trigger_mpi(struct MPT3SAS_ADAPTER *ioc, u16 ioc_status, u32 loginfo) 3788c2ecf20Sopenharmony_ci{ 3798c2ecf20Sopenharmony_ci struct SL_WH_TRIGGERS_EVENT_DATA_T event_data; 3808c2ecf20Sopenharmony_ci struct SL_WH_MPI_TRIGGER_T *mpi_trigger; 3818c2ecf20Sopenharmony_ci int i; 3828c2ecf20Sopenharmony_ci unsigned long flags; 3838c2ecf20Sopenharmony_ci u8 found_match; 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci spin_lock_irqsave(&ioc->diag_trigger_lock, flags); 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci /* check to see if trace buffers are currently registered */ 3888c2ecf20Sopenharmony_ci if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & 3898c2ecf20Sopenharmony_ci MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) { 3908c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 3918c2ecf20Sopenharmony_ci return; 3928c2ecf20Sopenharmony_ci } 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci /* check to see if trace buffers are currently released */ 3958c2ecf20Sopenharmony_ci if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & 3968c2ecf20Sopenharmony_ci MPT3_DIAG_BUFFER_IS_RELEASED) { 3978c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 3988c2ecf20Sopenharmony_ci return; 3998c2ecf20Sopenharmony_ci } 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci dTriggerDiagPrintk(ioc, 4028c2ecf20Sopenharmony_ci ioc_info(ioc, "%s: enter - ioc_status = 0x%04x, loginfo = 0x%08x\n", 4038c2ecf20Sopenharmony_ci __func__, ioc_status, loginfo)); 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci /* don't send trigger if an trigger is currently active */ 4068c2ecf20Sopenharmony_ci if (ioc->diag_trigger_active) { 4078c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 4088c2ecf20Sopenharmony_ci goto out; 4098c2ecf20Sopenharmony_ci } 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci /* check for the trigger condition */ 4128c2ecf20Sopenharmony_ci mpi_trigger = ioc->diag_trigger_mpi.MPITriggerEntry; 4138c2ecf20Sopenharmony_ci for (i = 0 , found_match = 0; i < ioc->diag_trigger_mpi.ValidEntries 4148c2ecf20Sopenharmony_ci && !found_match; i++, mpi_trigger++) { 4158c2ecf20Sopenharmony_ci if (mpi_trigger->IOCStatus != ioc_status) 4168c2ecf20Sopenharmony_ci continue; 4178c2ecf20Sopenharmony_ci if (!(mpi_trigger->IocLogInfo == 0xFFFFFFFF || 4188c2ecf20Sopenharmony_ci mpi_trigger->IocLogInfo == loginfo)) 4198c2ecf20Sopenharmony_ci continue; 4208c2ecf20Sopenharmony_ci found_match = 1; 4218c2ecf20Sopenharmony_ci ioc->diag_trigger_active = 1; 4228c2ecf20Sopenharmony_ci } 4238c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci if (!found_match) 4268c2ecf20Sopenharmony_ci goto out; 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci dTriggerDiagPrintk(ioc, 4298c2ecf20Sopenharmony_ci ioc_info(ioc, "%s: setting diag_trigger_active flag\n", 4308c2ecf20Sopenharmony_ci __func__)); 4318c2ecf20Sopenharmony_ci memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T)); 4328c2ecf20Sopenharmony_ci event_data.trigger_type = MPT3SAS_TRIGGER_MPI; 4338c2ecf20Sopenharmony_ci event_data.u.mpi.IOCStatus = ioc_status; 4348c2ecf20Sopenharmony_ci event_data.u.mpi.IocLogInfo = loginfo; 4358c2ecf20Sopenharmony_ci mpt3sas_send_trigger_data_event(ioc, &event_data); 4368c2ecf20Sopenharmony_ci out: 4378c2ecf20Sopenharmony_ci dTriggerDiagPrintk(ioc, ioc_info(ioc, "%s: exit\n", 4388c2ecf20Sopenharmony_ci __func__)); 4398c2ecf20Sopenharmony_ci} 440