aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/sg.c53
1 files changed, 48 insertions, 5 deletions
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 661f9f21650a..487c7776cc4e 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -137,6 +137,7 @@ typedef struct sg_request { /* SG_MAX_QUEUE requests outstanding per file */
137 char orphan; /* 1 -> drop on sight, 0 -> normal */ 137 char orphan; /* 1 -> drop on sight, 0 -> normal */
138 char sg_io_owned; /* 1 -> packet belongs to SG_IO */ 138 char sg_io_owned; /* 1 -> packet belongs to SG_IO */
139 volatile char done; /* 0->before bh, 1->before read, 2->read */ 139 volatile char done; /* 0->before bh, 1->before read, 2->read */
140 struct request *rq;
140} Sg_request; 141} Sg_request;
141 142
142typedef struct sg_fd { /* holds the state of a file descriptor */ 143typedef struct sg_fd { /* holds the state of a file descriptor */
@@ -176,7 +177,7 @@ typedef struct sg_device { /* holds the state of each scsi generic device */
176static int sg_fasync(int fd, struct file *filp, int mode); 177static int sg_fasync(int fd, struct file *filp, int mode);
177/* tasklet or soft irq callback */ 178/* tasklet or soft irq callback */
178static void sg_cmd_done(void *data, char *sense, int result, int resid); 179static void sg_cmd_done(void *data, char *sense, int result, int resid);
179static int sg_start_req(Sg_request * srp); 180static int sg_start_req(Sg_request *srp, unsigned char *cmd);
180static void sg_finish_rem_req(Sg_request * srp); 181static void sg_finish_rem_req(Sg_request * srp);
181static int sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size); 182static int sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size);
182static int sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp, 183static int sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp,
@@ -229,6 +230,11 @@ static int sg_allow_access(struct file *filp, unsigned char *cmd)
229 cmd, filp->f_mode & FMODE_WRITE); 230 cmd, filp->f_mode & FMODE_WRITE);
230} 231}
231 232
233static void sg_rq_end_io(struct request *rq, int uptodate)
234{
235 sg_cmd_done(rq->end_io_data, rq->sense, rq->errors, rq->data_len);
236}
237
232static int 238static int
233sg_open(struct inode *inode, struct file *filp) 239sg_open(struct inode *inode, struct file *filp)
234{ 240{
@@ -732,7 +738,8 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
732 SCSI_LOG_TIMEOUT(4, printk("sg_common_write: scsi opcode=0x%02x, cmd_size=%d\n", 738 SCSI_LOG_TIMEOUT(4, printk("sg_common_write: scsi opcode=0x%02x, cmd_size=%d\n",
733 (int) cmnd[0], (int) hp->cmd_len)); 739 (int) cmnd[0], (int) hp->cmd_len));
734 740
735 if ((k = sg_start_req(srp))) { 741 k = sg_start_req(srp, cmnd);
742 if (k) {
736 SCSI_LOG_TIMEOUT(1, printk("sg_common_write: start_req err=%d\n", k)); 743 SCSI_LOG_TIMEOUT(1, printk("sg_common_write: start_req err=%d\n", k));
737 sg_finish_rem_req(srp); 744 sg_finish_rem_req(srp);
738 return k; /* probably out of space --> ENOMEM */ 745 return k; /* probably out of space --> ENOMEM */
@@ -765,6 +772,12 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
765 hp->duration = jiffies_to_msecs(jiffies); 772 hp->duration = jiffies_to_msecs(jiffies);
766/* Now send everything of to mid-level. The next time we hear about this 773/* Now send everything of to mid-level. The next time we hear about this
767 packet is when sg_cmd_done() is called (i.e. a callback). */ 774 packet is when sg_cmd_done() is called (i.e. a callback). */
775 if (srp->rq) {
776 srp->rq->timeout = timeout;
777 blk_execute_rq_nowait(sdp->device->request_queue, sdp->disk,
778 srp->rq, 1, sg_rq_end_io);
779 return 0;
780 }
768 if (scsi_execute_async(sdp->device, cmnd, hp->cmd_len, data_dir, srp->data.buffer, 781 if (scsi_execute_async(sdp->device, cmnd, hp->cmd_len, data_dir, srp->data.buffer,
769 hp->dxfer_len, srp->data.k_use_sg, timeout, 782 hp->dxfer_len, srp->data.k_use_sg, timeout,
770 SG_DEFAULT_RETRIES, srp, sg_cmd_done, 783 SG_DEFAULT_RETRIES, srp, sg_cmd_done,
@@ -1634,8 +1647,32 @@ exit_sg(void)
1634 idr_destroy(&sg_index_idr); 1647 idr_destroy(&sg_index_idr);
1635} 1648}
1636 1649
1637static int 1650static int __sg_start_req(struct sg_request *srp, struct sg_io_hdr *hp,
1638sg_start_req(Sg_request * srp) 1651 unsigned char *cmd)
1652{
1653 struct sg_fd *sfp = srp->parentfp;
1654 struct request_queue *q = sfp->parentdp->device->request_queue;
1655 struct request *rq;
1656 int rw = hp->dxfer_direction == SG_DXFER_TO_DEV ? WRITE : READ;
1657
1658 rq = blk_get_request(q, rw, GFP_ATOMIC);
1659 if (!rq)
1660 return -ENOMEM;
1661
1662 memcpy(rq->cmd, cmd, hp->cmd_len);
1663
1664 rq->cmd_len = hp->cmd_len;
1665 rq->cmd_type = REQ_TYPE_BLOCK_PC;
1666
1667 srp->rq = rq;
1668 rq->end_io_data = srp;
1669 rq->sense = srp->sense_b;
1670 rq->retries = SG_DEFAULT_RETRIES;
1671
1672 return 0;
1673}
1674
1675static int sg_start_req(Sg_request *srp, unsigned char *cmd)
1639{ 1676{
1640 int res; 1677 int res;
1641 Sg_fd *sfp = srp->parentfp; 1678 Sg_fd *sfp = srp->parentfp;
@@ -1646,8 +1683,10 @@ sg_start_req(Sg_request * srp)
1646 Sg_scatter_hold *rsv_schp = &sfp->reserve; 1683 Sg_scatter_hold *rsv_schp = &sfp->reserve;
1647 1684
1648 SCSI_LOG_TIMEOUT(4, printk("sg_start_req: dxfer_len=%d\n", dxfer_len)); 1685 SCSI_LOG_TIMEOUT(4, printk("sg_start_req: dxfer_len=%d\n", dxfer_len));
1686
1649 if ((dxfer_len <= 0) || (dxfer_dir == SG_DXFER_NONE)) 1687 if ((dxfer_len <= 0) || (dxfer_dir == SG_DXFER_NONE))
1650 return 0; 1688 return __sg_start_req(srp, hp, cmd);
1689
1651 if (sg_allow_dio && (hp->flags & SG_FLAG_DIRECT_IO) && 1690 if (sg_allow_dio && (hp->flags & SG_FLAG_DIRECT_IO) &&
1652 (dxfer_dir != SG_DXFER_UNKNOWN) && (0 == hp->iovec_count) && 1691 (dxfer_dir != SG_DXFER_UNKNOWN) && (0 == hp->iovec_count) &&
1653 (!sfp->parentdp->device->host->unchecked_isa_dma)) { 1692 (!sfp->parentdp->device->host->unchecked_isa_dma)) {
@@ -1678,6 +1717,10 @@ sg_finish_rem_req(Sg_request * srp)
1678 sg_unlink_reserve(sfp, srp); 1717 sg_unlink_reserve(sfp, srp);
1679 else 1718 else
1680 sg_remove_scat(req_schp); 1719 sg_remove_scat(req_schp);
1720
1721 if (srp->rq)
1722 blk_put_request(srp->rq);
1723
1681 sg_remove_request(sfp, srp); 1724 sg_remove_request(sfp, srp);
1682} 1725}
1683 1726