aic79xx: remove qfrozen
Subsystems (2)
PATCH 1/7 aic79xx: remove qfrozen
This patch removes the need for platform_data->qfrozen. We're now using complete() instead of semaphores thus simplifying ahd_freeze_simq() quite a lot.
This also fixes some deadlocks in the recovery code (again).
Signed-off-by Hannes Reinecke <[email protected]>
Signature · 4 lines
Dr. Hannes Reinecke [email protected] SuSE Linux Products GmbH S390 & zSeries Maxfeldstraße 5 +49 911 74053 688 90409 Nürnberg http://www.suse.de
[PATCH 01/07] aic79xx: remove qfrozen
This patch removes the need for platform_data->qfrozen. We're now using complete() instead of semaphores thus simplifying ahd_freeze_simq() quite a lot.
This also fixes some deadlocks in the recovery code (again).
Signed-off-by Hannes Reinecke <[email protected]>
--- aic79xx_osm.c | 104 ++++++++++++++-------------------------------------------- aic79xx_osm.h | 5 -- 2 files changed, 27 insertions(+), 82 deletions(-)
drivers/scsi/aic7xxx/aic79xx_osm.c +26 -78
@@ -373,7 +373,6 @@ static void ahd_linux_handle_scsi_status struct scb *);static void ahd_linux_queue_cmd_complete (struct ahd_softc *ahd,struct scsi_cmnd *cmd); -static void ahd_linux_sem_timeout (u_long arg);static int ahd_linux_queue_recovery_cmd (struct scsi_cmnd *cmd,scb_flag flag);static void ahd_linux_initialize_scsi_bus (struct ahd_softc *ahd); static u_int ahd_linux_user_tagdepth(struct ahd_softc *ahd,
@@ -453,18 +452,13 @@ ahd_linux_queue(struct scsi_cmnd * cmd,struct ahd_softc *ahd;struct ahd_linux_device *dev =scsi_transport_device_data (cmd->device);int rtn =SCSI_MLQUEUE_HOST_BUSY ; -unsigned long flags; ahd = *(struct ahd_softc **)cmd->device->host->hostdata; -ahd_lock (ahd, &flags); -if (ahd->platform_data->qfrozen ==0 ) { - cmd->scsi_done = scsi_done; - cmd->result =CAM_REQ_INPROG <<16 ; - rtn =ahd_linux_run_command (ahd, dev, cmd); + cmd->scsi_done = scsi_done; + cmd->result =CAM_REQ_INPROG <<16 ; + rtn =ahd_linux_run_command (ahd, dev, cmd); - } -ahd_unlock (ahd, &flags);return rtn; }
@@ -682,7 +676,6 @@ static int ahd_linux_bus_reset(struct scsi_cmnd *cmd) {struct ahd_softc *ahd; -u_long s;int found; ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
@@ -691,10 +684,8 @@ ahd_linux_bus_reset(struct scsi_cmnd *cmprintf ("%s: Bus reset called for cmd %p\n" ,ahd_name (ahd), cmd);#endif -ahd_lock (ahd, &s); found =ahd_reset_channel (ahd,scmd_channel (cmd) +'A' ,/*initiate reset*/ TRUE); -ahd_unlock (ahd, &s);if (bootverbose) printf("%s: SCSI bus reset delivered. "
@@ -1194,7 +1185,6 @@ ahd_platform_alloc(struct ahd_softc *ahdmemset (ahd->platform_data,0 ,sizeof (struct ahd_platform_data )); ahd->platform_data->irq =AHD_LINUX_NOIRQ ;ahd_lockinit (ahd); -init_MUTEX_LOCKED (&ahd->platform_data->eh_sem); ahd->seltime = (aic79xx_seltime &0x3 ) <<4 ;return (0 ); }
@@ -1443,6 +1433,9 @@ ahd_linux_run_command(struct ahd_softc *struct ahd_tmode_tstate *tstate;u_int col_idx;uint16_t mask; +unsigned long flags; + +ahd_lock (ahd, &flags);/* * Get an scb to use.
@@ -1458,6 +1451,7 @@ ahd_linux_run_command(struct ahd_softc * }if ((scb =ahd_get_scb (ahd, col_idx)) ==NULL ) { ahd->flags |=AHD_RESOURCE_SHORTAGE ; +ahd_unlock (ahd, &flags);return SCSI_MLQUEUE_HOST_BUSY ; }
@@ -1583,6 +1577,8 @@ ahd_linux_run_command(struct ahd_softc * scb->flags |=SCB_ACTIVE ;ahd_queue_scb (ahd, scb); +ahd_unlock (ahd, &flags); +return 0 ; }
@@ -1618,7 +1614,6 @@ ahd_send_async(struct ahd_softc *ahd, ch {char buf[80 ];struct scsi_target *starget; -struct ahd_linux_target *targ;struct info_str info;struct ahd_initiator_tinfo *tinfo;struct ahd_tmode_tstate *tstate;
@@ -1651,7 +1646,6 @@ ahd_send_async(struct ahd_softc *ahd, ch starget = ahd->platform_data->starget[target];if (starget ==NULL )break ; - targ =scsi_transport_target_data (starget); target_ppr_options = (spi_dt (starget) ?MSG_EXT_PPR_DT_REQ :0 )
@@ -1803,10 +1797,9 @@ ahd_done(struct ahd_softc *ahd, struct sif (ahd_get_transaction_status (scb) ==CAM_BDR_SENT ||ahd_get_transaction_status (scb) ==CAM_REQ_ABORTED )ahd_set_transaction_status (scb,CAM_CMD_TIMEOUT ); -if ((ahd->platform_data->flags &AHD_SCB_UP_EH_SEM ) !=0 ) { - ahd->platform_data->flags &= ~AHD_SCB_UP_EH_SEM ; -up (&ahd->platform_data->eh_sem); - } + +if (ahd->platform_data->eh_done) +complete (ahd->platform_data->eh_done); }ahd_free_scb (ahd, scb);
@@ -2030,60 +2023,16 @@ ahd_linux_queue_cmd_complete(struct ahd_ cmd->scsi_done (cmd); } -static void -ahd_linux_sem_timeout (u_long arg) -{ -struct ahd_softc *ahd; -u_long s; - - ahd = (struct ahd_softc *)arg; - -ahd_lock (ahd, &s); -if ((ahd->platform_data->flags &AHD_SCB_UP_EH_SEM ) !=0 ) { - ahd->platform_data->flags &= ~AHD_SCB_UP_EH_SEM ; -up (&ahd->platform_data->eh_sem); - } -ahd_unlock (ahd, &s); -} -void ahd_freeze_simq (struct ahd_softc *ahd) { -unsigned long s; - -ahd_lock (ahd, &s); - ahd->platform_data->qfrozen++; -if (ahd->platform_data->qfrozen ==1 ) { -scsi_block_requests (ahd->platform_data->host); -ahd_platform_abort_scbs (ahd,CAM_TARGET_WILDCARD ,ALL_CHANNELS , -CAM_LUN_WILDCARD ,SCB_LIST_NULL , -ROLE_INITIATOR ,CAM_REQUEUE_REQ ); - } -ahd_unlock (ahd, &s); +scsi_block_requests (ahd->platform_data->host); }void ahd_release_simq (struct ahd_softc *ahd) { -u_long s; -int unblock_reqs; - - unblock_reqs =0 ; -ahd_lock (ahd, &s); -if (ahd->platform_data->qfrozen >0 ) - ahd->platform_data->qfrozen--; -if (ahd->platform_data->qfrozen ==0 ) { - unblock_reqs =1 ; - } -ahd_unlock (ahd, &s); -/* -* There is still a race here. The mid-layer -* should keep its own freeze count and use -* a bottom half handler to run the queues -* so we can unblock with our own lock held. -*/ -if (unblock_reqs) -scsi_unblock_requests (ahd->platform_data->host); +scsi_unblock_requests (ahd->platform_data->host); } static int
@@ -2344,30 +2293,29 @@ done:if (paused)ahd_unpause (ahd);if (wait) { -struct timer_list timer; -int ret; +DECLARE_COMPLETION (done); - ahd->platform_data->flags |=AHD_SCB_UP_EH_SEM ; + ahd->platform_data->eh_done = &done;ahd_unlock (ahd, &flags); -init_timer (&timer); - timer.data = (u_long )ahd; - timer.expires = jiffies + (5 *HZ ); - timer.function = ahd_linux_sem_timeout; -add_timer (&timer);printf ("%s: Recovery code sleeping\n" ,ahd_name (ahd)); -down (&ahd->platform_data->eh_sem); -printf ("%s: Recovery code awake\n" ,ahd_name (ahd)); - ret =del_timer_sync (&timer); -if (ret ==0 ) { +if (!wait_for_completion_timeout (&done,5 *HZ )) { +ahd_lock (ahd, &flags); + ahd->platform_data->eh_done =NULL ; +ahd_unlock (ahd, &flags);printf ("%s: Timer Expired (active %d)\n" ,ahd_name (ahd), dev->active); retval =FAILED ; } +printf ("Recovery code awake\n" ); }else ahd_unlock (ahd, &flags); -return (retval); +if (retval !=SUCCESS ) +printf ("%s: Command abort returning 0x%x\n" , +ahd_name (ahd), retval); + +return retval; }static void ahd_linux_set_width (struct scsi_target *starget,int width)
drivers/scsi/aic7xxx/aic79xx_osm.h +1 -4
@@ -381,15 +381,12 @@ struct ahd_platform_data {struct scsi_target *starget[AHD_NUM_TARGETS ];spinlock_t spin_lock; -u_int qfrozen; -struct semaphore eh_sem; +struct completion *eh_done;struct Scsi_Host *host;/* pointer to scsi host */ #define AHD_LINUX_NOIRQ ((uint32_t)~0)uint32_t irq;/* IRQ for this adapter */ uint32_t bios_address;uint32_t mem_busaddr;/* Mem Base Addr */ -#define AHD_SCB_UP_EH_SEM 0x1 -uint32_t flags; };/************************** OS Utility Wrappers *******************************/