Commit b333a819 authored by Douglas Gilbert's avatar Douglas Gilbert Committed by Martin K. Petersen

scsi_debug: replace jiffy timers with hr timers

The driver supports two command delay interfaces, the original one whose
unit is a jiffy, and a newer one whose unit is a nanosecond. Each had
different implementations.  Keep both interfaces but simplify the
implemenation to use a single delay mechanism based on high resolution
timers.
Signed-off-by: default avatarDouglas Gilbert <dgilbert@interlog.com>
Reviewed-by: default avatarHannes Reinicke <hare@suse.de>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 185dd232
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/timer.h> #include <linux/jiffies.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/string.h> #include <linux/string.h>
...@@ -518,7 +518,7 @@ struct sdebug_scmd_extra_t { ...@@ -518,7 +518,7 @@ struct sdebug_scmd_extra_t {
static int sdebug_add_host = DEF_NUM_HOST; static int sdebug_add_host = DEF_NUM_HOST;
static int sdebug_ato = DEF_ATO; static int sdebug_ato = DEF_ATO;
static int sdebug_delay = DEF_DELAY; static int sdebug_delay = DEF_DELAY; /* in jiffies */
static int sdebug_dev_size_mb = DEF_DEV_SIZE_MB; static int sdebug_dev_size_mb = DEF_DEV_SIZE_MB;
static int sdebug_dif = DEF_DIF; static int sdebug_dif = DEF_DIF;
static int sdebug_dix = DEF_DIX; static int sdebug_dix = DEF_DIX;
...@@ -530,7 +530,7 @@ static int sdebug_lowest_aligned = DEF_LOWEST_ALIGNED; ...@@ -530,7 +530,7 @@ static int sdebug_lowest_aligned = DEF_LOWEST_ALIGNED;
static int sdebug_max_luns = DEF_MAX_LUNS; static int sdebug_max_luns = DEF_MAX_LUNS;
static int sdebug_max_queue = SCSI_DEBUG_CANQUEUE; static int sdebug_max_queue = SCSI_DEBUG_CANQUEUE;
static atomic_t retired_max_queue; /* if > 0 then was prior max_queue */ static atomic_t retired_max_queue; /* if > 0 then was prior max_queue */
static int sdebug_ndelay = DEF_NDELAY; static int sdebug_ndelay = DEF_NDELAY; /* in nanoseconds */
static int sdebug_no_lun_0 = DEF_NO_LUN_0; static int sdebug_no_lun_0 = DEF_NO_LUN_0;
static int sdebug_no_uld; static int sdebug_no_uld;
static int sdebug_num_parts = DEF_NUM_PARTS; static int sdebug_num_parts = DEF_NUM_PARTS;
...@@ -617,7 +617,6 @@ struct sdebug_hrtimer { /* ... is derived from hrtimer */ ...@@ -617,7 +617,6 @@ struct sdebug_hrtimer { /* ... is derived from hrtimer */
struct sdebug_queued_cmd { struct sdebug_queued_cmd {
/* in_use flagged by a bit in queued_in_use_bm[] */ /* in_use flagged by a bit in queued_in_use_bm[] */
struct timer_list *cmnd_timerp;
struct tasklet_struct *tletp; struct tasklet_struct *tletp;
struct sdebug_hrtimer *sd_hrtp; struct sdebug_hrtimer *sd_hrtp;
struct scsi_cmnd * a_cmnd; struct scsi_cmnd * a_cmnd;
...@@ -3151,7 +3150,7 @@ resp_unmap(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) ...@@ -3151,7 +3150,7 @@ resp_unmap(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
return check_condition_result; return check_condition_result;
} }
buf = kmalloc(scsi_bufflen(scp), GFP_ATOMIC); buf = kzalloc(scsi_bufflen(scp), GFP_ATOMIC);
if (!buf) { if (!buf) {
mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC, mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
INSUFF_RES_ASCQ); INSUFF_RES_ASCQ);
...@@ -3298,7 +3297,7 @@ static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba, ...@@ -3298,7 +3297,7 @@ static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
struct sg_mapping_iter miter; struct sg_mapping_iter miter;
/* better not to use temporary buffer. */ /* better not to use temporary buffer. */
buf = kmalloc(scsi_bufflen(scp), GFP_ATOMIC); buf = kzalloc(scsi_bufflen(scp), GFP_ATOMIC);
if (!buf) { if (!buf) {
mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC, mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
INSUFF_RES_ASCQ); INSUFF_RES_ASCQ);
...@@ -3350,7 +3349,7 @@ resp_xdwriteread_10(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) ...@@ -3350,7 +3349,7 @@ resp_xdwriteread_10(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
return resp_xdwriteread(scp, lba, num, devip); return resp_xdwriteread(scp, lba, num, devip);
} }
/* When timer or tasklet goes off this function is called. */ /* When tasklet goes off this function is called. */
static void sdebug_q_cmd_complete(unsigned long indx) static void sdebug_q_cmd_complete(unsigned long indx)
{ {
int qa_indx; int qa_indx;
...@@ -3592,14 +3591,11 @@ static int stop_queued_cmnd(struct scsi_cmnd *cmnd) ...@@ -3592,14 +3591,11 @@ static int stop_queued_cmnd(struct scsi_cmnd *cmnd)
sqcp->a_cmnd = NULL; sqcp->a_cmnd = NULL;
spin_unlock_irqrestore(&queued_arr_lock, spin_unlock_irqrestore(&queued_arr_lock,
iflags); iflags);
if (sdebug_ndelay > 0) { if ((sdebug_delay > 0) ||
(sdebug_ndelay > 0)) {
if (sqcp->sd_hrtp) if (sqcp->sd_hrtp)
hrtimer_cancel( hrtimer_cancel(
&sqcp->sd_hrtp->hrt); &sqcp->sd_hrtp->hrt);
} else if (sdebug_delay > 0) {
if (sqcp->cmnd_timerp)
del_timer_sync(
sqcp->cmnd_timerp);
} else if (sdebug_delay < 0) { } else if (sdebug_delay < 0) {
if (sqcp->tletp) if (sqcp->tletp)
tasklet_kill(sqcp->tletp); tasklet_kill(sqcp->tletp);
...@@ -3633,14 +3629,11 @@ static void stop_all_queued(void) ...@@ -3633,14 +3629,11 @@ static void stop_all_queued(void)
sqcp->a_cmnd = NULL; sqcp->a_cmnd = NULL;
spin_unlock_irqrestore(&queued_arr_lock, spin_unlock_irqrestore(&queued_arr_lock,
iflags); iflags);
if (sdebug_ndelay > 0) { if ((sdebug_delay > 0) ||
(sdebug_ndelay > 0)) {
if (sqcp->sd_hrtp) if (sqcp->sd_hrtp)
hrtimer_cancel( hrtimer_cancel(
&sqcp->sd_hrtp->hrt); &sqcp->sd_hrtp->hrt);
} else if (sdebug_delay > 0) {
if (sqcp->cmnd_timerp)
del_timer_sync(
sqcp->cmnd_timerp);
} else if (sdebug_delay < 0) { } else if (sdebug_delay < 0) {
if (sqcp->tletp) if (sqcp->tletp)
tasklet_kill(sqcp->tletp); tasklet_kill(sqcp->tletp);
...@@ -3663,8 +3656,6 @@ static void free_all_queued(void) ...@@ -3663,8 +3656,6 @@ static void free_all_queued(void)
spin_lock_irqsave(&queued_arr_lock, iflags); spin_lock_irqsave(&queued_arr_lock, iflags);
for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) { for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
sqcp = &queued_arr[k]; sqcp = &queued_arr[k];
kfree(sqcp->cmnd_timerp);
sqcp->cmnd_timerp = NULL;
kfree(sqcp->tletp); kfree(sqcp->tletp);
sqcp->tletp = NULL; sqcp->tletp = NULL;
kfree(sqcp->sd_hrtp); kfree(sqcp->sd_hrtp);
...@@ -3921,24 +3912,19 @@ schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, ...@@ -3921,24 +3912,19 @@ schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
sqcp->a_cmnd = cmnd; sqcp->a_cmnd = cmnd;
cmnd->result = scsi_result; cmnd->result = scsi_result;
spin_unlock_irqrestore(&queued_arr_lock, iflags); spin_unlock_irqrestore(&queued_arr_lock, iflags);
if (delta_jiff > 0) { if ((delta_jiff > 0) || (sdebug_ndelay > 0)) {
if (NULL == sqcp->cmnd_timerp) {
sqcp->cmnd_timerp = kmalloc(sizeof(struct timer_list),
GFP_ATOMIC);
if (NULL == sqcp->cmnd_timerp)
return SCSI_MLQUEUE_HOST_BUSY;
init_timer(sqcp->cmnd_timerp);
}
sqcp->cmnd_timerp->function = sdebug_q_cmd_complete;
sqcp->cmnd_timerp->data = k;
sqcp->cmnd_timerp->expires = get_jiffies_64() + delta_jiff;
add_timer(sqcp->cmnd_timerp);
} else if (sdebug_ndelay > 0) {
ktime_t kt = ktime_set(0, sdebug_ndelay);
struct sdebug_hrtimer *sd_hp = sqcp->sd_hrtp; struct sdebug_hrtimer *sd_hp = sqcp->sd_hrtp;
ktime_t kt;
if (delta_jiff > 0) {
struct timespec ts;
jiffies_to_timespec(delta_jiff, &ts);
kt = ktime_set(ts.tv_sec, ts.tv_nsec);
} else
kt = ktime_set(0, sdebug_ndelay);
if (NULL == sd_hp) { if (NULL == sd_hp) {
sd_hp = kmalloc(sizeof(*sd_hp), GFP_ATOMIC); sd_hp = kzalloc(sizeof(*sd_hp), GFP_ATOMIC);
if (NULL == sd_hp) if (NULL == sd_hp)
return SCSI_MLQUEUE_HOST_BUSY; return SCSI_MLQUEUE_HOST_BUSY;
sqcp->sd_hrtp = sd_hp; sqcp->sd_hrtp = sd_hp;
...@@ -3950,7 +3936,7 @@ schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, ...@@ -3950,7 +3936,7 @@ schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
hrtimer_start(&sd_hp->hrt, kt, HRTIMER_MODE_REL); hrtimer_start(&sd_hp->hrt, kt, HRTIMER_MODE_REL);
} else { /* delay < 0 */ } else { /* delay < 0 */
if (NULL == sqcp->tletp) { if (NULL == sqcp->tletp) {
sqcp->tletp = kmalloc(sizeof(*sqcp->tletp), sqcp->tletp = kzalloc(sizeof(*sqcp->tletp),
GFP_ATOMIC); GFP_ATOMIC);
if (NULL == sqcp->tletp) if (NULL == sqcp->tletp)
return SCSI_MLQUEUE_HOST_BUSY; return SCSI_MLQUEUE_HOST_BUSY;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment