aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/sg.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/sg.c')
-rw-r--r--drivers/scsi/sg.c80
1 files changed, 33 insertions, 47 deletions
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 9a56c0d320bf..c0b6866eece9 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -202,7 +202,6 @@ static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id);
202static Sg_request *sg_add_request(Sg_fd * sfp); 202static Sg_request *sg_add_request(Sg_fd * sfp);
203static int sg_remove_request(Sg_fd * sfp, Sg_request * srp); 203static int sg_remove_request(Sg_fd * sfp, Sg_request * srp);
204static int sg_res_in_use(Sg_fd * sfp); 204static int sg_res_in_use(Sg_fd * sfp);
205static int sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len);
206static Sg_device *sg_get_dev(int dev); 205static Sg_device *sg_get_dev(int dev);
207#ifdef CONFIG_SCSI_PROC_FS 206#ifdef CONFIG_SCSI_PROC_FS
208static int sg_last_dev(void); 207static int sg_last_dev(void);
@@ -1628,16 +1627,17 @@ exit_sg(void)
1628 1627
1629static int sg_start_req(Sg_request *srp, unsigned char *cmd) 1628static int sg_start_req(Sg_request *srp, unsigned char *cmd)
1630{ 1629{
1631 int res = 0; 1630 int res;
1632 struct request *rq; 1631 struct request *rq;
1633 Sg_fd *sfp = srp->parentfp; 1632 Sg_fd *sfp = srp->parentfp;
1634 sg_io_hdr_t *hp = &srp->header; 1633 sg_io_hdr_t *hp = &srp->header;
1635 int dxfer_len = (int) hp->dxfer_len; 1634 int dxfer_len = (int) hp->dxfer_len;
1636 int dxfer_dir = hp->dxfer_direction; 1635 int dxfer_dir = hp->dxfer_direction;
1636 unsigned int iov_count = hp->iovec_count;
1637 Sg_scatter_hold *req_schp = &srp->data; 1637 Sg_scatter_hold *req_schp = &srp->data;
1638 Sg_scatter_hold *rsv_schp = &sfp->reserve; 1638 Sg_scatter_hold *rsv_schp = &sfp->reserve;
1639 struct request_queue *q = sfp->parentdp->device->request_queue; 1639 struct request_queue *q = sfp->parentdp->device->request_queue;
1640 struct rq_map_data map_data; 1640 struct rq_map_data *md, map_data;
1641 int rw = hp->dxfer_direction == SG_DXFER_TO_DEV ? WRITE : READ; 1641 int rw = hp->dxfer_direction == SG_DXFER_TO_DEV ? WRITE : READ;
1642 1642
1643 SCSI_LOG_TIMEOUT(4, printk(KERN_INFO "sg_start_req: dxfer_len=%d\n", 1643 SCSI_LOG_TIMEOUT(4, printk(KERN_INFO "sg_start_req: dxfer_len=%d\n",
@@ -1660,38 +1660,43 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd)
1660 if ((dxfer_len <= 0) || (dxfer_dir == SG_DXFER_NONE)) 1660 if ((dxfer_len <= 0) || (dxfer_dir == SG_DXFER_NONE))
1661 return 0; 1661 return 0;
1662 1662
1663 if (sg_allow_dio && (hp->flags & SG_FLAG_DIRECT_IO) && 1663 if (sg_allow_dio && hp->flags & SG_FLAG_DIRECT_IO &&
1664 (dxfer_dir != SG_DXFER_UNKNOWN) && (0 == hp->iovec_count) && 1664 dxfer_dir != SG_DXFER_UNKNOWN && !iov_count &&
1665 (!sfp->parentdp->device->host->unchecked_isa_dma) && 1665 !sfp->parentdp->device->host->unchecked_isa_dma &&
1666 blk_rq_aligned(q, hp->dxferp, dxfer_len)) 1666 blk_rq_aligned(q, hp->dxferp, dxfer_len))
1667 return sg_build_direct(srp, sfp, dxfer_len); 1667 md = NULL;
1668 else
1669 md = &map_data;
1670
1671 if (md) {
1672 if (!sg_res_in_use(sfp) && dxfer_len <= rsv_schp->bufflen)
1673 sg_link_reserve(sfp, srp, dxfer_len);
1674 else {
1675 res = sg_build_indirect(req_schp, sfp, dxfer_len);
1676 if (res)
1677 return res;
1678 }
1668 1679
1669 if ((!sg_res_in_use(sfp)) && (dxfer_len <= rsv_schp->bufflen)) 1680 md->pages = req_schp->pages;
1670 sg_link_reserve(sfp, srp, dxfer_len); 1681 md->page_order = req_schp->page_order;
1682 md->nr_entries = req_schp->k_use_sg;
1683 }
1684
1685 if (iov_count)
1686 res = blk_rq_map_user_iov(q, rq, md, hp->dxferp, iov_count,
1687 hp->dxfer_len, GFP_ATOMIC);
1671 else 1688 else
1672 res = sg_build_indirect(req_schp, sfp, dxfer_len); 1689 res = blk_rq_map_user(q, rq, md, hp->dxferp,
1690 hp->dxfer_len, GFP_ATOMIC);
1673 1691
1674 if (!res) { 1692 if (!res) {
1675 struct request *rq = srp->rq; 1693 srp->bio = rq->bio;
1676 Sg_scatter_hold *schp = &srp->data;
1677 int iovec_count = (int) hp->iovec_count;
1678
1679 map_data.pages = schp->pages;
1680 map_data.page_order = schp->page_order;
1681 map_data.nr_entries = schp->k_use_sg;
1682
1683 if (iovec_count)
1684 res = blk_rq_map_user_iov(q, rq, &map_data, hp->dxferp,
1685 iovec_count,
1686 hp->dxfer_len, GFP_ATOMIC);
1687 else
1688 res = blk_rq_map_user(q, rq, &map_data, hp->dxferp,
1689 hp->dxfer_len, GFP_ATOMIC);
1690 1694
1691 if (!res) 1695 if (!md) {
1692 srp->bio = rq->bio; 1696 req_schp->dio_in_use = 1;
1697 hp->info |= SG_INFO_DIRECT_IO;
1698 }
1693 } 1699 }
1694
1695 return res; 1700 return res;
1696} 1701}
1697 1702
@@ -1730,25 +1735,6 @@ sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp, int tablesize)
1730 return tablesize; /* number of scat_gath elements allocated */ 1735 return tablesize; /* number of scat_gath elements allocated */
1731} 1736}
1732 1737
1733/* Returns: -ve -> error, 0 -> done, 1 -> try indirect */
1734static int
1735sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len)
1736{
1737 sg_io_hdr_t *hp = &srp->header;
1738 Sg_scatter_hold *schp = &srp->data;
1739 int res;
1740 struct request *rq = srp->rq;
1741 struct request_queue *q = sfp->parentdp->device->request_queue;
1742
1743 res = blk_rq_map_user(q, rq, NULL, hp->dxferp, dxfer_len, GFP_ATOMIC);
1744 if (res)
1745 return res;
1746 srp->bio = rq->bio;
1747 schp->dio_in_use = 1;
1748 hp->info |= SG_INFO_DIRECT_IO;
1749 return 0;
1750}
1751
1752static int 1738static int
1753sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size) 1739sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size)
1754{ 1740{