brintos

brintos / linux-shallow public Read only

0
0
Text · 14.4 KiB · d9b7d0e Raw
474 lines · c
1/*2 * This module provides common API to set Diagnostic trigger for MPT3 * (Message Passing Technology) based controllers4 *5 * This code is based on drivers/scsi/mpt3sas/mpt3sas_trigger_diag.c6 * Copyright (C) 2012-2014  LSI Corporation7 * Copyright (C) 2013-2014 Avago Technologies8 *  (mailto: MPT-FusionLinux.pdl@avagotech.com)9 *10 * This program is free software; you can redistribute it and/or11 * modify it under the terms of the GNU General Public License12 * as published by the Free Software Foundation; either version 213 * 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 of17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the18 * GNU General Public License for more details.19 *20 * NO WARRANTY21 * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR22 * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT23 * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,24 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is25 * solely responsible for determining the appropriateness of using and26 * distributing the Program and assumes all risks associated with its27 * exercise of rights under this Agreement, including but not limited to28 * 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 LIABILITY32 * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY33 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL34 * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND35 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR36 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE37 * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED38 * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES39 40 * You should have received a copy of the GNU General Public License41 * along with this program; if not, write to the Free Software42 * 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 app64 * @ioc: per adapter object65 * @event_data: ?66 */67static void68_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 trigger108 * @ioc: per adapter object109 * @event_data: ?110 */111void112mpt3sas_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 caused125		 * the release126		 */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 handler172 * @ioc: per adapter object173 * @trigger_bitmask:174 *175 */176void177mpt3sas_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	} else241		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 handler250 * @ioc: per adapter object251 * @event: ?252 * @log_entry_qualifier: ?253 *254 */255void256mpt3sas_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.ValidEntries294	    && !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 handler329 * @ioc: per adapter object330 * @sense_key: ?331 * @asc: ?332 * @ascq: ?333 *334 */335void336mpt3sas_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.ValidEntries374	    && !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 handler405 * @ioc: per adapter object406 * @ioc_status: ?407 * @loginfo: ?408 *409 */410void411mpt3sas_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.ValidEntries448	    && !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}474