*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+#include "linux_compat.h" /* linux-2.6 tweaks */
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h> /* for mdelay */
#include <linux/interrupt.h> /* needed for in_interrupt() proto */
#include <linux/reboot.h> /* notifier code */
-#include "../../scsi/scsi.h"
-#include <scsi/scsi_host.h>
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
#include "mptbase.h"
#include "mptscsih.h"
/* Set string for command line args from insmod */
#ifdef MODULE
-char *mptscsih = 0;
+char *mptscsih = NULL;
#endif
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
* Other private/forward protos...
*/
static int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
-static void mptscsih_report_queue_full(Scsi_Cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
+static void mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
static int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
-static int mptscsih_AddSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt,
+static int mptscsih_AddSGE(MPT_SCSI_HOST *hd, struct scsi_cmnd *SCpnt,
SCSIIORequest_t *pReq, int req_idx);
static void mptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx);
static int mptscsih_initChainBuffers (MPT_SCSI_HOST *hd, int init);
-static void copy_sense_data(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
+static void copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
-static u32 SCPNT_TO_LOOKUP_IDX(Scsi_Cmnd *sc);
+static u32 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
static MPT_FRAME_HDR *mptscsih_search_pendingQ(MPT_SCSI_HOST *hd, int scpnt_idx);
static void post_pendingQ_commands(MPT_SCSI_HOST *hd);
static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
static int mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum);
-static struct mpt_work_struct mptscsih_rstTask;
+static struct work_struct mptscsih_rstTask;
#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
static int mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io);
static spinlock_t dvtaskQ_lock = SPIN_LOCK_UNLOCKED;
static int dvtaskQ_active = 0;
static int dvtaskQ_release = 0;
-static struct mpt_work_struct mptscsih_dvTask;
+static struct work_struct mptscsih_dvTask;
#endif
/*
driver_setup = MPTSCSIH_DRIVER_SETUP;
#ifdef MPTSCSIH_DBG_TIMEOUT
-static Scsi_Cmnd *foo_to[8];
+static struct scsi_cmnd *foo_to[8];
#endif
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-
-/* see mptscsih.h */
-
-static struct scsi_host_template driver_template = {
- .proc_name = "mptscsih",
- .proc_info = x_scsi_proc_info,
- .name = "MPT SCSI Host",
- .info = x_scsi_info,
- .queuecommand = x_scsi_queuecommand,
- .slave_alloc = x_scsi_slave_alloc,
- .slave_configure = x_scsi_slave_configure,
- .slave_destroy = x_scsi_slave_destroy,
- .eh_abort_handler = x_scsi_abort,
- .eh_device_reset_handler = x_scsi_dev_reset,
- .eh_bus_reset_handler = x_scsi_bus_reset,
- .eh_host_reset_handler = x_scsi_host_reset,
- .bios_param = x_scsi_bios_param,
- .can_queue = MPT_SCSI_CAN_QUEUE,
- .this_id = -1,
- .sg_tablesize = MPT_SCSI_SG_DEPTH,
- .max_sectors = MPT_SCSI_MAX_SECTORS,
- .cmd_per_lun = MPT_SCSI_CMD_PER_LUN,
- .use_clustering = ENABLE_CLUSTERING,
-};
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- * Private inline routines...
- */
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* 19991030 -sralston
- * Return absolute SCSI data direction:
- * 1 = _DATA_OUT
- * 0 = _DIR_NONE
- * -1 = _DATA_IN
- *
- * Changed: 3-20-2002 pdelaney to use the default data
- * direction and the defines set up in the
- * 2.4 kernel series
- * 1 = _DATA_OUT changed to SCSI_DATA_WRITE (1)
- * 0 = _DIR_NONE changed to SCSI_DATA_NONE (3)
- * -1 = _DATA_IN changed to SCSI_DATA_READ (2)
- * If the direction is unknown, fall through to original code.
- *
- * Mid-layer bug fix(): sg interface generates the wrong data
- * direction in some cases. Set the direction the hard way for
- * the most common commands.
- */
-static inline int
-mptscsih_io_direction(Scsi_Cmnd *cmd)
-{
- switch (cmd->cmnd[0]) {
- case WRITE_6:
- case WRITE_10:
- case WRITE_16:
- return SCSI_DATA_WRITE;
- break;
- case READ_6:
- case READ_10:
- case READ_16:
- return SCSI_DATA_READ;
- break;
- }
-
- if (cmd->sc_data_direction != SCSI_DATA_UNKNOWN)
- return cmd->sc_data_direction;
-
- switch (cmd->cmnd[0]) {
- /* _DATA_OUT commands */
- case WRITE_6: case WRITE_10: case WRITE_12:
- case WRITE_16:
- case WRITE_LONG: case WRITE_SAME: case WRITE_BUFFER:
- case WRITE_VERIFY: case WRITE_VERIFY_12:
- case COMPARE: case COPY: case COPY_VERIFY:
- case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW:
- case SEARCH_EQUAL_12: case SEARCH_HIGH_12: case SEARCH_LOW_12:
- case MODE_SELECT: case MODE_SELECT_10: case LOG_SELECT:
- case SEND_DIAGNOSTIC: case CHANGE_DEFINITION: case UPDATE_BLOCK:
- case SET_WINDOW: case MEDIUM_SCAN: case SEND_VOLUME_TAG:
- case REASSIGN_BLOCKS:
- case PERSISTENT_RESERVE_OUT:
- case 0xea:
- case 0xa3:
- return SCSI_DATA_WRITE;
-
- /* No data transfer commands */
- case SEEK_6: case SEEK_10:
- case RESERVE: case RELEASE:
- case TEST_UNIT_READY:
- case START_STOP:
- case ALLOW_MEDIUM_REMOVAL:
- return SCSI_DATA_NONE;
-
- /* Conditional data transfer commands */
- case FORMAT_UNIT:
- if (cmd->cmnd[1] & 0x10) /* FmtData (data out phase)? */
- return SCSI_DATA_WRITE;
- else
- return SCSI_DATA_NONE;
-
- case VERIFY:
- if (cmd->cmnd[1] & 0x02) /* VERIFY:BYTCHK (data out phase)? */
- return SCSI_DATA_WRITE;
- else
- return SCSI_DATA_NONE;
-
- case RESERVE_10:
- if (cmd->cmnd[1] & 0x03) /* RESERVE:{LongID|Extent} (data out phase)? */
- return SCSI_DATA_WRITE;
- else
- return SCSI_DATA_NONE;
-
- /* Must be data _IN! */
- default:
- return SCSI_DATA_READ;
- }
-} /* mptscsih_io_direction() */
+static struct scsi_host_template driver_template;
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
* mptscsih_AddSGE - Add a SGE (plus chain buffers) to the
* SCSIIORequest_t Message Frame.
* @hd: Pointer to MPT_SCSI_HOST structure
- * @SCpnt: Pointer to Scsi_Cmnd structure
+ * @SCpnt: Pointer to scsi_cmnd structure
* @pReq: Pointer to SCSIIORequest_t structure
*
* Returns ...
*/
static int
-mptscsih_AddSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt,
+mptscsih_AddSGE(MPT_SCSI_HOST *hd, struct scsi_cmnd *SCpnt,
SCSIIORequest_t *pReq, int req_idx)
{
char *psge;
if ( (sges_left = SCpnt->use_sg) ) {
sges_left = pci_map_sg(hd->ioc->pcidev,
(struct scatterlist *) SCpnt->request_buffer,
- SCpnt->use_sg,
- scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
+ SCpnt->use_sg,
+ SCpnt->sc_data_direction);
if (sges_left == 0)
return FAILED;
} else if (SCpnt->request_bufflen) {
- dma_addr_t buf_dma_addr;
- scPrivate *my_priv;
-
- buf_dma_addr = pci_map_single(hd->ioc->pcidev,
+ SCpnt->SCp.dma_handle = pci_map_single(hd->ioc->pcidev,
SCpnt->request_buffer,
SCpnt->request_bufflen,
- scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
-
- /* We hide it here for later unmap. */
- my_priv = (scPrivate *) &SCpnt->SCp;
- my_priv->p1 = (void *)(ulong) buf_dma_addr;
-
+ SCpnt->sc_data_direction);
dsgprintk((MYIOC_s_INFO_FMT "SG: non-SG for %p, len=%d\n",
hd->ioc->name, SCpnt, SCpnt->request_bufflen));
-
mptscsih_add_sge((char *) &pReq->SGL,
0xD1000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|SCpnt->request_bufflen,
- buf_dma_addr);
+ SCpnt->SCp.dma_handle);
return SUCCESS;
}
static int
mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
{
- Scsi_Cmnd *sc;
+ struct scsi_cmnd *sc;
MPT_SCSI_HOST *hd;
SCSIIORequest_t *pScsiReq;
SCSIIOReply_t *pScsiReply;
if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
copy_sense_data(sc, hd, mf, pScsiReply);
+
+ /*
+ * Look for + dump FCP ResponseInfo[]!
+ */
+ if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID) {
+ printk(KERN_NOTICE " FCP_ResponseInfo=%08xh\n",
+ le32_to_cpu(pScsiReply->ResponseInfo));
+ }
switch(status) {
case MPI_IOCSTATUS_BUSY: /* 0x0002 */
break;
case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
+ sc->result = (DRIVER_SENSE << 24) | (DID_OK << 16) |
+ (CHECK_CONDITION << 1);
+ sc->sense_buffer[0] = 0x70;
+ sc->sense_buffer[2] = NO_SENSE;
+ sc->sense_buffer[12] = 0;
+ sc->sense_buffer[13] = 0;
+ dprintk((KERN_NOTICE "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->target));
+ break;
+
case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
/*
* Do upfront check for valid SenseData and give it
break;
case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
- if (pScsiReply->SCSIState & MPI_SCSI_STATE_TERMINATED) {
- /* Not real sure here either... */
- sc->result = DID_RESET << 16;
- } else
sc->result = DID_SOFT_ERROR << 16;
break;
/* Unmap the DMA buffers, if any. */
if (sc->use_sg) {
pci_unmap_sg(ioc->pcidev, (struct scatterlist *) sc->request_buffer,
- sc->use_sg, scsi_to_pci_dma_dir(sc->sc_data_direction));
+ sc->use_sg, sc->sc_data_direction);
} else if (sc->request_bufflen) {
- scPrivate *my_priv;
-
- my_priv = (scPrivate *) &sc->SCp;
- pci_unmap_single(ioc->pcidev, (dma_addr_t)(ulong)my_priv->p1,
- sc->request_bufflen,
- scsi_to_pci_dma_dir(sc->sc_data_direction));
+ pci_unmap_single(ioc->pcidev, sc->SCp.dma_handle,
+ sc->request_bufflen, sc->sc_data_direction);
}
hd->ScsiLookup[req_idx] = NULL;
flush_doneQ(MPT_SCSI_HOST *hd)
{
MPT_DONE_Q *buffer;
- Scsi_Cmnd *SCpnt;
+ struct scsi_cmnd *SCpnt;
unsigned long flags;
/* Flush the doneQ.
*/
Q_DEL_ITEM(buffer);
- /* Set the Scsi_Cmnd pointer
+ /* Set the struct scsi_cmnd pointer
*/
- SCpnt = (Scsi_Cmnd *) buffer->argp;
+ SCpnt = (struct scsi_cmnd *) buffer->argp;
buffer->argp = NULL;
/* Add to the freeQ
* Calling function will finish processing.
*/
static void
-search_doneQ_for_cmd(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt)
+search_doneQ_for_cmd(MPT_SCSI_HOST *hd, struct scsi_cmnd *SCpnt)
{
unsigned long flags;
MPT_DONE_Q *buffer;
if (!Q_IS_EMPTY(&hd->doneQ)) {
buffer = hd->doneQ.head;
do {
- Scsi_Cmnd *sc = (Scsi_Cmnd *) buffer->argp;
+ struct scsi_cmnd *sc = (struct scsi_cmnd *) buffer->argp;
if (SCpnt == sc) {
Q_DEL_ITEM(buffer);
SCpnt->result = sc->result;
- /* Set the Scsi_Cmnd pointer
+ /* Set the struct scsi_cmnd pointer
*/
buffer->argp = NULL;
static void
mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
{
- Scsi_Cmnd *SCpnt;
+ struct scsi_cmnd *SCpnt;
MPT_FRAME_HDR *mf;
MPT_DONE_Q *buffer;
int ii;
* Do OS callback
* Free driver resources (chain, msg buffers)
*/
- if (SCpnt->use_sg) {
- pci_unmap_sg(hd->ioc->pcidev, (struct scatterlist *) SCpnt->request_buffer,
- SCpnt->use_sg, scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
- } else if (SCpnt->request_bufflen) {
- scPrivate *my_priv;
-
- my_priv = (scPrivate *) &SCpnt->SCp;
- pci_unmap_single(hd->ioc->pcidev, (dma_addr_t)(ulong)my_priv->p1,
- SCpnt->request_bufflen,
- scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
+ if (scsi_device_online(SCpnt->device)) {
+ if (SCpnt->use_sg) {
+ pci_unmap_sg(hd->ioc->pcidev,
+ (struct scatterlist *) SCpnt->request_buffer,
+ SCpnt->use_sg,
+ SCpnt->sc_data_direction);
+ } else if (SCpnt->request_bufflen) {
+ pci_unmap_single(hd->ioc->pcidev,
+ SCpnt->SCp.dma_handle,
+ SCpnt->request_bufflen,
+ SCpnt->sc_data_direction);
+ }
}
SCpnt->result = DID_RESET << 16;
SCpnt->host_scribble = NULL;
mptscsih_freeChainBuffers(hd, ii);
/* Free Message frames */
- mpt_free_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
+ mpt_free_msg_frame(ScsiDoneCtx, hd->ioc, mf);
#if 1
/* Post to doneQ, do not reply until POST phase
buffer = hd->freeQ.head;
Q_DEL_ITEM(buffer);
- /* Set the Scsi_Cmnd pointer
+ /* Set the struct scsi_cmnd pointer
*/
buffer->argp = (void *)SCpnt;
* mptscsih_search_running_cmds - Delete any commands associated
* with the specified target and lun. Function called only
* when a lun is disable by mid-layer.
- * Do NOT access the referenced Scsi_Cmnd structure or
+ * Do NOT access the referenced scsi_cmnd structure or
* members. Will cause either a paging or NULL ptr error.
* @hd: Pointer to a SCSI HOST structure
* @target: target id
*/
hd->ScsiLookup[ii] = NULL;
mptscsih_freeChainBuffers(hd, ii);
- mpt_free_msg_frame(ScsiDoneCtx, hd->ioc->id, (MPT_FRAME_HDR *)mf);
+ mpt_free_msg_frame(ScsiDoneCtx, hd->ioc, (MPT_FRAME_HDR *)mf);
}
}
/*
* mptscsih_report_queue_full - Report QUEUE_FULL status returned
* from a SCSI target device.
- * @sc: Pointer to Scsi_Cmnd structure
+ * @sc: Pointer to scsi_cmnd structure
* @pScsiReply: Pointer to SCSIIOReply_t
* @pScsiReq: Pointer to original SCSI request
*
* printk() API call, not more than once every 10 seconds.
*/
static void
-mptscsih_report_queue_full(Scsi_Cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
+mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
{
long time = jiffies;
}
sh->max_lun = MPT_LAST_LUN + 1;
- sh->max_sectors = MPT_SCSI_MAX_SECTORS;
sh->max_channel = 0;
sh->this_id = ioc->pfacts[0].PortSCSIID;
hd->is_multipath = 1;
}
- /* SCSI needs Scsi_Cmnd lookup table!
+ /* SCSI needs scsi_cmnd lookup table!
* (with size equal to req_depth*PtrSz!)
*/
sz = hd->ioc->req_depth * sizeof(void *);
}
dprintk((MYIOC_s_INFO_FMT
- "Free'd ScsiLookup (%d), chain (%d) and Target (%d+%d) memory\n",
- hd->ioc->name, sz1, szchain, sz3, sztarget));
+ "Free'd ScsiLookup (%d) Target (%d+%d) memory\n",
+ hd->ioc->name, sz1, sz3, sztarget));
dprintk(("Free'd done and free Q (%d) memory\n", szQ));
/* NULL the Scsi_Host pointer
if (!dvtaskQ_active) {
dvtaskQ_active = 1;
spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
- MPT_INIT_WORK(&mptscsih_dvTask,
+ INIT_WORK(&mptscsih_dvTask,
mptscsih_domainValidation, (void *) hd);
- SCHEDULE_TASK(&mptscsih_dvTask);
+ schedule_work(&mptscsih_dvTask);
} else {
spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
}
#endif
};
-
/* SCSI host fops start here... */
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
static void __exit
mptscsih_exit(void)
{
- MPT_ADAPTER *ioc;
-
- /* removing devices */
- for(ioc = mpt_adapter_find_first(); ioc != NULL;
- ioc = mpt_adapter_find_next(ioc)) {
- if ((ioc->last_state != MPI_IOC_STATE_OPERATIONAL) ||
- (ioc->sh == NULL))
- continue;
- mptscsih_remove(ioc->pcidev);
- }
+ mpt_device_driver_deregister(MPTSCSIH_DRIVER);
mpt_reset_deregister(ScsiDoneCtx);
dprintk((KERN_INFO MYNAM
dprintk((KERN_INFO MYNAM
": Deregistered for IOC event notifications\n"));
- mpt_device_driver_deregister(MPTSCSIH_DRIVER);
mpt_deregister(ScsiScanDvCtx);
mpt_deregister(ScsiTaskCtx);
mpt_deregister(ScsiDoneCtx);
* mptscsih_info - Return information about MPT adapter
* @SChost: Pointer to Scsi_Host structure
*
- * (linux Scsi_Host_Template.info routine)
+ * (linux scsi_host_template.info routine)
*
* Returns pointer to buffer where information was written.
*/
/**
* mptscsih_proc_info - Return information about MPT adapter
*
- * (linux Scsi_Host_Template.info routine)
+ * (linux scsi_host_template.info routine)
*
* buffer: if write, user data; if read, buffer for user
* length: if write, return length;
int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
int length, int func)
{
- MPT_ADAPTER *ioc;
- MPT_SCSI_HOST *hd = NULL;
+ MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
+ MPT_ADAPTER *ioc = hd->ioc;
int size = 0;
- dprintk(("Called mptscsih_proc_info: hostno=%d, func=%d\n", host->host_no, func));
- dprintk(("buffer %p, start=%p (%p) offset=%ld length = %d\n",
- buffer, start, *start, offset, length));
-
- for (ioc = mpt_adapter_find_first(); ioc != NULL; ioc = mpt_adapter_find_next(ioc)) {
- if ((ioc->sh) && (ioc->sh == host)) {
- hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
- break;
- }
- }
- if ((ioc == NULL) || (ioc->sh == NULL) || (hd == NULL))
- return 0;
-
if (func) {
size = mptscsih_user_command(ioc, buffer, length);
} else {
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
* mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.
- * @SCpnt: Pointer to Scsi_Cmnd structure
+ * @SCpnt: Pointer to scsi_cmnd structure
* @done: Pointer SCSI mid-layer IO completion function
*
- * (linux Scsi_Host_Template.queuecommand routine)
+ * (linux scsi_host_template.queuecommand routine)
* This is the primary SCSI IO start routine. Create a MPI SCSIIORequest
- * from a linux Scsi_Cmnd request and send it to the IOC.
+ * from a linux scsi_cmnd request and send it to the IOC.
*
* Returns 0. (rtn value discarded by linux scsi mid-layer)
*/
int
-mptscsih_qcmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
+mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
{
MPT_SCSI_HOST *hd;
MPT_FRAME_HDR *mf;
unsigned long flags;
int target;
int lun;
- int datadir;
u32 datalen;
u32 scsictl;
u32 scsidir;
/*
* Put together a MPT SCSI request...
*/
- if ((mf = mpt_get_msg_frame(ScsiDoneCtx, hd->ioc->id)) == NULL) {
+ if ((mf = mpt_get_msg_frame(ScsiDoneCtx, hd->ioc)) == NULL) {
dprintk((MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
hd->ioc->name));
did_errcode = 2;
ADD_INDEX_LOG(my_idx);
- /*
- * The scsi layer should be handling this stuff
- * (In 2.3.x it does -DaveM)
- */
-
/* BUG FIX! 19991030 -sralston
* TUR's being issued with scsictl=0x02000000 (DATA_IN)!
* Seems we may receive a buffer (datalen>0) even when there
* will be no data transfer! GRRRRR...
*/
- datadir = mptscsih_io_direction(SCpnt);
- if (datadir == SCSI_DATA_READ) {
+ if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) {
datalen = SCpnt->request_bufflen;
scsidir = MPI_SCSIIO_CONTROL_READ; /* DATA IN (host<--ioc<--dev) */
- } else if (datadir == SCSI_DATA_WRITE) {
+ } else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {
datalen = SCpnt->request_bufflen;
scsidir = MPI_SCSIIO_CONTROL_WRITE; /* DATA OUT (host-->ioc-->dev) */
} else {
if (dvStatus || hd->ioc->spi_data.forceDv) {
- /* Write SDP1 on this I/O to this target */
- if (dvStatus & MPT_SCSICFG_NEGOTIATE) {
- mptscsih_writeSDP1(hd, 0, target, hd->negoNvram);
- dvStatus &= ~MPT_SCSICFG_NEGOTIATE;
- hd->ioc->spi_data.dvStatus[target] = dvStatus;
- } else if (dvStatus & MPT_SCSICFG_BLK_NEGO) {
- mptscsih_writeSDP1(hd, 0, target, MPT_SCSICFG_BLK_NEGO);
- dvStatus &= ~MPT_SCSICFG_BLK_NEGO;
- hd->ioc->spi_data.dvStatus[target] = dvStatus;
- }
-
#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
if ((dvStatus & MPT_SCSICFG_NEED_DV) ||
(hd->ioc->spi_data.forceDv & MPT_SCSICFG_NEED_DV)) {
if (!dvtaskQ_active) {
dvtaskQ_active = 1;
spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
- MPT_INIT_WORK(&mptscsih_dvTask, mptscsih_domainValidation, (void *) hd);
+ INIT_WORK(&mptscsih_dvTask, mptscsih_domainValidation, (void *) hd);
- SCHEDULE_TASK(&mptscsih_dvTask);
+ schedule_work(&mptscsih_dvTask);
} else {
spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
}
#endif
if (issueCmd) {
- mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
+ mpt_put_msg_frame(ScsiDoneCtx, hd->ioc, mf);
dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
hd->ioc->name, SCpnt, mf, my_idx));
} else {
}
} else {
mptscsih_freeChainBuffers(hd, my_idx);
- mpt_free_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
+ mpt_free_msg_frame(ScsiDoneCtx, hd->ioc, mf);
did_errcode = 3;
goto did_error;
}
buffer = hd->freeQ.head;
Q_DEL_ITEM(buffer);
- /* Set the Scsi_Cmnd pointer
+ /* Set the scsi_cmnd pointer
*/
buffer->argp = (void *)SCpnt;
/* Return Fail to calling function if no message frames available.
*/
- if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc->id)) == NULL) {
+ if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc)) == NULL) {
dtmprintk((MYIOC_s_WARN_FMT "IssueTaskMgmt, no msg frames!!\n",
hd->ioc->name));
//return FAILED;
hd->TMtimer.expires = jiffies + timeout;
add_timer(&hd->TMtimer);
- if ((retval = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id,
+ if ((retval = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc,
sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, sleepFlag))
!= 0) {
dtmprintk((MYIOC_s_WARN_FMT "_send_handshake FAILED!"
hd->numTMrequests--;
hd->tmPtr = NULL;
del_timer(&hd->TMtimer);
- mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
+ mpt_free_msg_frame(ScsiTaskCtx, hd->ioc, mf);
}
return retval;
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
- * mptscsih_abort - Abort linux Scsi_Cmnd routine, new_eh variant
- * @SCpnt: Pointer to Scsi_Cmnd structure, IO to be aborted
+ * mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant
+ * @SCpnt: Pointer to scsi_cmnd structure, IO to be aborted
*
- * (linux Scsi_Host_Template.eh_abort_handler routine)
+ * (linux scsi_host_template.eh_abort_handler routine)
*
* Returns SUCCESS or FAILED.
*/
int
-mptscsih_abort(Scsi_Cmnd * SCpnt)
+mptscsih_abort(struct scsi_cmnd * SCpnt)
{
MPT_SCSI_HOST *hd;
MPT_FRAME_HDR *mf;
* and then following up with the reset request.
*/
if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) {
- mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
+ mpt_put_msg_frame(ScsiDoneCtx, hd->ioc, mf);
post_pendingQ_commands(hd);
dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
"Posting pended cmd! (sc=%p)\n",
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
* mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant
- * @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
+ * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
*
- * (linux Scsi_Host_Template.eh_dev_reset_handler routine)
+ * (linux scsi_host_template.eh_dev_reset_handler routine)
*
* Returns SUCCESS or FAILED.
*/
int
-mptscsih_dev_reset(Scsi_Cmnd * SCpnt)
+mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
{
MPT_SCSI_HOST *hd;
spinlock_t *host_lock = SCpnt->device->host->host_lock;
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
* mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant
- * @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
+ * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
*
- * (linux Scsi_Host_Template.eh_bus_reset_handler routine)
+ * (linux scsi_host_template.eh_bus_reset_handler routine)
*
* Returns SUCCESS or FAILED.
*/
int
-mptscsih_bus_reset(Scsi_Cmnd * SCpnt)
+mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
{
MPT_SCSI_HOST *hd;
spinlock_t *host_lock = SCpnt->device->host->host_lock;
/**
* mptscsih_host_reset - Perform a SCSI host adapter RESET!
* new_eh variant
- * @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
+ * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
*
- * (linux Scsi_Host_Template.eh_host_reset_handler routine)
+ * (linux scsi_host_template.eh_host_reset_handler routine)
*
* Returns SUCCESS or FAILED.
*/
int
-mptscsih_host_reset(Scsi_Cmnd *SCpnt)
+mptscsih_host_reset(struct scsi_cmnd *SCpnt)
{
MPT_SCSI_HOST * hd;
int status = SUCCESS;
* Init memory once per id (not LUN).
*/
int
-mptscsih_slave_alloc(Scsi_Device *device)
+mptscsih_slave_alloc(struct scsi_device *device)
{
struct Scsi_Host *host = device->host;
MPT_SCSI_HOST *hd;
* Called if no device present or device being unloaded
*/
void
-mptscsih_slave_destroy(Scsi_Device *device)
+mptscsih_slave_destroy(struct scsi_device *device)
{
struct Scsi_Host *host = device->host;
MPT_SCSI_HOST *hd;
* Return non-zero if fails.
*/
int
-mptscsih_slave_configure(Scsi_Device *device)
+mptscsih_slave_configure(struct scsi_device *device)
{
struct Scsi_Host *sh = device->host;
VirtDevice *pTarget;
*
*/
static void
-copy_sense_data(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
+copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
{
VirtDevice *target;
SCSIIORequest_t *pReq;
}
static u32
-SCPNT_TO_LOOKUP_IDX(Scsi_Cmnd *sc)
+SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
{
MPT_SCSI_HOST *hd;
int i;
continue;
}
- mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
+ mpt_put_msg_frame(ScsiDoneCtx, hd->ioc, mf);
#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
{
u16 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
- Scsi_Cmnd *sc = hd->ScsiLookup[req_idx];
+ struct scsi_cmnd *sc = hd->ScsiLookup[req_idx];
printk(MYIOC_s_INFO_FMT "Issued SCSI cmd (sc=%p) idx=%d (mf=%p)\n",
hd->ioc->name, sc, req_idx, mf);
}
*/
if (hd->cmdPtr) {
del_timer(&hd->timer);
- mpt_free_msg_frame(ScsiScanDvCtx, ioc->id, hd->cmdPtr);
+ mpt_free_msg_frame(ScsiScanDvCtx, ioc, hd->cmdPtr);
}
/* 2d. If a task management has not completed,
*/
if (hd->tmPtr) {
del_timer(&hd->TMtimer);
- mpt_free_msg_frame(ScsiTaskCtx, ioc->id, hd->tmPtr);
+ mpt_free_msg_frame(ScsiTaskCtx, ioc, hd->tmPtr);
}
#ifdef MPTSCSIH_DBG_TIMEOUT
return 1; /* currently means nothing really */
}
+static struct scsi_host_template driver_template = {
+ .proc_name = "mptscsih",
+ .proc_info = mptscsih_proc_info,
+ .name = "MPT SCSI Host",
+ .info = mptscsih_info,
+ .queuecommand = mptscsih_qcmd,
+ .slave_alloc = mptscsih_slave_alloc,
+ .slave_configure = mptscsih_slave_configure,
+ .slave_destroy = mptscsih_slave_destroy,
+ .eh_abort_handler = mptscsih_abort,
+ .eh_device_reset_handler = mptscsih_dev_reset,
+ .eh_bus_reset_handler = mptscsih_bus_reset,
+ .eh_host_reset_handler = mptscsih_host_reset,
+ .bios_param = mptscsih_bios_param,
+ .can_queue = MPT_SCSI_CAN_QUEUE,
+ .this_id = -1,
+ .sg_tablesize = MPT_SCSI_SG_DEPTH,
+ .max_sectors = 8192,
+ .cmd_per_lun = 7,
+ .use_clustering = ENABLE_CLUSTERING,
+};
+
+
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* Private data...
}
}
- data_56 = 0;
+ data_56 = 0x0F; /* Default to full capabilities if Inq data length is < 57 */
if (dlen > 56) {
if ( (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) {
/* Update the target capabilities
}
if (target->inq_data[7] & 0x10) {
- /* bits 2 & 3 show DT support
+ /* bits 2 & 3 show Clocking support
*/
- if ((byte56 & 0x04) == 0)
+ if ((byte56 & 0x0C) == 0)
factor = MPT_ULTRA2;
- else if ((byte56 & 0x03) == 0)
- factor = MPT_ULTRA160;
- else
- factor = MPT_ULTRA320;
+ else {
+ if ((byte56 & 0x03) == 0)
+ factor = MPT_ULTRA160;
+ else
+ factor = MPT_ULTRA320;
+ }
offset = pspi_data->maxSyncOffset;
/* If RAID, never disable QAS
* bit 1 QAS support, non-raid only
* bit 0 IU support
*/
- if ((target->raidVolume == 1) || ((byte56 & 0x02) != 0))
+ if ((target->raidVolume == 1) || (byte56 & 0x02)) {
noQas = 0;
+ }
} else {
factor = MPT_ASYNC;
offset = 0;
/* Disable QAS in a mixed configuration case
*/
-// ddvtprintk((KERN_INFO "Disabling QAS!\n"));
+ ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
for (ii = 0; ii < id; ii++) {
if ( (vdev = hd->Targets[ii]) ) {
vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
}
}
}
+
+ /* Write SDP1 on this I/O to this target */
+ if (pspi_data->dvStatus[id] & MPT_SCSICFG_NEGOTIATE) {
+ mptscsih_writeSDP1(hd, 0, id, hd->negoNvram);
+ pspi_data->dvStatus[id] &= ~MPT_SCSICFG_NEGOTIATE;
+ } else if (pspi_data->dvStatus[id] & MPT_SCSICFG_BLK_NEGO) {
+ mptscsih_writeSDP1(hd, 0, id, MPT_SCSICFG_BLK_NEGO);
+ pspi_data->dvStatus[id] &= ~MPT_SCSICFG_BLK_NEGO;
+ }
}
return;
/* Get a MF for this command.
*/
- if ((mf = mpt_get_msg_frame(ScsiDoneCtx, ioc->id)) == NULL) {
+ if ((mf = mpt_get_msg_frame(ScsiDoneCtx, ioc)) == NULL) {
dprintk((MYIOC_s_WARN_FMT "write SDP1: no msg frames!\n",
ioc->name));
return -EAGAIN;
ioc->name, id, (id | (bus<<8)),
requested, configuration));
- mpt_put_msg_frame(ScsiDoneCtx, ioc->id, mf);
+ mpt_put_msg_frame(ScsiDoneCtx, ioc, mf);
}
return 0;
/* Get a MF for this command.
*/
- if ((mf = mpt_get_msg_frame(ScsiDoneCtx, ioc->id)) == NULL) {
+ if ((mf = mpt_get_msg_frame(ScsiDoneCtx, ioc)) == NULL) {
dprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
ioc->name));
return -EAGAIN;
"writeIOCPage4: pgaddr 0x%x\n",
ioc->name, (target_id | (bus<<8))));
- mpt_put_msg_frame(ScsiDoneCtx, ioc->id, mf);
+ mpt_put_msg_frame(ScsiDoneCtx, ioc, mf);
return 0;
}
/* Call the reset handler. Already had a TM request
* timeout - so issue a diagnostic reset
*/
- MPT_INIT_WORK(&mptscsih_rstTask, mptscsih_schedule_reset, (void *)hd);
- SCHEDULE_TASK(&mptscsih_rstTask);
+ INIT_WORK(&mptscsih_rstTask, mptscsih_schedule_reset, (void *)hd);
+ schedule_work(&mptscsih_rstTask);
return;
}
/* Get and Populate a free Frame
*/
- if ((mf = mpt_get_msg_frame(ScsiScanDvCtx, hd->ioc->id)) == NULL) {
+ if ((mf = mpt_get_msg_frame(ScsiScanDvCtx, hd->ioc)) == NULL) {
ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n",
hd->ioc->name));
return -EAGAIN;
hd->ioc->name, action, io->id));
hd->pLocal = NULL;
- hd->timer.expires = jiffies + HZ*2; /* 2 second timeout */
+ hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
scandv_wait_done = 0;
/* Save cmd pointer, for resource free if timeout or
hd->cmdPtr = mf;
add_timer(&hd->timer);
- mpt_put_msg_frame(ScsiScanDvCtx, hd->ioc->id, mf);
+ mpt_put_msg_frame(ScsiScanDvCtx, hd->ioc, mf);
wait_event(scandv_waitq, scandv_wait_done);
if ((hd->pLocal == NULL) || (hd->pLocal->completion != MPT_SCANDV_GOOD))
/* Get and Populate a free Frame
*/
- if ((mf = mpt_get_msg_frame(ScsiScanDvCtx, hd->ioc->id)) == NULL) {
+ if ((mf = mpt_get_msg_frame(ScsiScanDvCtx, hd->ioc)) == NULL) {
ddvprintk((MYIOC_s_WARN_FMT "No msg frames!\n",
hd->ioc->name));
return -EBUSY;
hd->cmdPtr = mf;
add_timer(&hd->timer);
- mpt_put_msg_frame(ScsiScanDvCtx, hd->ioc->id, mf);
+ mpt_put_msg_frame(ScsiScanDvCtx, hd->ioc, mf);
wait_event(scandv_waitq, scandv_wait_done);
if (hd->pLocal) {
did = 1;
while (did) {
did = 0;
- for (ioc = mpt_adapter_find_first(); ioc != NULL; ioc = mpt_adapter_find_next(ioc)) {
+ list_for_each_entry(ioc, &ioc_list, list) {
spin_lock_irqsave(&dvtaskQ_lock, flags);
if (dvtaskQ_release) {
dvtaskQ_active = 0;