bk://linux-scsi.bkbits.net/scsi-misc-2.6 stern@rowland.harvard.edu[jejb]|ChangeSet|20050222092131|54112 stern # This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2005/03/01 18:42:59-08:00 akpm@bix.(none) # Merge bk://linux-scsi.bkbits.net/scsi-misc-2.6 # into bix.(none):/usr/src/bk-scsi # # drivers/scsi/scsi_transport_fc.c # 2005/03/01 18:42:55-08:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/scsi/scsi_devinfo.c # 2005/03/01 18:42:55-08:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/scsi/megaraid/megaraid_mm.c # 2005/03/01 18:42:55-08:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/scsi/Kconfig # 2005/03/01 18:42:55-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/02/22 10:21:31+01:00 stern@rowland.harvard.edu # [PATCH] Add a NOREPORTLUN blacklist flag # # This patch adds a NOREPORTLUN blacklist flag for a disk made by "WDC" # (Winchester?). The drive's firmware crashes when it receives REPORT_LUNS, # even though it claims to be SCSI rev 04. # # Signed-off-by: Alan Stern # Signed-off-by: James Bottomley # # drivers/scsi/scsi_devinfo.c # 2005/02/16 17:30:56+01:00 stern@rowland.harvard.edu +1 -0 # Add a NOREPORTLUN blacklist flag # # ChangeSet # 2005/02/22 10:18:48+01:00 stern@rowland.harvard.edu # [PATCH] Retry supposedly "unrecoverable" hardware errors # # This is an updated and unmangled version of the patch sent in by Martin # Peschke. Apparently some drives report Hardware Error sense for # problems which do improve after retrying, so the patch retries these # supposedly "unrecoverable" errors for such devices. # # In addition to the IBM ESS drive it adds a blacklist entry for the drive # inside the MPIO HS200 Gigabox. # # Signed-off-by: Martin Peschke # Signed-off-by: Alan Stern # Signed-off-by: James Bottomley # # include/scsi/scsi_devinfo.h # 2005/02/11 19:21:51+01:00 stern@rowland.harvard.edu +1 -0 # Retry supposedly "unrecoverable" hardware errors # # drivers/scsi/scsi_error.c # 2005/02/11 19:23:45+01:00 stern@rowland.harvard.edu +10 -1 # Retry supposedly "unrecoverable" hardware errors # # drivers/scsi/scsi_devinfo.c # 2005/02/11 19:25:41+01:00 stern@rowland.harvard.edu +2 -0 # Retry supposedly "unrecoverable" hardware errors # # ChangeSet # 2005/02/22 10:13:21+01:00 Kai.Makisara@kolumbus.fi # [PATCH] SCSI tape descriptor based sense data support # # The patch at the end of this message converts the SCSI tape driver to support # also descriptor based sense data. Test for deferred sense data have been added # in a couple of places and the EOM tests have been unified. Some tests have been # simplified but the patch is not meant to change the current behavior. The # patch is against 2.6.11-rc4 and has been tested to some extent. # # The patch also includes the msleep_interruptible change from from kernel # janitors. # # Thanks to Doug Gilbert for doing a first version of this sense data # conversion. # # Signed-off-by: Kai Makisara # Signed-off-by: James Bottomley # # drivers/scsi/st.h # 2005/02/13 09:40:21+01:00 Kai.Makisara@kolumbus.fi +18 -1 # SCSI tape descriptor based sense data support # # drivers/scsi/st.c # 2005/02/13 21:42:48+01:00 Kai.Makisara@kolumbus.fi +178 -141 # SCSI tape descriptor based sense data support # # ChangeSet # 2005/02/22 10:06:06+01:00 hch@lst.de # [PATCH] mark qlogicisp broken # # It's lacking EH support and the hardware is supported by the qla1280 # driver now. # # Signed-off-by: James Bottomley # # drivers/scsi/Kconfig # 2005/02/10 14:59:56+01:00 hch@lst.de +1 -1 # mark qlogicisp broken # # ChangeSet # 2005/02/22 10:03:39+01:00 hch@lst.de # [PATCH] mark eata_pio broken # # it oopses when trying to use it with my SmartRaid IV card, it's a mess # and the only hardware supported by it but not the eata driver are two # 10-year old ISA boards. # # Signed-off-by: James Bottomley # # drivers/scsi/Kconfig # 2005/02/10 14:59:56+01:00 hch@lst.de +1 -1 # mark eata_pio broken # # ChangeSet # 2005/02/22 10:01:04+01:00 hch@lst.de # [PATCH] qla1280: update changelog # # Signed-off-by: James Bottomley # # drivers/scsi/qla1280.c # 2005/02/10 13:42:44+01:00 hch@lst.de +3 -0 # qla1280: update changelog # # ChangeSet # 2005/02/22 09:57:38+01:00 hch@lst.de # [PATCH] qla1280: use pci_map_single # # Signed-off-by: James Bottomley # # drivers/scsi/qla1280.c # 2005/02/10 13:42:44+01:00 hch@lst.de +12 -20 # qla1280: use pci_map_single # # ChangeSet # 2005/02/22 09:54:33+01:00 hch@lst.de # [PATCH] qla1280: remove qla1280_proc_info # # reading the /proc/scsi/qla1280/* files can easily corrupt kernel memory. # # As the feature is deprecated, and the qla1280 implementation doesn't # return very usefull implementation but is so buggy that any serious # user would have noticed we just remove it. # # Signed-off-by: James Bottomley # # drivers/scsi/qla1280.c # 2005/02/10 13:42:44+01:00 hch@lst.de +0 -111 # qla1280: remove qla1280_proc_info # # ChangeSet # 2005/02/22 09:51:11+01:00 matthew@wil.cx # scsi: remove device_request_lock # # The static device_request_lock doesn't protect anything; remove it. # # Signed-off-by: Matthew Wilcox # Signed-off-by: James Bottomley # # drivers/scsi/scsi.c # 2005/02/06 20:57:07+01:00 matthew@wil.cx +2 -7 # scsi: remove device_request_lock # # ChangeSet # 2005/02/22 09:47:49+01:00 ak@suse.de # [PATCH] Fix selection of command serial numbers and pids # # This patch fixes one of Christroph's fixme comments in the SCSI midlayer. # # The selection of the serial number and pid for commands was done # by a global variable and not SMP safe. The race was not very # serious because it was only used for error handling, but it's # still better to fix it. # # I audited all the drivers and none seemed to use them # for anything interesting, so I just made it a per host counter # protected by host lock. # # (in fact they could be probably removed because they only see # to be used as a flag in exception handling and for debugging. # The patch would be unfortunately quite big because a lot # of driver printks use them) # # This should be slight faster on SMP too because the cache line of # the counter won't bounce around the machine. # # Signed-off-by: James Bottomley # # include/scsi/scsi_host.h # 2005/02/05 12:02:17+01:00 ak@suse.de +6 -1 # Fix selection of command serial numbers and pids # # include/scsi/scsi_cmnd.h # 2005/02/05 09:28:31+01:00 ak@suse.de +2 -1 # Fix selection of command serial numbers and pids # # drivers/scsi/scsi.c # 2005/02/05 12:02:50+01:00 ak@suse.de +21 -13 # Fix selection of command serial numbers and pids # # ChangeSet # 2005/02/04 09:12:34-06:00 bunk@stusta.de # [PATCH] SCSI sim710.c: make some code static # # This patch makes some needlessly global code static. # # Signed-off-by: Adrian Bunk # Signed-off-by: James Bottomley # # drivers/scsi/sim710.c # 2004/11/13 18:28:48-06:00 bunk@stusta.de +3 -3 # SCSI sim710.c: make some code static # # ChangeSet # 2005/02/03 22:08:04-06:00 jejb@mulgrave.(none) # SCSI: fix io statistics compile warnings # # Signed-off-by: James Bottomley # # drivers/scsi/scsi_sysfs.c # 2005/02/03 22:05:26-06:00 jejb@mulgrave.(none) +2 -2 # SCSI: fix io statistics compile warnings # # ChangeSet # 2005/02/03 21:37:56-06:00 jejb@mulgrave.(none) # SCSI: Add device io statistics # # From: James.Smart@Emulex.Com # # Adds io statistics (requests, completions, error count) as generic # attributes for scsi devices. # # Signed-off-by: James Bottomley # # include/scsi/scsi_device.h # 2005/02/03 21:35:03-06:00 jejb@mulgrave.(none) +4 -0 # SCSI: Add device io statistics # # drivers/scsi/scsi_sysfs.c # 2005/02/03 21:35:03-06:00 jejb@mulgrave.(none) +26 -0 # SCSI: Add device io statistics # # drivers/scsi/scsi.c # 2005/02/03 21:35:03-06:00 jejb@mulgrave.(none) +8 -0 # SCSI: Add device io statistics # # ChangeSet # 2005/02/03 21:29:59-06:00 hch@lst.de # [PATCH] drop some attibutes from the FC transport class # # I think the hardware_version, firmware_version, rom_version and # driver_version don't belong to the FC transport class, there's # nothing specific to FC or even SCSI specific in them. # # Signed-off-by: James Bottomley # # include/scsi/scsi_transport_fc.h # 2005/01/19 11:17:24-06:00 hch@lst.de +0 -4 # drop some attibutes from the FC transport class # # drivers/scsi/scsi_transport_fc.c # 2005/01/19 11:17:03-06:00 hch@lst.de +0 -16 # drop some attibutes from the FC transport class # # ChangeSet # 2005/02/03 20:51:38-06:00 jejb@mulgrave.(none) # SCSI: fix compat_ioctl compile warnings # # Signed-off-by: James Bottomley # # drivers/scsi/st.c # 2005/02/03 20:48:50-06:00 jejb@mulgrave.(none) +2 -2 # SCSI: fix compat_ioctl compile warnings # # drivers/scsi/osst.c # 2005/02/03 20:48:50-06:00 jejb@mulgrave.(none) +1 -1 # SCSI: fix compat_ioctl compile warnings # # drivers/scsi/aacraid/linit.c # 2005/02/03 20:48:49-06:00 jejb@mulgrave.(none) +2 -2 # SCSI: fix compat_ioctl compile warnings # # ChangeSet # 2005/02/03 20:01:17-06:00 jejb@mulgrave.(none) # mptfusion: delete watchdogs timers from mptctl and mptscsih # # From: Moore, Eric Dean # # 1) mptscsih.c: I have changed task management # requests so they complete in same thread before returning # to os. I removed the TMtimer code. # # (2) mptctl.c: I have deleted both TMtimer and timer code. Replaced # with wait_event_interruptible_timeout. So commands are now # completed in same thread. # # (3) mptctl_do_fw_download - nasty polling of global parameters # that are set in contents of interrupt handler(mptctl_reply), now using # wait_event_interruptible_timeout. # # (4) I have cleaned up mptctl_reply. # # Signed-off-by: Eric Moore # Signed-off-by: James Bottomley # # drivers/message/fusion/mptscsih.c # 2005/02/03 19:58:54-06:00 jejb@mulgrave.(none) +62 -123 # mptfusion: delete watchdogs timers from mptctl and mptscsih # # drivers/message/fusion/mptctl.c # 2005/02/03 19:58:54-06:00 jejb@mulgrave.(none) +199 -300 # mptfusion: delete watchdogs timers from mptctl and mptscsih # # drivers/message/fusion/mptbase.h # 2005/02/03 19:58:54-06:00 jejb@mulgrave.(none) +2 -8 # mptfusion: delete watchdogs timers from mptctl and mptscsih # # ChangeSet # 2005/02/03 19:49:11-06:00 ak@muc.de # [PATCH] Add compat_ioctl to mptctl # # Convert mptctl to compat_ioctl. I also changed it to unlocked_ioctl # while I was on it. # # Signed-off-by: Andi Kleen # Signed-off-by: James Bottomley # # drivers/message/fusion/mptctl.c # 2005/01/18 05:11:30-06:00 ak@muc.de +56 -81 # Add compat_ioctl to mptctl # # ChangeSet # 2005/02/03 19:38:47-06:00 ak@muc.de # [PATCH] Convert megaraid2 to compat_ioctl # # Convert megaraid2 driver to new compat_ioctl entry points. # # Signed-off-by: Andi Kleen # Signed-off-by: James Bottomley # # drivers/scsi/megaraid/megaraid_mm.c # 2005/01/17 23:28:34-06:00 ak@muc.de +14 -12 # Convert megaraid2 to compat_ioctl # # ChangeSet # 2005/02/03 19:27:13-06:00 ak@muc.de # [PATCH] Add compat_ioctl to SG # # Add compat_ioctl to SG driver # # Signed-off-by: Andi Kleen # Signed-off-by: James Bottomley # # drivers/scsi/sg.c # 2005/01/17 22:24:28-06:00 ak@muc.de +26 -0 # Add compat_ioctl to SG # # ChangeSet # 2005/02/03 19:17:33-06:00 ak@muc.de # [PATCH] Convert aacraid to compat_ioctl # # Convert aacraid driver to the compat_ioctl entry points. # # I don't have hardware, so this is only compile tested, but I just # did some transformations on the existing code. # # Signed-off-by: Andi Kleen # Signed-off-by: James Bottomley # # drivers/scsi/aacraid/linit.c # 2005/01/18 00:58:31-06:00 ak@muc.de +60 -50 # Convert aacraid to compat_ioctl # # ChangeSet # 2005/02/03 18:56:42-06:00 ak@muc.de # [PATCH] Add compat_ioctl to osst # # Add compat_ioctl to osst # # Signed-off-by: Andi Kleen # Signed-off-by: James Bottomley # # drivers/scsi/osst.c # 2005/01/17 22:14:59-06:00 ak@muc.de +19 -0 # Add compat_ioctl to osst # # ChangeSet # 2005/02/03 18:52:01-06:00 ak@muc.de # [PATCH] Add comment for compat_ioctl to SR # # Add comment that SR doesn't support compat_ioctl (because it doesn't # pass down any driver ioctls right now) # # Signed-off-by: Andi Kleen # Signed-off-by: James Bottomley # # drivers/scsi/sr.c # 2005/01/17 21:54:59-06:00 ak@muc.de +4 -0 # Add comment for compat_ioctl to SR # # ChangeSet # 2005/02/03 18:47:23-06:00 ak@muc.de # [PATCH] Add compat_ioctl to st # # Call new compat_ioctl host vector from tape driver # # Signed-off-by: Andi Kleen # Signed-off-by: James Bottomley # # drivers/scsi/st.c # 2005/01/17 21:50:09-06:00 ak@muc.de +19 -0 # Add compat_ioctl to st # # ChangeSet # 2005/02/03 18:33:31-06:00 ak@muc.de # [PATCH] Add compat_ioctl to SD # # Add compat_ioctl entry point to SD # # Signed-off-by: Andi Kleen # Signed-off-by: James Bottomley # # drivers/scsi/sd.c # 2005/01/17 21:55:17-06:00 ak@muc.de +39 -0 # Add compat_ioctl to SD # diff -Nru a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h --- a/drivers/message/fusion/mptbase.h 2005-03-03 21:48:52 -08:00 +++ b/drivers/message/fusion/mptbase.h 2005-03-03 21:48:52 -08:00 @@ -83,8 +83,8 @@ #define COPYRIGHT "Copyright (c) 1999-2004 " MODULEAUTHOR #endif -#define MPT_LINUX_VERSION_COMMON "3.01.18" -#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.01.18" +#define MPT_LINUX_VERSION_COMMON "3.01.19" +#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.01.19" #define WHAT_MAGIC_STRING "@" "(" "#" ")" #define show_mptmod_ver(s,ver) \ @@ -420,7 +420,6 @@ typedef struct _MPT_IOCTL { struct _MPT_ADAPTER *ioc; - struct timer_list timer; /* timer function for this adapter */ u8 ReplyFrame[MPT_DEFAULT_FRAME_SIZE]; /* reply frame data */ u8 sense[MPT_SENSE_BUFFER_ALLOC]; int wait_done; /* wake-up value for this ioc */ @@ -428,8 +427,6 @@ u8 status; /* current command status */ u8 reset; /* 1 if bus reset allowed */ u8 target; /* target for reset */ - void *tmPtr; - struct timer_list TMtimer; /* timer function for this adapter */ struct semaphore sem_ioc; } MPT_IOCTL; @@ -882,11 +879,9 @@ int port; u32 pad0; struct scsi_cmnd **ScsiLookup; - u32 qtag_tick; VirtDevice **Targets; MPT_LOCAL_REPLY *pLocal; /* used for internal commands */ struct timer_list timer; - struct timer_list TMtimer; /* Timer for TM commands ONLY */ /* Pool of memory for holding SCpnts before doing * OS callbacks. freeQ is the free pool. */ @@ -896,7 +891,6 @@ u8 pad1; u8 tmState; u8 rsvd[2]; - MPT_FRAME_HDR *tmPtr; /* Ptr to TM request*/ MPT_FRAME_HDR *cmdPtr; /* Ptr to nonOS request */ struct scsi_cmnd *abortSCpnt; MPT_LOCAL_REPLY localReply; /* internal cmd reply struct */ diff -Nru a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c --- a/drivers/message/fusion/mptctl.c 2005-03-03 21:48:52 -08:00 +++ b/drivers/message/fusion/mptctl.c 2005-03-03 21:48:52 -08:00 @@ -81,6 +81,7 @@ #include #include #include +#include /* for mdelay */ #include #include #include @@ -142,6 +143,9 @@ static int mptctl_probe(struct pci_dev *, const struct pci_device_id *); static void mptctl_remove(struct pci_dev *); +#ifdef CONFIG_COMPAT +static long compat_mpctl_ioctl(struct file *f, unsigned cmd, unsigned long arg); +#endif /* * Private function calls. */ @@ -151,7 +155,7 @@ struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc); static void kfree_sgl( MptSge_t *sgl, dma_addr_t sgl_dma, struct buflist *buflist, MPT_ADAPTER *ioc); -static void mptctl_timer_expired (unsigned long data); +static void mptctl_timeout_expired (MPT_IOCTL *ioctl); static int mptctl_bus_reset(MPT_IOCTL *ioctl); static int mptctl_set_tm_flags(MPT_SCSI_HOST *hd); static void mptctl_free_tm_flags(MPT_ADAPTER *ioc); @@ -184,9 +188,6 @@ #define MPT_IOCTL_DEFAULT_TIMEOUT 10 /* Default timeout value (seconds) */ -static u32 fwReplyBuffer[16]; -static pMPIDefaultReply_t ReplyMsg = NULL; - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mptctl_syscall_down - Down the MPT adapter syscall semaphore. @@ -204,11 +205,6 @@ int rc = 0; dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down(%p,%d) called\n", ioc, nonblock)); - if (ioc->ioctl->tmPtr != NULL) { - dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down BUSY\n")); - return -EBUSY; - } - if (nonblock) { if (down_trylock(&ioc->ioctl->sem_ioc)) rc = -EAGAIN; @@ -235,131 +231,101 @@ u16 iocStatus; u8 cmd; - dctlprintk((MYIOC_s_INFO_FMT ": mptctl_reply()!\n", ioc->name)); + dctlprintk(("mptctl_reply()!\n")); if (req) cmd = req->u.hdr.Function; else return 1; if (ioc->ioctl) { - /* If timer is not running, then an error occurred. - * A timeout will call the reset routine to reload the messaging - * queues. - * Main callback will free message and reply frames. - */ - if (reply && (cmd == MPI_FUNCTION_SCSI_TASK_MGMT) && - (ioc->ioctl->status & MPT_IOCTL_STATUS_TMTIMER_ACTIVE)) { - /* This is internally generated TM - */ - del_timer (&ioc->ioctl->TMtimer); - ioc->ioctl->status &= ~MPT_IOCTL_STATUS_TMTIMER_ACTIVE; - mptctl_free_tm_flags(ioc); + if (reply==NULL) { - /* If TM failed, reset the timer on the existing command, - * will trigger an adapter reset. - */ - iocStatus = reply->u.reply.IOCStatus & MPI_IOCSTATUS_MASK; - if (iocStatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED) { - if (ioc->ioctl->status & MPT_IOCTL_STATUS_TIMER_ACTIVE) { - ioc->ioctl->reset &= ~MPTCTL_RESET_OK; - del_timer (&ioc->ioctl->timer); - ioc->ioctl->timer.expires = jiffies + HZ; - add_timer(&ioc->ioctl->timer); - } - } - ioc->ioctl->tmPtr = NULL; + dctlprintk(("mptctl_reply() NULL Reply " + "Function=%x!\n", cmd)); - } else if (ioc->ioctl->status & MPT_IOCTL_STATUS_TIMER_ACTIVE) { - /* Delete this timer - */ - del_timer (&ioc->ioctl->timer); - ioc->ioctl->status &= ~MPT_IOCTL_STATUS_TIMER_ACTIVE; + ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD; + ioc->ioctl->reset &= ~MPTCTL_RESET_OK; - /* Set the overall status byte. Good if: - * IOC status is good OR if no reply and a SCSI IO request - */ - if (reply) { - /* Copy the reply frame (which much exist - * for non-SCSI I/O) to the IOC structure. - */ - dctlprintk((MYIOC_s_INFO_FMT ": Copying Reply Frame @%p to IOC!\n", - ioc->name, reply)); - memcpy(ioc->ioctl->ReplyFrame, reply, - min(ioc->reply_sz, 4*reply->u.reply.MsgLength)); - ioc->ioctl->status |= MPT_IOCTL_STATUS_RF_VALID; + /* We are done, issue wake up + */ + ioc->ioctl->wait_done = 1; + wake_up (&mptctl_wait); + return 1; - /* Set the command status to GOOD if IOC Status is GOOD - * OR if SCSI I/O cmd and data underrun or recovered error. - */ - iocStatus = reply->u.reply.IOCStatus & MPI_IOCSTATUS_MASK; - if (iocStatus == MPI_IOCSTATUS_SUCCESS) - ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD; - - if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) || - (cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) { - ioc->ioctl->reset &= ~MPTCTL_RESET_OK; - - if ((iocStatus == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN) || - (iocStatus == MPI_IOCSTATUS_SCSI_RECOVERED_ERROR)) { - ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD; - } - } + } - /* Copy the sense data - if present - */ - if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) && - (reply->u.sreply.SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID)){ + dctlprintk(("mptctl_reply() with req=%p " + "reply=%p Function=%x!\n", req, reply, cmd)); - sz = req->u.scsireq.SenseBufferLength; - req_index = le16_to_cpu(req->u.frame.hwhdr.msgctxu.fld.req_idx); - sense_data = ((u8 *)ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC)); - memcpy(ioc->ioctl->sense, sense_data, sz); - ioc->ioctl->status |= MPT_IOCTL_STATUS_SENSE_VALID; - } + /* Copy the reply frame (which much exist + * for non-SCSI I/O) to the IOC structure. + */ + dctlprintk(("Copying Reply Frame @%p to ioc%d!\n", + reply, ioc->id)); + memcpy(ioc->ioctl->ReplyFrame, reply, + min(ioc->reply_sz, 4*reply->u.reply.MsgLength)); + ioc->ioctl->status |= MPT_IOCTL_STATUS_RF_VALID; - if (cmd == MPI_FUNCTION_SCSI_TASK_MGMT) - mptctl_free_tm_flags(ioc); + /* Set the command status to GOOD if IOC Status is GOOD + * OR if SCSI I/O cmd and data underrun or recovered error. + */ + iocStatus = reply->u.reply.IOCStatus & MPI_IOCSTATUS_MASK; + if (iocStatus == MPI_IOCSTATUS_SUCCESS) + ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD; + if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) || + (cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) { + ioc->ioctl->reset &= ~MPTCTL_RESET_OK; - } else if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) || - (cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) { - ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD; - ioc->ioctl->reset &= ~MPTCTL_RESET_OK; + if ((iocStatus == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN) || + (iocStatus == MPI_IOCSTATUS_SCSI_RECOVERED_ERROR)) { + ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD; } + } - /* We are done, issue wake up - */ - ioc->ioctl->wait_done = 1; - wake_up (&mptctl_wait); - } else if (reply && cmd == MPI_FUNCTION_FW_DOWNLOAD) { - /* Two paths to FW DOWNLOAD! */ - // NOTE: Expects/requires non-Turbo reply! - dctlprintk((MYIOC_s_INFO_FMT ":Caching MPI_FUNCTION_FW_DOWNLOAD reply!\n", - ioc->name)); - memcpy(fwReplyBuffer, reply, min_t(int, sizeof(fwReplyBuffer), 4*reply->u.reply.MsgLength)); - ReplyMsg = (pMPIDefaultReply_t) fwReplyBuffer; + /* Copy the sense data - if present + */ + if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) && + (reply->u.sreply.SCSIState & + MPI_SCSI_STATE_AUTOSENSE_VALID)){ + sz = req->u.scsireq.SenseBufferLength; + req_index = + le16_to_cpu(req->u.frame.hwhdr.msgctxu.fld.req_idx); + sense_data = + ((u8 *)ioc->sense_buf_pool + + (req_index * MPT_SENSE_BUFFER_ALLOC)); + memcpy(ioc->ioctl->sense, sense_data, sz); + ioc->ioctl->status |= MPT_IOCTL_STATUS_SENSE_VALID; } + + if (cmd == MPI_FUNCTION_SCSI_TASK_MGMT) + mptctl_free_tm_flags(ioc); + + /* We are done, issue wake up + */ + ioc->ioctl->wait_done = 1; + wake_up (&mptctl_wait); } return 1; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mptctl_timer_expired +/* mptctl_timeout_expired * - * Call back for timer process. Used only for ioctl functionality. + * Expecting an interrupt, however timed out. * */ -static void mptctl_timer_expired (unsigned long data) +static void mptctl_timeout_expired (MPT_IOCTL *ioctl) { - MPT_IOCTL *ioctl = (MPT_IOCTL *) data; int rc = 1; - dctlprintk((KERN_NOTICE MYNAM ": Timer Expired! Host %d\n", + dctlprintk((KERN_NOTICE MYNAM ": Timeout Expired! Host %d\n", ioctl->ioc->id)); if (ioctl == NULL) return; + ioctl->wait_done = 0; if (ioctl->reset & MPTCTL_RESET_OK) rc = mptctl_bus_reset(ioctl); @@ -367,6 +333,8 @@ /* Issue a reset for this device. * The IOC is not responding. */ + dctlprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n", + ioctl->ioc->name)); mpt_HardResetHandler(ioctl->ioc, NO_SLEEP); } return; @@ -391,7 +359,7 @@ if (ioctl->ioc->sh == NULL) return -EPERM; - + hd = (MPT_SCSI_HOST *) ioctl->ioc->sh->hostdata; if (hd == NULL) return -EPERM; @@ -431,26 +399,34 @@ pScsiTm->Reserved2[ii] = 0; pScsiTm->TaskMsgContext = 0; - dtmprintk((MYIOC_s_INFO_FMT "mptctl_bus_reset: issued.\n", ioctl->ioc->name)); + dtmprintk((MYIOC_s_INFO_FMT + "mptctl_bus_reset: issued.\n", ioctl->ioc->name)); - ioctl->tmPtr = mf; - ioctl->TMtimer.expires = jiffies + HZ * 20; /* 20 seconds */ - ioctl->status |= MPT_IOCTL_STATUS_TMTIMER_ACTIVE; - add_timer(&ioctl->TMtimer); - - retval = mpt_send_handshake_request(mptctl_id, ioctl->ioc, - sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, NO_SLEEP); - - if (retval != 0) { - dtmprintk((MYIOC_s_WARN_FMT "_send_handshake FAILED!" - " (hd %p, ioc %p, mf %p) \n", ioctl->ioc->name, hd, hd->ioc, mf)); + DBG_DUMP_TM_REQUEST_FRAME((u32 *)mf); - mptctl_free_tm_flags(ioctl->ioc); - del_timer(&ioctl->TMtimer); - mpt_free_msg_frame(ioctl->ioc, mf); - ioctl->tmPtr = NULL; + ioctl->wait_done=0; + if ((retval = mpt_send_handshake_request(mptctl_id, ioctl->ioc, + sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP)) != 0) { + dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!" + " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, + hd->ioc, mf)); + goto mptctl_bus_reset_done; } + /* Now wait for the command to complete */ + ii = wait_event_interruptible_timeout(mptctl_wait, + ioctl->wait_done == 1, + HZ*5 /* 5 second timeout */); + + if(ii <=0 && (ioctl->wait_done != 1 )) { + ioctl->wait_done = 0; + retval = -1; /* return failure */ + } + +mptctl_bus_reset_done: + + mpt_free_msg_frame(hd->ioc, mf); + mptctl_free_tm_flags(ioctl->ioc); return retval; } @@ -491,7 +467,6 @@ return; } - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* mptctl_ioc_reset * @@ -504,43 +479,22 @@ { MPT_IOCTL *ioctl = ioc->ioctl; dctlprintk((KERN_INFO MYNAM ": IOC %s_reset routed to IOCTL driver!\n", - reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( - reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"))); - - if (reset_phase == MPT_IOC_SETUP_RESET){ - ; - } else if (reset_phase == MPT_IOC_PRE_RESET){ - - /* Someone has called the reset handler to - * do a hard reset. No more replies from the FW. - * Delete the timer. TM flags cleaned up by SCSI driver. - * Do not need to free msg frame, as re-initialized - */ - if (ioctl && (ioctl->status & MPT_IOCTL_STATUS_TIMER_ACTIVE)){ - del_timer(&ioctl->timer); - } - if (ioctl && (ioctl->status & MPT_IOCTL_STATUS_TMTIMER_ACTIVE)){ - ioctl->status &= ~MPT_IOCTL_STATUS_TMTIMER_ACTIVE; - del_timer(&ioctl->TMtimer); - mpt_free_msg_frame(ioc, ioctl->tmPtr); - } - - } else { - ioctl->tmPtr = NULL; + reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( + reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"))); - /* Set the status and continue IOCTL - * processing. All memory will be free'd - * by originating thread after wake_up is - * called. - */ - if (ioctl && (ioctl->status & MPT_IOCTL_STATUS_TIMER_ACTIVE)){ - ioctl->status |= MPT_IOCTL_STATUS_DID_IOCRESET; + if(ioctl == NULL) + return 1; - /* Wake up the calling process - */ - ioctl->wait_done = 1; - wake_up(&mptctl_wait); - } + switch(reset_phase) { + case MPT_IOC_SETUP_RESET: + ioctl->status |= MPT_IOCTL_STATUS_DID_IOCRESET; + break; + case MPT_IOC_POST_RESET: + ioctl->status &= ~MPT_IOCTL_STATUS_DID_IOCRESET; + break; + case MPT_IOC_PRE_RESET: + default: + break; } return 1; @@ -552,8 +506,8 @@ * cmd - specify the particular IOCTL command to be issued * arg - data specific to the command. Must not be null. */ -static int -mptctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +static long +__mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { mpt_ioctl_header __user *uhdr = (void __user *) arg; mpt_ioctl_header khdr; @@ -637,6 +591,16 @@ return ret; } +static long +mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + long ret; + lock_kernel(); + ret = __mptctl_ioctl(file, cmd, arg); + unlock_kernel(); + return ret; +} + static int mptctl_do_reset(unsigned long arg) { struct mpt_ioctl_diag_reset __user *urinfo = (void __user *) arg; @@ -735,9 +699,9 @@ u32 nib; int fw_bytes_copied = 0; int i; - int cntdn; int sge_offset = 0; u16 iocstat; + pFWDownloadReply_t ReplyMsg = NULL; dctlprintk((KERN_INFO "mptctl_do_fwdl called. mptctl_id = %xh.\n", mptctl_id)); @@ -868,31 +832,25 @@ /* * Finally, perform firmware download. */ - ReplyMsg = NULL; + iocp->ioctl->wait_done = 0; mpt_put_msg_frame(mptctl_id, iocp, mf); - /* - * Wait until the reply has been received - */ - for (cntdn=HZ*60, i=1; ReplyMsg == NULL; cntdn--, i++) { - if (!cntdn) { - ret = -ETIME; - goto fwdl_out; - } - - if (!(i%HZ)) { - dctlprintk((KERN_INFO "DbG::_do_fwdl: " - "In ReplyMsg loop - iteration %d\n", - i)); - } - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); + /* Now wait for the command to complete */ + ret = wait_event_interruptible_timeout(mptctl_wait, + iocp->ioctl->wait_done == 1, + HZ*60); + + if(ret <=0 && (iocp->ioctl->wait_done != 1 )) { + /* Now we need to reset the board */ + mptctl_timeout_expired(iocp->ioctl); + ret = -ENODATA; + goto fwdl_out; } if (sgl) kfree_sgl(sgl, sgl_dma, buflist, iocp); + ReplyMsg = (pFWDownloadReply_t)iocp->ioctl->ReplyFrame; iocstat = le16_to_cpu(ReplyMsg->IOCStatus) & MPI_IOCSTATUS_MASK; if (iocstat == MPI_IOCSTATUS_SUCCESS) { printk(KERN_INFO MYNAM ": F/W update successfully sent to %s!\n", iocp->name); @@ -1180,14 +1138,14 @@ cim_rev = 0; /* obsolete */ else return -EFAULT; - + karg = kmalloc(data_size, GFP_KERNEL); if (karg == NULL) { printk(KERN_ERR "%s::mpt_ioctl_iocinfo() @%d - no memory available!\n", __FILE__, __LINE__); return -ENOMEM; } - + if (copy_from_user(karg, uarg, data_size)) { printk(KERN_ERR "%s@%d::mptctl_getiocinfo - " "Unable to read in mpt_ioctl_iocinfo struct @ %p\n", @@ -1812,8 +1770,8 @@ int iocnum, flagsLength; int sz, rc = 0; int msgContext; - int tm_flags_set = 0; u16 req_idx; + ulong timeout; dctlprintk(("mptctl_do_mpt_command called.\n")); bufIn.kptr = bufOut.kptr = NULL; @@ -2029,7 +1987,6 @@ rc = -EPERM; goto done_free_mem; } - tm_flags_set = 1; } break; @@ -2181,136 +2138,108 @@ mpt_add_sge(psge, flagsLength, (dma_addr_t) -1); } - /* The request is complete. Set the timer parameters - * and issue the request. - */ - if (karg.timeout > 0) { - ioc->ioctl->timer.expires = jiffies + HZ*karg.timeout; - } else { - ioc->ioctl->timer.expires = jiffies + HZ*MPT_IOCTL_DEFAULT_TIMEOUT; - } - ioc->ioctl->wait_done = 0; - ioc->ioctl->status |= MPT_IOCTL_STATUS_TIMER_ACTIVE; - add_timer(&ioc->ioctl->timer); - if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT) { + DBG_DUMP_TM_REQUEST_FRAME((u32 *)mf); - rc = mpt_send_handshake_request(mptctl_id, ioc, - sizeof(SCSITaskMgmt_t), (u32*)mf, CAN_SLEEP); - if (rc == 0) { - wait_event(mptctl_wait, ioc->ioctl->wait_done); - } else { + + if (mpt_send_handshake_request(mptctl_id, ioc, + sizeof(SCSITaskMgmt_t), (u32*)mf, + CAN_SLEEP) != 0) { + dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!" + " (ioc %p, mf %p) \n", ioc->name, + ioc, mf)); mptctl_free_tm_flags(ioc); - tm_flags_set= 0; - del_timer(&ioc->ioctl->timer); - ioc->ioctl->status &= ~MPT_IOCTL_STATUS_TIMER_ACTIVE; - ioc->ioctl->status |= MPT_IOCTL_STATUS_TM_FAILED; - mpt_free_msg_frame(ioc, mf); + rc = -ENODATA; + goto done_free_mem; } - } else { + + } else mpt_put_msg_frame(mptctl_id, ioc, mf); - wait_event(mptctl_wait, ioc->ioctl->wait_done); + + /* Now wait for the command to complete */ + timeout = (karg.timeout > 0) ? karg.timeout : MPT_IOCTL_DEFAULT_TIMEOUT; + timeout = wait_event_interruptible_timeout(mptctl_wait, + ioc->ioctl->wait_done == 1, + HZ*timeout); + + if(timeout <=0 && (ioc->ioctl->wait_done != 1 )) { + /* Now we need to reset the board */ + + if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT) + mptctl_free_tm_flags(ioc); + + mptctl_timeout_expired(ioc->ioctl); + rc = -ENODATA; + goto done_free_mem; } mf = NULL; - /* MF Cleanup: - * If command failed and failure triggered a diagnostic reset - * OR a diagnostic reset happens during command processing, - * no data, messaging queues are reset (mf cannot be accessed), - * and status is DID_IOCRESET - * - * If a user-requested bus reset fails to be handshaked, then - * mf is returned to free queue and status is TM_FAILED. - * - * Otherise, the command completed and the mf was freed - # by ISR (mf cannot be touched). + /* If a valid reply frame, copy to the user. + * Offset 2: reply length in U32's */ - if (ioc->ioctl->status & MPT_IOCTL_STATUS_DID_IOCRESET) { - /* The timer callback deleted the - * timer and reset the adapter queues. - */ - printk(KERN_WARNING "%s@%d::mptctl_do_mpt_command - " - "Timeout Occurred on IOCTL! Reset IOC.\n", __FILE__, __LINE__); - tm_flags_set= 0; - rc = -ETIME; - } else if (ioc->ioctl->status & MPT_IOCTL_STATUS_TM_FAILED) { - /* User TM request failed! mf has not been freed. - */ - rc = -ENODATA; - } else { - /* If a valid reply frame, copy to the user. - * Offset 2: reply length in U32's - */ - if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) { - if (karg.maxReplyBytes < ioc->reply_sz) { - sz = min(karg.maxReplyBytes, 4*ioc->ioctl->ReplyFrame[2]); - } else { - sz = min(ioc->reply_sz, 4*ioc->ioctl->ReplyFrame[2]); - } - - if (sz > 0) { - if (copy_to_user(karg.replyFrameBufPtr, - &ioc->ioctl->ReplyFrame, sz)){ - - printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " - "Unable to write out reply frame %p\n", - __FILE__, __LINE__, karg.replyFrameBufPtr); - rc = -ENODATA; - goto done_free_mem; - } - } + if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) { + if (karg.maxReplyBytes < ioc->reply_sz) { + sz = min(karg.maxReplyBytes, 4*ioc->ioctl->ReplyFrame[2]); + } else { + sz = min(ioc->reply_sz, 4*ioc->ioctl->ReplyFrame[2]); } - /* If valid sense data, copy to user. - */ - if (ioc->ioctl->status & MPT_IOCTL_STATUS_SENSE_VALID) { - sz = min(karg.maxSenseBytes, MPT_SENSE_BUFFER_SIZE); - if (sz > 0) { - if (copy_to_user(karg.senseDataPtr, ioc->ioctl->sense, sz)) { - printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " - "Unable to write sense data to user %p\n", - __FILE__, __LINE__, - karg.senseDataPtr); - rc = -ENODATA; - goto done_free_mem; - } + if (sz > 0) { + if (copy_to_user(karg.replyFrameBufPtr, + &ioc->ioctl->ReplyFrame, sz)){ + printk(KERN_ERR + "%s@%d::mptctl_do_mpt_command - " + "Unable to write out reply frame %p\n", + __FILE__, __LINE__, karg.replyFrameBufPtr); + rc = -ENODATA; + goto done_free_mem; } } + } - /* If the overall status is _GOOD and data in, copy data - * to user. - */ - if ((ioc->ioctl->status & MPT_IOCTL_STATUS_COMMAND_GOOD) && - (karg.dataInSize > 0) && (bufIn.kptr)) { - - if (copy_to_user(karg.dataInBufPtr, - bufIn.kptr, karg.dataInSize)) { + /* If valid sense data, copy to user. + */ + if (ioc->ioctl->status & MPT_IOCTL_STATUS_SENSE_VALID) { + sz = min(karg.maxSenseBytes, MPT_SENSE_BUFFER_SIZE); + if (sz > 0) { + if (copy_to_user(karg.senseDataPtr, ioc->ioctl->sense, sz)) { printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " - "Unable to write data to user %p\n", - __FILE__, __LINE__, - karg.dataInBufPtr); + "Unable to write sense data to user %p\n", + __FILE__, __LINE__, + karg.senseDataPtr); rc = -ENODATA; + goto done_free_mem; } } } + /* If the overall status is _GOOD and data in, copy data + * to user. + */ + if ((ioc->ioctl->status & MPT_IOCTL_STATUS_COMMAND_GOOD) && + (karg.dataInSize > 0) && (bufIn.kptr)) { + + if (copy_to_user(karg.dataInBufPtr, + bufIn.kptr, karg.dataInSize)) { + printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + "Unable to write data to user %p\n", + __FILE__, __LINE__, + karg.dataInBufPtr); + rc = -ENODATA; + } + } + done_free_mem: - /* Clear all status bits except TMTIMER_ACTIVE, this bit is cleared - * upon completion of the TM command. - * ioc->ioctl->status = 0; - */ - ioc->ioctl->status &= ~(MPT_IOCTL_STATUS_TIMER_ACTIVE | MPT_IOCTL_STATUS_TM_FAILED | - MPT_IOCTL_STATUS_COMMAND_GOOD | MPT_IOCTL_STATUS_SENSE_VALID | - MPT_IOCTL_STATUS_RF_VALID | MPT_IOCTL_STATUS_DID_IOCRESET); - if (tm_flags_set) - mptctl_free_tm_flags(ioc); + ioc->ioctl->status &= ~(MPT_IOCTL_STATUS_COMMAND_GOOD | + MPT_IOCTL_STATUS_SENSE_VALID | + MPT_IOCTL_STATUS_RF_VALID ); /* Free the allocated memory. */ - if (bufOut.kptr != NULL) { + if (bufOut.kptr != NULL) { pci_free_consistent(ioc->pcidev, bufOut.len, (void *) bufOut.kptr, dma_addr_out); } @@ -2549,7 +2478,7 @@ __FILE__, __LINE__, uarg); return -EFAULT; } - + if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { dctlprintk((KERN_ERR "%s::mptctl_hp_targetinfo() @%d - ioc%d not found!\n", @@ -2567,7 +2496,7 @@ if (ioc->sh->host_no != karg.hdr.host) return -ENODEV; - + /* Get the data transfer speeds */ data_sz = ioc->spi_data.sdp0length * 4; @@ -2669,7 +2598,10 @@ static struct file_operations mptctl_fops = { .owner = THIS_MODULE, .llseek = no_llseek, - .ioctl = mptctl_ioctl, + .unlocked_ioctl = mptctl_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = compat_mpctl_ioctl, +#endif }; static struct miscdevice mptctl_miscdev = { @@ -2684,29 +2616,9 @@ #include -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* compat_XXX functions are used to provide a conversion between - * pointers and u32's. If the arg does not contain any pointers, then - * a specialized function (compat_XXX) is not needed. If the arg - * does contain pointer(s), then the specialized function is used - * to ensure the structure contents is properly processed by mptctl. - */ static int -compat_mptctl_ioctl(unsigned int fd, unsigned int cmd, - unsigned long arg, struct file *filp) -{ - int ret; - - lock_kernel(); - dctlprintk((KERN_INFO MYNAM "::compat_mptctl_ioctl() called\n")); - ret = mptctl_ioctl(filp->f_dentry->d_inode, filp, cmd, arg); - unlock_kernel(); - return ret; -} - -static int -compat_mptfwxfer_ioctl(unsigned int fd, unsigned int cmd, - unsigned long arg, struct file *filp) +compat_mptfwxfer_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg) { struct mpt_fw_xfer32 kfw32; struct mpt_fw_xfer kfw; @@ -2744,8 +2656,8 @@ } static int -compat_mpt_command(unsigned int fd, unsigned int cmd, - unsigned long arg, struct file *filp) +compat_mpt_command(struct file *filp, unsigned int cmd, + unsigned long arg) { struct mpt_ioctl_command32 karg32; struct mpt_ioctl_command32 __user *uarg = (struct mpt_ioctl_command32 __user *) arg; @@ -2797,6 +2709,38 @@ return ret; } +static long compat_mpctl_ioctl(struct file *f, unsigned int cmd, unsigned long arg) +{ + long ret; + lock_kernel(); + switch (cmd) { + case MPTIOCINFO: + case MPTIOCINFO1: + case MPTIOCINFO2: + case MPTTARGETINFO: + case MPTEVENTQUERY: + case MPTEVENTENABLE: + case MPTEVENTREPORT: + case MPTHARDRESET: + case HP_GETHOSTINFO: + case HP_GETTARGETINFO: + case MPTTEST: + ret = __mptctl_ioctl(f, cmd, arg); + break; + case MPTCOMMAND32: + ret = compat_mpt_command(f, cmd, arg); + break; + case MPTFWDOWNLOAD32: + ret = compat_mptfwxfer_ioctl(f, cmd, arg); + break; + default: + ret = -ENOIOCTLCMD; + break; + } + unlock_kernel(); + return ret; +} + #endif @@ -2830,12 +2774,6 @@ memset(mem, 0, sz); ioc->ioctl = (MPT_IOCTL *) mem; ioc->ioctl->ioc = ioc; - init_timer (&ioc->ioctl->timer); - ioc->ioctl->timer.data = (unsigned long) ioc->ioctl; - ioc->ioctl->timer.function = mptctl_timer_expired; - init_timer (&ioc->ioctl->TMtimer); - ioc->ioctl->TMtimer.data = (unsigned long) ioc->ioctl; - ioc->ioctl->TMtimer.function = mptctl_timer_expired; sema_init(&ioc->ioctl->sem_ioc, 1); return 0; @@ -2879,36 +2817,6 @@ ": failed to register dd callbacks\n")); } -#ifdef CONFIG_COMPAT - err = register_ioctl32_conversion(MPTIOCINFO, compat_mptctl_ioctl); - if (++where && err) goto out_fail; - err = register_ioctl32_conversion(MPTIOCINFO1, compat_mptctl_ioctl); - if (++where && err) goto out_fail; - err = register_ioctl32_conversion(MPTIOCINFO2, compat_mptctl_ioctl); - if (++where && err) goto out_fail; - err = register_ioctl32_conversion(MPTTARGETINFO, compat_mptctl_ioctl); - if (++where && err) goto out_fail; - err = register_ioctl32_conversion(MPTTEST, compat_mptctl_ioctl); - if (++where && err) goto out_fail; - err = register_ioctl32_conversion(MPTEVENTQUERY, compat_mptctl_ioctl); - if (++where && err) goto out_fail; - err = register_ioctl32_conversion(MPTEVENTENABLE, compat_mptctl_ioctl); - if (++where && err) goto out_fail; - err = register_ioctl32_conversion(MPTEVENTREPORT, compat_mptctl_ioctl); - if (++where && err) goto out_fail; - err = register_ioctl32_conversion(MPTHARDRESET, compat_mptctl_ioctl); - if (++where && err) goto out_fail; - err = register_ioctl32_conversion(MPTCOMMAND32, compat_mpt_command); - if (++where && err) goto out_fail; - err = register_ioctl32_conversion(MPTFWDOWNLOAD32, - compat_mptfwxfer_ioctl); - if (++where && err) goto out_fail; - err = register_ioctl32_conversion(HP_GETHOSTINFO, compat_mptctl_ioctl); - if (++where && err) goto out_fail; - err = register_ioctl32_conversion(HP_GETTARGETINFO, compat_mptctl_ioctl); - if (++where && err) goto out_fail; -#endif - /* Register this device */ err = misc_register(&mptctl_miscdev); if (err < 0) { @@ -2940,24 +2848,6 @@ out_fail: -#ifdef CONFIG_COMPAT - printk(KERN_ERR MYNAM ": ERROR: Failed to register ioctl32_conversion!" - " (%d:err=%d)\n", where, err); - unregister_ioctl32_conversion(MPTIOCINFO); - unregister_ioctl32_conversion(MPTIOCINFO1); - unregister_ioctl32_conversion(MPTIOCINFO2); - unregister_ioctl32_conversion(MPTTARGETINFO); - unregister_ioctl32_conversion(MPTTEST); - unregister_ioctl32_conversion(MPTEVENTQUERY); - unregister_ioctl32_conversion(MPTEVENTENABLE); - unregister_ioctl32_conversion(MPTEVENTREPORT); - unregister_ioctl32_conversion(MPTHARDRESET); - unregister_ioctl32_conversion(MPTCOMMAND32); - unregister_ioctl32_conversion(MPTFWDOWNLOAD32); - unregister_ioctl32_conversion(HP_GETHOSTINFO); - unregister_ioctl32_conversion(HP_GETTARGETINFO); -#endif - mpt_device_driver_deregister(MPTCTL_DRIVER); return err; @@ -2979,22 +2869,6 @@ printk(KERN_INFO MYNAM ": Deregistered from Fusion MPT base driver\n"); mpt_device_driver_deregister(MPTCTL_DRIVER); - -#ifdef CONFIG_COMPAT - unregister_ioctl32_conversion(MPTIOCINFO); - unregister_ioctl32_conversion(MPTIOCINFO1); - unregister_ioctl32_conversion(MPTIOCINFO2); - unregister_ioctl32_conversion(MPTTARGETINFO); - unregister_ioctl32_conversion(MPTTEST); - unregister_ioctl32_conversion(MPTEVENTQUERY); - unregister_ioctl32_conversion(MPTEVENTENABLE); - unregister_ioctl32_conversion(MPTEVENTREPORT); - unregister_ioctl32_conversion(MPTHARDRESET); - unregister_ioctl32_conversion(MPTCOMMAND32); - unregister_ioctl32_conversion(MPTFWDOWNLOAD32); - unregister_ioctl32_conversion(HP_GETHOSTINFO); - unregister_ioctl32_conversion(HP_GETTARGETINFO); -#endif } diff -Nru a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c --- a/drivers/message/fusion/mptscsih.c 2005-03-03 21:48:52 -08:00 +++ b/drivers/message/fusion/mptscsih.c 2005-03-03 21:48:52 -08:00 @@ -179,10 +179,11 @@ static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx); static void copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply); static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd); +static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout ); static u32 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc); -static int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag); -static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag); +static int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); +static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); static int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); static int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); @@ -196,13 +197,9 @@ static int mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus); static int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); static void mptscsih_timer_expired(unsigned long data); -static void mptscsih_taskmgmt_timeout(unsigned long data); -static void mptscsih_schedule_reset(void *hd); static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd); static int mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum); -static struct work_struct mptscsih_rstTask; - #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION static int mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io); static void mptscsih_domainValidation(void *hd); @@ -1207,7 +1204,6 @@ hd->tmState = TM_STATE_NONE; hd->resetPending = 0; hd->abortSCpnt = NULL; - hd->tmPtr = NULL; /* Clear the pointer used to store * single-threaded commands, i.e., those @@ -1224,14 +1220,6 @@ hd->timer.data = (unsigned long) hd; hd->timer.function = mptscsih_timer_expired; - init_timer(&hd->TMtimer); - hd->TMtimer.data = (unsigned long) hd; - hd->TMtimer.function = mptscsih_taskmgmt_timeout; - hd->qtag_tick = jiffies; - - /* Moved Earlier Pam D */ - /* ioc->sh = sh; */ - if (ioc->bus_type == SCSI) { /* Update with the driver setup * values. @@ -1925,7 +1913,6 @@ * @target: Logical Target ID for reset (if appropriate) * @lun: Logical Unit for reset (if appropriate) * @ctx2abort: Context for the task to be aborted (if appropriate) - * @sleepFlag: If set, use udelay instead of schedule in handshake code. * * Remark: Currently invoked from a non-interrupt thread (_bh). * @@ -1935,7 +1922,7 @@ * Returns 0 for SUCCESS or -1 if FAILED. */ static int -mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag) +mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout) { MPT_ADAPTER *ioc; int rc = -1; @@ -2015,7 +2002,7 @@ */ if (hd->hard_resets < -1) hd->hard_resets++; - rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, timeout, sleepFlag); + rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, timeout); if (rc) { printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name); } else { @@ -2029,7 +2016,7 @@ ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) { dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n", hd->ioc->name)); - rc = mpt_HardResetHandler(hd->ioc, sleepFlag); + rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP); } dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc)); @@ -2046,7 +2033,6 @@ * @target: Logical Target ID for reset (if appropriate) * @lun: Logical Unit for reset (if appropriate) * @ctx2abort: Context for the task to be aborted (if appropriate) - * @sleepFlag: If set, use udelay instead of schedule in handshake code. * * Remark: _HardResetHandler can be invoked from an interrupt thread (timer) * or a non-interrupt thread. In the former, must not call schedule(). @@ -2057,7 +2043,7 @@ * else other non-zero value returned. */ static int -mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag) +mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout) { MPT_FRAME_HDR *mf; SCSITaskMgmt_t *pScsiTm; @@ -2087,7 +2073,7 @@ pScsiTm->TaskType = type; pScsiTm->Reserved1 = 0; pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) - ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0; + ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0; for (ii= 0; ii < 8; ii++) { pScsiTm->LUN[ii] = 0; @@ -2099,29 +2085,32 @@ pScsiTm->TaskMsgContext = ctx2abort; - /* MPI v0.10 requires SCSITaskMgmt requests be sent via Doorbell/handshake - mpt_put_msg_frame(hd->ioc->id, mf); - * Save the MF pointer in case the request times out. - */ - hd->tmPtr = mf; - hd->TMtimer.expires = jiffies + timeout; - add_timer(&hd->TMtimer); - - dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n", - hd->ioc->name, ctx2abort, type)); + dtmprintk((MYIOC_s_INFO_FMT + "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n", + hd->ioc->name, ctx2abort, type)); DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm); if ((retval = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc, - sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, sleepFlag)) - != 0) { + sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, + CAN_SLEEP)) != 0) { dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!" - " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, hd->ioc, mf)); - hd->tmPtr = NULL; - del_timer(&hd->TMtimer); + " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, + hd->ioc, mf)); mpt_free_msg_frame(hd->ioc, mf); + return retval; } - + + if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) { + dfailprintk((MYIOC_s_ERR_FMT "_wait_for_completion FAILED!" + " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, + hd->ioc, mf)); + mpt_free_msg_frame(hd->ioc, mf); + dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n", + hd->ioc->name)); + retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP); + } + return retval; } @@ -2187,13 +2176,13 @@ */ mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx); ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext; - + hd->abortSCpnt = SCpnt; spin_unlock_irq(host_lock); if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, SCpnt->device->channel, SCpnt->device->id, SCpnt->device->lun, - ctx2abort, (HZ*2) /* 2 second timeout */,CAN_SLEEP) + ctx2abort, 2 /* 2 second timeout */) < 0) { /* The TM request failed and the subsequent FW-reload failed! @@ -2206,7 +2195,7 @@ */ hd->tmPending = 0; hd->tmState = TM_STATE_NONE; - + spin_lock_irq(host_lock); /* Unmap the DMA buffers, if any. */ @@ -2226,7 +2215,6 @@ } spin_lock_irq(host_lock); return SUCCESS; - } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -2259,15 +2247,10 @@ printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p)\n", hd->ioc->name, SCpnt); - /* Supported for FC only. - */ - if (hd->ioc->bus_type == SCSI) - return FAILED; - spin_unlock_irq(host_lock); if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, SCpnt->device->channel, SCpnt->device->id, - 0, 0, (HZ*5) /* 5 second timeout */, CAN_SLEEP) + 0, 0, 5 /* 5 second timeout */) < 0){ /* The TM request failed and the subsequent FW-reload failed! * Fatal error case. @@ -2317,7 +2300,7 @@ /* We are now ready to execute the task management request. */ spin_unlock_irq(host_lock); if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, - SCpnt->device->channel, 0, 0, 0, (HZ*5) /* 5 second timeout */, CAN_SLEEP) + SCpnt->device->channel, 0, 0, 0, 5 /* 5 second timeout */) < 0){ /* The TM request failed and the subsequent FW-reload failed! @@ -2398,7 +2381,7 @@ mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd) { unsigned long flags; - int loop_count = 10 * 4; /* Wait 10 seconds */ + int loop_count = 4 * 10; /* Wait 10 seconds */ int status = FAILED; do { @@ -2406,8 +2389,8 @@ if (hd->tmState == TM_STATE_NONE) { hd->tmState = TM_STATE_IN_PROGRESS; hd->tmPending = 1; - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); status = SUCCESS; + spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); break; } spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); @@ -2419,6 +2402,34 @@ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** + * mptscsih_tm_wait_for_completion - wait for completion of TM task + * @hd: Pointer to MPT host structure. + * + * Returns {SUCCESS,FAILED}. + */ +static int +mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout ) +{ + unsigned long flags; + int loop_count = 4 * timeout; + int status = FAILED; + + do { + spin_lock_irqsave(&hd->ioc->FreeQlock, flags); + if(hd->tmPending == 0) { + status = SUCCESS; + spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); + break; + } + spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); + msleep_interruptible(250); + } while (--loop_count); + + return status; +} + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/** * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver * @ioc: Pointer to MPT_ADAPTER structure * @mf: Pointer to SCSI task mgmt request frame @@ -2449,9 +2460,6 @@ * Decrement count of outstanding TM requests. */ hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; - if (hd->tmPtr) { - del_timer(&hd->TMtimer); - } } else { dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n", ioc->name)); @@ -2505,7 +2513,6 @@ } } - hd->tmPtr = NULL; spin_lock_irqsave(&ioc->FreeQlock, flags); hd->tmPending = 0; spin_unlock_irqrestore(&ioc->FreeQlock, flags); @@ -2913,14 +2920,6 @@ mpt_free_msg_frame(ioc, hd->cmdPtr); } - /* 2d. If a task management has not completed, - * free resources associated with this request. - */ - if (hd->tmPtr) { - del_timer(&hd->TMtimer); - mpt_free_msg_frame(ioc, hd->tmPtr); - } - dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name)); } else { @@ -2942,12 +2941,6 @@ /* 2. Chain Buffer initialization */ - /* 3. tmPtr clear - */ - if (hd->tmPtr) { - hd->tmPtr = NULL; - } - /* 4. Renegotiate to all devices, if SCSI */ if (ioc->bus_type == SCSI) { @@ -3808,60 +3801,6 @@ mpt_put_msg_frame(ScsiDoneCtx, ioc, mf); return 0; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mptscsih_taskmgmt_timeout - Call back for timeout on a - * task management request. - * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long - * - */ -static void mptscsih_taskmgmt_timeout(unsigned long data) -{ - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data; - - dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_taskmgmt_timeout: " - "TM request timed out!\n", hd->ioc->name)); - - /* Delete the timer that triggered this callback. - * Remark: del_timer checks to make sure timer is active - * before deleting. - */ - del_timer(&hd->TMtimer); - - /* Call the reset handler. Already had a TM request - * timeout - so issue a diagnostic reset - */ - INIT_WORK(&mptscsih_rstTask, mptscsih_schedule_reset, (void *)hd); - schedule_work(&mptscsih_rstTask); - return; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mptscsih_schedule_reset - Call back for timeout on a - * task management request. - * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long - * - */ -static void -mptscsih_schedule_reset(void *arg) -{ - MPT_SCSI_HOST *hd; - hd = (MPT_SCSI_HOST *) arg; - - if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0) { - printk((KERN_WARNING " Firmware Reload FAILED!!\n")); - } else { - /* Because we have reset the IOC, no TM requests can be - * pending. So let's make sure the tmPending flag is reset. - */ - dtmprintk((KERN_WARNING MYNAM - ": %s: mptscsih_taskmgmt_timeout\n", - hd->ioc->name)); - hd->tmPending = 0; - } - - return; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ diff -Nru a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig --- a/drivers/scsi/Kconfig 2005-03-03 21:48:52 -08:00 +++ b/drivers/scsi/Kconfig 2005-03-03 21:48:52 -08:00 @@ -619,7 +619,7 @@ config SCSI_EATA_PIO tristate "EATA-PIO (old DPT PM2001, PM2012A) support" - depends on (ISA || EISA || PCI) && SCSI + depends on (ISA || EISA || PCI) && SCSI && BROKEN ---help--- This driver supports all EATA-PIO protocol compliant SCSI Host Adapters like the DPT PM2001 and the PM2012A. EATA-DMA compliant @@ -1257,7 +1257,7 @@ config SCSI_QLOGIC_ISP tristate "Qlogic ISP SCSI support (old driver)" - depends on PCI && SCSI + depends on PCI && SCSI && BROKEN ---help--- This driver works for all QLogic PCI SCSI host adapters (IQ-PCI, IQ-PCI-10, IQ_PCI-D) except for the PCI-basic card. (This latter diff -Nru a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c --- a/drivers/scsi/aacraid/linit.c 2005-03-03 21:48:52 -08:00 +++ b/drivers/scsi/aacraid/linit.c 2005-03-03 21:48:52 -08:00 @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -191,28 +192,6 @@ { aac_rkt_init, "aacraid", "ADAPTEC ", "RAID ", 2 } /* Adaptec Rocket Catch All */ }; -#ifdef CONFIG_COMPAT -/* - * Promote 32 bit apps that call get_next_adapter_fib_ioctl to 64 bit version - */ -static int aac_get_next_adapter_fib_ioctl(unsigned int fd, unsigned int cmd, - unsigned long arg, struct file *file) -{ - struct fib_ioctl __user *f; - - f = compat_alloc_user_space(sizeof(*f)); - if (!access_ok(VERIFY_WRITE, f, sizeof(*f))) - return -EFAULT; - - clear_user(f, sizeof(*f)); - if (copy_in_user(f, (void __user *)arg, sizeof(struct fib_ioctl) - sizeof(u32))) - return -EFAULT; - - return sys_ioctl(fd, cmd, (unsigned long)f); -} -#endif - - /** * aac_queuecommand - queue a SCSI command * @cmd: SCSI command to queue @@ -494,9 +473,65 @@ return aac_do_ioctl(file->private_data, cmd, (void __user *)arg); } +#ifdef CONFIG_COMPAT +static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long arg) +{ + long ret; + lock_kernel(); + switch (cmd) { + case FSACTL_MINIPORT_REV_CHECK: + case FSACTL_SENDFIB: + case FSACTL_OPEN_GET_ADAPTER_FIB: + case FSACTL_CLOSE_GET_ADAPTER_FIB: + case FSACTL_SEND_RAW_SRB: + case FSACTL_GET_PCI_INFO: + case FSACTL_QUERY_DISK: + case FSACTL_DELETE_DISK: + case FSACTL_FORCE_DELETE_DISK: + case FSACTL_GET_CONTAINERS: + ret = aac_do_ioctl(dev, cmd, (void __user *)arg); + break; + + case FSACTL_GET_NEXT_ADAPTER_FIB: { + struct fib_ioctl __user *f; + + f = compat_alloc_user_space(sizeof(*f)); + ret = 0; + if (clear_user(f, sizeof(*f) != sizeof(*f))) + ret = -EFAULT; + if (copy_in_user(f, (void __user *)arg, sizeof(struct fib_ioctl) - sizeof(u32))) + ret = -EFAULT; + if (!ret) + ret = aac_do_ioctl(dev, cmd, (void __user *)arg); + break; + } + + default: + ret = -ENOIOCTLCMD; + break; + } + unlock_kernel(); + return ret; +} + +static int aac_compat_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) +{ + struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata; + return aac_compat_do_ioctl(dev, cmd, (unsigned long)arg); +} + +static long aac_compat_cfg_ioctl(struct file *file, unsigned cmd, unsigned long arg) +{ + return aac_compat_do_ioctl((struct aac_dev *)file->private_data, cmd, arg); +} +#endif + static struct file_operations aac_cfg_fops = { .owner = THIS_MODULE, .ioctl = aac_cfg_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = aac_compat_cfg_ioctl, +#endif .open = aac_cfg_open, }; @@ -506,6 +541,9 @@ .proc_name = "aacraid", .info = aac_info, .ioctl = aac_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = aac_compat_ioctl, +#endif .queuecommand = aac_queuecommand, .bios_param = aac_biosparm, .slave_configure = aac_slave_configure, @@ -699,39 +737,11 @@ printk(KERN_WARNING "aacraid: unable to register \"aac\" device.\n"); } -#ifdef CONFIG_COMPAT - register_ioctl32_conversion(FSACTL_MINIPORT_REV_CHECK, NULL); - register_ioctl32_conversion(FSACTL_SENDFIB, NULL); - register_ioctl32_conversion(FSACTL_OPEN_GET_ADAPTER_FIB, NULL); - register_ioctl32_conversion(FSACTL_GET_NEXT_ADAPTER_FIB, - aac_get_next_adapter_fib_ioctl); - register_ioctl32_conversion(FSACTL_CLOSE_GET_ADAPTER_FIB, NULL); - register_ioctl32_conversion(FSACTL_SEND_RAW_SRB, NULL); - register_ioctl32_conversion(FSACTL_GET_PCI_INFO, NULL); - register_ioctl32_conversion(FSACTL_QUERY_DISK, NULL); - register_ioctl32_conversion(FSACTL_DELETE_DISK, NULL); - register_ioctl32_conversion(FSACTL_FORCE_DELETE_DISK, NULL); - register_ioctl32_conversion(FSACTL_GET_CONTAINERS, NULL); -#endif - return 0; } static void __exit aac_exit(void) { -#ifdef CONFIG_COMPAT - unregister_ioctl32_conversion(FSACTL_MINIPORT_REV_CHECK); - unregister_ioctl32_conversion(FSACTL_SENDFIB); - unregister_ioctl32_conversion(FSACTL_OPEN_GET_ADAPTER_FIB); - unregister_ioctl32_conversion(FSACTL_GET_NEXT_ADAPTER_FIB); - unregister_ioctl32_conversion(FSACTL_CLOSE_GET_ADAPTER_FIB); - unregister_ioctl32_conversion(FSACTL_SEND_RAW_SRB); - unregister_ioctl32_conversion(FSACTL_GET_PCI_INFO); - unregister_ioctl32_conversion(FSACTL_QUERY_DISK); - unregister_ioctl32_conversion(FSACTL_DELETE_DISK); - unregister_ioctl32_conversion(FSACTL_FORCE_DELETE_DISK); - unregister_ioctl32_conversion(FSACTL_GET_CONTAINERS); -#endif unregister_chrdev(aac_cfg_major, "aac"); pci_unregister_driver(&aac_pci_driver); } diff -Nru a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c --- a/drivers/scsi/megaraid/megaraid_mm.c 2005-03-03 21:48:52 -08:00 +++ b/drivers/scsi/megaraid/megaraid_mm.c 2005-03-03 21:48:52 -08:00 @@ -16,6 +16,7 @@ */ #include "megaraid_mm.h" +#include // Entry points for char node driver @@ -43,8 +44,7 @@ static void mraid_mm_teardown_dma_pools(mraid_mmadp_t *); #ifdef CONFIG_COMPAT -static int mraid_mm_compat_ioctl(unsigned int, unsigned int, unsigned long, - struct file *); +static long mraid_mm_compat_ioctl(struct file *, unsigned int, unsigned long); #endif MODULE_AUTHOR("LSI Logic Corporation"); @@ -71,6 +71,9 @@ static struct file_operations lsi_fops = { .open = mraid_mm_open, .ioctl = mraid_mm_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = mraid_mm_compat_ioctl, +#endif .owner = THIS_MODULE, }; @@ -1215,8 +1218,6 @@ INIT_LIST_HEAD(&adapters_list_g); - register_ioctl32_conversion(MEGAIOCCMD, mraid_mm_compat_ioctl); - return 0; } @@ -1225,13 +1226,15 @@ * mraid_mm_compat_ioctl : 32bit to 64bit ioctl conversion routine */ #ifdef CONFIG_COMPAT -static int -mraid_mm_compat_ioctl(unsigned int fd, unsigned int cmd, - unsigned long arg, struct file *filep) -{ - struct inode *inode = filep->f_dentry->d_inode; - - return mraid_mm_ioctl(inode, filep, cmd, arg); +static long +mraid_mm_compat_ioctl(struct file *filep, unsigned int cmd, + unsigned long arg) +{ + int err; + lock_kernel(); + err = mraid_mm_ioctl(NULL, filep, cmd, arg); + unlock_kernel(); + return err; } #endif @@ -1244,7 +1247,6 @@ con_log(CL_DLEVEL1 , ("exiting common mod\n")); unregister_chrdev(majorno, "megadev"); - unregister_ioctl32_conversion(MEGAIOCCMD); } module_init(mraid_mm_init); diff -Nru a/drivers/scsi/osst.c b/drivers/scsi/osst.c --- a/drivers/scsi/osst.c 2005-03-03 21:48:52 -08:00 +++ b/drivers/scsi/osst.c 2005-03-03 21:48:52 -08:00 @@ -5121,6 +5121,22 @@ return retval; } +#ifdef CONFIG_COMPAT +static long osst_compat_ioctl(struct file * file, unsigned int cmd_in, unsigned long arg) +{ + struct osst_tape *STp = file->private_data; + struct scsi_device *sdev = STp->device; + int ret = -ENOIOCTLCMD; + if (sdev->host->hostt->compat_ioctl) { + + ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg); + + } + return ret; +} +#endif + + /* Memory handling routines */ @@ -5456,6 +5472,9 @@ .read = osst_read, .write = osst_write, .ioctl = osst_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = osst_compat_ioctl, +#endif .open = os_scsi_tape_open, .flush = os_scsi_tape_flush, .release = os_scsi_tape_close, diff -Nru a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c --- a/drivers/scsi/qla1280.c 2005-03-03 21:48:52 -08:00 +++ b/drivers/scsi/qla1280.c 2005-03-03 21:48:52 -08:00 @@ -20,6 +20,9 @@ #define QLA1280_VERSION "3.25" /***************************************************************************** Revision History: + Rev 3.25.1, February 10, 2005 Christoph Hellwig + - use pci_map_single to map non-S/G requests + - remove qla1280_proc_info Rev 3.25, September 28, 2004, Christoph Hellwig - add support for ISP1020/1040 - don't include "scsi.h" anymore for 2.6.x @@ -670,8 +673,6 @@ }; static int qla1280_verbose = 1; -static int qla1280_buffer_size; -static char *qla1280_buffer; #if DEBUG_QLA1280 static int ql_debug_level = 1; @@ -694,97 +695,6 @@ #define LEAVE_INTR(x) dprintk(4, "qla1280 : Leaving %s()\n", x); -/************************************************************************* - * qla1280_proc_info - * - * Description: - * Return information to handle /proc support for the driver. - * - * buffer - ptrs to a page buffer - * - * Returns: - *************************************************************************/ -#define PROC_BUF &qla1280_buffer[len] - -static int qla1280_proc_info(struct Scsi_Host *host, char *buffer, - char **start, off_t offset, int length, int inout) -{ - struct scsi_qla_host *ha = (struct scsi_qla_host *)host->hostdata; - struct qla_boards *bdp = &ql1280_board_tbl[ha->devnum]; - int size = 0; - int len = 0; - - if (inout) - return -ENOSYS; - - /* - * if our old buffer is the right size use it otherwise - * allocate a new one. - */ - if (qla1280_buffer_size != PAGE_SIZE) { - /* deallocate this buffer and get a new one */ - if (qla1280_buffer != NULL) { - free_page((unsigned long)qla1280_buffer); - qla1280_buffer_size = 0; - } - qla1280_buffer = (char *)get_zeroed_page(GFP_KERNEL); - } - if (qla1280_buffer == NULL) { - size = sprintf(buffer, "qla1280 - kmalloc error at line %d\n", - __LINE__); - return size; - } - /* save the size of our buffer */ - qla1280_buffer_size = PAGE_SIZE; - - /* 3.20 clear the buffer we use for proc display */ - memset(qla1280_buffer, 0, PAGE_SIZE); - - /* start building the print buffer */ - size = sprintf(PROC_BUF, - "QLogic PCI to SCSI Adapter for ISP 1280/12160:\n" - " Firmware version: %2d.%02d.%02d, Driver version %s\n", - bdp->fwver[0], bdp->fwver[1], bdp->fwver[2], - QLA1280_VERSION); - - len += size; - - size = sprintf(PROC_BUF, "SCSI Host Adapter Information: %s\n", - bdp->name); - len += size; - size = sprintf(PROC_BUF, "Request Queue count= 0x%x, Response " - "Queue count= 0x%x\n", - REQUEST_ENTRY_CNT, RESPONSE_ENTRY_CNT); - len += size; - size = sprintf(PROC_BUF, "Number of pending commands = 0x%lx\n", - ha->actthreads); - len += size; - size = sprintf(PROC_BUF, "Number of free request entries = %d\n", - ha->req_q_cnt); - len += size; - size = sprintf(PROC_BUF, "\n"); /* 1 */ - len += size; - - if (len >= qla1280_buffer_size) { - printk(KERN_WARNING - "qla1280: Overflow buffer in qla1280_proc.c\n"); - } - - if (offset > len - 1) { - free_page((unsigned long) qla1280_buffer); - qla1280_buffer = NULL; - qla1280_buffer_size = length = 0; - *start = NULL; - } else { - *start = &qla1280_buffer[offset]; /* Start of wanted data */ - if (len - offset < length) { - length = len - offset; - } - } - return length; -} - - static int qla1280_read_nvram(struct scsi_qla_host *ha) { uint16_t *wptr; @@ -1334,22 +1244,6 @@ { return qla1280_biosparam(disk->device, NULL, disk->capacity, geom); } - -static int -qla1280_proc_info_old(char *buffer, char **start, off_t offset, int length, - int hostno, int inout) -{ - struct Scsi_Host *host; - - for (host = scsi_hostlist; host; host = host->next) { - if (host->host_no == hostno) { - return qla1280_proc_info(host, buffer, start, - offset, length, inout); - } - } - - return -ESRCH; -} #endif /************************************************************************** @@ -1571,16 +1465,12 @@ /* Release memory used for this I/O */ if (cmd->use_sg) { - dprintk(3, "S/G unmap_sg cmd=%p\n", cmd); - pci_unmap_sg(ha->pdev, cmd->request_buffer, - cmd->use_sg, cmd->sc_data_direction); + cmd->use_sg, cmd->sc_data_direction); } else if (cmd->request_bufflen) { - /*dprintk(1, "No S/G unmap_single cmd=%x saved_dma_handle=%lx\n", - cmd, sp->saved_dma_handle); */ - - pci_unmap_page(ha->pdev, sp->saved_dma_handle, - cmd->request_bufflen, cmd->sc_data_direction); + pci_unmap_single(ha->pdev, sp->saved_dma_handle, + cmd->request_bufflen, + cmd->sc_data_direction); } /* Call the mid-level driver interrupt handler */ @@ -3354,14 +3244,11 @@ REQUEST_ENTRY_SIZE); } } else { /* No scatter gather data transfer */ - struct page *page = virt_to_page(cmd->request_buffer); - unsigned long off = (unsigned long)cmd->request_buffer & ~PAGE_MASK; - - dma_handle = pci_map_page(ha->pdev, page, off, - cmd->request_bufflen, - cmd->sc_data_direction); + dma_handle = pci_map_single(ha->pdev, + cmd->request_buffer, + cmd->request_bufflen, + cmd->sc_data_direction); - /* save dma_handle for pci_unmap_page */ sp->saved_dma_handle = dma_handle; #if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) if (ha->flags.use_pci_vchannel) @@ -3636,11 +3523,10 @@ REQUEST_ENTRY_SIZE); } } else { /* No S/G data transfer */ - struct page *page = virt_to_page(cmd->request_buffer); - unsigned long off = (unsigned long)cmd->request_buffer & ~PAGE_MASK; - dma_handle = pci_map_page(ha->pdev, page, off, - cmd->request_bufflen, - cmd->sc_data_direction); + dma_handle = pci_map_single(ha->pdev, + cmd->request_buffer, + cmd->request_bufflen, + cmd->sc_data_direction); sp->saved_dma_handle = dma_handle; *dword_ptr++ = cpu_to_le32(pci_dma_lo32(dma_handle)); @@ -4668,7 +4554,6 @@ .eh_bus_reset_handler = qla1280_eh_bus_reset, .eh_host_reset_handler = qla1280_eh_adapter_reset, .bios_param = qla1280_biosparam, - .proc_info = qla1280_proc_info, .can_queue = 0xfffff, .this_id = -1, .sg_tablesize = SG_ALL, @@ -4688,7 +4573,6 @@ .eh_bus_reset_handler = qla1280_eh_bus_reset, .eh_host_reset_handler = qla1280_eh_adapter_reset, .bios_param = qla1280_biosparam_old, - .proc_info = qla1280_proc_info_old, .can_queue = 0xfffff, .this_id = -1, .sg_tablesize = SG_ALL, diff -Nru a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c --- a/drivers/scsi/scsi.c 2005-03-03 21:48:52 -08:00 +++ b/drivers/scsi/scsi.c 2005-03-03 21:48:52 -08:00 @@ -88,12 +88,6 @@ COMMAND_SIZE((cmd)->cmnd[0]) : (cmd)->cmd_len) /* - * Data declarations. - */ -unsigned long scsi_pid; -static unsigned long serial_number; - -/* * Note - the initial logging level can be set here to log events at boot time. * After the system is up, you may enable logging via the /proc interface. */ @@ -510,6 +504,21 @@ } #endif +/* + * Assign a serial number and pid to the request for error recovery + * and debugging purposes. Protected by the Host_Lock of host. + */ +static inline void scsi_cmd_get_serial(struct Scsi_Host *host, struct scsi_cmnd *cmd) +{ + cmd->serial_number = host->cmd_serial_number++; + if (cmd->serial_number == 0) + cmd->serial_number = host->cmd_serial_number++; + + cmd->pid = host->cmd_pid++; + if (cmd->pid == 0) + cmd->pid = host->cmd_pid++; +} + /* * Function: scsi_dispatch_command * @@ -532,6 +541,7 @@ * returns an immediate error upwards, and signals * that the device is no longer present */ cmd->result = DID_NO_CONNECT << 16; + atomic_inc(&cmd->device->iorequest_cnt); scsi_done(cmd); /* return 0 (because the command has been processed) */ goto out; @@ -556,13 +566,6 @@ goto out; } - /* Assign a unique nonzero serial_number. */ - /* XXX(hch): this is racy */ - if (++serial_number == 0) - serial_number = 1; - cmd->serial_number = serial_number; - cmd->pid = scsi_pid++; - /* * If SCSI-2 or lower, store the LUN value in cmnd. */ @@ -593,6 +596,10 @@ host->resetting = 0; } + /* + * AK: unlikely race here: for some reason the timer could + * expire before the serial number is set up below. + */ scsi_add_timer(cmd, cmd->timeout_per_command, scsi_times_out); scsi_log_send(cmd); @@ -605,6 +612,8 @@ cmd->state = SCSI_STATE_QUEUED; cmd->owner = SCSI_OWNER_LOWLEVEL; + atomic_inc(&cmd->device->iorequest_cnt); + /* * Before we queue this command, check if the command * length exceeds what the host adapter can handle. @@ -619,6 +628,8 @@ } spin_lock_irqsave(host->host_lock, flags); + scsi_cmd_get_serial(host, cmd); + if (unlikely(test_bit(SHOST_CANCEL, &host->shost_state))) { cmd->result = (DID_NO_CONNECT << 16); scsi_done(cmd); @@ -627,6 +638,7 @@ } spin_unlock_irqrestore(host->host_lock, flags); if (rtn) { + atomic_inc(&cmd->device->iodone_cnt); scsi_queue_insert(cmd, (rtn == SCSI_MLQUEUE_DEVICE_BUSY) ? rtn : SCSI_MLQUEUE_HOST_BUSY); @@ -758,6 +770,10 @@ cmd->state = SCSI_STATE_BHQUEUE; cmd->owner = SCSI_OWNER_BH_HANDLER; + atomic_inc(&cmd->device->iodone_cnt); + if (cmd->result) + atomic_inc(&cmd->device->ioerr_cnt); + /* * Next, enqueue the command into the done queue. * It is a per-CPU queue, so we just disable local interrupts @@ -920,12 +936,9 @@ * the right thing depending on whether or not the device is * currently active and whether or not it even has the * command blocks built yet. - * - * XXX(hch): What exactly is device_request_lock trying to protect? */ void scsi_adjust_queue_depth(struct scsi_device *sdev, int tagged, int tags) { - static DEFINE_SPINLOCK(device_request_lock); unsigned long flags; /* @@ -934,8 +947,7 @@ if (tags <= 0) return; - spin_lock_irqsave(&device_request_lock, flags); - spin_lock(sdev->request_queue->queue_lock); + spin_lock_irqsave(sdev->request_queue->queue_lock, flags); /* Check to see if the queue is managed by the block layer * if it is, and we fail to adjust the depth, exit */ @@ -964,8 +976,7 @@ break; } out: - spin_unlock(sdev->request_queue->queue_lock); - spin_unlock_irqrestore(&device_request_lock, flags); + spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); } EXPORT_SYMBOL(scsi_adjust_queue_depth); diff -Nru a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c --- a/drivers/scsi/scsi_devinfo.c 2005-03-03 21:48:52 -08:00 +++ b/drivers/scsi/scsi_devinfo.c 2005-03-03 21:48:52 -08:00 @@ -159,6 +159,7 @@ {"HP", "C3323-300", "4269", BLIST_NOTQ}, {"IBM", "AuSaV1S2", NULL, BLIST_FORCELUN}, {"IBM", "ProFibre 4000R", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, + {"IBM", "2105", NULL, BLIST_RETRY_HWERROR}, {"iomega", "jaz 1GB", "J.86", BLIST_NOTQ | BLIST_NOLUN}, {"IOMEGA", "Io20S *F", NULL, BLIST_KEY}, {"INSITE", "Floptical F*8I", NULL, BLIST_KEY}, @@ -192,6 +193,7 @@ {"SMSC", "USB 2 HS-CF", NULL, BLIST_SPARSELUN | BLIST_INQUIRY_36}, {"SONY", "CD-ROM CDU-8001", NULL, BLIST_BORKEN}, {"SONY", "TSL", NULL, BLIST_FORCELUN}, /* DDS3 & DDS4 autoloaders */ + {"ST650211", "CF", NULL, BLIST_RETRY_HWERROR}, {"SUN", "T300", "*", BLIST_SPARSELUN}, {"SUN", "T4", "*", BLIST_SPARSELUN}, {"TEXEL", "CD-ROM", "1.06", BLIST_BORKEN}, @@ -201,6 +203,7 @@ {"WangDAT", "Model 2600", "01.7", BLIST_SELECT_NO_ATN}, {"WangDAT", "Model 3200", "02.2", BLIST_SELECT_NO_ATN}, {"WangDAT", "Model 1300", "02.4", BLIST_SELECT_NO_ATN}, + {"WDC WD25", "00JB-00FUA0", NULL, BLIST_NOREPORTLUN}, {"XYRATEX", "RS", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, {"Zzyzx", "RocketStor 500S", NULL, BLIST_SPARSELUN}, {"Zzyzx", "RocketStor 2000", NULL, BLIST_SPARSELUN}, diff -Nru a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c --- a/drivers/scsi/scsi_error.c 2005-03-03 21:48:52 -08:00 +++ b/drivers/scsi/scsi_error.c 2005-03-03 21:48:52 -08:00 @@ -31,6 +31,7 @@ #include #include #include +#include #include "scsi_priv.h" #include "scsi_logging.h" @@ -350,10 +351,18 @@ case MEDIUM_ERROR: return NEEDS_RETRY; + case HARDWARE_ERROR: + if (scsi_get_device_flags(scmd->device, + scmd->device->vendor, + scmd->device->model) + & BLIST_RETRY_HWERROR) + return NEEDS_RETRY; + else + return SUCCESS; + case ILLEGAL_REQUEST: case BLANK_CHECK: case DATA_PROTECT: - case HARDWARE_ERROR: default: return SUCCESS; } diff -Nru a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c --- a/drivers/scsi/scsi_sysfs.c 2005-03-03 21:48:52 -08:00 +++ b/drivers/scsi/scsi_sysfs.c 2005-03-03 21:48:52 -08:00 @@ -408,6 +408,28 @@ static DEVICE_ATTR(queue_type, S_IRUGO, show_queue_type_field, NULL); +static ssize_t +show_iostat_counterbits(struct device *dev, char *buf) +{ + return snprintf(buf, 20, "%d\n", (int)sizeof(atomic_t) * 8); +} + +static DEVICE_ATTR(iocounterbits, S_IRUGO, show_iostat_counterbits, NULL); + +#define show_sdev_iostat(field) \ +static ssize_t \ +show_iostat_##field(struct device *dev, char *buf) \ +{ \ + struct scsi_device *sdev = to_scsi_device(dev); \ + unsigned long long count = atomic_read(&sdev->field); \ + return snprintf(buf, 20, "0x%llx\n", count); \ +} \ +static DEVICE_ATTR(field, S_IRUGO, show_iostat_##field, NULL) + +show_sdev_iostat(iorequest_cnt); +show_sdev_iostat(iodone_cnt); +show_sdev_iostat(ioerr_cnt); + /* Default template for device attributes. May NOT be modified */ static struct device_attribute *scsi_sysfs_sdev_attrs[] = { @@ -423,6 +445,10 @@ &dev_attr_delete, &dev_attr_state, &dev_attr_timeout, + &dev_attr_iocounterbits, + &dev_attr_iorequest_cnt, + &dev_attr_iodone_cnt, + &dev_attr_ioerr_cnt, NULL }; diff -Nru a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c --- a/drivers/scsi/scsi_transport_fc.c 2005-03-03 21:48:52 -08:00 +++ b/drivers/scsi/scsi_transport_fc.c 2005-03-03 21:48:52 -08:00 @@ -254,16 +254,8 @@ sizeof(fc_host_symbolic_name(shost))); fc_host_supported_speeds(shost) = FC_PORTSPEED_UNKNOWN; fc_host_maxframe_size(shost) = -1; - memset(fc_host_hardware_version(shost), 0, - sizeof(fc_host_hardware_version(shost))); - memset(fc_host_firmware_version(shost), 0, - sizeof(fc_host_firmware_version(shost))); memset(fc_host_serial_number(shost), 0, sizeof(fc_host_serial_number(shost))); - memset(fc_host_opt_rom_version(shost), 0, - sizeof(fc_host_opt_rom_version(shost))); - memset(fc_host_driver_version(shost), 0, - sizeof(fc_host_driver_version(shost))); fc_host_port_id(shost) = -1; fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN; @@ -539,11 +531,7 @@ fc_private_host_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long); fc_private_host_rd_attr(symbolic_name, "%s\n", (FC_SYMBOLIC_NAME_SIZE +1)); fc_private_host_rd_attr(maxframe_size, "%u bytes\n", 20); -fc_private_host_rd_attr(hardware_version, "%s\n", (FC_VERSION_STRING_SIZE +1)); -fc_private_host_rd_attr(firmware_version, "%s\n", (FC_VERSION_STRING_SIZE +1)); fc_private_host_rd_attr(serial_number, "%s\n", (FC_SERIAL_NUMBER_SIZE +1)); -fc_private_host_rd_attr(opt_rom_version, "%s\n", (FC_VERSION_STRING_SIZE +1)); -fc_private_host_rd_attr(driver_version, "%s\n", (FC_VERSION_STRING_SIZE +1)); /* Dynamic Host Attributes */ @@ -817,11 +805,7 @@ SETUP_HOST_ATTRIBUTE_RD(symbolic_name); SETUP_HOST_ATTRIBUTE_RD(supported_speeds); SETUP_HOST_ATTRIBUTE_RD(maxframe_size); - SETUP_HOST_ATTRIBUTE_RD(hardware_version); - SETUP_HOST_ATTRIBUTE_RD(firmware_version); SETUP_HOST_ATTRIBUTE_RD(serial_number); - SETUP_HOST_ATTRIBUTE_RD(opt_rom_version); - SETUP_HOST_ATTRIBUTE_RD(driver_version); SETUP_HOST_ATTRIBUTE_RD(port_id); SETUP_HOST_ATTRIBUTE_RD(port_type); diff -Nru a/drivers/scsi/sd.c b/drivers/scsi/sd.c --- a/drivers/scsi/sd.c 2005-03-03 21:48:52 -08:00 +++ b/drivers/scsi/sd.c 2005-03-03 21:48:52 -08:00 @@ -741,11 +741,50 @@ sd_revalidate_disk(sdkp->disk); } + +#ifdef CONFIG_COMPAT +/* + * This gets directly called from VFS. When the ioctl + * is not recognized we go back to the other translation paths. + */ +static long sd_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct block_device *bdev = file->f_dentry->d_inode->i_bdev; + struct gendisk *disk = bdev->bd_disk; + struct scsi_device *sdev = scsi_disk(disk)->device; + + /* + * If we are in the middle of error recovery, don't let anyone + * else try and use this device. Also, if error recovery fails, it + * may try and take the device offline, in which case all further + * access to the device is prohibited. + */ + if (!scsi_block_when_processing_errors(sdev)) + return -ENODEV; + + if (sdev->host->hostt->compat_ioctl) { + int ret; + + ret = sdev->host->hostt->compat_ioctl(sdev, cmd, (void __user *)arg); + + return ret; + } + + /* + * Let the static ioctl translation table take care of it. + */ + return -ENOIOCTLCMD; +} +#endif + static struct block_device_operations sd_fops = { .owner = THIS_MODULE, .open = sd_open, .release = sd_release, .ioctl = sd_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = sd_compat_ioctl, +#endif .media_changed = sd_media_changed, .revalidate_disk = sd_revalidate_disk, }; diff -Nru a/drivers/scsi/sg.c b/drivers/scsi/sg.c --- a/drivers/scsi/sg.c 2005-03-03 21:48:52 -08:00 +++ b/drivers/scsi/sg.c 2005-03-03 21:48:52 -08:00 @@ -1037,6 +1037,29 @@ } } +#ifdef CONFIG_COMPAT +static long sg_compat_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) +{ + Sg_device *sdp; + Sg_fd *sfp; + struct scsi_device *sdev; + + if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) + return -ENXIO; + + sdev = sdp->device; + if (sdev->host->hostt->compat_ioctl) { + int ret; + + ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg); + + return ret; + } + + return -ENOIOCTLCMD; +} +#endif + static unsigned int sg_poll(struct file *filp, poll_table * wait) { @@ -1346,6 +1369,9 @@ .write = sg_write, .poll = sg_poll, .ioctl = sg_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = sg_compat_ioctl, +#endif .open = sg_open, .mmap = sg_mmap, .release = sg_release, diff -Nru a/drivers/scsi/sim710.c b/drivers/scsi/sim710.c --- a/drivers/scsi/sim710.c 2005-03-03 21:48:52 -08:00 +++ b/drivers/scsi/sim710.c 2005-03-03 21:48:52 -08:00 @@ -47,7 +47,7 @@ #define MAX_SLOTS 8 static __u8 __initdata id_array[MAX_SLOTS] = { [0 ... MAX_SLOTS-1] = 7 }; -char *sim710; /* command line passed by insmod */ +static char *sim710; /* command line passed by insmod */ MODULE_AUTHOR("Richard Hirst"); MODULE_DESCRIPTION("Simple NCR53C710 driver"); @@ -61,7 +61,7 @@ #define ARG_SEP ',' #endif -__init int +static __init int param_setup(char *str) { char *pos = str, *next; @@ -314,7 +314,7 @@ differential, scsi_id); } -struct eisa_driver sim710_eisa_driver = { +static struct eisa_driver sim710_eisa_driver = { .id_table = sim710_eisa_ids, .driver = { .name = "sim710", diff -Nru a/drivers/scsi/sr.c b/drivers/scsi/sr.c --- a/drivers/scsi/sr.c 2005-03-03 21:48:52 -08:00 +++ b/drivers/scsi/sr.c 2005-03-03 21:48:52 -08:00 @@ -518,6 +518,10 @@ .release = sr_block_release, .ioctl = sr_block_ioctl, .media_changed = sr_block_media_changed, + /* + * No compat_ioctl for now because sr_block_ioctl never + * seems to pass arbitary ioctls down to host drivers. + */ }; static int sr_open(struct cdrom_device_info *cdi, int purpose) diff -Nru a/drivers/scsi/st.c b/drivers/scsi/st.c --- a/drivers/scsi/st.c 2005-03-03 21:48:52 -08:00 +++ b/drivers/scsi/st.c 2005-03-03 21:48:52 -08:00 @@ -9,7 +9,7 @@ Steve Hirsch, Andreas Koppenh"ofer, Michael Leodolter, Eyal Lebedinsky, Michael Schaefer, J"org Weule, and Eric Youngdale. - Copyright 1992 - 2004 Kai Makisara + Copyright 1992 - 2005 Kai Makisara email Kai.Makisara@kolumbus.fi Some small formal changes - aeb, 950809 @@ -17,7 +17,7 @@ Last modified: 18-JAN-1998 Richard Gooch Devfs support */ -static char *verstr = "20041025"; +static char *verstr = "20050213"; #include @@ -144,7 +144,7 @@ #error "Buffer size should not exceed (2 << 24 - 1) bytes!" #endif -DEB( static int debugging = DEBUG; ) +static int debugging = DEBUG; #define MAX_RETRIES 0 #define MAX_WRITE_RETRIES 0 @@ -262,25 +262,57 @@ return tape->disk->disk_name; } + +static void st_analyze_sense(struct scsi_request *SRpnt, struct st_cmdstatus *s) +{ + const u8 *ucp; + const u8 *sense = SRpnt->sr_sense_buffer; + + s->have_sense = scsi_request_normalize_sense(SRpnt, &s->sense_hdr); + + if (s->have_sense) { + s->remainder_valid = + scsi_get_sense_info_fld(sense, SCSI_SENSE_BUFFERSIZE, &s->uremainder64); + switch (sense[0] & 0x7f) { + case 0x71: + s->deferred = 1; + case 0x70: + s->fixed_format = 1; + s->flags = sense[2] & 0xe0; + break; + case 0x73: + s->deferred = 1; + case 0x72: + s->fixed_format = 0; + ucp = scsi_sense_desc_find(sense, SCSI_SENSE_BUFFERSIZE, 4); + s->flags = ucp ? (ucp[3] & 0xe0) : 0; + break; + default: + s->flags = 0; + } + } +} + + /* Convert the result to success code */ static int st_chk_result(struct scsi_tape *STp, struct scsi_request * SRpnt) { int result = SRpnt->sr_result; - unsigned char *sense = SRpnt->sr_sense_buffer, scode; + u8 scode; DEB(const char *stp;) char *name = tape_name(STp); + struct st_cmdstatus *cmdstatp; - if (!result) { - sense[0] = 0; /* We don't have sense data if this byte is zero */ + if (!result) return 0; - } - if ((driver_byte(result) & DRIVER_MASK) == DRIVER_SENSE) - scode = sense[2] & 0x0f; - else { - sense[0] = 0; + cmdstatp = &STp->buffer->cmdstat; + st_analyze_sense(STp->buffer->last_SRpnt, cmdstatp); + + if (cmdstatp->have_sense) + scode = STp->buffer->cmdstat.sense_hdr.sense_key; + else scode = 0; - } DEB( if (debugging) { @@ -289,29 +321,30 @@ SRpnt->sr_cmnd[0], SRpnt->sr_cmnd[1], SRpnt->sr_cmnd[2], SRpnt->sr_cmnd[3], SRpnt->sr_cmnd[4], SRpnt->sr_cmnd[5], SRpnt->sr_bufflen); - if (driver_byte(result) & DRIVER_SENSE) - scsi_print_req_sense("st", SRpnt); - } else ) /* end DEB */ - if (!(driver_byte(result) & DRIVER_SENSE) || - ((sense[0] & 0x70) == 0x70 && - scode != NO_SENSE && - scode != RECOVERED_ERROR && - /* scode != UNIT_ATTENTION && */ - scode != BLANK_CHECK && - scode != VOLUME_OVERFLOW && - SRpnt->sr_cmnd[0] != MODE_SENSE && - SRpnt->sr_cmnd[0] != TEST_UNIT_READY)) { /* Abnormal conditions for tape */ - if (driver_byte(result) & DRIVER_SENSE) { - printk(KERN_WARNING "%s: Error with sense data: ", name); + if (cmdstatp->have_sense) scsi_print_req_sense("st", SRpnt); - } else + } ) /* end DEB */ + if (!debugging) { /* Abnormal conditions for tape */ + if (!cmdstatp->have_sense) printk(KERN_WARNING "%s: Error %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n", name, result, suggestion(result), - driver_byte(result) & DRIVER_MASK, host_byte(result)); + driver_byte(result) & DRIVER_MASK, host_byte(result)); + else if (cmdstatp->have_sense && + scode != NO_SENSE && + scode != RECOVERED_ERROR && + /* scode != UNIT_ATTENTION && */ + scode != BLANK_CHECK && + scode != VOLUME_OVERFLOW && + SRpnt->sr_cmnd[0] != MODE_SENSE && + SRpnt->sr_cmnd[0] != TEST_UNIT_READY) { + printk(KERN_WARNING "%s: Error with sense data: ", name); + scsi_print_req_sense("st", SRpnt); + } } - if (STp->cln_mode >= EXTENDED_SENSE_START) { + if (cmdstatp->fixed_format && + STp->cln_mode >= EXTENDED_SENSE_START) { /* Only fixed format sense */ if (STp->cln_sense_value) STp->cleaning_req |= ((SRpnt->sr_sense_buffer[STp->cln_mode] & STp->cln_sense_mask) == STp->cln_sense_value); @@ -319,12 +352,13 @@ STp->cleaning_req |= ((SRpnt->sr_sense_buffer[STp->cln_mode] & STp->cln_sense_mask) != 0); } - if (sense[12] == 0 && sense[13] == 0x17) /* ASC and ASCQ => cleaning requested */ - STp->cleaning_req = 1; + if (cmdstatp->have_sense && + cmdstatp->sense_hdr.asc == 0 && cmdstatp->sense_hdr.ascq == 0x17) + STp->cleaning_req = 1; /* ASC and ASCQ => cleaning requested */ STp->pos_unknown |= STp->device->was_reset; - if ((sense[0] & 0x70) == 0x70 && + if (cmdstatp->have_sense && scode == RECOVERED_ERROR #if ST_RECOVERED_WRITE_FATAL && SRpnt->sr_cmnd[0] != WRITE_6 @@ -346,7 +380,7 @@ STp->recover_count); } ) /* end DEB */ - if ((sense[2] & 0xe0) == 0) + if (cmdstatp->flags == 0) return 0; } return (-EIO); @@ -356,28 +390,10 @@ /* Wakeup from interrupt */ static void st_sleep_done(struct scsi_cmnd * SCpnt) { - int remainder; struct scsi_tape *STp = container_of(SCpnt->request->rq_disk->private_data, struct scsi_tape, driver); - if ((STp->buffer)->writing && - (SCpnt->sense_buffer[0] & 0x70) == 0x70 && - (SCpnt->sense_buffer[2] & 0x40)) { - /* EOM at write-behind, has all been written? */ - if ((SCpnt->sense_buffer[0] & 0x80) != 0) - remainder = (SCpnt->sense_buffer[3] << 24) | - (SCpnt->sense_buffer[4] << 16) | - (SCpnt->sense_buffer[5] << 8) | - SCpnt->sense_buffer[6]; - else - remainder = 0; - if ((SCpnt->sense_buffer[2] & 0x0f) == VOLUME_OVERFLOW || - remainder > 0) - (STp->buffer)->midlevel_result = SCpnt->result; /* Error */ - else - (STp->buffer)->midlevel_result = INT_MAX; /* OK */ - } else - (STp->buffer)->midlevel_result = SCpnt->result; + (STp->buffer)->cmdstat.midlevel_result = SCpnt->result; SCpnt->request->rq_status = RQ_SCSI_DONE; (STp->buffer)->last_SRpnt = SCpnt->sc_request; DEB( STp->write_pending = 0; ) @@ -421,6 +437,7 @@ SRpnt->sr_request->waiting = &(STp->wait); SRpnt->sr_request->rq_status = RQ_SCSI_BUSY; SRpnt->sr_request->rq_disk = STp->disk; + STp->buffer->cmdstat.have_sense = 0; scsi_do_req(SRpnt, (void *) cmd, bp, bytes, st_sleep_done, timeout, retries); @@ -434,13 +451,20 @@ } -/* Handle the write-behind checking (downs the semaphore) */ -static void write_behind_check(struct scsi_tape * STp) +/* Handle the write-behind checking (waits for completion). Returns -ENOSPC if + write has been correct but EOM early warning reached, -EIO if write ended in + error or zero if write successful. Asynchronous writes are used only in + variable block mode. */ +static int write_behind_check(struct scsi_tape * STp) { + int retval = 0; struct st_buffer *STbuffer; struct st_partstat *STps; + struct st_cmdstatus *cmdstatp; STbuffer = STp->buffer; + if (!STbuffer->writing) + return 0; DEB( if (STp->write_pending) @@ -463,9 +487,29 @@ else STps->drv_block += STbuffer->writing / STp->block_size; } + + cmdstatp = &STbuffer->cmdstat; + if (STbuffer->syscall_result) { + retval = -EIO; + if (cmdstatp->have_sense && !cmdstatp->deferred && + (cmdstatp->flags & SENSE_EOM) && + (cmdstatp->sense_hdr.sense_key == NO_SENSE || + cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR)) { + /* EOM at write-behind, has all data been written? */ + if (!cmdstatp->remainder_valid || + cmdstatp->uremainder64 == 0) + retval = -ENOSPC; + } + if (retval == -EIO) + STps->drv_block = -1; + } STbuffer->writing = 0; - return; + DEB(if (debugging && retval) + printk(ST_DEB_MSG "%s: Async write error %x, return value %d.\n", + tape_name(STp), STbuffer->cmdstat.midlevel_result, retval);) /* end DEB */ + + return retval; } @@ -496,7 +540,7 @@ scsi_release_request(SRpnt); SRpnt = NULL; - if ((STp->buffer)->midlevel_result != 0) + if ((STp->buffer)->cmdstat.midlevel_result != 0) printk(KERN_ERR "%s: Stepping over filemark %s failed.\n", tape_name(STp), forward ? "forward" : "backward"); @@ -513,19 +557,9 @@ struct scsi_request *SRpnt; struct st_partstat *STps; - if ((STp->buffer)->writing) { - write_behind_check(STp); - if ((STp->buffer)->syscall_result) { - DEBC(printk(ST_DEB_MSG - "%s: Async write error (flush) %x.\n", - tape_name(STp), (STp->buffer)->midlevel_result)) - if ((STp->buffer)->midlevel_result == INT_MAX) - return (-ENOSPC); - return (-EIO); - } - } - if (STp->block_size == 0) - return 0; + result = write_behind_check(STp); + if (result) + return result; result = 0; if (STp->dirty == 1) { @@ -553,18 +587,25 @@ STps = &(STp->ps[STp->partition]); if ((STp->buffer)->syscall_result != 0) { - if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 && - (SRpnt->sr_sense_buffer[2] & 0x40) && - (SRpnt->sr_sense_buffer[2] & 0x0f) == NO_SENSE) { + struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat; + + if (cmdstatp->have_sense && !cmdstatp->deferred && + (cmdstatp->flags & SENSE_EOM) && + (cmdstatp->sense_hdr.sense_key == NO_SENSE || + cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) && + (!cmdstatp->remainder_valid || + cmdstatp->uremainder64 == 0)) { /* All written at EOM early warning */ STp->dirty = 0; (STp->buffer)->buffer_bytes = 0; + if (STps->drv_block >= 0) + STps->drv_block += blks; result = (-ENOSPC); } else { printk(KERN_ERR "%s: Error on flush.\n", tape_name(STp)); + STps->drv_block = (-1); result = (-EIO); } - STps->drv_block = (-1); } else { if (STps->drv_block >= 0) STps->drv_block += blks; @@ -728,6 +769,7 @@ int retval = CHKRES_READY, new_session = 0; unsigned char cmd[MAX_COMMAND_SIZE]; struct scsi_request *SRpnt = NULL; + struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat; max_wait = do_wait ? ST_BLOCK_SECONDS : 0; @@ -742,9 +784,9 @@ break; } - if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70) { + if (cmdstatp->have_sense) { - scode = (SRpnt->sr_sense_buffer[2] & 0x0f); + scode = cmdstatp->sense_hdr.sense_key; if (scode == UNIT_ATTENTION) { /* New media? */ new_session = 1; @@ -760,9 +802,7 @@ if (scode == NOT_READY) { if (waits < max_wait) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ); - if (signal_pending(current)) { + if (msleep_interruptible(1000)) { retval = (-EINTR); break; } @@ -771,7 +811,7 @@ } else { if ((STp->device)->scsi_level >= SCSI_2 && - SRpnt->sr_sense_buffer[12] == 0x3a) /* Check ASC */ + cmdstatp->sense_hdr.asc == 0x3a) /* Check ASC */ retval = CHKRES_NO_TAPE; else retval = CHKRES_NOT_READY; @@ -877,7 +917,7 @@ goto err_out; } - if (!SRpnt->sr_result && !SRpnt->sr_sense_buffer[0]) { + if (!SRpnt->sr_result && !STp->buffer->cmdstat.have_sense) { STp->max_block = ((STp->buffer)->b_data[1] << 16) | ((STp->buffer)->b_data[2] << 8) | (STp->buffer)->b_data[3]; STp->min_block = ((STp->buffer)->b_data[4] << 8) | @@ -1108,6 +1148,7 @@ name, STp->nbr_requests, STp->nbr_dio, STp->nbr_pages, STp->nbr_combinable)); if (STps->rw == ST_WRITING && !STp->pos_unknown) { + struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat; DEBC(printk(ST_DEB_MSG "%s: File length %lld bytes.\n", name, (long long)filp->f_pos); @@ -1126,20 +1167,13 @@ goto out; } - if ((STp->buffer)->syscall_result != 0 && - ((SRpnt->sr_sense_buffer[0] & 0x70) != 0x70 || - (SRpnt->sr_sense_buffer[2] & 0x4f) != 0x40 || - ((SRpnt->sr_sense_buffer[0] & 0x80) != 0 && - (SRpnt->sr_sense_buffer[3] | SRpnt->sr_sense_buffer[4] | - SRpnt->sr_sense_buffer[5] | - SRpnt->sr_sense_buffer[6]) != 0))) { - /* Filter out successful write at EOM */ - scsi_release_request(SRpnt); - SRpnt = NULL; - printk(KERN_ERR "%s: Error on write filemark.\n", name); - if (result == 0) - result = (-EIO); - } else { + if (STp->buffer->syscall_result == 0 || + (cmdstatp->have_sense && !cmdstatp->deferred && + (cmdstatp->flags & SENSE_EOM) && + (cmdstatp->sense_hdr.sense_key == NO_SENSE || + cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) && + (!cmdstatp->remainder_valid || cmdstatp->uremainder64 == 0))) { + /* Write successful at EOM */ scsi_release_request(SRpnt); SRpnt = NULL; if (STps->drv_file >= 0) @@ -1149,6 +1183,13 @@ cross_eof(STp, 0); STps->eof = ST_FM; } + else { /* Write error */ + scsi_release_request(SRpnt); + SRpnt = NULL; + printk(KERN_ERR "%s: Error on write filemark.\n", name); + if (result == 0) + result = (-EIO); + } DEBC(printk(ST_DEB_MSG "%s: Buffer flushed, %d EOF(s) written\n", name, cmd[4])); @@ -1410,16 +1451,12 @@ } STbp = STp->buffer; - if (STbp->writing) { - write_behind_check(STp); - if (STbp->syscall_result) { - DEBC(printk(ST_DEB_MSG "%s: Async write error (write) %x.\n", - name, STbp->midlevel_result)); - if (STbp->midlevel_result == INT_MAX) - STps->eof = ST_EOM_OK; - else - STps->eof = ST_EOM_ERROR; - } + i = write_behind_check(STp); + if (i) { + if (i == -ENOSPC) + STps->eof = ST_EOM_OK; + else + STps->eof = ST_EOM_ERROR; } if (STps->eof == ST_EOM_OK) { @@ -1523,15 +1560,13 @@ } if (STbp->syscall_result != 0) { + struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat; + DEBC(printk(ST_DEB_MSG "%s: Error on write:\n", name)); - if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 && - (SRpnt->sr_sense_buffer[2] & 0x40)) { - scode = SRpnt->sr_sense_buffer[2] & 0x0f; - if ((SRpnt->sr_sense_buffer[0] & 0x80) != 0) - undone = (SRpnt->sr_sense_buffer[3] << 24) | - (SRpnt->sr_sense_buffer[4] << 16) | - (SRpnt->sr_sense_buffer[5] << 8) | - SRpnt->sr_sense_buffer[6]; + if (cmdstatp->have_sense && (cmdstatp->flags & SENSE_EOM)) { + scode = cmdstatp->sense_hdr.sense_key; + if (cmdstatp->remainder_valid) + undone = (int)cmdstatp->uremainder64; else if (STp->block_size == 0 && scode == VOLUME_OVERFLOW) undone = transfer; @@ -1556,11 +1591,11 @@ retval = (-ENOSPC); /* EOM within current request */ DEBC(printk(ST_DEB_MSG "%s: EOM with %d bytes unwritten.\n", - name, count)); + name, (int)count)); } else { /* EOT within data buffered earlier (possible only in fixed block mode without direct i/o) */ - if (!retry_eot && (SRpnt->sr_sense_buffer[0] & 1) == 0 && + if (!retry_eot && !cmdstatp->deferred && (scode == NO_SENSE || scode == RECOVERED_ERROR)) { move_buffer_data(STp->buffer, transfer - undone); retry_eot = 1; @@ -1690,6 +1725,8 @@ /* Something to check */ if (STbp->syscall_result) { + struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat; + retval = 1; DEBC(printk(ST_DEB_MSG "%s: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n", name, @@ -1697,25 +1734,22 @@ SRpnt->sr_sense_buffer[2], SRpnt->sr_sense_buffer[3], SRpnt->sr_sense_buffer[4], SRpnt->sr_sense_buffer[5], SRpnt->sr_sense_buffer[6], SRpnt->sr_sense_buffer[7])); - if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70) { /* extended sense */ + if (cmdstatp->have_sense) { - if ((SRpnt->sr_sense_buffer[2] & 0x0f) == BLANK_CHECK) - SRpnt->sr_sense_buffer[2] &= 0xcf; /* No need for EOM in this case */ + if (cmdstatp->sense_hdr.sense_key == BLANK_CHECK) + cmdstatp->flags &= 0xcf; /* No need for EOM in this case */ - if ((SRpnt->sr_sense_buffer[2] & 0xe0) != 0) { /* EOF, EOM, or ILI */ + if (cmdstatp->flags != 0) { /* EOF, EOM, or ILI */ /* Compute the residual count */ - if ((SRpnt->sr_sense_buffer[0] & 0x80) != 0) - transfer = (SRpnt->sr_sense_buffer[3] << 24) | - (SRpnt->sr_sense_buffer[4] << 16) | - (SRpnt->sr_sense_buffer[5] << 8) | - SRpnt->sr_sense_buffer[6]; + if (cmdstatp->remainder_valid) + transfer = (int)cmdstatp->uremainder64; else transfer = 0; if (STp->block_size == 0 && - (SRpnt->sr_sense_buffer[2] & 0x0f) == MEDIUM_ERROR) + cmdstatp->sense_hdr.sense_key == MEDIUM_ERROR) transfer = bytes; - if (SRpnt->sr_sense_buffer[2] & 0x20) { /* ILI */ + if (cmdstatp->flags & SENSE_ILI) { /* ILI */ if (STp->block_size == 0) { if (transfer <= 0) { if (transfer < 0) @@ -1749,7 +1783,7 @@ if (st_int_ioctl(STp, MTBSR, 1)) return (-EIO); } - } else if (SRpnt->sr_sense_buffer[2] & 0x80) { /* FM overrides EOM */ + } else if (cmdstatp->flags & SENSE_FMK) { /* FM overrides EOM */ if (STps->eof != ST_FM_HIT) STps->eof = ST_FM_HIT; else @@ -1762,7 +1796,7 @@ DEBC(printk(ST_DEB_MSG "%s: EOF detected (%d bytes read).\n", name, STbp->buffer_bytes)); - } else if (SRpnt->sr_sense_buffer[2] & 0x40) { + } else if (cmdstatp->flags & SENSE_EOM) { if (STps->eof == ST_FM) STps->eof = ST_EOD_1; else @@ -1783,7 +1817,7 @@ "%s: Tape error while reading.\n", name)); STps->drv_block = (-1); if (STps->eof == ST_FM && - (SRpnt->sr_sense_buffer[2] & 0x0f) == BLANK_CHECK) { + cmdstatp->sense_hdr.sense_key == BLANK_CHECK) { DEBC(printk(ST_DEB_MSG "%s: Zero returned for first BLANK CHECK after EOF.\n", name)); @@ -1907,7 +1941,7 @@ printk(ST_DEB_MSG "%s: EOF up (%d). Left %d, needed %d.\n", name, STps->eof, STbp->buffer_bytes, - count - total); + (int)(count - total)); ) /* end DEB */ transfer = STbp->buffer_bytes < count - total ? STbp->buffer_bytes : count - total; @@ -2695,23 +2729,26 @@ } else { /* SCSI command was not completely successful. Don't return from this block without releasing the SCSI command block! */ + struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat; - if (SRpnt->sr_sense_buffer[2] & 0x40) { + if (cmdstatp->flags & SENSE_EOM) { if (cmd_in != MTBSF && cmd_in != MTBSFM && cmd_in != MTBSR && cmd_in != MTBSS) STps->eof = ST_EOM_OK; STps->drv_block = 0; } - undone = ((SRpnt->sr_sense_buffer[3] << 24) + - (SRpnt->sr_sense_buffer[4] << 16) + - (SRpnt->sr_sense_buffer[5] << 8) + - SRpnt->sr_sense_buffer[6]); + if (cmdstatp->remainder_valid) + undone = (int)cmdstatp->uremainder64; + else + undone = 0; if (cmd_in == MTWEOF && - (SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 && - (SRpnt->sr_sense_buffer[2] & 0x4f) == 0x40 && - ((SRpnt->sr_sense_buffer[0] & 0x80) == 0 || undone == 0)) { + cmdstatp->have_sense && + (cmdstatp->flags & SENSE_EOM) && + (cmdstatp->sense_hdr.sense_key == NO_SENSE || + cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) && + undone == 0) { ioctl_result = 0; /* EOF written succesfully at EOM */ if (fileno >= 0) fileno++; @@ -2732,7 +2769,7 @@ STps->drv_block = 0; STps->eof = ST_NOEOF; } else if (cmd_in == MTFSR) { - if (SRpnt->sr_sense_buffer[2] & 0x80) { /* Hit filemark */ + if (cmdstatp->flags & SENSE_FMK) { /* Hit filemark */ if (STps->drv_file >= 0) STps->drv_file++; STps->drv_block = 0; @@ -2745,7 +2782,7 @@ STps->eof = ST_NOEOF; } } else if (cmd_in == MTBSR) { - if (SRpnt->sr_sense_buffer[2] & 0x80) { /* Hit filemark */ + if (cmdstatp->flags & SENSE_FMK) { /* Hit filemark */ STps->drv_file--; STps->drv_block = (-1); } else { @@ -2763,7 +2800,7 @@ cmd_in == MTSETDENSITY || cmd_in == MTSETDRVBUFFER || cmd_in == SET_DENS_AND_BLK) { - if ((SRpnt->sr_sense_buffer[2] & 0x0f) == ILLEGAL_REQUEST && + if (cmdstatp->sense_hdr.sense_key == ILLEGAL_REQUEST && !(STp->use_pf & PF_TESTED)) { /* Try the other possible state of Page Format if not already tried */ @@ -2775,7 +2812,7 @@ } else if (chg_eof) STps->eof = ST_NOEOF; - if ((SRpnt->sr_sense_buffer[2] & 0x0f) == BLANK_CHECK) + if (cmdstatp->sense_hdr.sense_key == BLANK_CHECK) STps->eof = ST_EOD; scsi_release_request(SRpnt); @@ -3425,6 +3462,22 @@ up(&STp->lock); return retval; } + +#ifdef CONFIG_COMPAT +static long st_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct scsi_tape *STp = file->private_data; + struct scsi_device *sdev = STp->device; + int ret = -ENOIOCTLCMD; + if (sdev->host->hostt->compat_ioctl) { + + ret = sdev->host->hostt->compat_ioctl(sdev, cmd, (void __user *)arg); + + } + return ret; +} +#endif + /* Try to allocate a new tape buffer. Calling function must not hold @@ -3716,6 +3769,9 @@ .read = st_read, .write = st_write, .ioctl = st_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = st_compat_ioctl, +#endif .open = st_open, .flush = st_flush, .release = st_release, diff -Nru a/drivers/scsi/st.h b/drivers/scsi/st.h --- a/drivers/scsi/st.h 2005-03-03 21:48:52 -08:00 +++ b/drivers/scsi/st.h 2005-03-03 21:48:52 -08:00 @@ -5,6 +5,18 @@ #include +/* Descriptor for analyzed sense data */ +struct st_cmdstatus { + int midlevel_result; + struct scsi_sense_hdr sense_hdr; + int have_sense; + u64 uremainder64; + u8 flags; + u8 remainder_valid; + u8 fixed_format; + u8 deferred; +}; + /* The tape buffer descriptor. */ struct st_buffer { unsigned char in_use; @@ -15,9 +27,9 @@ int buffer_bytes; int read_pointer; int writing; - int midlevel_result; int syscall_result; struct scsi_request *last_SRpnt; + struct st_cmdstatus cmdstat; unsigned char *b_data; unsigned short use_sg; /* zero or max number of s/g segments for this adapter */ unsigned short sg_segs; /* number of segments in s/g list */ @@ -191,5 +203,10 @@ #define ST_YES 2 #define EXTENDED_SENSE_START 18 + +/* Masks for some conditions in the sense data */ +#define SENSE_FMK 0x80 +#define SENSE_EOM 0x40 +#define SENSE_ILI 0x20 #endif diff -Nru a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h --- a/include/scsi/scsi_cmnd.h 2005-03-03 21:48:52 -08:00 +++ b/include/scsi/scsi_cmnd.h 2005-03-03 21:48:52 -08:00 @@ -54,6 +54,7 @@ * completed and the SCSI Command structure has already being reused * for another command, so that we can avoid incorrectly aborting or * resetting the new command. + * The serial number is only unique per host. */ unsigned long serial_number; unsigned long serial_number_at_timeout; @@ -139,7 +140,7 @@ int result; /* Status code from lower level driver */ unsigned char tag; /* SCSI-II queued command tag */ - unsigned long pid; /* Process ID, starts at 0 */ + unsigned long pid; /* Process ID, starts at 0. Unique per host. */ }; /* diff -Nru a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h --- a/include/scsi/scsi_device.h 2005-03-03 21:48:52 -08:00 +++ b/include/scsi/scsi_device.h 2005-03-03 21:48:52 -08:00 @@ -118,6 +118,10 @@ unsigned int max_device_blocked; /* what device_blocked counts down from */ #define SCSI_DEFAULT_DEVICE_BLOCKED 3 + atomic_t iorequest_cnt; + atomic_t iodone_cnt; + atomic_t ioerr_cnt; + int timeout; struct device sdev_gendev; diff -Nru a/include/scsi/scsi_devinfo.h b/include/scsi/scsi_devinfo.h --- a/include/scsi/scsi_devinfo.h 2005-03-03 21:48:52 -08:00 +++ b/include/scsi/scsi_devinfo.h 2005-03-03 21:48:52 -08:00 @@ -27,4 +27,5 @@ #define BLIST_NOT_LOCKABLE 0x80000 /* don't use PREVENT-ALLOW commands */ #define BLIST_NO_ULD_ATTACH 0x100000 /* device is actually for RAID config */ #define BLIST_SELECT_NO_ATN 0x200000 /* select without ATN */ +#define BLIST_RETRY_HWERROR 0x400000 /* retry HARDWARE_ERROR */ #endif diff -Nru a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h --- a/include/scsi/scsi_host.h 2005-03-03 21:48:52 -08:00 +++ b/include/scsi/scsi_host.h 2005-03-03 21:48:52 -08:00 @@ -483,7 +483,12 @@ short unsigned int sg_tablesize; short unsigned int max_sectors; unsigned long dma_boundary; - + /* + * Used to assign serial numbers to the cmds. + * Protected by the host lock. + */ + unsigned long cmd_serial_number, cmd_pid; + unsigned unchecked_isa_dma:1; unsigned use_clustering:1; unsigned use_blk_tcq:1; diff -Nru a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h --- a/include/scsi/scsi_transport_fc.h 2005-03-03 21:48:52 -08:00 +++ b/include/scsi/scsi_transport_fc.h 2005-03-03 21:48:52 -08:00 @@ -197,11 +197,7 @@ char symbolic_name[FC_SYMBOLIC_NAME_SIZE]; u32 supported_speeds; u32 maxframe_size; - char hardware_version[FC_VERSION_STRING_SIZE]; - char firmware_version[FC_VERSION_STRING_SIZE]; char serial_number[FC_SERIAL_NUMBER_SIZE]; - char opt_rom_version[FC_VERSION_STRING_SIZE]; - char driver_version[FC_VERSION_STRING_SIZE]; /* Dynamic Attributes */ u32 port_id;