mptscsih.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:201k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/drivers/message/fusion/mptscsih.c
  3.  *      High performance SCSI / Fibre Channel SCSI Host device driver.
  4.  *      For use with PCI chip/adapter(s):
  5.  *          LSIFC9xx/LSI409xx Fibre Channel
  6.  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  7.  *
  8.  *  Credits:
  9.  *      This driver would not exist if not for Alan Cox's development
  10.  *      of the linux i2o driver.
  11.  *
  12.  *      A special thanks to Pamela Delaney (LSI Logic) for tons of work
  13.  *      and countless enhancements while adding support for the 1030
  14.  *      chip family.  Pam has been instrumental in the development of
  15.  *      of the 2.xx.xx series fusion drivers, and her contributions are
  16.  *      far too numerous to hope to list in one place.
  17.  *
  18.  *      A huge debt of gratitude is owed to David S. Miller (DaveM)
  19.  *      for fixing much of the stupid and broken stuff in the early
  20.  *      driver while porting to sparc64 platform.  THANK YOU!
  21.  *
  22.  *      (see mptbase.c)
  23.  *
  24.  *  Copyright (c) 1999-2002 LSI Logic Corporation
  25.  *  Original author: Steven J. Ralston
  26.  *  (mailto:sjralston1@netscape.net)
  27.  *  (mailto:Pam.Delaney@lsil.com)
  28.  *
  29.  *  $Id: mptscsih.c,v 1.101 2002/09/05 22:30:11 pdelaney Exp $
  30.  */
  31. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  32. /*
  33.     This program is free software; you can redistribute it and/or modify
  34.     it under the terms of the GNU General Public License as published by
  35.     the Free Software Foundation; version 2 of the License.
  36.     This program is distributed in the hope that it will be useful,
  37.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  38.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  39.     GNU General Public License for more details.
  40.     NO WARRANTY
  41.     THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
  42.     CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
  43.     LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
  44.     MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
  45.     solely responsible for determining the appropriateness of using and
  46.     distributing the Program and assumes all risks associated with its
  47.     exercise of rights under this Agreement, including but not limited to
  48.     the risks and costs of program errors, damage to or loss of data,
  49.     programs or equipment, and unavailability or interruption of operations.
  50.     DISCLAIMER OF LIABILITY
  51.     NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
  52.     DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  53.     DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
  54.     ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
  55.     TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  56.     USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
  57.     HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
  58.     You should have received a copy of the GNU General Public License
  59.     along with this program; if not, write to the Free Software
  60.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  61. */
  62. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  63. #include <linux/module.h>
  64. #include <linux/version.h>
  65. #include <linux/kernel.h>
  66. #include <linux/init.h>
  67. #include <linux/errno.h>
  68. #include <linux/kdev_t.h>
  69. #include <linux/blkdev.h>
  70. #include <linux/blk.h> /* for io_request_lock (spinlock) decl */
  71. #include <linux/delay.h> /* for mdelay */
  72. #include <linux/interrupt.h> /* needed for in_interrupt() proto */
  73. #include <linux/reboot.h> /* notifier code */
  74. #include "../../scsi/scsi.h"
  75. #include "../../scsi/hosts.h"
  76. #include "../../scsi/sd.h"
  77. #include "mptbase.h"
  78. #include "mptscsih.h"
  79. #include "isense.h"
  80. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  81. #define my_NAME "Fusion MPT SCSI Host driver"
  82. #define my_VERSION MPT_LINUX_VERSION_COMMON
  83. #define MYNAM "mptscsih"
  84. MODULE_AUTHOR(MODULEAUTHOR);
  85. MODULE_DESCRIPTION(my_NAME);
  86. MODULE_LICENSE("GPL");
  87. /* Set string for command line args from insmod */
  88. #ifdef MODULE
  89. char *mptscsih = 0;
  90. MODULE_PARM(mptscsih, "s");
  91. #endif
  92. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  93. typedef struct _BIG_SENSE_BUF {
  94. u8 data[MPT_SENSE_BUFFER_ALLOC];
  95. } BIG_SENSE_BUF;
  96. #define MPT_SCANDV_GOOD (0x00000000) /* must be 0 */
  97. #define MPT_SCANDV_DID_RESET (0x00000001)
  98. #define MPT_SCANDV_SENSE (0x00000002)
  99. #define MPT_SCANDV_SOME_ERROR (0x00000004)
  100. #define MPT_SCANDV_SELECTION_TIMEOUT (0x00000008)
  101. #define MPT_SCANDV_MAX_RETRIES (10)
  102. #define MPT_ICFLAG_BUF_CAP 0x01 /* ReadBuffer Read Capacity format */
  103. #define MPT_ICFLAG_ECHO 0x02 /* ReadBuffer Echo buffer format */
  104. #define MPT_ICFLAG_PHYS_DISK 0x04 /* Any SCSI IO but do Phys Disk Format */
  105. #define MPT_ICFLAG_TAGGED_CMD 0x08 /* Do tagged IO */
  106. #define MPT_ICFLAG_DID_RESET 0x20 /* Bus Reset occured with this command */
  107. #define MPT_ICFLAG_RESERVED 0x40 /* Reserved has been issued */
  108. typedef struct _internal_cmd {
  109. char *data; /* data pointer */
  110. dma_addr_t data_dma; /* data dma address */
  111. int size; /* transfer size */
  112. u8 cmd; /* SCSI Op Code */
  113. u8 bus; /* bus number */
  114. u8 id; /* SCSI ID (virtual) */
  115. u8 lun;
  116. u8 flags; /* Bit Field - See above */
  117. u8 physDiskNum; /* Phys disk number, -1 else */
  118. u8 rsvd2;
  119. u8 rsvd;
  120. } INTERNAL_CMD;
  121. typedef struct _negoparms {
  122. u8 width;
  123. u8 offset;
  124. u8 factor;
  125. u8 flags;
  126. } NEGOPARMS;
  127. typedef struct _dv_parameters {
  128. NEGOPARMS  max;
  129. NEGOPARMS  now;
  130. u8  cmd;
  131. u8  id;
  132. u16  pad1;
  133. } DVPARAMETERS;
  134. /*
  135.  *  Other private/forward protos...
  136.  */
  137. static int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
  138. static void mptscsih_report_queue_full(Scsi_Cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
  139. static int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
  140. static int mptscsih_io_direction(Scsi_Cmnd *cmd);
  141. static int mptscsih_AddSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt,
  142.  SCSIIORequest_t *pReq, int req_idx);
  143. static int mptscsih_getFreeChainBuffer(MPT_SCSI_HOST *hd, int *retIndex);
  144. static void mptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx);
  145. static int mptscsih_initChainBuffers (MPT_SCSI_HOST *hd, int init);
  146. static void copy_sense_data(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
  147. #ifndef MPT_SCSI_USE_NEW_EH
  148. static void search_taskQ_for_cmd(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd);
  149. #else
  150. static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
  151. #endif
  152. static u32 SCPNT_TO_LOOKUP_IDX(Scsi_Cmnd *sc);
  153. static MPT_FRAME_HDR *mptscsih_search_pendingQ(MPT_SCSI_HOST *hd, int scpnt_idx);
  154. static void post_pendingQ_commands(MPT_SCSI_HOST *hd);
  155. static int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 target, u8 lun, int ctx2abort, int sleepFlag);
  156. static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 target, u8 lun, int ctx2abort, int sleepFlag);
  157. static int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
  158. static int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
  159. static VirtDevice *mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen);
  160. void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56);
  161. static void clear_sense_flag(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq);
  162. static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq);
  163. static void mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags);
  164. static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id);
  165. static int mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target, int flags);
  166. static int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
  167. static void mptscsih_timer_expired(unsigned long data);
  168. static void mptscsih_taskmgmt_timeout(unsigned long data);
  169. static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
  170. static int mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum);
  171. #ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
  172. static int mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io);
  173. static void mptscsih_domainValidation(void *hd);
  174. static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id);
  175. static void mptscsih_qas_check(MPT_SCSI_HOST *hd);
  176. static void mptscsih_doDv(MPT_SCSI_HOST *hd, int portnum, int target);
  177. static void mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage);
  178. static void mptscsih_fillbuf(char *buffer, int size, int index, int width);
  179. #endif
  180. static int mptscsih_setup(char *str);
  181. static int mptscsih_halt(struct notifier_block *nb, ulong event, void *buf);
  182. /*
  183.  * Reboot Notification
  184.  */
  185. static struct notifier_block mptscsih_notifier = {
  186. mptscsih_halt, NULL, 0
  187. };
  188. /*
  189.  * Private data...
  190.  */
  191. static int mpt_scsi_hosts = 0;
  192. static atomic_t queue_depth;
  193. static int ScsiDoneCtx = -1;
  194. static int ScsiTaskCtx = -1;
  195. static int ScsiScanDvCtx = -1; /* Used only for bus scan and dv */
  196. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,28)
  197. static struct proc_dir_entry proc_mpt_scsihost =
  198. {
  199. .low_ino = PROC_SCSI_MPT,
  200. .namelen = 8,
  201. .name = "mptscsih",
  202. .mode = S_IFDIR | S_IRUGO | S_IXUGO,
  203. .nlink = 2,
  204. };
  205. #endif
  206. #define SNS_LEN(scp) sizeof((scp)->sense_buffer)
  207. #ifndef MPT_SCSI_USE_NEW_EH
  208. /*
  209.  *  Stuff to handle single-threading SCSI TaskMgmt
  210.  *  (abort/reset) requests...
  211.  */
  212. static spinlock_t mytaskQ_lock = SPIN_LOCK_UNLOCKED;
  213. static int mytaskQ_bh_active = 0;
  214. static struct tq_struct mptscsih_ptaskfoo;
  215. static atomic_t mpt_taskQdepth;
  216. #endif
  217. #ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
  218. /*
  219.  * Domain Validation task structure
  220.  */
  221. static spinlock_t dvtaskQ_lock = SPIN_LOCK_UNLOCKED;
  222. static int dvtaskQ_active = 0;
  223. static int dvtaskQ_release = 0;
  224. static struct tq_struct mptscsih_dvTask;
  225. #endif
  226. /*
  227.  * Wait Queue setup
  228.  */
  229. static DECLARE_WAIT_QUEUE_HEAD (scandv_waitq);
  230. static int scandv_wait_done = 1;
  231. /* Driver default setup
  232.  */
  233. static struct mptscsih_driver_setup
  234. driver_setup = MPTSCSIH_DRIVER_SETUP;
  235. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  236. /*
  237.  * mptscsih_io_done - Main SCSI IO callback routine registered to
  238.  * Fusion MPT (base) driver
  239.  * @ioc: Pointer to MPT_ADAPTER structure
  240.  * @mf: Pointer to original MPT request frame
  241.  * @r: Pointer to MPT reply frame (NULL if TurboReply)
  242.  *
  243.  * This routine is called from mpt.c::mpt_interrupt() at the completion
  244.  * of any SCSI IO request.
  245.  * This routine is registered with the Fusion MPT (base) driver at driver
  246.  * load/init time via the mpt_register() API call.
  247.  *
  248.  * Returns 1 indicating alloc'd request frame ptr should be freed.
  249.  */
  250. static int
  251. mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
  252. {
  253. Scsi_Cmnd *sc;
  254. MPT_SCSI_HOST *hd;
  255. SCSIIORequest_t *pScsiReq;
  256. SCSIIOReply_t *pScsiReply;
  257. #ifndef MPT_SCSI_USE_NEW_EH
  258. unsigned long  flags;
  259. #endif
  260. u16  req_idx;
  261. hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
  262. if ((mf == NULL) ||
  263.     (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
  264. printk(MYIOC_s_ERR_FMT "%s req frame ptr! (=%p)!n",
  265. ioc->name, mf?"BAD":"NULL", (void *) mf);
  266. /* return 1; CHECKME SteveR. Don't free. */
  267. return 0;
  268. }
  269. req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
  270. sc = hd->ScsiLookup[req_idx];
  271. if (sc == NULL) {
  272. MPIHeader_t *hdr = (MPIHeader_t *)mf;
  273. atomic_dec(&queue_depth);
  274. /* writeSDP1 will use the ScsiDoneCtx
  275.  * There is no processing for the reply.
  276.  * Just return to the calling function.
  277.  */
  278. if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST)
  279. printk(MYIOC_s_ERR_FMT "NULL ScsiCmd ptr!n", ioc->name);
  280. mptscsih_freeChainBuffers(hd, req_idx);
  281. return 1;
  282. }
  283. dmfprintk((MYIOC_s_INFO_FMT "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)n",
  284. ioc->name, mf, mr, sc, req_idx));
  285. atomic_dec(&queue_depth);
  286. sc->result = DID_OK << 16; /* Set default reply as OK */
  287. pScsiReq = (SCSIIORequest_t *) mf;
  288. pScsiReply = (SCSIIOReply_t *) mr;
  289. #ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
  290. if (hd->is_spi) {
  291. u32 qtag = le32_to_cpu(pScsiReq->Control);
  292. if (qtag & MPI_SCSIIO_CONTROL_UNTAGGED)
  293. hd->ioc->spi_data.iocntr[sc->target]--;
  294. }
  295. #endif
  296. if (pScsiReply == NULL) {
  297. /* special context reply handling */
  298. /* If regular Inquiry cmd - save inquiry data
  299.  */
  300. if (pScsiReq->CDB[0] == INQUIRY && !(pScsiReq->CDB[1] & 0x3)) {
  301. int  dlen;
  302. dlen = le32_to_cpu(pScsiReq->DataLength);
  303. if (dlen >= SCSI_STD_INQUIRY_BYTES) {
  304. mptscsih_initTarget(hd,
  305. hd->port,
  306. sc->target,
  307. pScsiReq->LUN[1],
  308. sc->buffer,
  309. dlen);
  310. }
  311. }
  312. clear_sense_flag(hd, pScsiReq);
  313. } else {
  314. u32  xfer_cnt;
  315. u16  status;
  316. u8  scsi_state;
  317. status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
  318. scsi_state = pScsiReply->SCSIState;
  319. dprintk((KERN_NOTICE "  Uh-Oh! (%d:%d:%d) mf=%p, mr=%p, sc=%pn",
  320. ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1],
  321. mf, mr, sc));
  322. dprintk((KERN_NOTICE "  IOCStatus=%04xh, SCSIState=%02xh"
  323. ", SCSIStatus=%02xh, IOCLogInfo=%08xhn",
  324. status, scsi_state, pScsiReply->SCSIStatus,
  325. le32_to_cpu(pScsiReply->IOCLogInfo)));
  326. if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
  327. copy_sense_data(sc, hd, mf, pScsiReply);
  328. /*
  329.  *  Look for + dump FCP ResponseInfo[]!
  330.  */
  331. if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID) {
  332. dprintk((KERN_NOTICE "  FCP_ResponseInfo=%08xhn",
  333.      le32_to_cpu(pScsiReply->ResponseInfo)));
  334. }
  335. switch(status) {
  336. case MPI_IOCSTATUS_BUSY: /* 0x0002 */
  337. /* CHECKME!
  338.  * Maybe: DRIVER_BUSY | SUGGEST_RETRY | DID_SOFT_ERROR (retry)
  339.  * But not: DID_BUS_BUSY lest one risk
  340.  * killing interrupt handler:-(
  341.  */
  342. sc->result = STS_BUSY;
  343. break;
  344. case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
  345. case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
  346. sc->result = DID_BAD_TARGET << 16;
  347. break;
  348. case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
  349. /* Spoof to SCSI Selection Timeout! */
  350. sc->result = DID_NO_CONNECT << 16;
  351. break;
  352. case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
  353. #ifndef MPT_SCSI_USE_NEW_EH
  354. search_taskQ_for_cmd(sc, hd);
  355. #endif
  356. /* Linux handles an unsolicited DID_RESET better 
  357.  * than an unsolicited DID_ABORT.
  358.  */
  359. sc->result = DID_RESET << 16;
  360. /* GEM Workaround. */ 
  361. if (hd->is_spi)
  362. mptscsih_no_negotiate(hd, sc->target);
  363. break;
  364. case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
  365. case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
  366. #ifndef MPT_SCSI_USE_NEW_EH
  367. search_taskQ_for_cmd(sc, hd);
  368. #endif
  369. sc->result = DID_RESET << 16;
  370. /* GEM Workaround. */ 
  371. if (hd->is_spi)
  372. mptscsih_no_negotiate(hd, sc->target);
  373. break;
  374. case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
  375. case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
  376. /*
  377.  *  YIKES!  I just discovered that SCSI IO which
  378.  *  returns check condition, SenseKey=05 (ILLEGAL REQUEST)
  379.  *  and ASC/ASCQ=94/01 (LSI Logic RAID vendor specific),
  380.  *  comes down this path!
  381.  *  Do upfront check for valid SenseData and give it
  382.  *  precedence!
  383.  */
  384. sc->result = (DID_OK << 16) | pScsiReply->SCSIStatus;
  385. clear_sense_flag(hd, pScsiReq);
  386. if (pScsiReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
  387. /* Have already saved the status and sense data
  388.  */
  389. ;
  390. } else if (pScsiReply->SCSIState & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
  391. /* What to do?
  392.  */
  393. sc->result = DID_SOFT_ERROR << 16;
  394. }
  395. else if (pScsiReply->SCSIState & MPI_SCSI_STATE_TERMINATED) {
  396. /*  Not real sure here either...  */
  397. sc->result = DID_RESET << 16;
  398. }
  399. /* Give report and update residual count.
  400.  */
  401. xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
  402. dprintk((KERN_NOTICE "  sc->underflow={report ERR if < %02xh bytes xfer'd}n",
  403. sc->underflow));
  404. dprintk((KERN_NOTICE "  ActBytesXferd=%02xhn", xfer_cnt));
  405. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
  406. sc->resid = sc->request_bufflen - xfer_cnt;
  407. dprintk((KERN_NOTICE "  SET sc->resid=%02xhn", sc->resid));
  408. #endif
  409. /* Report Queue Full
  410.  */
  411. if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL)
  412. mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
  413. /* If regular Inquiry cmd and some data was transferred,
  414.  * save inquiry data
  415.  */
  416. if (    pScsiReq->CDB[0] == INQUIRY
  417.      && !(pScsiReq->CDB[1] & 0x3)
  418.      && xfer_cnt >= SCSI_STD_INQUIRY_BYTES
  419.    ) {
  420. mptscsih_initTarget(hd,
  421. hd->port,
  422. sc->target,
  423. pScsiReq->LUN[1],
  424. sc->buffer,
  425. xfer_cnt);
  426. }
  427. break;
  428. case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
  429. case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
  430. sc->result = (DID_OK << 16) | pScsiReply->SCSIStatus;
  431. clear_sense_flag(hd, pScsiReq);
  432. if (pScsiReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
  433. /*
  434.  * If running agains circa 200003dd 909 MPT f/w,
  435.  * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
  436.  * (QUEUE_FULL) returned from device! --> get 0x0000?128
  437.  * and with SenseBytes set to 0.
  438.  */
  439. if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL)
  440. mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
  441. #ifndef MPT_SCSI_USE_NEW_EH
  442. /* ADDED 20011120 -sralston
  443.  * Scsi mid-layer (old_eh) doesn't seem to like it
  444.  * when RAID returns SCSIStatus=02 (CHECK CONDITION),
  445.  * SenseKey=01 (RECOVERED ERROR), ASC/ASCQ=95/01.
  446.  * Seems to be * treating this as a IO error:-(
  447.  *
  448.  * So just lie about it altogether here.
  449.  *
  450.  * NOTE: It still gets reported to syslog via
  451.  * mpt_ScsiHost_ErrorReport from copy_sense_data
  452.  * call far above.
  453.  */
  454. if (    pScsiReply->SCSIStatus == STS_CHECK_CONDITION
  455.      && SD_Sense_Key(sc->sense_buffer) == SK_RECOVERED_ERROR
  456.    ) {
  457. sc->result = 0;
  458. }
  459. #endif
  460. }
  461. else if (pScsiReply->SCSIState &
  462.          (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)
  463.    ) {
  464. /*
  465.  * What to do?
  466.  */
  467. sc->result = DID_SOFT_ERROR << 16;
  468. }
  469. else if (pScsiReply->SCSIState & MPI_SCSI_STATE_TERMINATED) {
  470. /*  Not real sure here either...  */
  471. sc->result = DID_RESET << 16;
  472. }
  473. else if (pScsiReply->SCSIState & MPI_SCSI_STATE_QUEUE_TAG_REJECTED) {
  474. /* Device Inq. data indicates that it supports
  475.  * QTags, but rejects QTag messages.
  476.  * This command completed OK.
  477.  *
  478.  * Not real sure here either so do nothing...  */
  479. }
  480. if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL)
  481. mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
  482. /* Add handling of:
  483.  * Reservation Conflict, Busy,
  484.  * Command Terminated, CHECK
  485.  */
  486. /* If regular Inquiry cmd - save inquiry data
  487.  */
  488. xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
  489. if (    sc->result == (DID_OK << 16)
  490.      && pScsiReq->CDB[0] == INQUIRY
  491.      && !(pScsiReq->CDB[1] & 0x3)
  492.      && xfer_cnt >= SCSI_STD_INQUIRY_BYTES
  493.    ) {
  494. mptscsih_initTarget(hd,
  495. hd->port,
  496. sc->target,
  497. pScsiReq->LUN[1],
  498. sc->buffer,
  499. xfer_cnt);
  500. }
  501. break;
  502. case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
  503. if (pScsiReply->SCSIState & MPI_SCSI_STATE_TERMINATED) {
  504. /*  Not real sure here either...  */
  505. sc->result = DID_RESET << 16;
  506. } else
  507. sc->result = DID_SOFT_ERROR << 16;
  508. break;
  509. case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
  510. case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
  511. case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
  512. case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
  513. case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
  514. case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
  515. case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
  516. case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
  517. case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
  518. case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
  519. default:
  520. /*
  521.  * What to do?
  522.  */
  523. sc->result = DID_SOFT_ERROR << 16;
  524. break;
  525. } /* switch(status) */
  526. dprintk((KERN_NOTICE "  sc->result set to %08xhn", sc->result));
  527. } /* end of address reply case */
  528. /* Unmap the DMA buffers, if any. */
  529. if (sc->use_sg) {
  530. pci_unmap_sg(ioc->pcidev, (struct scatterlist *) sc->request_buffer,
  531.     sc->use_sg, scsi_to_pci_dma_dir(sc->sc_data_direction));
  532. } else if (sc->request_bufflen) {
  533. scPrivate *my_priv;
  534. my_priv = (scPrivate *) &sc->SCp;
  535. pci_unmap_single(ioc->pcidev, (dma_addr_t)(ulong)my_priv->p1,
  536.    sc->request_bufflen,
  537.    scsi_to_pci_dma_dir(sc->sc_data_direction));
  538. }
  539. hd->ScsiLookup[req_idx] = NULL;
  540. sc->host_scribble = NULL; /* CHECKME! - Do we need to clear this??? */
  541.         MPT_HOST_LOCK(flags);
  542. sc->scsi_done(sc); /* Issue the command callback */
  543.         MPT_HOST_UNLOCK(flags);
  544. /* Free Chain buffers */
  545. mptscsih_freeChainBuffers(hd, req_idx);
  546. return 1;
  547. }
  548. #ifndef MPT_SCSI_USE_NEW_EH /* { */
  549. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  550. /*
  551.  * search_taskQ - Search SCSI task mgmt request queue for specific
  552.  * request type.
  553.  * @remove: (Boolean) Should request be removed if found?
  554.  * @sc: Pointer to Scsi_Cmnd structure
  555.  * @task_type: Task type to search for
  556.  *
  557.  * Returns pointer to MPT request frame if found, or %NULL if request
  558.  * was not found.
  559.  */
  560. static MPT_FRAME_HDR *
  561. search_taskQ(int remove, Scsi_Cmnd *sc, MPT_SCSI_HOST *hd, u8 task_type)
  562. {
  563. MPT_FRAME_HDR *mf = NULL;
  564. unsigned long flags;
  565. int count = 0;
  566. int list_sz;
  567. dprintk((KERN_INFO MYNAM ": search_taskQ(%d,sc=%p,%d) calledn",
  568. remove, sc, task_type));
  569. spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
  570. list_sz = hd->taskQcnt;
  571. if (! Q_IS_EMPTY(&hd->taskQ)) {
  572. mf = hd->taskQ.head;
  573. do {
  574. count++;
  575. if (mf->u.frame.linkage.argp1 == sc &&
  576.     mf->u.frame.linkage.arg1 == task_type) {
  577. if (remove) {
  578. Q_DEL_ITEM(&mf->u.frame.linkage);
  579. hd->taskQcnt--;
  580. atomic_dec(&mpt_taskQdepth);
  581. /* Don't save mf into nextmf because
  582.  * exit after command has been deleted.
  583.  */
  584. /* Place the MF back on the FreeQ */
  585. Q_ADD_TAIL(&hd->ioc->FreeQ,
  586. &mf->u.frame.linkage,
  587. MPT_FRAME_HDR);
  588. #ifdef MFCNT
  589. hd->ioc->mfcnt--;
  590. #endif
  591. }
  592. break;
  593. }
  594. } while ((mf = mf->u.frame.linkage.forw) != (MPT_FRAME_HDR*)&hd->taskQ);
  595. if (mf == (MPT_FRAME_HDR*)&hd->taskQ) {
  596. mf = NULL;
  597. }
  598. }
  599. spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
  600. if (list_sz) {
  601. dprintk((KERN_INFO "  Results=%p (%sFOUND%s)!n",
  602.    mf,
  603.    mf ? "" : "NOT_",
  604.    (mf && remove) ? "+REMOVED" : "" ));
  605. dprintk((KERN_INFO "  (searched thru %d of %d items on taskQ)n",
  606.    count,
  607.    list_sz ));
  608. }
  609. return mf;
  610. }
  611. /*
  612.  * clean_taskQ - Clean the  SCSI task mgmt request for
  613.  * this SCSI host instance.
  614.  * @hd: MPT_SCSI_HOST pointer
  615.  *
  616.  * Returns: None.
  617.  */
  618. static void
  619. clean_taskQ(MPT_SCSI_HOST *hd)
  620. {
  621. MPT_FRAME_HDR *mf = NULL;
  622. MPT_FRAME_HDR *nextmf = NULL;
  623. MPT_ADAPTER *ioc = hd->ioc;
  624. unsigned long flags;
  625. dprintk((KERN_INFO MYNAM ": clean_taskQ calledn"));
  626. spin_lock_irqsave(&ioc->FreeQlock, flags);
  627. if (! Q_IS_EMPTY(&hd->taskQ)) {
  628. mf = hd->taskQ.head;
  629. do {
  630. Q_DEL_ITEM(&mf->u.frame.linkage);
  631. hd->taskQcnt--;
  632. atomic_dec(&mpt_taskQdepth);
  633. nextmf = mf->u.frame.linkage.forw;
  634. /* Place the MF back on the FreeQ */
  635. Q_ADD_TAIL(&ioc->FreeQ, &mf->u.frame.linkage,
  636. MPT_FRAME_HDR);
  637. #ifdef MFCNT
  638. hd->ioc->mfcnt--;
  639. #endif
  640. } while ((mf = nextmf) != (MPT_FRAME_HDR*)&hd->taskQ);
  641. }
  642. spin_unlock_irqrestore(&ioc->FreeQlock, flags);
  643. return;
  644. }
  645. /*
  646.  * search_taskQ_for_cmd - Search the  SCSI task mgmt request queue for
  647.  * the specified command. If found, delete
  648.  * @hd: MPT_SCSI_HOST pointer
  649.  *
  650.  * Returns: None.
  651.  */
  652. static void
  653. search_taskQ_for_cmd(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd)
  654. {
  655. MPT_FRAME_HDR *mf = NULL;
  656. unsigned long flags;
  657. int count = 0;
  658. dprintk((KERN_INFO MYNAM ": search_taskQ_for_cmd(sc=%p) calledn", sc));
  659. spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
  660. if (! Q_IS_EMPTY(&hd->taskQ)) {
  661. mf = hd->taskQ.head;
  662. do {
  663. count++;
  664. if (mf->u.frame.linkage.argp1 == sc) {
  665. Q_DEL_ITEM(&mf->u.frame.linkage);
  666. hd->taskQcnt--;
  667. atomic_dec(&mpt_taskQdepth);
  668. dprintk((KERN_INFO MYNAM
  669. ": Cmd %p found! Deleting.n", sc));
  670. /* Don't save mf into nextmf because
  671.  * exit after command has been deleted.
  672.  */
  673. /* Place the MF back on the FreeQ */
  674. Q_ADD_TAIL(&hd->ioc->FreeQ,
  675. &mf->u.frame.linkage,
  676. MPT_FRAME_HDR);
  677. #ifdef MFCNT
  678. hd->ioc->mfcnt--;
  679. #endif
  680. break;
  681. }
  682. } while ((mf = mf->u.frame.linkage.forw) != (MPT_FRAME_HDR*)&hd->taskQ);
  683. }
  684. spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
  685. return;
  686. }
  687. #endif /* } MPT_SCSI_USE_NEW_EH */
  688. /*
  689.  * Flush all commands on the doneQ.
  690.  * Lock Q when deleting/adding members
  691.  * Lock io_request_lock for OS callback.
  692.  */
  693. static void
  694. flush_doneQ(MPT_SCSI_HOST *hd)
  695. {
  696. MPT_DONE_Q *buffer;
  697. Scsi_Cmnd *SCpnt;
  698. unsigned long  flags;
  699. /* Flush the doneQ.
  700.  */
  701. dprintk((KERN_INFO MYNAM ": flush_doneQ calledn"));
  702. while (1) {
  703. spin_lock_irqsave(&hd->freedoneQlock, flags);
  704. if (Q_IS_EMPTY(&hd->doneQ)) {
  705. spin_unlock_irqrestore(&hd->freedoneQlock, flags);
  706. break;
  707. }
  708. buffer = hd->doneQ.head;
  709. /* Delete from Q
  710.  */
  711. Q_DEL_ITEM(buffer);
  712. /* Set the Scsi_Cmnd pointer
  713.  */
  714. SCpnt = (Scsi_Cmnd *) buffer->argp;
  715. buffer->argp = NULL;
  716. /* Add to the freeQ
  717.  */
  718. Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
  719. spin_unlock_irqrestore(&hd->freedoneQlock, flags);
  720. /* Do the OS callback.
  721.  */
  722.                 MPT_HOST_LOCK(flags);
  723. SCpnt->scsi_done(SCpnt);
  724.                 MPT_HOST_UNLOCK(flags);
  725. }
  726. return;
  727. }
  728. /*
  729.  * Search the doneQ for a specific command. If found, delete from Q.
  730.  * Calling function will finish processing.
  731.  */
  732. static void
  733. search_doneQ_for_cmd(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt)
  734. {
  735. unsigned long  flags;
  736. MPT_DONE_Q *buffer;
  737. spin_lock_irqsave(&hd->freedoneQlock, flags);
  738. if (!Q_IS_EMPTY(&hd->doneQ)) {
  739. buffer = hd->doneQ.head;
  740. do {
  741. Scsi_Cmnd *sc = (Scsi_Cmnd *) buffer->argp;
  742. if (SCpnt == sc) {
  743. Q_DEL_ITEM(buffer);
  744. SCpnt->result = sc->result;
  745. /* Set the Scsi_Cmnd pointer
  746.  */
  747. buffer->argp = NULL;
  748. /* Add to the freeQ
  749.  */
  750. Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
  751. break;
  752. }
  753. } while ((buffer = buffer->forw) != (MPT_DONE_Q *) &hd->doneQ);
  754. }
  755. spin_unlock_irqrestore(&hd->freedoneQlock, flags);
  756. return;
  757. }
  758. /*
  759.  * mptscsih_flush_running_cmds - For each command found, search
  760.  * Scsi_Host instance taskQ and reply to OS.
  761.  * Called only if recovering from a FW reload.
  762.  * @hd: Pointer to a SCSI HOST structure
  763.  *
  764.  * Returns: None.
  765.  *
  766.  * Must be called while new I/Os are being queued.
  767.  */
  768. static void
  769. mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
  770. {
  771. Scsi_Cmnd *SCpnt = NULL;
  772. MPT_FRAME_HDR *mf = NULL;
  773. int  ii;
  774. int  max = hd->ioc->req_depth;
  775. #ifndef MPT_SCSI_USE_NEW_EH
  776. unsigned long  flags;
  777. #endif
  778. dprintk((KERN_INFO MYNAM ": flush_ScsiLookup calledn"));
  779. for (ii= 0; ii < max; ii++) {
  780. if ((SCpnt = hd->ScsiLookup[ii]) != NULL) {
  781. /* Command found.
  782.  */
  783. #ifndef MPT_SCSI_USE_NEW_EH
  784. /* Search taskQ, if found, delete.
  785.  */
  786. search_taskQ_for_cmd(SCpnt, hd);
  787. #endif
  788. /* Search pendingQ, if found, 
  789.  * delete from Q. If found, do not decrement
  790.  * queue_depth, command never posted.
  791.  */
  792. if (mptscsih_search_pendingQ(hd, ii) == NULL)
  793. atomic_dec(&queue_depth);
  794. /* Null ScsiLookup index
  795.  */
  796. hd->ScsiLookup[ii] = NULL;
  797. mf = MPT_INDEX_2_MFPTR(hd->ioc, ii);
  798. dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)n",
  799. mf, SCpnt));
  800. /* Set status, free OS resources (SG DMA buffers)
  801.  * Do OS callback
  802.  * Free driver resources (chain, msg buffers)
  803.  */
  804. if (SCpnt->use_sg) {
  805. pci_unmap_sg(hd->ioc->pcidev, (struct scatterlist *) SCpnt->request_buffer,
  806.     SCpnt->use_sg, scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
  807. } else if (SCpnt->request_bufflen) {
  808. scPrivate *my_priv;
  809. my_priv = (scPrivate *) &SCpnt->SCp;
  810. pci_unmap_single(hd->ioc->pcidev, (dma_addr_t)(ulong)my_priv->p1,
  811.    SCpnt->request_bufflen,
  812.    scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
  813. }
  814. SCpnt->result = DID_RESET << 16;
  815. SCpnt->host_scribble = NULL;
  816.                         MPT_HOST_LOCK(flags);
  817. SCpnt->scsi_done(SCpnt); /* Issue the command callback */
  818.                         MPT_HOST_UNLOCK(flags);
  819. /* Free Chain buffers */
  820. mptscsih_freeChainBuffers(hd, ii);
  821. /* Free Message frames */
  822. mpt_free_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
  823. }
  824. }
  825. #ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
  826. /* Clear untagged counting array */
  827. for (ii= 0; ii < MPT_MAX_SCSI_DEVICES; ii++)
  828. hd->ioc->spi_data.iocntr[ii] = 0;
  829. #endif
  830. return;
  831. }
  832. #ifdef DROP_TEST
  833. /*  mptscsih_flush_drop_test - Free resources and do callback if
  834.  * DROP_TEST enabled.
  835.  *
  836.  * @hd: Pointer to a SCSI HOST structure
  837.  *
  838.  * Returns: None.
  839.  *
  840.  * Must be called while new I/Os are being queued.
  841.  */
  842. static void
  843. mptscsih_flush_drop_test (MPT_SCSI_HOST *hd)
  844. {
  845. Scsi_Cmnd *sc;
  846. unsigned long  flags;
  847. u16  req_idx;
  848. /* Free resources for the drop test MF
  849.  * and chain buffers.
  850.  */
  851. if (dropMfPtr) {
  852. req_idx = le16_to_cpu(dropMfPtr->u.frame.hwhdr.msgctxu.fld.req_idx);
  853. sc = hd->ScsiLookup[req_idx];
  854. if (sc == NULL) {
  855. printk(MYIOC_s_ERR_FMT "Drop Test: NULL ScsiCmd ptr!n",
  856. ioc->name);
  857. } else {
  858. /* unmap OS resources, set status, do callback
  859.  * free driver resources
  860.  */
  861. if (sc->use_sg) {
  862. pci_unmap_sg(ioc->pcidev, (struct scatterlist *) sc->request_buffer,
  863.     sc->use_sg, scsi_to_pci_dma_dir(sc->sc_data_direction));
  864. } else if (sc->request_bufflen) {
  865. scPrivate *my_priv;
  866. my_priv = (scPrivate *) &sc->SCp;
  867. pci_unmap_single(ioc->pcidev, (dma_addr_t)(ulong)my_priv->p1,
  868.    sc->request_bufflen,
  869.    scsi_to_pci_dma_dir(sc->sc_data_direction));
  870. }
  871. sc->host_scribble = NULL;
  872. sc->result = DID_RESET << 16;
  873. hd->ScsiLookup[req_idx] = NULL;
  874. atomic_dec(&queue_depth);
  875. MPT_HOST_LOCK(flags);
  876. sc->scsi_done(sc); /* Issue callback */
  877. MPT_HOST_UNLOCK(flags);
  878. }
  879. mptscsih_freeChainBuffers(hd, req_idx);
  880. mpt_free_msg_frame(ScsiDoneCtx, ioc->id, dropMfPtr);
  881. printk(MYIOC_s_INFO_FMT "Free'd Dropped cmd (%p)n",
  882. hd->ioc->name, sc);
  883. printk(MYIOC_s_INFO_FMT "mf (%p) reqidx (%4x)n",
  884. hd->ioc->name, dropMfPtr, req_idx);
  885. printk(MYIOC_s_INFO_FMT "Num Tot (%d) Good (%d) Bad (%d) n",
  886. hd->ioc->name, dropTestNum,
  887. dropTestOK, dropTestBad);
  888. }
  889. dropMfPtr = NULL;
  890. return;
  891. }
  892. #endif
  893. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  894. /*
  895.  * mptscsih_initChainBuffers - Allocate memory for and initialize
  896.  * chain buffers, chain buffer control arrays and spinlock.
  897.  * @hd: Pointer to MPT_SCSI_HOST structure
  898.  * @init: If set, initialize the spin lock.
  899.  */
  900. static int
  901. mptscsih_initChainBuffers (MPT_SCSI_HOST *hd, int init)
  902. {
  903. MPT_FRAME_HDR *chain;
  904. u8 *mem;
  905. unsigned long flags;
  906. int sz, ii, numChain;
  907.         /* Chain buffer allocations
  908.  * Allocate and initialize tracker structures
  909.  */
  910. if (hd->ioc->req_sz <= 64)
  911. numChain = MPT_SG_REQ_64_SCALE * hd->ioc->req_depth;
  912. else if (hd->ioc->req_sz <= 96)
  913. numChain = MPT_SG_REQ_96_SCALE * hd->ioc->req_depth;
  914. else
  915. numChain = MPT_SG_REQ_128_SCALE * hd->ioc->req_depth;
  916. sz = numChain * sizeof(int);
  917. if (hd->ReqToChain == NULL) {
  918. mem = kmalloc(sz, GFP_ATOMIC);
  919. if (mem == NULL)
  920. return -1;
  921. hd->ReqToChain = (int *) mem;
  922. } else {
  923. mem = (u8 *) hd->ReqToChain;
  924. }
  925. memset(mem, 0xFF, sz);
  926. if (hd->ChainToChain == NULL) {
  927. mem = kmalloc(sz, GFP_ATOMIC);
  928. if (mem == NULL)
  929. return -1;
  930. hd->ChainToChain = (int *) mem;
  931. } else {
  932. mem = (u8 *) hd->ChainToChain;
  933. }
  934. memset(mem, 0xFF, sz);
  935. if (hd->ChainBuffer == NULL) {
  936. /* Allocate free chain buffer pool
  937.  */
  938. sz = numChain * hd->ioc->req_sz;
  939. mem = pci_alloc_consistent(hd->ioc->pcidev, sz, &hd->ChainBufferDMA);
  940. if (mem == NULL)
  941. return -1;
  942. hd->ChainBuffer = (u8*)mem;
  943. } else {
  944. mem = (u8 *) hd->ChainBuffer;
  945. }
  946. memset(mem, 0, sz);
  947. dprintk((KERN_INFO "  ChainBuffer    @ %p(%p), sz=%dn",
  948.  hd->ChainBuffer, (void *)(ulong)hd->ChainBufferDMA, sz));
  949. /* Initialize the free chain Q.
  950.  */
  951. if (init) {
  952. spin_lock_init(&hd->FreeChainQlock);
  953. }
  954. spin_lock_irqsave (&hd->FreeChainQlock, flags);
  955. Q_INIT(&hd->FreeChainQ, MPT_FRAME_HDR);
  956. /* Post the chain buffers to the FreeChainQ.
  957.  */
  958. mem = (u8 *)hd->ChainBuffer;
  959. for (ii=0; ii < numChain; ii++) {
  960. chain = (MPT_FRAME_HDR *) mem;
  961. Q_ADD_TAIL(&hd->FreeChainQ.head, &chain->u.frame.linkage, MPT_FRAME_HDR);
  962. mem += hd->ioc->req_sz;
  963. }
  964. spin_unlock_irqrestore(&hd->FreeChainQlock, flags);
  965. return 0;
  966. }
  967. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  968. /*
  969.  *  Hack! It might be nice to report if a device is returning QUEUE_FULL
  970.  *  but maybe not each and every time...
  971.  */
  972. static long last_queue_full = 0;
  973. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  974. /*
  975.  * mptscsih_report_queue_full - Report QUEUE_FULL status returned
  976.  * from a SCSI target device.
  977.  * @sc: Pointer to Scsi_Cmnd structure
  978.  * @pScsiReply: Pointer to SCSIIOReply_t
  979.  * @pScsiReq: Pointer to original SCSI request
  980.  *
  981.  * This routine periodically reports QUEUE_FULL status returned from a
  982.  * SCSI target device.  It reports this to the console via kernel
  983.  * printk() API call, not more than once every 10 seconds.
  984.  */
  985. static void
  986. mptscsih_report_queue_full(Scsi_Cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
  987. {
  988. long time = jiffies;
  989. if (time - last_queue_full > 10 * HZ) {
  990. char *ioc_str = "ioc?";
  991. if (sc->host != NULL && sc->host->hostdata != NULL)
  992. ioc_str = ((MPT_SCSI_HOST *)sc->host->hostdata)->ioc->name;
  993. printk(MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!n",
  994. ioc_str, 0, sc->target, sc->lun);
  995. last_queue_full = time;
  996. }
  997. }
  998. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  999. static int BeenHereDoneThat = 0;
  1000. /*  SCSI host fops start here...  */
  1001. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  1002. /**
  1003.  * mptscsih_detect - Register MPT adapter(s) as SCSI host(s) with
  1004.  * linux scsi mid-layer.
  1005.  * @tpnt: Pointer to Scsi_Host_Template structure
  1006.  *
  1007.  * (linux Scsi_Host_Template.detect routine)
  1008.  *
  1009.  * Returns number of SCSI host adapters that were successfully
  1010.  * registered with the linux scsi mid-layer via the scsi_register()
  1011.  * API call.
  1012.  */
  1013. int
  1014. mptscsih_detect(Scsi_Host_Template *tpnt)
  1015. {
  1016. struct Scsi_Host *sh = NULL;
  1017. MPT_SCSI_HOST *hd = NULL;
  1018. MPT_ADAPTER *this;
  1019. MPT_DONE_Q *freedoneQ;
  1020. unsigned long  flags;
  1021. int  sz, ii;
  1022. int  numSGE = 0;
  1023. int  scale;
  1024. u8 *mem;
  1025. if (! BeenHereDoneThat++) {
  1026. show_mptmod_ver(my_NAME, my_VERSION);
  1027. ScsiDoneCtx = mpt_register(mptscsih_io_done, MPTSCSIH_DRIVER);
  1028. ScsiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSCSIH_DRIVER);
  1029. ScsiScanDvCtx = mpt_register(mptscsih_scandv_complete, MPTSCSIH_DRIVER);
  1030. #ifndef MPT_SCSI_USE_NEW_EH
  1031. spin_lock_init(&mytaskQ_lock);
  1032. #endif
  1033. if (mpt_event_register(ScsiDoneCtx, mptscsih_event_process) == 0) {
  1034. dprintk((KERN_INFO MYNAM ": Registered for IOC event notificationsn"));
  1035. } else {
  1036. /* FIXME! */
  1037. }
  1038. if (mpt_reset_register(ScsiDoneCtx, mptscsih_ioc_reset) == 0) {
  1039. dprintk((KERN_INFO MYNAM ": Registered for IOC reset notificationsn"));
  1040. } else {
  1041. /* FIXME! */
  1042. }
  1043. }
  1044. dprintk((KERN_INFO MYNAM ": mpt_scsih_detect()n"));
  1045. #ifdef MODULE
  1046. /* Evaluate the command line arguments, if any */
  1047. if (mptscsih)
  1048. mptscsih_setup(mptscsih);
  1049. #endif
  1050. #ifndef MPT_SCSI_USE_NEW_EH
  1051. atomic_set(&mpt_taskQdepth, 0);
  1052. #endif
  1053. this = mpt_adapter_find_first();
  1054. while (this != NULL) {
  1055. int  portnum;
  1056. for (portnum=0; portnum < this->facts.NumberOfPorts; portnum++) {
  1057. /* 20010215 -sralston
  1058.  *  Added sanity check on SCSI Initiator-mode enabled
  1059.  *  for this MPT adapter.
  1060.  */
  1061. if (!(this->pfacts[portnum].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR)) {
  1062. printk(MYIOC_s_WARN_FMT "Skipping because SCSI Initiator mode is NOT enabled!n",
  1063. this->name);
  1064. continue;
  1065. }
  1066. /* 20010202 -sralston
  1067.  *  Added sanity check on readiness of the MPT adapter.
  1068.  */
  1069. if (this->last_state != MPI_IOC_STATE_OPERATIONAL) {
  1070. printk(MYIOC_s_WARN_FMT "Skipping because it's not operational!n",
  1071. this->name);
  1072. continue;
  1073. }
  1074. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
  1075. tpnt->proc_dir = &proc_mpt_scsihost;
  1076. #endif
  1077. sh = scsi_register(tpnt, sizeof(MPT_SCSI_HOST));
  1078. if (sh != NULL) {
  1079. save_flags(flags);
  1080. cli();
  1081. sh->io_port = 0;
  1082. sh->n_io_port = 0;
  1083. sh->irq = 0;
  1084. /* Yikes!  This is important!
  1085.  * Otherwise, by default, linux
  1086.  * only scans target IDs 0-7!
  1087.  * pfactsN->MaxDevices unreliable
  1088.  * (not supported in early
  1089.  * versions of the FW).
  1090.  * max_id = 1 + actual max id,
  1091.  * max_lun = 1 + actual last lun,
  1092.  * see hosts.h :o(
  1093.  */
  1094. if ((int)this->chip_type > (int)FC929)
  1095. sh->max_id = MPT_MAX_SCSI_DEVICES;
  1096. else {
  1097. /* For FC, increase the queue depth
  1098.  * from MPT_SCSI_CAN_QUEUE (31)
  1099.  * to MPT_FC_CAN_QUEUE (63).
  1100.  */
  1101. sh->can_queue = MPT_FC_CAN_QUEUE;
  1102. sh->max_id = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
  1103. }
  1104. sh->max_lun = MPT_LAST_LUN + 1;
  1105. sh->this_id = this->pfacts[portnum].PortSCSIID;
  1106. /* OS entry to allow host drivers to force
  1107.  * a queue depth on a per device basis.
  1108.  */
  1109. sh->select_queue_depths = mptscsih_select_queue_depths;
  1110. /* Verify that we won't exceed the maximum
  1111.  * number of chain buffers
  1112.  * We can optimize:  ZZ = req_sz/sizeof(SGE)
  1113.  * For 32bit SGE's:
  1114.  *  numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
  1115.  *               + (req_sz - 64)/sizeof(SGE)
  1116.  * A slightly different algorithm is required for
  1117.  * 64bit SGEs.
  1118.  */
  1119. scale = this->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
  1120. if (sizeof(dma_addr_t) == sizeof(u64)) {
  1121. numSGE = (scale - 1) * (this->facts.MaxChainDepth-1) + scale +
  1122. (this->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
  1123. } else {
  1124. numSGE = 1 + (scale - 1) * (this->facts.MaxChainDepth-1) + scale +
  1125. (this->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
  1126. if (numSGE < sh->sg_tablesize) {
  1127. /* Reset this value */
  1128. dprintk((MYIOC_s_INFO_FMT
  1129.  "Resetting sg_tablesize to %d from %dn",
  1130.  this->name, numSGE, sh->sg_tablesize));
  1131. sh->sg_tablesize = numSGE;
  1132. }
  1133. /* Set the pci device pointer in Scsi_Host structure.
  1134.  */
  1135. scsi_set_pci_device(sh, this->pcidev);
  1136. restore_flags(flags);
  1137. hd = (MPT_SCSI_HOST *) sh->hostdata;
  1138. hd->ioc = this;
  1139. if ((int)this->chip_type > (int)FC929)
  1140. hd->is_spi = 1;
  1141. if (DmpService &&
  1142.     (this->chip_type == FC919 || this->chip_type == FC929))
  1143. hd->is_multipath = 1;
  1144. hd->port = 0; /* FIXME! */
  1145. /* SCSI needs Scsi_Cmnd lookup table!
  1146.  * (with size equal to req_depth*PtrSz!)
  1147.  */
  1148. sz = hd->ioc->req_depth * sizeof(void *);
  1149. mem = kmalloc(sz, GFP_ATOMIC);
  1150. if (mem == NULL)
  1151. goto done;
  1152. memset(mem, 0, sz);
  1153. hd->ScsiLookup = (struct scsi_cmnd **) mem;
  1154. dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%dn",
  1155.  this->name, hd->ScsiLookup, sz));
  1156. if (mptscsih_initChainBuffers(hd, 1) < 0)
  1157. goto done;
  1158. /* Allocate memory for free and doneQ's
  1159.  */
  1160. sz = sh->can_queue * sizeof(MPT_DONE_Q);
  1161. mem = kmalloc(sz, GFP_ATOMIC);
  1162. if (mem == NULL)
  1163. goto done;
  1164. memset(mem, 0xFF, sz);
  1165. hd->memQ = mem;
  1166. /* Initialize the free, done and pending Qs.
  1167.  */
  1168. Q_INIT(&hd->freeQ, MPT_DONE_Q);
  1169. Q_INIT(&hd->doneQ, MPT_DONE_Q);
  1170. Q_INIT(&hd->pendingQ, MPT_DONE_Q);
  1171. spin_lock_init(&hd->freedoneQlock);
  1172. mem = hd->memQ;
  1173. for (ii=0; ii < sh->can_queue; ii++) {
  1174. freedoneQ = (MPT_DONE_Q *) mem;
  1175. Q_ADD_TAIL(&hd->freeQ.head, freedoneQ, MPT_DONE_Q);
  1176. mem += sizeof(MPT_DONE_Q);
  1177. }
  1178. /* Initialize this Scsi_Host
  1179.  * internal task Q.
  1180.  */
  1181. Q_INIT(&hd->taskQ, MPT_FRAME_HDR);
  1182. hd->taskQcnt = 0;
  1183. /* Allocate memory for the device structures.
  1184.  * A non-Null pointer at an offset
  1185.  * indicates a device exists.
  1186.  * max_id = 1 + maximum id (hosts.h)
  1187.  */
  1188. sz = sh->max_id * sizeof(void *);
  1189. mem = kmalloc(sz, GFP_ATOMIC);
  1190. if (mem == NULL)
  1191. goto done;
  1192. memset(mem, 0, sz);
  1193. hd->Targets = (VirtDevice **) mem;
  1194. dprintk((KERN_INFO "  Targets @ %p, sz=%dn", hd->Targets, sz));
  1195. /* Clear the TM flags
  1196.  */
  1197. hd->tmPending = 0;
  1198. #ifdef MPT_SCSI_USE_NEW_EH
  1199. hd->tmState = TM_STATE_NONE;
  1200. #endif
  1201. hd->resetPending = 0;
  1202. hd->abortSCpnt = NULL;
  1203. hd->tmPtr = NULL;
  1204. hd->numTMrequests = 0;
  1205. /* Clear the pointer used to store
  1206.  * single-threaded commands, i.e., those
  1207.  * issued during a bus scan, dv and
  1208.  * configuration pages.
  1209.  */
  1210. hd->cmdPtr = NULL;
  1211. /* Attach the SCSI Host to the IOC structure
  1212.  */
  1213. this->sh = sh;
  1214. /* Initialize this SCSI Hosts' timers
  1215.  * To use, set the timer expires field
  1216.  * and add_timer
  1217.  */
  1218. init_timer(&hd->timer);
  1219. hd->timer.data = (unsigned long) hd;
  1220. hd->timer.function = mptscsih_timer_expired;
  1221. init_timer(&hd->TMtimer);
  1222. hd->TMtimer.data = (unsigned long) hd;
  1223. hd->TMtimer.function = mptscsih_taskmgmt_timeout;
  1224. hd->qtag_tick = jiffies;
  1225. /* Moved Earlier Pam D */
  1226. /* this->sh = sh; */
  1227. if (hd->is_spi) {
  1228. /* Update with the driver setup
  1229.  * values.
  1230.  */
  1231. if (hd->ioc->spi_data.maxBusWidth > driver_setup.max_width)
  1232. hd->ioc->spi_data.maxBusWidth = driver_setup.max_width;
  1233. if (hd->ioc->spi_data.minSyncFactor < driver_setup.min_sync_fac)
  1234. hd->ioc->spi_data.minSyncFactor = driver_setup.min_sync_fac;
  1235. if (hd->ioc->spi_data.minSyncFactor == MPT_ASYNC)
  1236. hd->ioc->spi_data.maxSyncOffset = 0;
  1237. hd->negoNvram = 0;
  1238. #ifdef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
  1239. hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
  1240. #endif
  1241. if (driver_setup.dv == 0)
  1242. hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
  1243. hd->ioc->spi_data.forceDv = 0;
  1244. for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
  1245. hd->ioc->spi_data.dvStatus[ii] = MPT_SCSICFG_NEGOTIATE;
  1246. if (hd->negoNvram == 0) {
  1247. for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
  1248. hd->ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_DV_NOT_DONE;
  1249. }
  1250. ddvprintk((MYIOC_s_INFO_FMT
  1251. "dv %x width %x factor %x n",
  1252. hd->ioc->name, driver_setup.dv,
  1253. driver_setup.max_width,
  1254. driver_setup.min_sync_fac));
  1255. }
  1256. mpt_scsi_hosts++;
  1257. }
  1258. } /* for each adapter port */
  1259. this = mpt_adapter_find_next(this);
  1260. }
  1261. done:
  1262. if (mpt_scsi_hosts > 0)
  1263. register_reboot_notifier(&mptscsih_notifier);
  1264. return mpt_scsi_hosts;
  1265. }
  1266. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  1267.     static char *info_kbuf = NULL;
  1268. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  1269. /**
  1270.  * mptscsih_release - Unregister SCSI host from linux scsi mid-layer
  1271.  * @host: Pointer to Scsi_Host structure
  1272.  *
  1273.  * (linux Scsi_Host_Template.release routine)
  1274.  * This routine releases all resources associated with the SCSI host
  1275.  * adapter.
  1276.  *
  1277.  * Returns 0 for success.
  1278.  */
  1279. int
  1280. mptscsih_release(struct Scsi_Host *host)
  1281. {
  1282. MPT_SCSI_HOST *hd;
  1283. int   count;
  1284. unsigned long  flags;
  1285. hd = (MPT_SCSI_HOST *) host->hostdata;
  1286. #ifndef MPT_SCSI_USE_NEW_EH
  1287. #ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
  1288. spin_lock_irqsave(&dvtaskQ_lock, flags);
  1289. dvtaskQ_release = 1;
  1290. spin_unlock_irqrestore(&dvtaskQ_lock, flags);
  1291. #endif
  1292. count = 10 * HZ;
  1293. spin_lock_irqsave(&mytaskQ_lock, flags);
  1294. if (mytaskQ_bh_active) {
  1295. spin_unlock_irqrestore(&mytaskQ_lock, flags);
  1296. dprintk((KERN_INFO MYNAM ": Info: Zapping TaskMgmt thread!n"));
  1297. clean_taskQ(hd);
  1298. while(mytaskQ_bh_active && --count) {
  1299. set_current_state(TASK_INTERRUPTIBLE);
  1300. schedule_timeout(1);
  1301. }
  1302. } else {
  1303. spin_unlock_irqrestore(&mytaskQ_lock, flags);
  1304. }
  1305. if (!count)
  1306. printk(KERN_ERR MYNAM ": ERROR - TaskMgmt thread still active!n");
  1307. #endif
  1308. #ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
  1309. /* Check DV thread active */
  1310. count = 10 * HZ;
  1311. spin_lock_irqsave(&dvtaskQ_lock, flags);
  1312. if (dvtaskQ_active) {
  1313. spin_unlock_irqrestore(&dvtaskQ_lock, flags);
  1314. while(dvtaskQ_active && --count) {
  1315. set_current_state(TASK_INTERRUPTIBLE);
  1316. schedule_timeout(1);
  1317. }
  1318. } else {
  1319. spin_unlock_irqrestore(&dvtaskQ_lock, flags);
  1320. }
  1321. if (!count)
  1322. printk(KERN_ERR MYNAM ": ERROR - DV thread still active!n");
  1323. #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
  1324. else
  1325. printk(KERN_ERR MYNAM ": DV thread orig %d, count %dn", 10 * HZ, count);
  1326. #endif
  1327. #endif
  1328. unregister_reboot_notifier(&mptscsih_notifier);
  1329. if (hd != NULL) {
  1330. int sz1, sz2, sz3, sztarget=0;
  1331. int szr2chain = 0;
  1332. int szc2chain = 0;
  1333. int szchain = 0;
  1334. int szQ = 0;
  1335. int scale;
  1336. /* Synchronize disk caches
  1337.  */
  1338. (void) mptscsih_synchronize_cache(hd, 0);
  1339. sz1 = sz2 = sz3 = 0;
  1340. if (hd->ioc->req_sz <= 64)
  1341. scale = MPT_SG_REQ_64_SCALE;
  1342. else if (hd->ioc->req_sz <= 96)
  1343. scale = MPT_SG_REQ_96_SCALE;
  1344. else
  1345. scale = MPT_SG_REQ_128_SCALE;
  1346. if (hd->ScsiLookup != NULL) {
  1347. sz1 = hd->ioc->req_depth * sizeof(void *);
  1348. kfree(hd->ScsiLookup);
  1349. hd->ScsiLookup = NULL;
  1350. }
  1351. if (hd->ReqToChain != NULL) {
  1352. szr2chain = scale * hd->ioc->req_depth * sizeof(int);
  1353. kfree(hd->ReqToChain);
  1354. hd->ReqToChain = NULL;
  1355. }
  1356. if (hd->ChainToChain != NULL) {
  1357. szc2chain = scale * hd->ioc->req_depth * sizeof(int);
  1358. kfree(hd->ChainToChain);
  1359. hd->ChainToChain = NULL;
  1360. }
  1361. if (hd->ChainBuffer != NULL) {
  1362. sz2 = scale * hd->ioc->req_depth * hd->ioc->req_sz;
  1363. szchain = szr2chain + szc2chain + sz2;
  1364. pci_free_consistent(hd->ioc->pcidev, sz2,
  1365.     hd->ChainBuffer, hd->ChainBufferDMA);
  1366. hd->ChainBuffer = NULL;
  1367. }
  1368. if (hd->memQ != NULL) {
  1369. szQ = host->can_queue * sizeof(MPT_DONE_Q);
  1370. kfree(hd->memQ);
  1371. hd->memQ = NULL;
  1372. }
  1373. if (hd->Targets != NULL) {
  1374. int max, ii;
  1375. /*
  1376.  * Free any target structures that were allocated.
  1377.  */
  1378. if (hd->is_spi) {
  1379. max = MPT_MAX_SCSI_DEVICES;
  1380. } else {
  1381. max = MPT_MAX_FC_DEVICES;
  1382. }
  1383. for (ii=0; ii < max; ii++) {
  1384. if (hd->Targets[ii]) {
  1385. kfree(hd->Targets[ii]);
  1386. hd->Targets[ii] = NULL;
  1387. sztarget += sizeof(VirtDevice);
  1388. }
  1389. }
  1390. /*
  1391.  * Free pointer array.
  1392.  */
  1393. sz3 = max * sizeof(void *);
  1394. kfree(hd->Targets);
  1395. hd->Targets = NULL;
  1396. }
  1397. dprintk((MYIOC_s_INFO_FMT "Free'd ScsiLookup (%d), chain (%d) and Target (%d+%d) memoryn",
  1398. hd->ioc->name, sz1, szchain, sz3, sztarget));
  1399. dprintk(("Free'd done and free Q (%d) memoryn", szQ));
  1400. }
  1401. /* NULL the Scsi_Host pointer
  1402.  */
  1403. hd->ioc->sh = NULL;
  1404. scsi_unregister(host);
  1405. if (mpt_scsi_hosts) {
  1406. if (--mpt_scsi_hosts == 0) {
  1407. mpt_reset_deregister(ScsiDoneCtx);
  1408. dprintk((KERN_INFO MYNAM ": Deregistered for IOC reset notificationsn"));
  1409. mpt_event_deregister(ScsiDoneCtx);
  1410. dprintk((KERN_INFO MYNAM ": Deregistered for IOC event notificationsn"));
  1411. mpt_deregister(ScsiScanDvCtx);
  1412. mpt_deregister(ScsiTaskCtx);
  1413. mpt_deregister(ScsiDoneCtx);
  1414. if (info_kbuf != NULL)
  1415. kfree(info_kbuf);
  1416. }
  1417. }
  1418. return 0;
  1419. }
  1420. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  1421. /**
  1422.  * mptscsih_halt - Process the reboot notification
  1423.  * @nb: Pointer to a struct notifier_block (ignored)
  1424.  * @event: event (SYS_HALT, SYS_RESTART, SYS_POWER_OFF)
  1425.  * @buf: Pointer to a data buffer (ignored)
  1426.  *
  1427.  * This routine called if a system shutdown or reboot is to occur.
  1428.  *
  1429.  * Return NOTIFY_DONE if this is something other than a reboot message.
  1430.  * NOTIFY_OK if this is a reboot message.
  1431.  */
  1432. static int
  1433. mptscsih_halt(struct notifier_block *nb, ulong event, void *buf)
  1434. {
  1435. MPT_ADAPTER *ioc = NULL;
  1436. MPT_SCSI_HOST *hd = NULL;
  1437. /* Ignore all messages other than reboot message
  1438.  */
  1439. if ((event != SYS_RESTART) && (event != SYS_HALT)
  1440. && (event != SYS_POWER_OFF))
  1441. return (NOTIFY_DONE);
  1442. for (ioc = mpt_adapter_find_first(); ioc != NULL; ioc = mpt_adapter_find_next(ioc)) {
  1443. /* Flush the cache of this adapter
  1444.  */
  1445. if (ioc->sh) {
  1446. hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
  1447. if (hd) {
  1448. mptscsih_synchronize_cache(hd, 0);
  1449. }
  1450. }
  1451. }
  1452. unregister_reboot_notifier(&mptscsih_notifier);
  1453. return NOTIFY_OK;
  1454. }
  1455. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  1456. /**
  1457.  * mptscsih_info - Return information about MPT adapter
  1458.  * @SChost: Pointer to Scsi_Host structure
  1459.  *
  1460.  * (linux Scsi_Host_Template.info routine)
  1461.  *
  1462.  * Returns pointer to buffer where information was written.
  1463.  */
  1464. const char *
  1465. mptscsih_info(struct Scsi_Host *SChost)
  1466. {
  1467. MPT_SCSI_HOST *h;
  1468. int size = 0;
  1469. if (info_kbuf == NULL)
  1470. if ((info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
  1471. return info_kbuf;
  1472. h = (MPT_SCSI_HOST *)SChost->hostdata;
  1473. info_kbuf[0] = '';
  1474. mpt_print_ioc_summary(h->ioc, info_kbuf, &size, 0, 0);
  1475. info_kbuf[size-1] = '';
  1476. return info_kbuf;
  1477. }
  1478. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  1479. static int max_qd = 1;
  1480. #if 0
  1481. static int index_log[128];
  1482. static int index_ent = 0;
  1483. static __inline__ void ADD_INDEX_LOG(int req_ent)
  1484. {
  1485. int i = index_ent++;
  1486. index_log[i & (128 - 1)] = req_ent;
  1487. }
  1488. #else
  1489. #define ADD_INDEX_LOG(req_ent) do { } while(0)
  1490. #endif
  1491. #ifdef DROP_TEST
  1492. #define DROP_IOC 1 /* IOC to force failures */
  1493. #define DROP_TARGET 3 /* Target ID to force failures */
  1494. #define DROP_THIS_CMD 10000 /* iteration to drop command */
  1495. static int dropCounter = 0;
  1496. static int dropTestOK = 0; /* num did good */
  1497. static int dropTestBad = 0; /* num did bad */
  1498. static int dropTestNum = 0; /* total = good + bad + incomplete */
  1499. static int numTotCmds = 0;
  1500. static MPT_FRAME_HDR *dropMfPtr = NULL;
  1501. static int numTMrequested = 0;
  1502. #endif
  1503. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  1504. /*
  1505.  * mptscsih_put_msgframe - Wrapper routine to post message frame to F/W.
  1506.  * @context: Call back context (ScsiDoneCtx, ScsiScanDvCtx) 
  1507.  * @id: IOC id number 
  1508.  * @mf: Pointer to message frame 
  1509.  *
  1510.  * Handles the call to mptbase for posting request and queue depth 
  1511.  * tracking.
  1512.  *
  1513.  * Returns none.
  1514.  */
  1515. static void
  1516. mptscsih_put_msgframe(int context, int id, MPT_FRAME_HDR *mf)
  1517. {
  1518. /* Main banana... */
  1519. atomic_inc(&queue_depth);
  1520. if (atomic_read(&queue_depth) > max_qd) {
  1521. max_qd = atomic_read(&queue_depth);
  1522. dprintk((KERN_INFO MYNAM ": Queue depth now %d.n", max_qd));
  1523. }
  1524. mpt_put_msg_frame(context, id, mf);
  1525. return;
  1526. }
  1527. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  1528. /**
  1529.  * mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.
  1530.  * @SCpnt: Pointer to Scsi_Cmnd structure
  1531.  * @done: Pointer SCSI mid-layer IO completion function
  1532.  *
  1533.  * (linux Scsi_Host_Template.queuecommand routine)
  1534.  * This is the primary SCSI IO start routine.  Create a MPI SCSIIORequest
  1535.  * from a linux Scsi_Cmnd request and send it to the IOC.
  1536.  *
  1537.  * Returns 0. (rtn value discarded by linux scsi mid-layer)
  1538.  */
  1539. int
  1540. mptscsih_qcmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
  1541. {
  1542. MPT_SCSI_HOST *hd;
  1543. MPT_FRAME_HDR *mf;
  1544. SCSIIORequest_t *pScsiReq;
  1545. VirtDevice *pTarget;
  1546. MPT_DONE_Q *buffer = NULL;
  1547. unsigned long  flags;
  1548. int  target;
  1549. int  lun;
  1550. int  datadir;
  1551. u32  datalen;
  1552. u32  scsictl;
  1553. u32  scsidir;
  1554. u32  qtag;
  1555. u32  cmd_len;
  1556. int  my_idx;
  1557. int  ii;
  1558. int  rc;
  1559. int  did_errcode;
  1560. int  issueCmd;
  1561. did_errcode = 0;
  1562. hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata;
  1563. target = SCpnt->target;
  1564. lun = SCpnt->lun;
  1565. SCpnt->scsi_done = done;
  1566. pTarget = hd->Targets[target];
  1567. dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%pn",
  1568. (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done));
  1569. /* 20000617 -sralston
  1570.  *  GRRRRR...  Shouldn't have to do this but...
  1571.  *  Do explicit check for REQUEST_SENSE and cached SenseData.
  1572.  *  If yes, return cached SenseData.
  1573.  */
  1574. if (SCpnt->cmnd[0] == REQUEST_SENSE) {
  1575. u8 *dest = NULL;
  1576. int sz;
  1577. if (pTarget && (pTarget->tflags & MPT_TARGET_FLAGS_VALID_SENSE)) {
  1578. pTarget->tflags &= ~MPT_TARGET_FLAGS_VALID_SENSE; //sjr-moved-here
  1579. if (!SCpnt->use_sg) {
  1580. dest = SCpnt->request_buffer;
  1581. } else {
  1582. struct scatterlist *sg = (struct scatterlist *) SCpnt->request_buffer;
  1583. if (sg)
  1584. dest = (u8 *)(ulong)sg_dma_address(sg);
  1585. }
  1586. if (dest) {
  1587. sz = MIN (SCSI_STD_SENSE_BYTES, SCpnt->request_bufflen);
  1588. memcpy(dest, pTarget->sense, sz);
  1589. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
  1590. SCpnt->resid = SCpnt->request_bufflen - sz;
  1591. #endif
  1592. SCpnt->result = 0;
  1593. SCpnt->scsi_done(SCpnt);
  1594. //sjr-moved-up//pTarget->tflags &= ~MPT_TARGET_FLAGS_VALID_SENSE;
  1595. return 0;
  1596. }
  1597. }
  1598. }
  1599. if (hd->resetPending) {
  1600. /* Prevent new commands from being issued
  1601.  * while reloading the FW.
  1602.  */
  1603. did_errcode = 1;
  1604. goto did_error;
  1605. }
  1606. /*
  1607.  *  Put together a MPT SCSI request...
  1608.  */
  1609. if ((mf = mpt_get_msg_frame(ScsiDoneCtx, hd->ioc->id)) == NULL) {
  1610. dprintk((MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!n",
  1611. hd->ioc->name));
  1612. did_errcode = 2;
  1613. goto did_error;
  1614. }
  1615. pScsiReq = (SCSIIORequest_t *) mf;
  1616. my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
  1617. ADD_INDEX_LOG(my_idx);
  1618. /*
  1619.  *  The scsi layer should be handling this stuff
  1620.  *  (In 2.3.x it does -DaveM)
  1621.  */
  1622. /*  BUG FIX!  19991030 -sralston
  1623.  *    TUR's being issued with scsictl=0x02000000 (DATA_IN)!
  1624.  *    Seems we may receive a buffer (datalen>0) even when there
  1625.  *    will be no data transfer!  GRRRRR...
  1626.  */
  1627. datadir = mptscsih_io_direction(SCpnt);
  1628. if (datadir == SCSI_DATA_READ) {
  1629. datalen = SCpnt->request_bufflen;
  1630. scsidir = MPI_SCSIIO_CONTROL_READ; /* DATA IN  (host<--ioc<--dev) */
  1631. } else if (datadir == SCSI_DATA_WRITE) {
  1632. datalen = SCpnt->request_bufflen;
  1633. scsidir = MPI_SCSIIO_CONTROL_WRITE; /* DATA OUT (host-->ioc-->dev) */
  1634. } else {
  1635. datalen = 0;
  1636. scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER;
  1637. }
  1638. /* Default to untagged. Once a target structure has been allocated,
  1639.  * use the Inquiry data to determine if device supports tagged.
  1640.  */
  1641. qtag = MPI_SCSIIO_CONTROL_UNTAGGED;
  1642. if (pTarget && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
  1643. && (SCpnt->device->tagged_supported)) {
  1644. /*
  1645.  *  Some drives are too stupid to handle fairness issues
  1646.  *  with tagged queueing. We throw in the odd ordered
  1647.  *  tag to stop them starving themselves.
  1648.  */
  1649. if ((jiffies - hd->qtag_tick) > (5*HZ)) {
  1650. qtag = MPI_SCSIIO_CONTROL_ORDEREDQ;
  1651. hd->qtag_tick = jiffies;
  1652. }
  1653. else
  1654. qtag = MPI_SCSIIO_CONTROL_SIMPLEQ;
  1655. }
  1656. scsictl = scsidir | qtag;
  1657. /* Use the above information to set up the message frame
  1658.  */
  1659. pScsiReq->TargetID = target;
  1660. pScsiReq->Bus = hd->port;
  1661. pScsiReq->ChainOffset = 0;
  1662. pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
  1663. pScsiReq->CDBLength = SCpnt->cmd_len;
  1664. pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
  1665. pScsiReq->Reserved = 0;
  1666. pScsiReq->MsgFlags = mpt_msg_flags();
  1667. pScsiReq->LUN[0] = 0;
  1668. pScsiReq->LUN[1] = lun;
  1669. pScsiReq->LUN[2] = 0;
  1670. pScsiReq->LUN[3] = 0;
  1671. pScsiReq->LUN[4] = 0;
  1672. pScsiReq->LUN[5] = 0;
  1673. pScsiReq->LUN[6] = 0;
  1674. pScsiReq->LUN[7] = 0;
  1675. pScsiReq->Control = cpu_to_le32(scsictl);
  1676. /*
  1677.  *  Write SCSI CDB into the message
  1678.  */
  1679. cmd_len = SCpnt->cmd_len;
  1680. for (ii=0; ii < cmd_len; ii++)
  1681. pScsiReq->CDB[ii] = SCpnt->cmnd[ii];
  1682. for (ii=cmd_len; ii < 16; ii++)
  1683. pScsiReq->CDB[ii] = 0;
  1684. /* DataLength */
  1685. pScsiReq->DataLength = cpu_to_le32(datalen);
  1686. /* SenseBuffer low address */
  1687. pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
  1688.    + (my_idx * MPT_SENSE_BUFFER_ALLOC));
  1689. /* Now add the SG list
  1690.  * Always have a SGE even if null length.
  1691.  */
  1692. rc = SUCCESS;
  1693. if (datalen == 0) {
  1694. /* Add a NULL SGE */
  1695. mpt_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0,
  1696. (dma_addr_t) -1);
  1697. } else {
  1698. /* Add a 32 or 64 bit SGE */
  1699. rc = mptscsih_AddSGE(hd, SCpnt, pScsiReq, my_idx);
  1700. }
  1701. if (rc == SUCCESS) {
  1702. hd->ScsiLookup[my_idx] = SCpnt;
  1703. SCpnt->host_scribble = NULL;
  1704. #ifdef DROP_TEST
  1705. numTotCmds++;
  1706. /* If the IOC number and target match, increment
  1707.  * counter. If counter matches DROP_THIS, do not
  1708.  * issue command to FW to force a reset.
  1709.  * Save the MF pointer so we can free resources
  1710.  * when task mgmt completes.
  1711.  */
  1712. if ((hd->ioc->id == DROP_IOC) && (target == DROP_TARGET)) {
  1713. dropCounter++;
  1714. if (dropCounter == DROP_THIS_CMD) {
  1715. dropCounter = 0;
  1716. /* If global is set, then we are already
  1717.  * doing something - so keep issuing commands.
  1718.  */
  1719. if (dropMfPtr == NULL) {
  1720. dropTestNum++;
  1721. dropMfPtr = mf;
  1722. atomic_inc(&queue_depth);
  1723. printk(MYIOC_s_INFO_FMT
  1724. "Dropped SCSI cmd (%p)n",
  1725. hd->ioc->name, SCpnt);
  1726. printk("mf (%p) req (%4x) tot cmds (%d)n",
  1727. mf, my_idx, numTotCmds);
  1728. return 0;
  1729. }
  1730. }
  1731. }
  1732. #endif
  1733. /* SCSI specific processing */
  1734. issueCmd = 1;
  1735. if (hd->is_spi) {
  1736. int dvStatus = hd->ioc->spi_data.dvStatus[target];
  1737. if (dvStatus || hd->ioc->spi_data.forceDv) {
  1738. /* Write SDP1 on this I/O to this target */
  1739. if (dvStatus & MPT_SCSICFG_NEGOTIATE) {
  1740. mptscsih_writeSDP1(hd, 0, target, hd->negoNvram);
  1741. dvStatus &= ~MPT_SCSICFG_NEGOTIATE;
  1742. hd->ioc->spi_data.dvStatus[target] =  dvStatus;
  1743. } else if (dvStatus & MPT_SCSICFG_BLK_NEGO) {
  1744. mptscsih_writeSDP1(hd, 0, target, MPT_SCSICFG_BLK_NEGO);
  1745. dvStatus &= ~MPT_SCSICFG_BLK_NEGO;
  1746. hd->ioc->spi_data.dvStatus[target] =  dvStatus;
  1747. }
  1748. #ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
  1749. if ((dvStatus & MPT_SCSICFG_NEED_DV) || hd->ioc->spi_data.forceDv) {
  1750. unsigned long lflags;
  1751. /* Schedule DV if necessary */
  1752. spin_lock_irqsave(&dvtaskQ_lock, lflags);
  1753. if (!dvtaskQ_active) {
  1754. dvtaskQ_active = 1;
  1755. spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
  1756. mptscsih_dvTask.sync = 0;
  1757. mptscsih_dvTask.routine = mptscsih_domainValidation;
  1758. mptscsih_dvTask.data = (void *) hd;
  1759. SCHEDULE_TASK(&mptscsih_dvTask);
  1760. } else {
  1761. spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
  1762. }
  1763. hd->ioc->spi_data.forceDv = 0;
  1764. }
  1765. /* Trying to do DV to this target, extend timeout.
  1766.  * Wait to issue intil flag is clear 
  1767.  */
  1768. if (dvStatus & MPT_SCSICFG_DV_PENDING) {
  1769. mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ);
  1770. issueCmd = 0;
  1771. }
  1772. if (qtag == MPI_SCSIIO_CONTROL_UNTAGGED)
  1773. hd->ioc->spi_data.iocntr[target]++;
  1774. /* Set the DV flags.
  1775.  */
  1776. if (dvStatus & MPT_SCSICFG_DV_NOT_DONE)
  1777. mptscsih_set_dvflags(hd, pScsiReq);
  1778. #endif
  1779. }
  1780. }
  1781. if (issueCmd) {
  1782. mptscsih_put_msgframe(ScsiDoneCtx, hd->ioc->id, mf);
  1783. dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%dn",
  1784. hd->ioc->name, SCpnt, mf, my_idx));
  1785. } else {
  1786. ddvtprintk((MYIOC_s_INFO_FMT "Pending cmd=%p idx %dn",
  1787. hd->ioc->name, SCpnt, my_idx));
  1788. /* Place this command on the pendingQ if possible */
  1789. spin_lock_irqsave(&hd->freedoneQlock, flags);
  1790. if (!Q_IS_EMPTY(&hd->freeQ)) {
  1791. buffer = hd->freeQ.head;
  1792. Q_DEL_ITEM(buffer);
  1793. /* Save the mf pointer
  1794.  */
  1795. buffer->argp = (void *)mf;
  1796. /* Add to the pendingQ
  1797.  */
  1798. Q_ADD_TAIL(&hd->pendingQ.head, buffer, MPT_DONE_Q);
  1799. spin_unlock_irqrestore(&hd->freedoneQlock, flags);
  1800. } else {
  1801. spin_unlock_irqrestore(&hd->freedoneQlock, flags);
  1802. SCpnt->result = (DID_BUS_BUSY << 16);
  1803. SCpnt->scsi_done(SCpnt);
  1804. }
  1805. }
  1806. } else {
  1807. mptscsih_freeChainBuffers(hd, my_idx);
  1808. mpt_free_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
  1809. did_errcode = 3;
  1810. goto did_error;
  1811. }
  1812. return 0;
  1813. did_error:
  1814. dprintk((MYIOC_s_WARN_FMT "_qcmd did_errcode=%d (sc=%p)n",
  1815. hd->ioc->name, did_errcode, SCpnt));
  1816. /* Just wish OS to issue a retry */
  1817. SCpnt->result = (DID_BUS_BUSY << 16);
  1818. spin_lock_irqsave(&hd->freedoneQlock, flags);
  1819. if (!Q_IS_EMPTY(&hd->freeQ)) {
  1820. buffer = hd->freeQ.head;
  1821. Q_DEL_ITEM(buffer);
  1822. /* Set the Scsi_Cmnd pointer
  1823.  */
  1824. buffer->argp = (void *)SCpnt;
  1825. /* Add to the doneQ
  1826.  */
  1827. Q_ADD_TAIL(&hd->doneQ.head, buffer, MPT_DONE_Q);
  1828. spin_unlock_irqrestore(&hd->freedoneQlock, flags);
  1829. } else {
  1830. spin_unlock_irqrestore(&hd->freedoneQlock, flags);
  1831. SCpnt->scsi_done(SCpnt);
  1832. }
  1833. return 0;
  1834. }
  1835. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  1836. /*
  1837.  * mptscsih_AddSGE - Add a SGE (plus chain buffers) to the
  1838.  * SCSIIORequest_t Message Frame.
  1839.  * @hd: Pointer to MPT_SCSI_HOST structure
  1840.  * @SCpnt: Pointer to Scsi_Cmnd structure
  1841.  * @pReq: Pointer to SCSIIORequest_t structure
  1842.  *
  1843.  * Returns ...
  1844.  */
  1845. static int
  1846. mptscsih_AddSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt,
  1847.  SCSIIORequest_t *pReq, int req_idx)
  1848. {
  1849. char  *psge;
  1850. char *chainSge;
  1851. struct scatterlist *sg;
  1852. int  frm_sz;
  1853. int  sges_left, sg_done;
  1854. int  chain_idx = MPT_HOST_NO_CHAIN;
  1855. int  sgeOffset;
  1856. int  numSgeSlots, numSgeThisFrame;
  1857. u32  sgflags, sgdir, thisxfer = 0;
  1858. int  chain_dma_off = 0;
  1859. int  newIndex;
  1860. int  ii;
  1861. dma_addr_t v2;
  1862. sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK;
  1863. if (sgdir == MPI_SCSIIO_CONTROL_WRITE)  {
  1864. sgdir = MPT_TRANSFER_HOST_TO_IOC;
  1865. } else {
  1866. sgdir = MPT_TRANSFER_IOC_TO_HOST;
  1867. }
  1868. psge = (char *) &pReq->SGL;
  1869. frm_sz = hd->ioc->req_sz;
  1870. /* Map the data portion, if any.
  1871.  * sges_left  = 0 if no data transfer.
  1872.  */
  1873. sges_left = SCpnt->use_sg;
  1874. if (SCpnt->use_sg) {
  1875. sges_left = pci_map_sg(hd->ioc->pcidev,
  1876.        (struct scatterlist *) SCpnt->request_buffer,
  1877.        SCpnt->use_sg,
  1878.        scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
  1879. } else if (SCpnt->request_bufflen) {
  1880. dma_addr_t  buf_dma_addr;
  1881. scPrivate *my_priv;
  1882. buf_dma_addr = pci_map_single(hd->ioc->pcidev,
  1883.       SCpnt->request_buffer,
  1884.       SCpnt->request_bufflen,
  1885.       scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
  1886. /* We hide it here for later unmap. */
  1887. my_priv = (scPrivate *) &SCpnt->SCp;
  1888. my_priv->p1 = (void *)(ulong) buf_dma_addr;
  1889. dsgprintk((MYIOC_s_INFO_FMT "SG: non-SG for %p, len=%dn",
  1890. hd->ioc->name, SCpnt, SCpnt->request_bufflen));
  1891. mpt_add_sge((char *) &pReq->SGL,
  1892. 0xD1000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|SCpnt->request_bufflen,
  1893. buf_dma_addr);
  1894. return SUCCESS;
  1895. }
  1896. /* Handle the SG case.
  1897.  */
  1898. sg = (struct scatterlist *) SCpnt->request_buffer;
  1899. sg_done  = 0;
  1900. sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);
  1901. chainSge = NULL;
  1902. /* Prior to entering this loop - the following must be set
  1903.  * current MF:  sgeOffset (bytes)
  1904.  *              chainSge (Null if original MF is not a chain buffer)
  1905.  *              sg_done (num SGE done for this MF)
  1906.  */
  1907. nextSGEset:
  1908. numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) );
  1909. numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots;
  1910. sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir;
  1911. /* Get first (num - 1) SG elements
  1912.  * Skip any SG entries with a length of 0
  1913.  * NOTE: at finish, sg and psge pointed to NEXT data/location positions
  1914.  */
  1915. for (ii=0; ii < (numSgeThisFrame-1); ii++) {
  1916. thisxfer = sg_dma_len(sg);
  1917. if (thisxfer == 0) {
  1918. sg ++; /* Get next SG element from the OS */
  1919. sg_done++;
  1920. continue;
  1921. }
  1922. v2 = sg_dma_address(sg);
  1923. mpt_add_sge(psge, sgflags | thisxfer, v2);
  1924. sg++; /* Get next SG element from the OS */
  1925. psge += (sizeof(u32) + sizeof(dma_addr_t));
  1926. sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
  1927. sg_done++;
  1928. }
  1929. if (numSgeThisFrame == sges_left) {
  1930. /* Add last element, end of buffer and end of list flags.
  1931.  */
  1932. sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT |
  1933. MPT_SGE_FLAGS_END_OF_BUFFER |
  1934. MPT_SGE_FLAGS_END_OF_LIST;
  1935. /* Add last SGE and set termination flags.
  1936.  * Note: Last SGE may have a length of 0 - which should be ok.
  1937.  */
  1938. thisxfer = sg_dma_len(sg);
  1939. v2 = sg_dma_address(sg);
  1940. mpt_add_sge(psge, sgflags | thisxfer, v2);
  1941. /*
  1942. sg++;
  1943. psge += (sizeof(u32) + sizeof(dma_addr_t));
  1944. */
  1945. sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
  1946. sg_done++;
  1947. if (chainSge) {
  1948. /* The current buffer is a chain buffer,
  1949.  * but there is not another one.
  1950.  * Update the chain element
  1951.  * Offset and Length fields.
  1952.  */
  1953. mpt_add_chain((char *)chainSge, 0, sgeOffset, hd->ChainBufferDMA + chain_dma_off);
  1954. } else {
  1955. /* The current buffer is the original MF
  1956.  * and there is no Chain buffer.
  1957.  */
  1958. pReq->ChainOffset = 0;
  1959. }
  1960. } else {
  1961. /* At least one chain buffer is needed.
  1962.  * Complete the first MF
  1963.  *  - last SGE element, set the LastElement bit
  1964.  *  - set ChainOffset (words) for orig MF
  1965.  *             (OR finish previous MF chain buffer)
  1966.  *  - update MFStructPtr ChainIndex
  1967.  *  - Populate chain element
  1968.  * Also
  1969.  * Loop until done.
  1970.  */
  1971. dsgprintk((MYIOC_s_INFO_FMT "SG: Chain Required! sg done %dn",
  1972. hd->ioc->name, sg_done));
  1973. /* Set LAST_ELEMENT flag for last non-chain element
  1974.  * in the buffer. Since psge points at the NEXT
  1975.  * SGE element, go back one SGE element, update the flags
  1976.  * and reset the pointer. (Note: sgflags & thisxfer are already
  1977.  * set properly).
  1978.  */
  1979. if (sg_done) {
  1980. u32 *ptmp = (u32 *) (psge - (sizeof(u32) + sizeof(dma_addr_t)));
  1981. sgflags = le32_to_cpu(*ptmp);
  1982. sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT;
  1983. *ptmp = cpu_to_le32(sgflags);
  1984. }
  1985. if (chainSge) {
  1986. /* The current buffer is a chain buffer.
  1987.  * chainSge points to the previous Chain Element.
  1988.  * Update its chain element Offset and Length (must
  1989.  * include chain element size) fields.
  1990.  * Old chain element is now complete.
  1991.  */
  1992. u8 nextChain = (u8) (sgeOffset >> 2);
  1993. sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
  1994. mpt_add_chain((char *)chainSge, nextChain, sgeOffset, hd->ChainBufferDMA + chain_dma_off);
  1995. } else {
  1996. /* The original MF buffer requires a chain buffer -
  1997.  * set the offset.
  1998.  * Last element in this MF is a chain element.
  1999.  */
  2000. pReq->ChainOffset = (u8) (sgeOffset >> 2);
  2001. }
  2002. sges_left -= sg_done;
  2003. /* NOTE: psge points to the beginning of the chain element
  2004.  * in current buffer. Get a chain buffer.
  2005.  */
  2006. if ((mptscsih_getFreeChainBuffer(hd, &newIndex)) == FAILED)
  2007. return FAILED;
  2008. /* Update the tracking arrays.
  2009.  * If chainSge == NULL, update ReqToChain, else ChainToChain
  2010.  */
  2011. if (chainSge) {
  2012. hd->ChainToChain[chain_idx] = newIndex;
  2013. } else {
  2014. hd->ReqToChain[req_idx] = newIndex;
  2015. }
  2016. chain_idx = newIndex;
  2017. chain_dma_off = hd->ioc->req_sz * chain_idx;
  2018. /* Populate the chainSGE for the current buffer.
  2019.  * - Set chain buffer pointer to psge and fill
  2020.  *   out the Address and Flags fields.
  2021.  */
  2022. chainSge = (char *) psge;
  2023. dsgprintk((KERN_INFO "  Current buff @ %p (index 0x%x)",
  2024. psge, req_idx));
  2025. /* Start the SGE for the next buffer
  2026.  */
  2027. psge = (char *) (hd->ChainBuffer + chain_dma_off);
  2028. sgeOffset = 0;
  2029. sg_done = 0;
  2030. dsgprintk((KERN_INFO "  Chain buff @ %p (index 0x%x)n",
  2031. psge, chain_idx));
  2032. /* Start the SGE for the next buffer
  2033.  */
  2034. goto nextSGEset;
  2035. }
  2036. return SUCCESS;
  2037. }
  2038. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  2039. /*
  2040.  * mptscsih_getFreeChainBuffes - Function to get a free chain
  2041.  * from the MPT_SCSI_HOST FreeChainQ.
  2042.  * @hd: Pointer to the MPT_SCSI_HOST instance
  2043.  * @req_idx: Index of the SCSI IO request frame. (output)
  2044.  *
  2045.  * return SUCCESS or FAILED
  2046.  */
  2047. static int
  2048. mptscsih_getFreeChainBuffer(MPT_SCSI_HOST *hd, int *retIndex)
  2049. {
  2050. MPT_FRAME_HDR *chainBuf = NULL;
  2051. unsigned long flags;
  2052. int rc = FAILED;
  2053. int chain_idx = MPT_HOST_NO_CHAIN;
  2054. //spin_lock_irqsave(&hd->FreeChainQlock, flags);
  2055. spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
  2056. if (!Q_IS_EMPTY(&hd->FreeChainQ)) {
  2057. int offset;
  2058. chainBuf = hd->FreeChainQ.head;
  2059. Q_DEL_ITEM(&chainBuf->u.frame.linkage);
  2060. offset = (u8 *)chainBuf - (u8 *)hd->ChainBuffer;
  2061. chain_idx = offset / hd->ioc->req_sz;
  2062. rc = SUCCESS;
  2063. }
  2064. //spin_unlock_irqrestore(&hd->FreeChainQlock, flags);
  2065. spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
  2066. *retIndex = chain_idx;
  2067. dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer (index %d), got buf=%pn",
  2068. hd->ioc->name, *retIndex, chainBuf));
  2069. return rc;
  2070. }
  2071. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  2072. /*
  2073.  * mptscsih_freeChainBuffers - Function to free chain buffers associated
  2074.  * with a SCSI IO request
  2075.  * @hd: Pointer to the MPT_SCSI_HOST instance
  2076.  * @req_idx: Index of the SCSI IO request frame.
  2077.  *
  2078.  * Called if SG chain buffer allocation fails and mptscsih callbacks.
  2079.  * No return.
  2080.  */
  2081. static void
  2082. mptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx)
  2083. {
  2084. MPT_FRAME_HDR *chain = NULL;
  2085. unsigned long flags;
  2086. int chain_idx;
  2087. int next;
  2088. /* Get the first chain index and reset
  2089.  * tracker state.
  2090.  */
  2091. chain_idx = hd->ReqToChain[req_idx];
  2092. hd->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
  2093. while (chain_idx != MPT_HOST_NO_CHAIN) {
  2094. /* Save the next chain buffer index */
  2095. next = hd->ChainToChain[chain_idx];
  2096. /* Free this chain buffer and reset
  2097.  * tracker
  2098.  */
  2099. hd->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
  2100. chain = (MPT_FRAME_HDR *) (hd->ChainBuffer
  2101. + (chain_idx * hd->ioc->req_sz));
  2102. spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
  2103. Q_ADD_TAIL(&hd->FreeChainQ.head,
  2104. &chain->u.frame.linkage, MPT_FRAME_HDR);
  2105. spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
  2106. dmfprintk((MYIOC_s_INFO_FMT "FreeChainBuffers (index %d)n",
  2107. hd->ioc->name, chain_idx));
  2108. /* handle next */
  2109. chain_idx = next;
  2110. }
  2111. return;
  2112. }
  2113. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  2114. /*
  2115.  * Reset Handling
  2116.  */
  2117. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  2118. /*
  2119.  * mptscsih_TMHandler - Generic handler for SCSI Task Management.
  2120.  * Fall through to mpt_HardResetHandler if: not operational, too many
  2121.  * failed TM requests or handshake failure.
  2122.  *
  2123.  * @ioc: Pointer to MPT_ADAPTER structure
  2124.  * @type: Task Management type
  2125.  * @target: Logical Target ID for reset (if appropriate)
  2126.  * @lun: Logical Unit for reset (if appropriate)
  2127.  * @ctx2abort: Context for the task to be aborted (if appropriate)
  2128.  * @sleepFlag: If set, use udelay instead of schedule in handshake code.
  2129.  *
  2130.  * Remark: Currently invoked from a non-interrupt thread (_bh).
  2131.  *
  2132.  * Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
  2133.  * will be active.
  2134.  *
  2135.  * Returns 0 for SUCCESS or -1 if FAILED.
  2136.  */
  2137. static int
  2138. mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 target, u8 lun, int ctx2abort, int sleepFlag)
  2139. {
  2140. MPT_ADAPTER *ioc = NULL;
  2141. int  rc = -1;
  2142. int  doTask = 1;
  2143. u32  ioc_raw_state;
  2144. unsigned long  flags;
  2145. /* If FW is being reloaded currently, return success to
  2146.  * the calling function.
  2147.  */
  2148. if (hd == NULL)
  2149. return 0;
  2150. ioc = hd->ioc;
  2151. dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!n", ioc->name));
  2152. if (ioc == NULL) {
  2153. printk(KERN_ERR MYNAM " TMHandler" " NULL ioc!n");
  2154. return 0;
  2155. }
  2156. // SJR - CHECKME - Can we avoid this here?
  2157. // (mpt_HardResetHandler has this check...)
  2158. spin_lock_irqsave(&ioc->diagLock, flags);
  2159. if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) {
  2160. spin_unlock_irqrestore(&ioc->diagLock, flags);
  2161. return 0;
  2162. }
  2163. spin_unlock_irqrestore(&ioc->diagLock, flags);
  2164. /* Do not do a Task Management if there are
  2165.  * too many failed TMs on this adapter.
  2166.  */
  2167. if (hd->numTMrequests > MPT_HOST_TOO_MANY_TM)
  2168. doTask = 0;
  2169. /* Is operational?
  2170.  */
  2171. ioc_raw_state = mpt_GetIocState(hd->ioc, 0);
  2172. #ifdef MPT_DEBUG_RESET
  2173. if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
  2174. printk(MYIOC_s_WARN_FMT 
  2175. "TM Handler: IOC Not operational! state 0x%x Calling HardResetHandlern", 
  2176. hd->ioc->name, ioc_raw_state);
  2177. }
  2178. #endif
  2179. if (doTask && ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL)
  2180. && !(ioc_raw_state & MPI_DOORBELL_ACTIVE)) {
  2181. /* Isse the Task Mgmt request.
  2182.  */
  2183. rc = mptscsih_IssueTaskMgmt(hd, type, target, lun, ctx2abort, sleepFlag);
  2184. if (rc) {
  2185. #ifdef MPT_SCSI_USE_NEW_EH
  2186. hd->tmState = TM_STATE_ERROR;
  2187. #endif
  2188. printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!n", hd->ioc->name);
  2189. } else {
  2190. printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!n", hd->ioc->name);
  2191. }
  2192. }
  2193. #ifdef DROP_TEST
  2194. numTMrequested++;
  2195. if (numTMrequested > 5) {
  2196. rc = 0; /* set to 1 to force a hard reset */
  2197. numTMrequested = 0;
  2198. }
  2199. #endif
  2200. if (rc) {
  2201. dtmprintk((MYIOC_s_INFO_FMT "Falling through to HardReset! n",
  2202.  hd->ioc->name));
  2203. rc = mpt_HardResetHandler(hd->ioc, sleepFlag);
  2204. }
  2205. dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!n", hd->ioc->name, rc));
  2206. #ifndef MPT_SCSI_USE_NEW_EH
  2207. dtmprintk((MYIOC_s_INFO_FMT "TMHandler: _bh_handler state (%d) taskQ count (%d)n",
  2208. ioc->name, mytaskQ_bh_active, hd->taskQcnt));
  2209. #endif
  2210. return rc;
  2211. }
  2212. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  2213. /*
  2214.  * mptscsih_IssueTaskMgmt - Generic send Task Management function.
  2215.  * @hd: Pointer to MPT_SCSI_HOST structure
  2216.  * @type: Task Management type
  2217.  * @target: Logical Target ID for reset (if appropriate)
  2218.  * @lun: Logical Unit for reset (if appropriate)
  2219.  * @ctx2abort: Context for the task to be aborted (if appropriate)
  2220.  * @sleepFlag: If set, use udelay instead of schedule in handshake code.
  2221.  *
  2222.  * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
  2223.  * or a non-interrupt thread.  In the former, must not call schedule().
  2224.  *
  2225.  * Not all fields are meaningfull for all task types.
  2226.  *
  2227.  * Returns 0 for SUCCESS, -999 for "no msg frames",
  2228.  * else other non-zero value returned.
  2229.  */
  2230. static int
  2231. mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 target, u8 lun, int ctx2abort, int sleepFlag)
  2232. {
  2233. MPT_FRAME_HDR *mf;
  2234. SCSITaskMgmt_t *pScsiTm;
  2235. int  ii;
  2236. int  retval;
  2237. /* Return Fail to calling function if no message frames available.
  2238.  */
  2239. if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc->id)) == NULL) {
  2240. dtmprintk((MYIOC_s_WARN_FMT "IssueTaskMgmt, no msg frames!!n",
  2241. hd->ioc->name));
  2242. //return FAILED;
  2243. return -999;
  2244. }
  2245. dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %pn",
  2246. hd->ioc->name, mf));
  2247. /* Format the Request
  2248.  */
  2249. pScsiTm = (SCSITaskMgmt_t *) mf;
  2250. pScsiTm->TargetID = target;
  2251. pScsiTm->Bus = hd->port;
  2252. pScsiTm->ChainOffset = 0;
  2253. pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
  2254. pScsiTm->Reserved = 0;
  2255. pScsiTm->TaskType = type;
  2256. pScsiTm->Reserved1 = 0;
  2257. pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
  2258.                     ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
  2259. for (ii= 0; ii < 8; ii++) {
  2260. pScsiTm->LUN[ii] = 0;
  2261. }
  2262. pScsiTm->LUN[1] = lun;
  2263. for (ii=0; ii < 7; ii++)
  2264. pScsiTm->Reserved2[ii] = 0;
  2265. pScsiTm->TaskMsgContext = ctx2abort;
  2266. dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt, ctx2abort (0x%08x), type (%d)n",
  2267. hd->ioc->name, ctx2abort, type));
  2268. /* MPI v0.10 requires SCSITaskMgmt requests be sent via Doorbell/handshake
  2269. mpt_put_msg_frame(hd->ioc->id, mf);
  2270. * Save the MF pointer in case the request times out.
  2271. */
  2272. hd->tmPtr = mf;
  2273. hd->numTMrequests++;
  2274. hd->TMtimer.expires = jiffies + HZ*20;  /* 20 seconds */
  2275. add_timer(&hd->TMtimer);
  2276. if ((retval = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id,
  2277. sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, sleepFlag))
  2278. != 0) {
  2279. dtmprintk((MYIOC_s_WARN_FMT "_send_handshake FAILED!"
  2280. " (hd %p, ioc %p, mf %p) n", hd->ioc->name, hd, hd->ioc, mf));
  2281. hd->numTMrequests--;
  2282. hd->tmPtr = NULL;
  2283. del_timer(&hd->TMtimer);
  2284. mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
  2285. }
  2286. return retval;
  2287. }
  2288. #ifdef MPT_SCSI_USE_NEW_EH /* { */
  2289. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  2290. /**
  2291.  * mptscsih_abort - Abort linux Scsi_Cmnd routine, new_eh variant
  2292.  * @SCpnt: Pointer to Scsi_Cmnd structure, IO to be aborted
  2293.  *
  2294.  * (linux Scsi_Host_Template.eh_abort_handler routine)
  2295.  *
  2296.  * Returns SUCCESS or FAILED.
  2297.  */
  2298. int
  2299. mptscsih_abort(Scsi_Cmnd * SCpnt)
  2300. {
  2301. MPT_SCSI_HOST *hd;
  2302. MPT_FRAME_HDR *mf;
  2303. unsigned long  flags;
  2304. u32  ctx2abort;
  2305. int  scpnt_idx;
  2306. /* If we can't locate our host adapter structure, return FAILED status.
  2307.  */
  2308. if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL) {
  2309. SCpnt->result = DID_RESET << 16;
  2310. SCpnt->scsi_done(SCpnt);
  2311. nehprintk((KERN_WARNING MYNAM ": mptscsih_abort: "
  2312.    "Can't locate host! (sc=%p)n",
  2313.    SCpnt));
  2314. return FAILED;
  2315. }
  2316. printk(KERN_WARNING MYNAM ": %s: >> Attempting task abort! (sc=%p)n",
  2317.        hd->ioc->name, SCpnt);
  2318. printk(KERN_WARNING MYNAM ": %s: IOs outstanding = %dn",
  2319.        hd->ioc->name, atomic_read(&queue_depth));
  2320. /* Find this command
  2321.  */
  2322. if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
  2323. /* Cmd not found in ScsiLookup. If found in
  2324.  * doneQ, delete from Q. Do OS callback.
  2325.  */
  2326. search_doneQ_for_cmd(hd, SCpnt);
  2327. SCpnt->result = DID_RESET << 16;
  2328. SCpnt->scsi_done(SCpnt);
  2329. nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
  2330.    "Command not in the active list! (sc=%p)n",
  2331.    hd->ioc->name, SCpnt));
  2332. return SUCCESS;
  2333. }
  2334. /*  Wait a fixed amount of time for the TM pending flag to be cleared.
  2335.  *  If we time out, then we return a FAILED status to the caller.  This
  2336.  *  call to mptscsih_tm_pending_wait() will set the pending flag if we are
  2337.  *  successful.
  2338.  */
  2339. if (mptscsih_tm_pending_wait(hd) == FAILED){
  2340. nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
  2341.    "Timed out waiting for previous TM to complete! "
  2342.    "(sc = %p)n",
  2343.    hd->ioc->name, SCpnt));
  2344. return FAILED;
  2345. }
  2346. /* If this command is pended, then timeout/hang occurred
  2347.  * during DV. Post command and flush pending Q
  2348.  * and then following up with the reset request.
  2349.  */
  2350. if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) {
  2351. mptscsih_put_msgframe(ScsiDoneCtx, hd->ioc->id, mf);
  2352. post_pendingQ_commands(hd);
  2353. nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
  2354.    "Found command in pending queue! (sc=%p)n",
  2355.    hd->ioc->name, SCpnt));
  2356. }
  2357. /* Most important!  Set TaskMsgContext to SCpnt's MsgContext!
  2358.  * (the IO to be ABORT'd)
  2359.  *
  2360.  * NOTE: Since we do not byteswap MsgContext, we do not
  2361.  *  swap it here either.  It is an opaque cookie to
  2362.  *  the controller, so it does not matter. -DaveM
  2363.  */
  2364. mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
  2365. ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
  2366. hd->abortSCpnt = SCpnt;
  2367. if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
  2368.                        SCpnt->target, SCpnt->lun, ctx2abort, CAN_SLEEP) 
  2369. < 0
  2370.     || hd->tmState == TM_STATE_ERROR) {
  2371. /* The TM request failed and the subsequent FW-reload failed!
  2372.  * Fatal error case.
  2373.  */
  2374. printk(MYIOC_s_WARN_FMT "Error issuing abort task! (sc=%p)n",
  2375.        hd->ioc->name, SCpnt);
  2376. /* If command not found, do not do callback,
  2377.  *  just return failed.  CHECKME
  2378.  */
  2379. if (hd->ScsiLookup[scpnt_idx] != NULL) {
  2380. SCpnt->result = STS_BUSY;
  2381. SCpnt->scsi_done(SCpnt);
  2382. }
  2383. /* We must clear our pending flag before clearing our state.
  2384.  */
  2385. hd->tmPending = 0;
  2386. hd->tmState = TM_STATE_NONE;
  2387. return FAILED;
  2388. }
  2389. /* Our task management request will either complete or time out.  So we
  2390.  * spin until tmPending is != 1. If tmState is set to TM_STATE_ERROR, 
  2391.  * we encountered an error executing the task management request.
  2392.  */
  2393. while (hd->tmPending == 1){
  2394. set_current_state(TASK_INTERRUPTIBLE);
  2395. schedule_timeout(HZ/4);
  2396. }
  2397. spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
  2398. if (hd->tmState == TM_STATE_ERROR){
  2399. hd->tmState = TM_STATE_NONE;
  2400. spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
  2401. nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
  2402.    "TM timeout error! (sc=%p)n",
  2403.    hd->ioc->name,
  2404.    SCpnt));
  2405. return FAILED;
  2406. }
  2407. hd->tmState = TM_STATE_NONE;
  2408. spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
  2409. nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
  2410.    "Abort was successful! (sc=%p)n",
  2411.    hd->ioc->name,
  2412.    SCpnt));
  2413. return SUCCESS;
  2414. }
  2415. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  2416. /**
  2417.  * mptscsih_dev_reset - Perform a SCSI TARGET_RESET!  new_eh variant
  2418.  * @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
  2419.  *
  2420.  * (linux Scsi_Host_Template.eh_dev_reset_handler routine)
  2421.  *
  2422.  * Returns SUCCESS or FAILED.
  2423.  */
  2424. int
  2425. mptscsih_dev_reset(Scsi_Cmnd * SCpnt)
  2426. {
  2427. MPT_SCSI_HOST *hd;
  2428. unsigned long  flags;
  2429. /* If we can't locate our host adapter structure, return FAILED status.
  2430.  */
  2431. if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL){
  2432. nehprintk((KERN_WARNING MYNAM ": mptscsih_dev_reset: "
  2433.    "Can't locate host! (sc=%p)n",
  2434.    SCpnt));
  2435. return FAILED;
  2436. }
  2437. printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p)n",
  2438.        hd->ioc->name, SCpnt);
  2439. printk(KERN_WARNING MYNAM ": %s: IOs outstanding = %dn",
  2440.        hd->ioc->name, atomic_read(&queue_depth));
  2441. /*  Wait a fixed amount of time for the TM pending flag to be cleared.
  2442.  *  If we time out, then we return a FAILED status to the caller.  This
  2443.  *  call to mptscsih_tm_pending_wait() will set the pending flag if we are
  2444.  *  successful.
  2445.  */
  2446. if (mptscsih_tm_pending_wait(hd) == FAILED) {
  2447. nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_dev_reset: "
  2448.    "Timed out waiting for previous TM to complete! "
  2449.    "(sc = %p)n",
  2450.    hd->ioc->name, SCpnt));
  2451. return FAILED;
  2452. }
  2453. if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
  2454.                        SCpnt->target, 0, 0, CAN_SLEEP) 
  2455. < 0){
  2456. /* The TM request failed and the subsequent FW-reload failed!
  2457.  * Fatal error case.
  2458.  */
  2459. printk(MYIOC_s_WARN_FMT "Error processing TaskMgmt request (sc=%p)n",
  2460.   hd->ioc->name, SCpnt);
  2461. hd->tmPending = 0;
  2462. hd->tmState = TM_STATE_NONE;
  2463. return FAILED;
  2464. }
  2465. /* Our task management request will either complete or time out.  So we
  2466.  * spin until tmPending is != 1. If tmState is set to TM_STATE_ERROR, 
  2467.  * we encountered an error executing the task management request.
  2468.  */
  2469. while (hd->tmPending == 1){
  2470. set_current_state(TASK_INTERRUPTIBLE);
  2471. schedule_timeout(HZ/4);
  2472. }
  2473. spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
  2474. if (hd->tmState == TM_STATE_ERROR){
  2475. hd->tmState = TM_STATE_NONE;
  2476. spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
  2477. nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_dev_reset: "
  2478.    "TM timeout error! (sc=%p)n",
  2479.    hd->ioc->name,
  2480.    SCpnt));
  2481. return FAILED;
  2482. }
  2483. hd->tmState = TM_STATE_NONE;
  2484. spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
  2485. nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_dev_reset: "
  2486.    "Device reset was successful! (sc=%p)n",
  2487.    hd->ioc->name,
  2488.    SCpnt));
  2489. return SUCCESS;
  2490. }
  2491. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  2492. /**
  2493.  * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant
  2494.  * @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
  2495.  *
  2496.  * (linux Scsi_Host_Template.eh_bus_reset_handler routine)
  2497.  *
  2498.  * Returns SUCCESS or FAILED.
  2499.  */
  2500. int
  2501. mptscsih_bus_reset(Scsi_Cmnd * SCpnt)
  2502. {
  2503. MPT_SCSI_HOST *hd;
  2504. unsigned long  flags;
  2505. /* If we can't locate our host adapter structure, return FAILED status.
  2506.  */
  2507. if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL){
  2508. nehprintk((KERN_WARNING MYNAM ": mptscsih_bus_reset: "
  2509.    "Can't locate host! (sc=%p)n",
  2510.    SCpnt ) );
  2511. return FAILED;
  2512. }
  2513. printk(KERN_WARNING MYNAM ": %s: >> Attempting bus reset! (sc=%p)n",
  2514.        hd->ioc->name, SCpnt);
  2515. printk(KERN_WARNING MYNAM ": %s: IOs outstanding = %dn",
  2516.        hd->ioc->name, atomic_read(&queue_depth));
  2517. /*  Wait a fixed amount of time for the TM pending flag to be cleared.
  2518.  *  If we time out, then we return a FAILED status to the caller.  This
  2519.  *  call to mptscsih_tm_pending_wait() will set the pending flag if we are
  2520.  *  successful.
  2521.  */
  2522. if (mptscsih_tm_pending_wait(hd) == FAILED) {
  2523. nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_bus_reset: "
  2524.    "Timed out waiting for previous TM to complete! "
  2525.    "(sc = %p)n",
  2526.    hd->ioc->name, SCpnt ) );
  2527. return FAILED;
  2528. }
  2529. /* We are now ready to execute the task management request. */
  2530. if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
  2531.                        0, 0, 0, CAN_SLEEP) 
  2532.     < 0){
  2533. /* The TM request failed and the subsequent FW-reload failed!
  2534.  * Fatal error case.
  2535.  */
  2536. printk(MYIOC_s_WARN_FMT 
  2537.        "Error processing TaskMgmt request (sc=%p)n",
  2538.        hd->ioc->name, SCpnt);
  2539. hd->tmPending = 0;
  2540. hd->tmState = TM_STATE_NONE;
  2541. return FAILED;
  2542. }
  2543. /* Our task management request will either complete or time out.  So we
  2544.  * spin until tmPending is != 1. If tmState is set to TM_STATE_ERROR, 
  2545.  * we encountered an error executing the task management request.
  2546.  */
  2547. while (hd->tmPending == 1){
  2548. set_current_state(TASK_INTERRUPTIBLE);
  2549. schedule_timeout(HZ/4);
  2550. }
  2551. spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
  2552. if (hd->tmState == TM_STATE_ERROR){
  2553. hd->tmState = TM_STATE_NONE;
  2554. spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
  2555. nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_bus_reset: "
  2556.    "TM timeout error! (sc=%p)n",
  2557.    hd->ioc->name,
  2558.    SCpnt));
  2559. return FAILED;
  2560. }
  2561. hd->tmState = TM_STATE_NONE;
  2562. spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
  2563. nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_bus_reset: "
  2564.    "Bus reset was successful! (sc=%p)n",
  2565.    hd->ioc->name,
  2566.    SCpnt));
  2567. return SUCCESS;
  2568. }
  2569. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  2570. /**
  2571.  * mptscsih_host_reset - Perform a SCSI host adapter RESET!
  2572.  * new_eh variant
  2573.  * @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
  2574.  *
  2575.  * (linux Scsi_Host_Template.eh_host_reset_handler routine)
  2576.  *
  2577.  * Returns SUCCESS or FAILED.
  2578.  */
  2579. int
  2580. mptscsih_host_reset(Scsi_Cmnd *SCpnt)
  2581. {
  2582. MPT_SCSI_HOST *  hd;
  2583. int              status = SUCCESS;
  2584. /*  If we can't locate the host to reset, then we failed. */
  2585. if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL){
  2586. nehprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: "
  2587.      "Can't locate host! (sc=%p)n",
  2588.      SCpnt ) );
  2589. return FAILED;
  2590. }
  2591. printk(KERN_WARNING MYNAM ": %s: >> Attempting host reset! (sc=%p)n",
  2592.        hd->ioc->name, SCpnt);
  2593. printk(KERN_WARNING MYNAM ": %s: IOs outstanding = %dn",
  2594.        hd->ioc->name, atomic_read(&queue_depth));
  2595. /*  If our attempts to reset the host failed, then return a failed
  2596.  *  status.  The host will be taken off line by the SCSI mid-layer.
  2597.  */
  2598. if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0){
  2599. status = FAILED;
  2600. } else {
  2601. /*  Make sure TM pending is cleared and TM state is set to 
  2602.  *  NONE. 
  2603.  */
  2604. hd->tmPending = 0;
  2605. hd->tmState = TM_STATE_NONE;
  2606. }
  2607. nehprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: "
  2608.      "Status = %sn",
  2609.      (status == SUCCESS) ? "SUCCESS" : "FAILED" ) );
  2610. return status;
  2611. }
  2612. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  2613. /**
  2614.  * mptscsih_tm_pending_wait - wait for pending task management request to 
  2615.  * complete.
  2616.  * @hd: Pointer to MPT host structure.
  2617.  *
  2618.  * Returns {SUCCESS,FAILED}.
  2619.  */
  2620. static int
  2621. mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
  2622. {
  2623. unsigned long  flags;
  2624. int            loop_count = 60 * 4;  /* Wait 60 seconds */
  2625. int            status = FAILED;
  2626. do {
  2627. spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
  2628. if (hd->tmState == TM_STATE_NONE) {
  2629. hd->tmState = TM_STATE_IN_PROGRESS;
  2630. hd->tmPending = 1;
  2631. spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
  2632. status = SUCCESS;
  2633. break;
  2634. }
  2635. spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
  2636. set_current_state(TASK_INTERRUPTIBLE);
  2637. schedule_timeout(HZ/4);
  2638. } while (--loop_count);
  2639. return status;
  2640. }
  2641. #else /* MPT_SCSI old EH stuff... */
  2642. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  2643. /**
  2644.  * mptscsih_old_abort - Abort linux Scsi_Cmnd routine
  2645.  * @SCpnt: Pointer to Scsi_Cmnd structure, IO to be aborted
  2646.  *
  2647.  * (linux Scsi_Host_Template.abort routine)
  2648.  *
  2649.  * Returns SCSI_ABORT_{SUCCESS,BUSY,PENDING}.
  2650.  */
  2651. int
  2652. mptscsih_old_abort(Scsi_Cmnd *SCpnt)
  2653. {
  2654. MPT_SCSI_HOST *hd;
  2655. MPT_FRAME_HDR *mf;
  2656. struct tq_struct *ptaskfoo;
  2657. unsigned long  flags;
  2658. int  scpnt_idx;
  2659. printk(KERN_WARNING MYNAM ": OldAbort scheduling ABORT SCSI IO (sc=%p)n", (void *) SCpnt);
  2660. printk(KERN_WARNING "  IOs outstanding = %dn", atomic_read(&queue_depth));
  2661. if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL) {
  2662. printk(KERN_WARNING "  WARNING - OldAbort, NULL hostdata ptr!!n");
  2663. SCpnt->result = DID_ERROR << 16;
  2664. SCpnt->scsi_done(SCpnt);
  2665. return SCSI_ABORT_NOT_RUNNING;
  2666. }
  2667. if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
  2668. /* Cmd not found in ScsiLookup.
  2669.  * If found in doneQ, delete from Q.
  2670.  * Do OS callback.
  2671.  */
  2672. search_doneQ_for_cmd(hd, SCpnt);
  2673. SCpnt->result = DID_RESET << 16;
  2674. SCpnt->scsi_done(SCpnt);
  2675. return SCSI_ABORT_SUCCESS;
  2676. } else {
  2677. /* If this command is pended, then timeout/hang occurred
  2678.  * during DV. Force bus reset by posting command to F/W
  2679.  * and then following up with the reset request.
  2680.  */
  2681. if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) {
  2682. mptscsih_put_msgframe(ScsiDoneCtx, hd->ioc->id, mf);
  2683. post_pendingQ_commands(hd);
  2684. }
  2685. }
  2686. /*
  2687.  *  Check to see if there's already an ABORT queued for this guy.
  2688.  */
  2689. mf = search_taskQ(0, SCpnt, hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK);
  2690. if (mf != NULL) {
  2691. dtmprintk((MYIOC_s_INFO_FMT "OldAbort:Abort Task PENDING cmd (%p) taskQ depth (%d)n",
  2692. hd->ioc->name, SCpnt, hd->taskQcnt));
  2693. return SCSI_ABORT_PENDING;
  2694. }
  2695. // SJR - CHECKME - Can we avoid this here?
  2696. // (mpt_HardResetHandler has this check...)
  2697. /* If IOC is reloading FW, return PENDING.
  2698.  */
  2699. spin_lock_irqsave(&hd->ioc->diagLock, flags);
  2700. if (hd->ioc->diagPending) {
  2701. spin_unlock_irqrestore(&hd->ioc->diagLock, flags);
  2702. return SCSI_ABORT_PENDING;
  2703. }
  2704. spin_unlock_irqrestore(&hd->ioc->diagLock, flags);
  2705. /* If there are no message frames what should we do?
  2706.  */
  2707. if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc->id)) == NULL) {
  2708. printk((KERN_WARNING "  WARNING - OldAbort, no msg frames!!n"));
  2709. /* We are out of message frames!
  2710.  * Call the reset handler to do a FW reload.
  2711.  */
  2712. printk((KERN_WARNING " Reloading Firmware!!n"));
  2713. if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
  2714. printk((KERN_WARNING " Firmware Reload FAILED!!n"));
  2715. }
  2716. return SCSI_ABORT_PENDING;
  2717. }
  2718. /*
  2719.  *  Add ourselves to (end of) taskQ .
  2720.  *  Check to see if our _bh is running.  If NOT, schedule it.
  2721.  */
  2722. spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
  2723. Q_ADD_TAIL(&hd->taskQ, &mf->u.frame.linkage, MPT_FRAME_HDR);
  2724. hd->taskQcnt++;
  2725. atomic_inc(&mpt_taskQdepth);
  2726. spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
  2727. spin_lock_irqsave(&mytaskQ_lock, flags);
  2728. /* Save the original SCpnt mf pointer
  2729.  */
  2730. SCpnt->host_scribble = (u8 *) MPT_INDEX_2_MFPTR (hd->ioc, scpnt_idx);
  2731. /* For the time being, force bus reset on any abort
  2732.  * requests for the 1030 FW.
  2733.  */
  2734. if (hd->is_spi)
  2735. mf->u.frame.linkage.arg1 = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS;
  2736. else
  2737. mf->u.frame.linkage.arg1 = MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK;
  2738. mf->u.frame.linkage.argp1 = SCpnt;
  2739. mf->u.frame.linkage.argp2 = (void *) hd;
  2740. dtmprintk((MYIOC_s_INFO_FMT "OldAbort:_bh_handler state (%d) taskQ count (%d)n",
  2741. hd->ioc->name, mytaskQ_bh_active, hd->taskQcnt));
  2742. if (! mytaskQ_bh_active) {
  2743. mytaskQ_bh_active = 1;
  2744. spin_unlock_irqrestore(&mytaskQ_lock, flags);
  2745. /*
  2746.  *  Oh how cute, no alloc/free/mgmt needed if we use
  2747.  *  (bottom/unused portion of) MPT request frame.
  2748.  */
  2749. ptaskfoo = (struct tq_struct *) &mptscsih_ptaskfoo;
  2750. ptaskfoo->sync = 0;
  2751. ptaskfoo->routine = mptscsih_taskmgmt_bh;
  2752. ptaskfoo->data = SCpnt;
  2753. SCHEDULE_TASK(ptaskfoo);
  2754. } else  {
  2755. spin_unlock_irqrestore(&mytaskQ_lock, flags);
  2756. }
  2757. return SCSI_ABORT_PENDING;
  2758. }
  2759. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  2760. /**
  2761.  * mptscsih_old_reset - Perform a SCSI BUS_RESET!
  2762.  * @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
  2763.  * @reset_flags: (not used?)
  2764.  *
  2765.  * (linux Scsi_Host_Template.reset routine)
  2766.  *
  2767.  * Returns SCSI_RESET_{SUCCESS,PUNT,PENDING}.
  2768.  */
  2769. int
  2770. mptscsih_old_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags)
  2771. {
  2772. MPT_SCSI_HOST *hd;
  2773. MPT_FRAME_HDR *mf;
  2774. struct tq_struct *ptaskfoo;
  2775. unsigned long  flags;
  2776. int  scpnt_idx;
  2777. printk(KERN_WARNING MYNAM ": OldReset scheduling BUS_RESET (sc=%p)n", (void *) SCpnt);
  2778. printk(KERN_WARNING "  IOs outstanding = %dn", atomic_read(&queue_depth));
  2779. if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL) {
  2780. SCpnt->result = DID_RESET << 16;
  2781. SCpnt->scsi_done(SCpnt);
  2782. return SCSI_RESET_SUCCESS;
  2783. }
  2784. if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
  2785. /* Cmd not found in ScsiLookup.
  2786.  * If found in doneQ, delete from Q.
  2787.  * Do OS callback.
  2788.  */
  2789. search_doneQ_for_cmd(hd, SCpnt);
  2790. SCpnt->result = DID_RESET << 16;
  2791. SCpnt->scsi_done(SCpnt);
  2792. return SCSI_RESET_SUCCESS;
  2793. } else {
  2794. /* If this command is pended, then timeout/hang occurred
  2795.  * during DV. Force bus reset by posting command to F/W
  2796.  * and then following up with the reset request.
  2797.  */
  2798. if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) {
  2799. mptscsih_put_msgframe(ScsiDoneCtx, hd->ioc->id, mf);
  2800. post_pendingQ_commands(hd);
  2801. }
  2802. }
  2803. /*
  2804.  *  Check to see if there's an ABORT_TASK queued for this guy.
  2805.  *  If so, delete.
  2806.  */
  2807. search_taskQ(1, SCpnt, hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK);
  2808. /*
  2809.  *  Check to see if there's already a BUS_RESET queued for this guy.
  2810.  */
  2811. mf = search_taskQ(0, SCpnt, hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS);
  2812. if (mf != NULL) {
  2813. dtmprintk((MYIOC_s_INFO_FMT "OldReset:Reset Task PENDING cmd (%p) taskQ depth (%d)n",
  2814. hd->ioc->name, SCpnt, hd->taskQcnt));
  2815. return SCSI_RESET_PENDING;
  2816. }
  2817. // SJR - CHECKME - Can we avoid this here?
  2818. // (mpt_HardResetHandler has this check...)
  2819. /* If IOC is reloading FW, return PENDING.
  2820.  */
  2821. spin_lock_irqsave(&hd->ioc->diagLock, flags);
  2822. if (hd->ioc->diagPending) {
  2823. spin_unlock_irqrestore(&hd->ioc->diagLock, flags);
  2824. return SCSI_RESET_PENDING;
  2825. }
  2826. spin_unlock_irqrestore(&hd->ioc->diagLock, flags);
  2827. if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc->id)) == NULL) {
  2828. /* We are out of message frames!
  2829.  * Call the reset handler to do a FW reload.
  2830.  */
  2831. printk((KERN_WARNING " Reloading Firmware!!n"));
  2832. if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
  2833. printk((KERN_WARNING " Firmware Reload FAILED!!n"));
  2834. }
  2835. return SCSI_RESET_PENDING;
  2836. }
  2837. /*
  2838.  *  Add ourselves to (end of) taskQ.
  2839.  *  Check to see if our _bh is running.  If NOT, schedule it.
  2840.  */
  2841. spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
  2842. Q_ADD_TAIL(&hd->taskQ, &mf->u.frame.linkage, MPT_FRAME_HDR);
  2843. hd->taskQcnt++;
  2844. atomic_inc(&mpt_taskQdepth);
  2845. spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
  2846. dtmprintk((MYIOC_s_INFO_FMT "OldReset: _bh_handler state (%d) taskQ count (%d)n",
  2847. hd->ioc->name, mytaskQ_bh_active, hd->taskQcnt));
  2848. spin_lock_irqsave(&mytaskQ_lock, flags);
  2849. /* Save the original SCpnt mf pointer
  2850.  */
  2851. SCpnt->host_scribble = (u8 *) MPT_INDEX_2_MFPTR (hd->ioc, scpnt_idx);
  2852. mf->u.frame.linkage.arg1 = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS;
  2853. mf->u.frame.linkage.argp1 = SCpnt;
  2854. mf->u.frame.linkage.argp2 = (void *) hd;
  2855. if (! mytaskQ_bh_active) {
  2856. mytaskQ_bh_active = 1;
  2857. spin_unlock_irqrestore(&mytaskQ_lock, flags);
  2858. /*
  2859.  *  Oh how cute, no alloc/free/mgmt needed if we use
  2860.  *  (bottom/unused portion of) MPT request frame.
  2861.  */
  2862. ptaskfoo = (struct tq_struct *) &mptscsih_ptaskfoo;
  2863. ptaskfoo->sync = 0;
  2864. ptaskfoo->routine = mptscsih_taskmgmt_bh;
  2865. ptaskfoo->data = SCpnt;
  2866. SCHEDULE_TASK(ptaskfoo);
  2867. } else  {
  2868. spin_unlock_irqrestore(&mytaskQ_lock, flags);
  2869. }
  2870. return SCSI_RESET_PENDING;
  2871. }
  2872. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  2873. /*
  2874.  * mptscsih_taskmgmt_bh - SCSI task mgmt bottom half handler
  2875.  * @sc: (unused)
  2876.  *
  2877.  * This routine (thread) is active whenever there are any outstanding
  2878.  * SCSI task management requests for a SCSI host adapter.
  2879.  * IMPORTANT!  This routine is scheduled therefore should never be
  2880.  * running in ISR context.  i.e., it's safe to sleep here.
  2881.  */
  2882. void
  2883. mptscsih_taskmgmt_bh(void *sc)
  2884. {
  2885. MPT_ADAPTER *ioc;
  2886. Scsi_Cmnd *SCpnt;
  2887. MPT_FRAME_HDR *mf = NULL;
  2888. MPT_SCSI_HOST *hd;
  2889. u32  ctx2abort = 0;
  2890. unsigned long  flags;
  2891. int  scpnt_idx;
  2892. int  did;
  2893. u8  task_type;
  2894. spin_lock_irqsave(&mytaskQ_lock, flags);
  2895. mytaskQ_bh_active = 1;
  2896. spin_unlock_irqrestore(&mytaskQ_lock, flags);
  2897. do {
  2898. set_current_state(TASK_INTERRUPTIBLE);
  2899. schedule_timeout(HZ/4);
  2900. did = 0;
  2901. for (ioc = mpt_adapter_find_first(); ioc != NULL; ioc = mpt_adapter_find_next(ioc)) {
  2902. if (ioc->sh) {
  2903. hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
  2904. if (hd == NULL) {
  2905. printk(KERN_ERR MYNAM
  2906. ": ERROR - TaskMgmt NULL SCSI Host!"
  2907. "(ioc=%p, sh=%p hd=%p)n",
  2908. (void *) ioc, (void *) ioc->sh, (void *) hd);
  2909. continue;
  2910. }
  2911. spin_lock_irqsave(&ioc->FreeQlock, flags);
  2912. if (Q_IS_EMPTY(&hd->taskQ)) {
  2913. spin_unlock_irqrestore(&ioc->FreeQlock, flags);
  2914. continue;
  2915. }
  2916. /* If we ever find a non-empty queue,
  2917.  * keep the handler alive
  2918.  */
  2919. did++;
  2920. /* tmPending is SMP lock-protected */
  2921. if (hd->tmPending || hd->tmPtr) {
  2922. spin_unlock_irqrestore(&ioc->FreeQlock, flags);
  2923. continue;
  2924. }
  2925. hd->tmPending = 1;
  2926. /* Process this request
  2927.  */
  2928.                                 mf = hd->taskQ.head;
  2929. Q_DEL_ITEM(&mf->u.frame.linkage);
  2930. hd->taskQcnt--;
  2931. atomic_dec(&mpt_taskQdepth);
  2932. spin_unlock_irqrestore(&ioc->FreeQlock, flags);
  2933. SCpnt = (Scsi_Cmnd*)mf->u.frame.linkage.argp1;
  2934. if (SCpnt == NULL) {
  2935. printk(KERN_ERR MYNAM ": ERROR - TaskMgmt has NULL SCpnt! (mf=%p:sc=%p)n",
  2936. (void *) mf, (void *) SCpnt);
  2937. mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
  2938. spin_lock_irqsave(&ioc->FreeQlock, flags);
  2939. hd->tmPending = 0;
  2940. spin_unlock_irqrestore(&ioc->FreeQlock, flags);
  2941. continue;
  2942. }
  2943. /* Get the ScsiLookup index pointer
  2944.  * from the SC pointer.
  2945.  */
  2946. if (!SCpnt->host_scribble || ((MPT_SCSI_HOST *)SCpnt->host->hostdata != hd)) {
  2947. /* The command associated with the
  2948.  * abort/reset request must have
  2949.  * completed and this is a stale
  2950.  * request. We are done.
  2951.  * Free the current MF and continue.
  2952.  */
  2953. mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
  2954. spin_lock_irqsave(&ioc->FreeQlock, flags);
  2955. hd->tmPending = 0;
  2956. spin_unlock_irqrestore(&ioc->FreeQlock, flags);
  2957. continue;
  2958. }
  2959. scpnt_idx = MFPTR_2_MPT_INDEX(hd->ioc, SCpnt->host_scribble);
  2960. if (scpnt_idx != SCPNT_TO_LOOKUP_IDX(SCpnt)) {
  2961. /* Error! this should never happen!!
  2962.  */
  2963. mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
  2964. spin_lock_irqsave(&ioc->FreeQlock, flags);
  2965. hd->tmPending = 0;
  2966. spin_unlock_irqrestore(&ioc->FreeQlock, flags);
  2967. continue;
  2968. }
  2969. task_type = mf->u.frame.linkage.arg1;
  2970. ctx2abort = 0;
  2971. if (task_type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
  2972. MPT_FRAME_HDR *SCpntMf;
  2973. /*
  2974.  * Most important!  Set TaskMsgContext to SCpnt's MsgContext!
  2975.  * (the IO to be ABORT'd)
  2976.  *
  2977.  * NOTE: Since we do not byteswap MsgContext, we do not
  2978.  *  swap it here either.  It is an opaque cookie to
  2979.  *  the controller, so it does not matter. -DaveM
  2980.  */
  2981. SCpntMf = (MPT_FRAME_HDR *) SCpnt->host_scribble;
  2982. ctx2abort = SCpntMf->u.frame.hwhdr.msgctxu.MsgContext;
  2983. hd->abortSCpnt = SCpnt;
  2984. printk(KERN_WARNING MYNAM ": Attempting ABORT SCSI IO! (mf=%p:sc=%p)n",
  2985. (void *) mf, (void *) SCpnt);
  2986. }
  2987. /* The TM handler will allocate a new mf,
  2988.  * so free the current mf.
  2989.  */
  2990. mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
  2991. mf = NULL;
  2992. if (mptscsih_TMHandler(hd, task_type, SCpnt->target, SCpnt->lun, ctx2abort, NO_SLEEP) < 0) {
  2993. /* The TM request failed and the subsequent FW-reload failed!
  2994.  * Fatal error case.
  2995.  */
  2996. printk(KERN_WARNING MYNAM
  2997. ": WARNING[1] - IOC error processing TaskMgmt request (sc=%p)n", (void *) SCpnt);
  2998. if (hd->ScsiLookup[scpnt_idx] != NULL) {
  2999. atomic_dec(&queue_depth);
  3000. SCpnt->result = DID_SOFT_ERROR << 16;
  3001.                                                 MPT_HOST_LOCK(flags);
  3002. SCpnt->scsi_done(SCpnt);
  3003.                                                 MPT_HOST_UNLOCK(flags);
  3004. mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
  3005. }
  3006. spin_lock_irqsave(&ioc->FreeQlock, flags);
  3007. hd->tmPending = 0;
  3008. spin_unlock_irqrestore(&ioc->FreeQlock, flags);
  3009. hd->abortSCpnt = NULL;
  3010. }
  3011. }
  3012. }
  3013. if (atomic_read(&mpt_taskQdepth) > 0)
  3014. did++;
  3015. } while ( did );
  3016. spin_lock_irqsave(&mytaskQ_lock, flags);
  3017. mytaskQ_bh_active = 0;
  3018. spin_unlock_irqrestore(&mytaskQ_lock, flags);
  3019. return;
  3020. }
  3021. #endif /* } */
  3022. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  3023. /**
  3024.  * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
  3025.  * @ioc: Pointer to MPT_ADAPTER structure
  3026.  * @mf: Pointer to SCSI task mgmt request frame
  3027.  * @mr: Pointer to SCSI task mgmt reply frame
  3028.  *
  3029.  * This routine is called from mptbase.c::mpt_interrupt() at the completion
  3030.  * of any SCSI task management request.
  3031.  * This routine is registered with the MPT (base) driver at driver
  3032.  * load/init time via the mpt_register() API call.
  3033.  *
  3034.  * Returns 1 indicating alloc'd request frame ptr should be freed.
  3035.  */
  3036. static int
  3037. mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
  3038. {
  3039. SCSITaskMgmtReply_t *pScsiTmReply;
  3040. SCSITaskMgmt_t *pScsiTmReq;
  3041. MPT_SCSI_HOST *hd = NULL;
  3042. unsigned long  flags;
  3043. u8  tmType = 0;
  3044. dtmprintk((MYIOC_s_INFO_FMT "SCSI TaskMgmt completed (mf=%p,r=%p)n",
  3045. ioc->name, mf, mr));
  3046. if (ioc->sh) {
  3047. /* Depending on the thread, a timer is activated for
  3048.  * the TM request.  Delete this timer on completion of TM.
  3049.  * Decrement count of outstanding TM requests.
  3050.  */
  3051. hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
  3052. if (hd->tmPtr) {
  3053. del_timer(&hd->TMtimer);
  3054. }
  3055. dtmprintk((MYIOC_s_INFO_FMT "taskQcnt (%d)n",
  3056. ioc->name, hd->taskQcnt));
  3057. } else {
  3058. dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptrn",
  3059. ioc->name));
  3060. return 1;
  3061. }
  3062. if (mr == NULL) {
  3063. dtmprintk((MYIOC_s_WARN_FMT "ERROR! TaskMgmt Reply: NULL Request %pn",
  3064. ioc->name, mf));
  3065. return 1;
  3066. } else {
  3067. pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
  3068. pScsiTmReq = (SCSITaskMgmt_t*)mf;
  3069. /* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */
  3070. tmType = pScsiTmReq->TaskType;
  3071. dtmprintk((KERN_INFO "  TaskType = %d, TerminationCount=%dn",
  3072. tmType, le32_to_cpu(pScsiTmReply->TerminationCount)));
  3073. /* Error?  (anything non-zero?) */
  3074. if (*(u32 *)&pScsiTmReply->Reserved2[0]) {
  3075. u16  iocstatus;
  3076. iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
  3077. dtmprintk((KERN_INFO "  SCSI TaskMgmt (%d) - Oops!n", tmType));
  3078. dtmprintk((KERN_INFO "  IOCStatus = %04xhn", iocstatus));
  3079. dtmprintk((KERN_INFO "  IOCLogInfo = %08xhn",
  3080.  le32_to_cpu(pScsiTmReply->IOCLogInfo)));
  3081. /* clear flags and continue.
  3082.  */
  3083. if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
  3084. hd->abortSCpnt = NULL;
  3085. #ifdef DROP_TEST
  3086. if (dropMfPtr)
  3087. dropTestBad++;
  3088. #endif
  3089. /* If an internal command is present
  3090.  * or the TM failed - reload the FW.
  3091.  * FC FW may respond FAILED to an ABORT
  3092.  */
  3093. if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
  3094. if ((hd->cmdPtr) ||
  3095.     (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED)) {
  3096. if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) {
  3097. printk((KERN_WARNING
  3098. " Firmware Reload FAILED!!n"));
  3099. }
  3100. }
  3101. }
  3102. #ifdef MPT_SCSI_USE_NEW_EH
  3103. hd->tmState = TM_STATE_ERROR;
  3104. #endif
  3105. } else {
  3106. dtmprintk((KERN_INFO "  SCSI TaskMgmt SUCCESS!n"));
  3107. #ifndef MPT_SCSI_USE_NEW_EH
  3108. if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
  3109. /* clean taskQ - remove tasks associated with
  3110.  * completed commands.
  3111.  */
  3112. clean_taskQ(hd);
  3113. } else if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
  3114. /* If taskQ contains another request
  3115.  * for this SCpnt, delete this request.
  3116.  */
  3117. search_taskQ_for_cmd(hd->abortSCpnt, hd);
  3118. }
  3119. #endif
  3120. hd->numTMrequests--;
  3121. hd->abortSCpnt = NULL;
  3122. flush_doneQ(hd);
  3123. #ifdef DROP_TEST
  3124. if (dropMfPtr)
  3125. dropTestOK++;
  3126. #endif
  3127. }
  3128. }
  3129. #ifdef DROP_TEST
  3130. mptscsih_flush_drop_test(hd);
  3131. #endif
  3132. #ifndef MPT_SCSI_USE_NEW_EH
  3133. /*
  3134.  *  Signal to _bh thread that we finished.
  3135.  *  This IOC can now process another TM command.
  3136.  */
  3137. dtmprintk((MYIOC_s_INFO_FMT "taskmgmt_complete: (=%p) done! Num Failed(%d) Task Count (%d)n",
  3138. ioc->name, mf, hd->numTMrequests, hd->taskQcnt));
  3139. #endif
  3140. hd->tmPtr = NULL;
  3141. spin_lock_irqsave(&ioc->FreeQlock, flags);
  3142. hd->tmPending = 0;
  3143. spin_unlock_irqrestore(&ioc->FreeQlock, flags);
  3144. return 1;
  3145. }
  3146. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  3147. /*
  3148.  * This is anyones guess quite frankly.
  3149.  */
  3150. int
  3151. mptscsih_bios_param(Disk * disk, kdev_t dev, int *ip)
  3152. {
  3153. int size;
  3154. size = disk->capacity;
  3155. ip[0] = 64; /* heads */
  3156. ip[1] = 32; /* sectors */
  3157. if ((ip[2] = size >> 11) > 1024) { /* cylinders, test for big disk */
  3158. ip[0] = 255; /* heads */
  3159. ip[1] = 63; /* sectors */
  3160. ip[2] = size / (255 * 63); /* cylinders */
  3161. }
  3162. return 0;
  3163. }
  3164. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  3165. /*
  3166.  * OS entry point to adjust the queue_depths on a per-device basis.
  3167.  * Called once per device the bus scan. Use it to force the queue_depth
  3168.  * member to 1 if a device does not support Q tags.
  3169.  */
  3170. void
  3171. mptscsih_select_queue_depths(struct Scsi_Host *sh, Scsi_Device *sdList)
  3172. {
  3173. struct scsi_device *device;
  3174. VirtDevice *pTarget;
  3175. MPT_SCSI_HOST *hd;
  3176. int  ii, max;
  3177. for (device = sdList; device != NULL; device = device->next) {
  3178. if (device->host != sh)
  3179. continue;
  3180. hd = (MPT_SCSI_HOST *) sh->hostdata;
  3181. if (hd == NULL)
  3182. continue;
  3183. if (hd->Targets != NULL) {
  3184. if (hd->is_spi)
  3185. max = MPT_MAX_SCSI_DEVICES;
  3186. else
  3187. max = MPT_MAX_FC_DEVICES;
  3188. for (ii=0; ii < max; ii++) {
  3189. pTarget = hd->Targets[ii];
  3190. if (pTarget && !(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)) {
  3191. device->queue_depth = 1;
  3192. }
  3193. }
  3194. }
  3195. }
  3196. }
  3197. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  3198. /*
  3199.  *  Private routines...
  3200.  */
  3201. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  3202. /* 19991030 -sralston
  3203.  *  Return absolute SCSI data direction:
  3204.  *     1 = _DATA_OUT
  3205.  *     0 = _DIR_NONE
  3206.  *    -1 = _DATA_IN
  3207.  *
  3208.  * Changed: 3-20-2002 pdelaney to use the default data
  3209.  * direction and the defines set up in the
  3210.  * 2.4 kernel series
  3211.  *     1 = _DATA_OUT changed to SCSI_DATA_WRITE (1)
  3212.  *     0 = _DIR_NONE changed to SCSI_DATA_NONE (3)
  3213.  *    -1 = _DATA_IN changed to SCSI_DATA_READ (2)
  3214.  * If the direction is unknown, fall through to original code.
  3215.  *
  3216.  * Mid-layer bug fix(): sg interface generates the wrong data 
  3217.  * direction in some cases. Set the direction the hard way for 
  3218.  * the most common commands.
  3219.  */
  3220. static int
  3221. mptscsih_io_direction(Scsi_Cmnd *cmd)
  3222. {
  3223. switch (cmd->cmnd[0]) {
  3224. case WRITE_6:
  3225. case WRITE_10:
  3226. return SCSI_DATA_WRITE;
  3227. break;
  3228. case READ_6:
  3229. case READ_10:
  3230. return SCSI_DATA_READ;
  3231. break;
  3232. }
  3233. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  3234. if (cmd->sc_data_direction != SCSI_DATA_UNKNOWN)
  3235. return cmd->sc_data_direction;
  3236. #endif
  3237. switch (cmd->cmnd[0]) {
  3238. /*  _DATA_OUT commands */
  3239. case WRITE_6: case WRITE_10: case WRITE_12:
  3240. case WRITE_LONG: case WRITE_SAME: case WRITE_BUFFER:
  3241. case WRITE_VERIFY: case WRITE_VERIFY_12:
  3242. case COMPARE: case COPY: case COPY_VERIFY:
  3243. case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW:
  3244. case SEARCH_EQUAL_12: case SEARCH_HIGH_12: case SEARCH_LOW_12:
  3245. case MODE_SELECT: case MODE_SELECT_10: case LOG_SELECT:
  3246. case SEND_DIAGNOSTIC: case CHANGE_DEFINITION: case UPDATE_BLOCK:
  3247. case SET_WINDOW: case MEDIUM_SCAN: case SEND_VOLUME_TAG:
  3248. case REASSIGN_BLOCKS:
  3249. case PERSISTENT_RESERVE_OUT:
  3250. case 0xea: