[Linux1394-cvslog] rev 768 - trunk
Brought to you by:
aeb,
bencollins
From: SVN U. <ben...@li...> - 2003-02-05 04:41:53
|
Author: bencollins Date: 2003-02-04 23:41:18 -0500 (Tue, 04 Feb 2003) New Revision: 768 Modified: trunk/sbp2.c Log: Patch from Sancho Dauskard fixing sbp2 SMP lockups. Modified: trunk/sbp2.c ============================================================================== --- trunk/sbp2.c (original) +++ trunk/sbp2.c 2003-02-04 23:41:19.000000000 -0500 @@ -296,6 +296,9 @@ * returns the dead bit in status. Thanks to Chandan (ch...@to...) for this one. * 04/27/02 - Fix sbp2 login problem on SMP systems, enable real spinlocks by default. (JSG) * 06/09/02 - Don't force 36-bute SCSI inquiry, but leave in a define for badly behaved devices. (JSG) + * 02/04/03 - Fixed a SMP deadlock (don't hold sbp2_command_lock while calling sbp2scsi_complete_command). + * Also save/restore irq flags in sbp2scsi_complete_command - Sancho Dauskardt <sd...@bd...> + * */ @@ -2605,13 +2608,6 @@ } SBP2_ORB_DEBUG("completing command orb %p", &command->command_orb); - - /* - * Complete the SCSI command - */ - SBP2_DEBUG("Completing SCSI command"); - sbp2scsi_complete_command(hi, scsi_id, scsi_status, SCpnt, command->Current_done); - SBP2_ORB_DEBUG("command orb completed"); } /* @@ -2636,6 +2632,22 @@ } sbp2_spin_unlock(&hi->sbp2_command_lock, flags); + + + if (SCpnt) { + + /* + * Complete the SCSI command. + * + * Only do it after we've released the sbp2_command_lock, + * as it might otherwise deadlock with the + * io_request_lock (in sbp2scsi_queuecommand). + */ + SBP2_DEBUG("Completing SCSI command"); + sbp2scsi_complete_command(hi, scsi_id, scsi_status, SCpnt, command->Current_done); + SBP2_ORB_DEBUG("command orb completed"); + } + return(RCODE_COMPLETE); } @@ -2761,10 +2773,14 @@ /* * This function is called in order to complete a regular SBP-2 command. + * + * This can be called in interrupt context. */ static void sbp2scsi_complete_command(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id, u32 scsi_status, Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { + unsigned long flags; + SBP2_DEBUG("sbp2scsi_complete_command"); /* @@ -2864,13 +2880,13 @@ * Tell scsi stack that we're done with this command */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - spin_lock_irq(&io_request_lock); + spin_lock_irqsave(&io_request_lock,flags); done (SCpnt); - spin_unlock_irq(&io_request_lock); + spin_unlock_irqrestore(&io_request_lock,flags); #else - spin_lock_irq(hi->scsi_host->host_lock); + spin_lock_irqsave(hi->scsi_host->host_lock,flags); done (SCpnt); - spin_unlock_irq(hi->scsi_host->host_lock); + spin_unlock_irqrestore(hi->scsi_host->host_lock,flags); #endif return; |