diff options
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/sg.c | 80 |
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); | |||
202 | static Sg_request *sg_add_request(Sg_fd * sfp); | 202 | static Sg_request *sg_add_request(Sg_fd * sfp); |
203 | static int sg_remove_request(Sg_fd * sfp, Sg_request * srp); | 203 | static int sg_remove_request(Sg_fd * sfp, Sg_request * srp); |
204 | static int sg_res_in_use(Sg_fd * sfp); | 204 | static int sg_res_in_use(Sg_fd * sfp); |
205 | static int sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len); | ||
206 | static Sg_device *sg_get_dev(int dev); | 205 | static Sg_device *sg_get_dev(int dev); |
207 | #ifdef CONFIG_SCSI_PROC_FS | 206 | #ifdef CONFIG_SCSI_PROC_FS |
208 | static int sg_last_dev(void); | 207 | static int sg_last_dev(void); |
@@ -1628,16 +1627,17 @@ exit_sg(void) | |||
1628 | 1627 | ||
1629 | static int sg_start_req(Sg_request *srp, unsigned char *cmd) | 1628 | static 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 */ | ||
1734 | static int | ||
1735 | sg_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 | |||
1752 | static int | 1738 | static int |
1753 | sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size) | 1739 | sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size) |
1754 | { | 1740 | { |