浏览代码

[SCSI] aic79xx: Fix timer handling

Fix the timer handling in aic79xx to use the SCSI-ML provided handling
instead of implementing our own.
It also fixes a deadlock in the command recovery code.

Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Hannes Reinecke 19 年之前
父节点
当前提交
eb22184954

+ 2 - 2
drivers/scsi/aic7xxx/Kconfig.aic79xx

@@ -37,13 +37,13 @@ config AIC79XX_CMDS_PER_DEVICE
 config AIC79XX_RESET_DELAY_MS
 config AIC79XX_RESET_DELAY_MS
 	int "Initial bus reset delay in milli-seconds"
 	int "Initial bus reset delay in milli-seconds"
 	depends on SCSI_AIC79XX
 	depends on SCSI_AIC79XX
-	default "15000"
+	default "5000"
 	---help---
 	---help---
 	The number of milliseconds to delay after an initial bus reset.
 	The number of milliseconds to delay after an initial bus reset.
 	The bus settle delay following all error recovery actions is
 	The bus settle delay following all error recovery actions is
 	dictated by the SCSI layer and is not affected by this value.
 	dictated by the SCSI layer and is not affected by this value.
 
 
-	Default: 15000 (15 seconds)
+	Default: 5000 (5 seconds)
 
 
 config AIC79XX_BUILD_FIRMWARE
 config AIC79XX_BUILD_FIRMWARE
 	bool "Build Adapter Firmware with Kernel Build"
 	bool "Build Adapter Firmware with Kernel Build"

+ 0 - 5
drivers/scsi/aic7xxx/aic79xx_core.c

@@ -8273,11 +8273,6 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb)
 		ahd_setup_data_scb(ahd, scb);
 		ahd_setup_data_scb(ahd, scb);
 		scb->flags |= SCB_SENSE;
 		scb->flags |= SCB_SENSE;
 		ahd_queue_scb(ahd, scb);
 		ahd_queue_scb(ahd, scb);
-		/*
-		 * Ensure we have enough time to actually
-		 * retrieve the sense.
-		 */
-		ahd_scb_timer_reset(scb, 5 * 1000000);
 		break;
 		break;
 	}
 	}
 	case SCSI_STATUS_OK:
 	case SCSI_STATUS_OK:

+ 15 - 11
drivers/scsi/aic7xxx/aic79xx_osm.c

@@ -1089,7 +1089,6 @@ ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *templa
 		return (ENOMEM);
 		return (ENOMEM);
 
 
 	*((struct ahd_softc **)host->hostdata) = ahd;
 	*((struct ahd_softc **)host->hostdata) = ahd;
-	ahd_lock(ahd, &s);
 	ahd->platform_data->host = host;
 	ahd->platform_data->host = host;
 	host->can_queue = AHD_MAX_QUEUE;
 	host->can_queue = AHD_MAX_QUEUE;
 	host->cmd_per_lun = 2;
 	host->cmd_per_lun = 2;
@@ -1100,7 +1099,9 @@ ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *templa
 	host->max_lun = AHD_NUM_LUNS;
 	host->max_lun = AHD_NUM_LUNS;
 	host->max_channel = 0;
 	host->max_channel = 0;
 	host->sg_tablesize = AHD_NSEG;
 	host->sg_tablesize = AHD_NSEG;
+	ahd_lock(ahd, &s);
 	ahd_set_unit(ahd, ahd_linux_unit++);
 	ahd_set_unit(ahd, ahd_linux_unit++);
+	ahd_unlock(ahd, &s);
 	sprintf(buf, "scsi%d", host->host_no);
 	sprintf(buf, "scsi%d", host->host_no);
 	new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
 	new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
 	if (new_name != NULL) {
 	if (new_name != NULL) {
@@ -1110,7 +1111,6 @@ ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *templa
 	host->unique_id = ahd->unit;
 	host->unique_id = ahd->unit;
 	ahd_linux_initialize_scsi_bus(ahd);
 	ahd_linux_initialize_scsi_bus(ahd);
 	ahd_intr_enable(ahd, TRUE);
 	ahd_intr_enable(ahd, TRUE);
-	ahd_unlock(ahd, &s);
 
 
 	host->transportt = ahd_linux_transport_template;
 	host->transportt = ahd_linux_transport_template;
 
 
@@ -1144,6 +1144,7 @@ ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd)
 {
 {
 	u_int target_id;
 	u_int target_id;
 	u_int numtarg;
 	u_int numtarg;
+	unsigned long s;
 
 
 	target_id = 0;
 	target_id = 0;
 	numtarg = 0;
 	numtarg = 0;
@@ -1156,6 +1157,8 @@ ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd)
 	else
 	else
 		numtarg = (ahd->features & AHD_WIDE) ? 16 : 8;
 		numtarg = (ahd->features & AHD_WIDE) ? 16 : 8;
 
 
+	ahd_lock(ahd, &s);
+
 	/*
 	/*
 	 * Force negotiation to async for all targets that
 	 * Force negotiation to async for all targets that
 	 * will not see an initial bus reset.
 	 * will not see an initial bus reset.
@@ -1172,16 +1175,12 @@ ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd)
 		ahd_update_neg_request(ahd, &devinfo, tstate,
 		ahd_update_neg_request(ahd, &devinfo, tstate,
 				       tinfo, AHD_NEG_ALWAYS);
 				       tinfo, AHD_NEG_ALWAYS);
 	}
 	}
+	ahd_unlock(ahd, &s);
 	/* Give the bus some time to recover */
 	/* Give the bus some time to recover */
 	if ((ahd->flags & AHD_RESET_BUS_A) != 0) {
 	if ((ahd->flags & AHD_RESET_BUS_A) != 0) {
 		ahd_freeze_simq(ahd);
 		ahd_freeze_simq(ahd);
-		init_timer(&ahd->platform_data->reset_timer);
-		ahd->platform_data->reset_timer.data = (u_long)ahd;
-		ahd->platform_data->reset_timer.expires =
-		    jiffies + (AIC79XX_RESET_DELAY * HZ)/1000;
-		ahd->platform_data->reset_timer.function =
-		    (ahd_linux_callback_t *)ahd_release_simq;
-		add_timer(&ahd->platform_data->reset_timer);
+		msleep(AIC79XX_RESET_DELAY);
+		ahd_release_simq(ahd);
 	}
 	}
 }
 }
 
 
@@ -2050,6 +2049,9 @@ ahd_linux_sem_timeout(u_long arg)
 void
 void
 ahd_freeze_simq(struct ahd_softc *ahd)
 ahd_freeze_simq(struct ahd_softc *ahd)
 {
 {
+	unsigned long s;
+
+	ahd_lock(ahd, &s);
 	ahd->platform_data->qfrozen++;
 	ahd->platform_data->qfrozen++;
 	if (ahd->platform_data->qfrozen == 1) {
 	if (ahd->platform_data->qfrozen == 1) {
 		scsi_block_requests(ahd->platform_data->host);
 		scsi_block_requests(ahd->platform_data->host);
@@ -2057,6 +2059,7 @@ ahd_freeze_simq(struct ahd_softc *ahd)
 					CAM_LUN_WILDCARD, SCB_LIST_NULL,
 					CAM_LUN_WILDCARD, SCB_LIST_NULL,
 					ROLE_INITIATOR, CAM_REQUEUE_REQ);
 					ROLE_INITIATOR, CAM_REQUEUE_REQ);
 	}
 	}
+	ahd_unlock(ahd, &s);
 }
 }
 
 
 void
 void
@@ -2361,8 +2364,9 @@ done:
 			       ahd_name(ahd), dev->active);
 			       ahd_name(ahd), dev->active);
 			retval = FAILED;
 			retval = FAILED;
 		}
 		}
-	}
-	ahd_unlock(ahd, &flags);
+	} else
+		ahd_unlock(ahd, &flags);
+
 	return (retval);
 	return (retval);
 }
 }
 
 

+ 0 - 8
drivers/scsi/aic7xxx/aic79xx_osm.h

@@ -228,7 +228,6 @@ typedef struct timer_list ahd_timer_t;
 typedef void ahd_linux_callback_t (u_long);  
 typedef void ahd_linux_callback_t (u_long);  
 static __inline void ahd_timer_reset(ahd_timer_t *timer, int usec,
 static __inline void ahd_timer_reset(ahd_timer_t *timer, int usec,
 				     ahd_callback_t *func, void *arg);
 				     ahd_callback_t *func, void *arg);
-static __inline void ahd_scb_timer_reset(struct scb *scb, u_int usec);
 
 
 static __inline void
 static __inline void
 ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg)
 ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg)
@@ -243,12 +242,6 @@ ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg)
 	add_timer(timer);
 	add_timer(timer);
 }
 }
 
 
-static __inline void
-ahd_scb_timer_reset(struct scb *scb, u_int usec)
-{
-	mod_timer(&scb->io_ctx->eh_timeout, jiffies + (usec * HZ)/1000000);
-}
-
 /***************************** SMP support ************************************/
 /***************************** SMP support ************************************/
 #include <linux/spinlock.h>
 #include <linux/spinlock.h>
 
 
@@ -389,7 +382,6 @@ struct ahd_platform_data {
 
 
 	spinlock_t		 spin_lock;
 	spinlock_t		 spin_lock;
 	u_int			 qfrozen;
 	u_int			 qfrozen;
-	struct timer_list	 reset_timer;
 	struct semaphore	 eh_sem;
 	struct semaphore	 eh_sem;
 	struct Scsi_Host        *host;		/* pointer to scsi host */
 	struct Scsi_Host        *host;		/* pointer to scsi host */
 #define AHD_LINUX_NOIRQ	((uint32_t)~0)
 #define AHD_LINUX_NOIRQ	((uint32_t)~0)