diff options
Diffstat (limited to 'drivers/staging/unisys/visorhba/visorhba_main.c')
-rw-r--r-- | drivers/staging/unisys/visorhba/visorhba_main.c | 114 |
1 files changed, 68 insertions, 46 deletions
diff --git a/drivers/staging/unisys/visorhba/visorhba_main.c b/drivers/staging/unisys/visorhba/visorhba_main.c index e93bb1dbfd97..6a4570d10642 100644 --- a/drivers/staging/unisys/visorhba/visorhba_main.c +++ b/drivers/staging/unisys/visorhba/visorhba_main.c @@ -52,6 +52,8 @@ static int visorhba_resume(struct visor_device *dev, static ssize_t info_debugfs_read(struct file *file, char __user *buf, size_t len, loff_t *offset); +static int set_no_disk_inquiry_result(unsigned char *buf, + size_t len, bool is_lun0); static struct dentry *visorhba_debugfs_dir; static const struct file_operations debugfs_info_fops = { .read = info_debugfs_read, @@ -83,12 +85,6 @@ static struct visor_driver visorhba_driver = { MODULE_DEVICE_TABLE(visorbus, visorhba_channel_types); MODULE_ALIAS("visorbus:" SPAR_VHBA_CHANNEL_PROTOCOL_UUID_STR); -struct visor_thread_info { - struct task_struct *task; - struct completion has_stopped; - int id; -}; - struct visordisk_info { u32 valid; u32 channel, id, lun; /* Disk Path */ @@ -135,7 +131,7 @@ struct visorhba_devdata { struct visordisk_info head; unsigned int max_buff_len; int devnum; - struct visor_thread_info threadinfo; + struct task_struct *thread; int thread_wait_ms; }; @@ -152,28 +148,36 @@ static struct visorhba_devices_open visorhbas_open[VISORHBA_OPEN_MAX]; (iter->lun == match->lun)) /** * visor_thread_start - starts a thread for the device - * @thrinfo: The thread to start * @threadfn: Function the thread starts * @thrcontext: Context to pass to the thread, i.e. devdata * @name: string describing name of thread * * Starts a thread for the device. * - * Return 0 on success; + * Return the task_struct * denoting the thread on success, + * or NULL on failure */ -static int visor_thread_start(struct visor_thread_info *thrinfo, - int (*threadfn)(void *), - void *thrcontext, char *name) +static struct task_struct *visor_thread_start +(int (*threadfn)(void *), void *thrcontext, char *name) { - /* used to stop the thread */ - init_completion(&thrinfo->has_stopped); - thrinfo->task = kthread_run(threadfn, thrcontext, "%s", name); - if (IS_ERR(thrinfo->task)) { - thrinfo->id = 0; - return PTR_ERR(thrinfo->task); + struct task_struct *task; + + task = kthread_run(threadfn, thrcontext, "%s", name); + if (IS_ERR(task)) { + pr_err("visorbus failed to start thread\n"); + return NULL; } - thrinfo->id = thrinfo->task->pid; - return 0; + return task; +} + +/** + * visor_thread_stop - stops the thread if it is running + */ +static void visor_thread_stop(struct task_struct *task) +{ + if (!task) + return; /* no thread running */ + kthread_stop(task); } /** @@ -231,16 +235,17 @@ static void *del_scsipending_ent(struct visorhba_devdata *devdata, int del) { unsigned long flags; - void *sent = NULL; + void *sent; - if (del < MAX_PENDING_REQUESTS) { - spin_lock_irqsave(&devdata->privlock, flags); - sent = devdata->pending[del].sent; + if (del >= MAX_PENDING_REQUESTS) + return NULL; - devdata->pending[del].cmdtype = 0; - devdata->pending[del].sent = NULL; - spin_unlock_irqrestore(&devdata->privlock, flags); - } + spin_lock_irqsave(&devdata->privlock, flags); + sent = devdata->pending[del].sent; + + devdata->pending[del].cmdtype = 0; + devdata->pending[del].sent = NULL; + spin_unlock_irqrestore(&devdata->privlock, flags); return sent; } @@ -681,7 +686,7 @@ static void visorhba_serverdown_complete(struct visorhba_devdata *devdata) /* Stop using the IOVM response queue (queue should be drained * by the end) */ - kthread_stop(devdata->threadinfo.task); + visor_thread_stop(devdata->thread); /* Fail commands that weren't completed */ spin_lock_irqsave(&devdata->privlock, flags); @@ -772,6 +777,24 @@ do_scsi_linuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd) } } +static int set_no_disk_inquiry_result(unsigned char *buf, + size_t len, bool is_lun0) +{ + if (!buf || len < NO_DISK_INQUIRY_RESULT_LEN) + return -EINVAL; + memset(buf, 0, NO_DISK_INQUIRY_RESULT_LEN); + buf[2] = SCSI_SPC2_VER; + if (is_lun0) { + buf[0] = DEV_DISK_CAPABLE_NOT_PRESENT; + buf[3] = DEV_HISUPPORT; + } else { + buf[0] = DEV_NOT_CAPABLE; + } + buf[4] = NO_DISK_INQUIRY_RESULT_LEN - 5; + strncpy(buf + 8, "DELLPSEUDO DEVICE .", NO_DISK_INQUIRY_RESULT_LEN - 8); + return 0; +} + /** * do_scsi_nolinuxstat - scsi command didn't have linuxstat * @cmdrsp: response from IOVM @@ -804,10 +827,8 @@ do_scsi_nolinuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd) * a disk there so we'll present a processor * there. */ - SET_NO_DISK_INQUIRY_RESULT(buf, cmdrsp->scsi.bufflen, - scsidev->lun, - DEV_DISK_CAPABLE_NOT_PRESENT, - DEV_NOT_CAPABLE); + set_no_disk_inquiry_result(buf, (size_t)cmdrsp->scsi.bufflen, + scsidev->lun == 0); if (scsi_sg_count(scsicmd) == 0) { memcpy(scsi_sglist(scsicmd), buf, @@ -929,14 +950,15 @@ static void process_disk_notify(struct Scsi_Host *shost, struct diskaddremove *dar; dar = kzalloc(sizeof(*dar), GFP_ATOMIC); - if (dar) { - dar->add = cmdrsp->disknotify.add; - dar->shost = shost; - dar->channel = cmdrsp->disknotify.channel; - dar->id = cmdrsp->disknotify.id; - dar->lun = cmdrsp->disknotify.lun; - queue_disk_add_remove(dar); - } + if (!dar) + return; + + dar->add = cmdrsp->disknotify.add; + dar->shost = shost; + dar->channel = cmdrsp->disknotify.channel; + dar->id = cmdrsp->disknotify.id; + dar->lun = cmdrsp->disknotify.lun; + queue_disk_add_remove(dar); } /** @@ -1064,8 +1086,8 @@ static int visorhba_resume(struct visor_device *dev, if (devdata->serverdown && !devdata->serverchangingstate) devdata->serverchangingstate = true; - visor_thread_start(&devdata->threadinfo, process_incoming_rsps, - devdata, "vhba_incming"); + devdata->thread = visor_thread_start(process_incoming_rsps, devdata, + "vhba_incming"); devdata->serverdown = false; devdata->serverchangingstate = false; @@ -1141,8 +1163,8 @@ static int visorhba_probe(struct visor_device *dev) goto err_scsi_remove_host; devdata->thread_wait_ms = 2; - visor_thread_start(&devdata->threadinfo, process_incoming_rsps, - devdata, "vhba_incoming"); + devdata->thread = visor_thread_start(process_incoming_rsps, devdata, + "vhba_incoming"); scsi_scan_host(scsihost); @@ -1172,7 +1194,7 @@ static void visorhba_remove(struct visor_device *dev) return; scsihost = devdata->scsihost; - kthread_stop(devdata->threadinfo.task); + visor_thread_stop(devdata->thread); scsi_remove_host(scsihost); scsi_host_put(scsihost); |