cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mpt3sas_trigger_diag.c (14786B)


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