--- ../vhba-module-1.1.0/vhba.c 2008-06-28 12:08:33.000000000 +0200 +++ vhba.c 2008-11-22 16:43:01.000000000 +0100 @@ -1,7 +1,7 @@ /* * vhba.c * - * Copyright (C) 2007 Chia-I Wu + * Copyright (C) 2007 Chia-I Wu * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -31,6 +31,7 @@ #include #include #include +#include #include @@ -60,6 +61,8 @@ #define DATA_TO_DEVICE(dir) ((dir) == DMA_TO_DEVICE || (dir) == DMA_BIDIRECTIONAL) #define DATA_FROM_DEVICE(dir) ((dir) == DMA_FROM_DEVICE || (dir) == DMA_BIDIRECTIONAL) +unsigned long flags; + enum vhba_req_state { VHBA_REQ_FREE, VHBA_REQ_PENDING, @@ -117,7 +120,7 @@ static struct vhba_device *vhba_device_alloc(void) { struct vhba_device *vdev; - + vdev = kzalloc(sizeof(struct vhba_device), GFP_KERNEL); if (!vdev) return NULL; @@ -147,16 +150,16 @@ static int vhba_device_queue(struct vhba_device *vdev, struct scsi_cmnd *cmd) { struct vhba_command *vcmd; - + vcmd = vhba_alloc_command(); if (!vcmd) return SCSI_MLQUEUE_HOST_BUSY; vcmd->cmd = cmd; - spin_lock_bh(&vdev->cmd_lock); + spin_lock_irqsave(&vdev->cmd_lock, flags); list_add_tail(&vcmd->entry, &vdev->cmd_list); - spin_unlock_bh(&vdev->cmd_lock); + spin_unlock_irqrestore(&vdev->cmd_lock, flags); wake_up_interruptible(&vdev->cmd_wq); @@ -167,8 +170,8 @@ { struct vhba_command *vcmd; int retval; - - spin_lock_bh(&vdev->cmd_lock); + + spin_lock_irqsave(&vdev->cmd_lock, flags); list_for_each_entry(vcmd, &vdev->cmd_list, entry) { if (vcmd->cmd == cmd) @@ -182,24 +185,24 @@ /* command not found */ if (&vcmd->entry == &vdev->cmd_list) { - spin_unlock_bh(&vdev->cmd_lock); + spin_unlock_irqrestore(&vdev->cmd_lock, flags); return SUCCESS; } while (vcmd->status == VHBA_REQ_READING || vcmd->status == VHBA_REQ_WRITING) { - spin_unlock_bh(&vdev->cmd_lock); + spin_unlock_irqrestore(&vdev->cmd_lock, flags); scmd_dbg(cmd, "wait for I/O before aborting\n"); schedule_timeout(1); - spin_lock_bh(&vdev->cmd_lock); + spin_lock_irqsave(&vdev->cmd_lock, flags); } retval = (vcmd->status == VHBA_REQ_SENT) ? FAILED : SUCCESS; vhba_free_command(vcmd); - spin_unlock_bh(&vdev->cmd_lock); + spin_unlock_irqrestore(&vdev->cmd_lock, flags); return retval; } @@ -214,10 +217,10 @@ { int remove; - spin_lock_bh(&vhost->dev_lock); + spin_lock_irqsave(&vhost->dev_lock, flags); clear_bit(id, vhost->chgmap); remove = !(vhost->devices[id]); - spin_unlock_bh(&vhost->dev_lock); + spin_unlock_irqrestore(&vhost->dev_lock, flags); dev_dbg(&vhost->shost->shost_gendev, "try to %s target 0:%d:0\n", (remove) ? "remove" : "add", id); @@ -247,10 +250,10 @@ vhba_device_get(vdev); - spin_lock_bh(&vhost->dev_lock); + spin_lock_irqsave(&vhost->dev_lock, flags); if (vhost->num_devices >= vhost->shost->max_id) { - spin_unlock_bh(&vhost->dev_lock); + spin_unlock_irqrestore(&vhost->dev_lock, flags); vhba_device_put(vdev); return -EBUSY; @@ -268,7 +271,7 @@ break; } } - spin_unlock_bh(&vhost->dev_lock); + spin_unlock_irqrestore(&vhost->dev_lock, flags); schedule_work(&vhost->scan_devices); @@ -281,12 +284,12 @@ vhost = platform_get_drvdata(&vhba_platform_device); - spin_lock_bh(&vhost->dev_lock); + spin_lock_irqsave(&vhost->dev_lock, flags); set_bit(vdev->id, vhost->chgmap); vhost->devices[vdev->id] = NULL; vhost->num_devices--; vdev->id = VHBA_INVALID_ID; - spin_unlock_bh(&vhost->dev_lock); + spin_unlock_irqrestore(&vhost->dev_lock, flags); vhba_device_put(vdev); @@ -304,11 +307,11 @@ if (likely(id < vhost->shost->max_id)) { - spin_lock_bh(&vhost->dev_lock); + spin_lock_irqsave(&vhost->dev_lock, flags); vdev = vhost->devices[id]; if (vdev) vdev = vhba_device_get(vdev); - spin_unlock_bh(&vhost->dev_lock); + spin_unlock_irqrestore(&vhost->dev_lock, flags); } return vdev; @@ -319,10 +322,10 @@ struct vhba_host *vhost; struct vhba_command *vcmd; int i; - + vhost = platform_get_drvdata(&vhba_platform_device); - spin_lock_bh(&vhost->cmd_lock); + spin_lock_irqsave(&vhost->cmd_lock, flags); vcmd = vhost->commands + vhost->cmd_next++; if (vcmd->status != VHBA_REQ_FREE) @@ -347,7 +350,7 @@ vcmd->status = VHBA_REQ_PENDING; vhost->cmd_next %= vhost->shost->can_queue; - spin_unlock_bh(&vhost->cmd_lock); + spin_unlock_irqrestore(&vhost->cmd_lock, flags); return vcmd; } @@ -358,9 +361,9 @@ vhost = platform_get_drvdata(&vhba_platform_device); - spin_lock_bh(&vhost->cmd_lock); + spin_lock_irqsave(&vhost->cmd_lock, flags); vcmd->status = VHBA_REQ_FREE; - spin_unlock_bh(&vhost->cmd_lock); + spin_unlock_irqrestore(&vhost->cmd_lock, flags); } static int vhba_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) @@ -421,25 +424,17 @@ .sg_tablesize = 256, }; -static ssize_t do_request(struct scsi_cmnd *cmd, char __user *buf, size_t buf_len) +static ssize_t do_request(const struct scsi_cmnd *cmd, char __user *buf, size_t buf_len) { struct vhba_request vreq; ssize_t ret; - +// struct scatterlist *sg, scmd_dbg(cmd, "request %lu, cdb 0x%x, bufflen %d, use_sg %d\n", -#ifdef KAT_HAVE_SCSI_MACROS - cmd->serial_number, cmd->cmnd[0], scsi_bufflen(cmd), scsi_sg_count(cmd)); -#else - cmd->serial_number, cmd->cmnd[0], cmd->request_bufflen, cmd->use_sg); -#endif - + cmd->serial_number, cmd->cmnd[0], cmd->sdb.length, cmd->sdb.table.nents); + ret = sizeof(vreq); if (DATA_TO_DEVICE(cmd->sc_data_direction)) -#ifdef KAT_HAVE_SCSI_MACROS - ret += scsi_bufflen(cmd); -#else - ret += cmd->request_bufflen; -#endif + ret += cmd->sdb.length; if (ret > buf_len) { @@ -452,11 +447,7 @@ vreq.lun = cmd->device->lun; memcpy(vreq.cdb, cmd->cmnd, MAX_COMMAND_SIZE); vreq.cdb_len = cmd->cmd_len; -#ifdef KAT_HAVE_SCSI_MACROS - vreq.data_len = scsi_bufflen(cmd); -#else - vreq.data_len = cmd->request_bufflen; -#endif + vreq.data_len = cmd->sdb.length; if (copy_to_user(buf, &vreq, sizeof(vreq))) return -EFAULT; @@ -466,11 +457,7 @@ buf += sizeof(vreq); /* XXX use_sg? */ -#ifdef KAT_HAVE_SCSI_MACROS - if (copy_to_user(buf, scsi_sglist(cmd), vreq.data_len)) -#else - if (copy_to_user(buf, cmd->request_buffer, vreq.data_len)) -#endif + if (copy_to_user(buf, cmd->sdb.table.sgl, vreq.data_len)) return -EFAULT; } @@ -482,11 +469,7 @@ ssize_t ret = 0; scmd_dbg(cmd, "response %lu, status %x, data len %d, use_sg %d\n", -#ifdef KAT_HAVE_SCSI_MACROS - cmd->serial_number, res->status, res->data_len, scsi_sg_count(cmd)); -#else - cmd->serial_number, res->status, res->data_len, cmd->use_sg); -#endif + cmd->serial_number, res->status, res->data_len, cmd->sdb.table.nents); if (res->status) { @@ -503,43 +486,23 @@ ret += res->data_len; } -#ifdef KAT_HAVE_SCSI_MACROS - else if (DATA_FROM_DEVICE(cmd->sc_data_direction) && scsi_bufflen(cmd)) -#else - else if (DATA_FROM_DEVICE(cmd->sc_data_direction) && cmd->request_bufflen) -#endif + else if (DATA_FROM_DEVICE(cmd->sc_data_direction) && cmd->sdb.length) { size_t to_read; -#ifdef KAT_HAVE_SCSI_MACROS - if (res->data_len > scsi_bufflen(cmd)) - { - scmd_warn(cmd, "truncate data (%d < %d)\n", scsi_bufflen(cmd), res->data_len); - res->data_len = scsi_bufflen(cmd); - } -#else - if (res->data_len > cmd->request_bufflen) + if (res->data_len > cmd->sdb.length) { - scmd_warn(cmd, "truncate data (%d < %d)\n", cmd->request_bufflen, res->data_len); - res->data_len = cmd->request_bufflen; + scmd_warn(cmd, "truncate data (%d < %d)\n", cmd->sdb.length, res->data_len); + res->data_len = cmd->sdb.length; } -#endif - + to_read = res->data_len; -#ifdef KAT_HAVE_SCSI_MACROS - if (scsi_sg_count(cmd)) -#else - if (cmd->use_sg) -#endif + if (cmd->sdb.table.nents) { unsigned char buf_stack[64]; unsigned char *kaddr, *uaddr, *kbuf; -#ifdef KAT_HAVE_SCSI_MACROS - struct scatterlist *sg = scsi_sglist(cmd); -#else - struct scatterlist *sg = cmd->request_buffer; -#endif + struct scatterlist *sg = cmd->sdb.table.sgl; int i; uaddr = (unsigned char *) buf; @@ -549,11 +512,7 @@ else kbuf = buf_stack; -#ifdef KAT_HAVE_SCSI_MACROS - for (i = 0; i < scsi_sg_count(cmd); i++) -#else - for (i = 0; i < cmd->use_sg; i++) -#endif + for (i = 0; i < cmd->sdb.table.nents; i++) { size_t len = (sg[i].length < to_read) ? sg[i].length : to_read; @@ -584,21 +543,13 @@ } else { -#ifdef KAT_HAVE_SCSI_MACROS - if (copy_from_user(scsi_sglist(cmd), buf, res->data_len)) -#else - if (copy_from_user(cmd->request_buffer, buf, res->data_len)) -#endif + if (copy_from_user(cmd->sdb.table.sgl, buf, res->data_len)) return -EFAULT; to_read -= res->data_len; } -#ifdef KAT_HAVE_SCSI_MACROS - scsi_set_resid(cmd, to_read); -#else - cmd->resid = to_read; -#endif + cmd->sdb.resid = to_read; ret += res->data_len - to_read; } @@ -650,11 +601,11 @@ prepare_to_wait(&vdev->cmd_wq, &wait, TASK_INTERRUPTIBLE); - spin_unlock_bh(&vdev->cmd_lock); + spin_unlock_irqrestore(&vdev->cmd_lock, flags); schedule(); - spin_lock_bh(&vdev->cmd_lock); + spin_lock_irqsave(&vdev->cmd_lock, flags); } finish_wait(&vdev->cmd_wq, &wait); @@ -672,16 +623,16 @@ vdev = file->private_data; - spin_lock_bh(&vdev->cmd_lock); + spin_lock_irqsave(&vdev->cmd_lock, flags); vcmd = wait_command(vdev); - spin_unlock_bh(&vdev->cmd_lock); + spin_unlock_irqrestore(&vdev->cmd_lock, flags); if (!vcmd) return -ERESTARTSYS; ret = do_request(vcmd->cmd, buf, buf_len); - spin_lock_bh(&vdev->cmd_lock); + spin_lock_irqsave(&vdev->cmd_lock, flags); if (ret >= 0) { vcmd->status = VHBA_REQ_SENT; @@ -689,7 +640,7 @@ } else vcmd->status = VHBA_REQ_PENDING; - spin_unlock_bh(&vdev->cmd_lock); + spin_unlock_irqrestore(&vdev->cmd_lock, flags); return ret; } @@ -709,21 +660,21 @@ vdev = file->private_data; - spin_lock_bh(&vdev->cmd_lock); + spin_lock_irqsave(&vdev->cmd_lock, flags); vcmd = match_command(vdev, res.tag); if (!vcmd || vcmd->status != VHBA_REQ_SENT) { - spin_unlock_bh(&vdev->cmd_lock); + spin_unlock_irqrestore(&vdev->cmd_lock, flags); DPRINTK("not expecting response\n"); return -EIO; } vcmd->status = VHBA_REQ_WRITING; - spin_unlock_bh(&vdev->cmd_lock); + spin_unlock_irqrestore(&vdev->cmd_lock, flags); ret = do_response(vcmd->cmd, buf + sizeof(res), buf_len - sizeof(res), &res); - spin_lock_bh(&vdev->cmd_lock); + spin_lock_irqsave(&vdev->cmd_lock, flags); if (ret >= 0) { vcmd->cmd->scsi_done(vcmd->cmd); @@ -738,48 +689,11 @@ } else vcmd->status = VHBA_REQ_SENT; - spin_unlock_bh(&vdev->cmd_lock); + spin_unlock_irqrestore(&vdev->cmd_lock, flags); return ret; } -static int vhba_ctl_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -{ - struct vhba_device *vdev = file->private_data; - - switch (cmd) { - case 0xBEEF001: { - struct vhba_host *vhost; - struct scsi_device *sdev; - - vhost = platform_get_drvdata(&vhba_platform_device); - sdev = scsi_device_lookup(vhost->shost, 0, vdev->id, 0); - - if (sdev) - { - int id[4] = { - sdev->host->host_no, - sdev->channel, - sdev->id, - sdev->lun }; - - scsi_device_put(sdev); - - if (copy_to_user((void *)arg, id, sizeof(id))) - return -EFAULT; - - return 0; - } - else - { - return -ENODEV; - } - } - } - - return -ENOTTY; -} - static unsigned int vhba_ctl_poll(struct file *file, poll_table *wait) { struct vhba_device *vdev = file->private_data; @@ -787,10 +701,10 @@ poll_wait(file, &vdev->cmd_wq, wait); - spin_lock_bh(&vdev->cmd_lock); + spin_lock_irqsave(&vdev->cmd_lock, flags); if (next_command(vdev)) mask |= POLLIN | POLLRDNORM; - spin_unlock_bh(&vdev->cmd_lock); + spin_unlock_irqrestore(&vdev->cmd_lock, flags); return mask; } @@ -830,7 +744,7 @@ vhba_device_get(vdev); vhba_remove_device(vdev); - spin_lock_bh(&vdev->cmd_lock); + spin_lock_irqsave(&vdev->cmd_lock, flags); list_for_each_entry(vcmd, &vdev->cmd_list, entry) { WARN_ON(vcmd->status == VHBA_REQ_READING || vcmd->status == VHBA_REQ_WRITING); @@ -842,7 +756,7 @@ vhba_free_command(vcmd); } INIT_LIST_HEAD(&vdev->cmd_list); - spin_unlock_bh(&vdev->cmd_lock); + spin_unlock_irqrestore(&vdev->cmd_lock, flags); vhba_device_put(vdev); @@ -856,7 +770,6 @@ .read = vhba_ctl_read, .write = vhba_ctl_write, .poll = vhba_ctl_poll, - .ioctl = vhba_ctl_ioctl, }; static struct miscdevice vhba_miscdev = {