aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Jiang <dave.jiang@intel.com>2011-02-23 18:57:24 -0500
committerDan Williams <dan.j.williams@intel.com>2011-07-03 06:55:28 -0400
commit103a00c200ab3bb9e598923eb7ba3354fcb3de8d (patch)
tree316e592940b954f6e670b1a399375e5b32ecb346
parentf7885c8490717b010115d6413b339702c64d8a3b (diff)
isci: Make the driver copy data directly from and to sg for PIO
We can copy the data directly to and from sg for SATA PIO read operations. There is no reason to involve the hardware SGL. In the process we also need to kmap the sg because we don't know where that can come from. We also do to not call phys_to_virt(). The driver already has the information. We can just calculcate the appropriate offets. Signed-off-by: Dave Jiang <dave.jiang@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
-rw-r--r--drivers/scsi/isci/core/sci_util.c16
-rw-r--r--drivers/scsi/isci/core/sci_util.h9
-rw-r--r--drivers/scsi/isci/core/scic_sds_request.c9
-rw-r--r--drivers/scsi/isci/core/scic_sds_request.h8
-rw-r--r--drivers/scsi/isci/core/scic_sds_stp_request.c148
-rw-r--r--drivers/scsi/isci/core/scic_sds_stp_request.h2
-rw-r--r--drivers/scsi/isci/isci.h1
7 files changed, 84 insertions, 109 deletions
diff --git a/drivers/scsi/isci/core/sci_util.c b/drivers/scsi/isci/core/sci_util.c
index 5cdd96f29a9e..03f919ffb413 100644
--- a/drivers/scsi/isci/core/sci_util.c
+++ b/drivers/scsi/isci/core/sci_util.c
@@ -53,7 +53,9 @@
53 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 53 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54 */ 54 */
55 55
56#include <linux/kernel.h>
56#include "sci_util.h" 57#include "sci_util.h"
58#include "sci_environment.h"
57 59
58void scic_word_copy_with_swap( 60void scic_word_copy_with_swap(
59 u32 *destination, 61 u32 *destination,
@@ -68,3 +70,17 @@ void scic_word_copy_with_swap(
68 } 70 }
69} 71}
70 72
73void *scic_request_get_virt_addr(struct scic_sds_request *sci_req, dma_addr_t phys_addr)
74{
75 struct isci_request *ireq = sci_object_get_association(sci_req);
76 dma_addr_t offset;
77
78 BUG_ON(phys_addr < ireq->request_daddr);
79
80 offset = phys_addr - ireq->request_daddr;
81
82 BUG_ON(offset >= ireq->request_alloc_size);
83
84 return (char *)ireq + offset;
85}
86
diff --git a/drivers/scsi/isci/core/sci_util.h b/drivers/scsi/isci/core/sci_util.h
index 9748c76df387..50c272ebcdef 100644
--- a/drivers/scsi/isci/core/sci_util.h
+++ b/drivers/scsi/isci/core/sci_util.h
@@ -57,6 +57,7 @@
57#define _SCI_UTIL_H_ 57#define _SCI_UTIL_H_
58 58
59#include <linux/string.h> 59#include <linux/string.h>
60#include "scic_sds_request.h"
60 61
61/** 62/**
62 * SCIC_SWAP_DWORD() - 63 * SCIC_SWAP_DWORD() -
@@ -96,9 +97,9 @@
96 * byte swap. 97 * byte swap.
97 * 98 *
98 */ 99 */
99void scic_word_copy_with_swap( 100void scic_word_copy_with_swap(u32 *destination, u32 *source, u32 word_count);
100 u32 *destination, 101
101 u32 *source, 102void *scic_request_get_virt_addr(struct scic_sds_request *sds_request,
102 u32 word_count); 103 dma_addr_t phys_addr);
103 104
104#endif /* _SCI_UTIL_H_ */ 105#endif /* _SCI_UTIL_H_ */
diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c
index 2bd47f49e536..9fa45cd0fc46 100644
--- a/drivers/scsi/isci/core/scic_sds_request.c
+++ b/drivers/scsi/isci/core/scic_sds_request.c
@@ -100,15 +100,6 @@
100 * **************************************************************************** */ 100 * **************************************************************************** */
101 101
102/** 102/**
103 * scic_sds_request_get_user_request() -
104 *
105 * This is a helper macro to return the os handle for this request object.
106 */
107#define scic_sds_request_get_user_request(request) \
108 ((request)->user_request)
109
110
111/**
112 * scic_ssp_io_request_get_object_size() - 103 * scic_ssp_io_request_get_object_size() -
113 * 104 *
114 * This macro returns the sizeof memory required to store the an SSP IO 105 * This macro returns the sizeof memory required to store the an SSP IO
diff --git a/drivers/scsi/isci/core/scic_sds_request.h b/drivers/scsi/isci/core/scic_sds_request.h
index 0691a7552a2a..60337e6981c7 100644
--- a/drivers/scsi/isci/core/scic_sds_request.h
+++ b/drivers/scsi/isci/core/scic_sds_request.h
@@ -400,6 +400,14 @@ extern const struct scic_sds_io_request_state_handler scic_sds_smp_request_start
400 (scu_sge).address_modifier = 0; \ 400 (scu_sge).address_modifier = 0; \
401 } 401 }
402 402
403/**
404 * scic_sds_request_get_user_request() -
405 *
406 * This is a helper macro to return the os handle for this request object.
407 */
408#define scic_sds_request_get_user_request(request) \
409 ((request)->user_request)
410
403/* 411/*
404 * ***************************************************************************** 412 * *****************************************************************************
405 * * CORE REQUEST PROTOTYPES 413 * * CORE REQUEST PROTOTYPES
diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c
index 6d280c0a2fc3..10f160e6ab43 100644
--- a/drivers/scsi/isci/core/scic_sds_stp_request.c
+++ b/drivers/scsi/isci/core/scic_sds_stp_request.c
@@ -486,45 +486,34 @@ void *scic_stp_io_request_get_d2h_reg_address(
486 * - if there are more SGL element pairs - advance to the next pair and return 486 * - if there are more SGL element pairs - advance to the next pair and return
487 * element A struct scu_sgl_element* 487 * element A struct scu_sgl_element*
488 */ 488 */
489struct scu_sgl_element *scic_sds_stp_request_pio_get_next_sgl( 489struct scu_sgl_element *scic_sds_stp_request_pio_get_next_sgl(struct scic_sds_stp_request *stp_req)
490 struct scic_sds_stp_request *this_request 490{
491 ) {
492 struct scu_sgl_element *current_sgl; 491 struct scu_sgl_element *current_sgl;
492 struct scic_sds_request *sci_req = &stp_req->parent;
493 struct scic_sds_request_pio_sgl *pio_sgl = &stp_req->type.pio.request_current;
493 494
494 if (this_request->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) { 495 if (pio_sgl->sgl_set == SCU_SGL_ELEMENT_PAIR_A) {
495 if ( 496 if (pio_sgl->sgl_pair->B.address_lower == 0 &&
496 (this_request->type.pio.request_current.sgl_pair->B.address_lower == 0) 497 pio_sgl->sgl_pair->B.address_upper == 0) {
497 && (this_request->type.pio.request_current.sgl_pair->B.address_upper == 0)
498 ) {
499 current_sgl = NULL; 498 current_sgl = NULL;
500 } else { 499 } else {
501 this_request->type.pio.request_current.sgl_set = SCU_SGL_ELEMENT_PAIR_B; 500 pio_sgl->sgl_set = SCU_SGL_ELEMENT_PAIR_B;
502 current_sgl = &(this_request->type.pio.request_current.sgl_pair->B); 501 current_sgl = &pio_sgl->sgl_pair->B;
503 } 502 }
504 } else { 503 } else {
505 if ( 504 if (pio_sgl->sgl_pair->next_pair_lower == 0 &&
506 (this_request->type.pio.request_current.sgl_pair->next_pair_lower == 0) 505 pio_sgl->sgl_pair->next_pair_upper == 0) {
507 && (this_request->type.pio.request_current.sgl_pair->next_pair_upper == 0)
508 ) {
509 current_sgl = NULL; 506 current_sgl = NULL;
510 } else { 507 } else {
511 dma_addr_t physical_address; 508 u64 phys_addr;
512
513 sci_cb_make_physical_address(
514 physical_address,
515 this_request->type.pio.request_current.sgl_pair->next_pair_upper,
516 this_request->type.pio.request_current.sgl_pair->next_pair_lower
517 );
518 509
519 this_request->type.pio.request_current.sgl_pair = 510 phys_addr = pio_sgl->sgl_pair->next_pair_upper;
520 (struct scu_sgl_element_pair *)scic_cb_get_virtual_address( 511 phys_addr <<= 32;
521 this_request->parent.owning_controller, 512 phys_addr |= pio_sgl->sgl_pair->next_pair_lower;
522 physical_address
523 );
524 513
525 this_request->type.pio.request_current.sgl_set = SCU_SGL_ELEMENT_PAIR_A; 514 pio_sgl->sgl_pair = scic_request_get_virt_addr(sci_req, phys_addr);
526 515 pio_sgl->sgl_set = SCU_SGL_ELEMENT_PAIR_A;
527 current_sgl = &(this_request->type.pio.request_current.sgl_pair->A); 516 current_sgl = &pio_sgl->sgl_pair->A;
528 } 517 }
529 } 518 }
530 519
@@ -882,82 +871,51 @@ static enum sci_status scic_sds_stp_request_pio_data_out_transmit_data(
882 871
883/** 872/**
884 * 873 *
885 * @this_request: The request that is used for the SGL processing. 874 * @stp_request: The request that is used for the SGL processing.
886 * @data_buffer: The buffer of data to be copied. 875 * @data_buffer: The buffer of data to be copied.
887 * @length: The length of the data transfer. 876 * @length: The length of the data transfer.
888 * 877 *
889 * Copy the data from the buffer for the length specified to the IO reqeust SGL 878 * Copy the data from the buffer for the length specified to the IO reqeust SGL
890 * specified data region. enum sci_status 879 * specified data region. enum sci_status
891 */ 880 */
892static enum sci_status scic_sds_stp_request_pio_data_in_copy_data_buffer( 881static enum sci_status
893 struct scic_sds_stp_request *this_request, 882scic_sds_stp_request_pio_data_in_copy_data_buffer(struct scic_sds_stp_request *stp_req,
894 u8 *data_buffer, 883 u8 *data_buf, u32 len)
895 u32 length)
896{ 884{
897 enum sci_status status; 885 struct scic_sds_request *sci_req;
898 struct scu_sgl_element *current_sgl; 886 struct isci_request *ireq;
899 u32 sgl_offset; 887 u8 *src_addr;
900 u32 data_offset; 888 int copy_len;
901 u8 *source_address; 889 struct sas_task *task;
902 u8 *destination_address; 890 struct scatterlist *sg;
903 u32 copy_length; 891 void *kaddr;
904 892 int total_len = len;
905 /* Initial setup to get the current working SGL and the offset within the buffer */ 893
906 current_sgl = 894 sci_req = &stp_req->parent;
907 (this_request->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) ? 895 ireq = scic_sds_request_get_user_request(sci_req);
908 &(this_request->type.pio.request_current.sgl_pair->A) : 896 task = isci_request_access_task(ireq);
909 &(this_request->type.pio.request_current.sgl_pair->B); 897 src_addr = data_buf;
910 898
911 sgl_offset = this_request->type.pio.request_current.sgl_offset; 899 if (task->num_scatter > 0) {
912 900 sg = task->scatter;
913 source_address = data_buffer; 901
914 data_offset = 0; 902 while (total_len > 0) {
915 903 struct page *page = sg_page(sg);
916 status = SCI_SUCCESS; 904
917 905 copy_len = min_t(int, total_len, sg_dma_len(sg));
918 /* While we are still doing Ok and there is more data to transfer */ 906 kaddr = kmap_atomic(page, KM_IRQ0);
919 while ( 907 memcpy(kaddr + sg->offset, src_addr, copy_len);
920 (length > 0) 908 kunmap_atomic(kaddr, KM_IRQ0);
921 && (status == SCI_SUCCESS) 909 total_len -= copy_len;
922 ) { 910 src_addr += copy_len;
923 if (current_sgl->length == sgl_offset) { 911 sg = sg_next(sg);
924 /* This SGL has been exauhasted so we need to get the next SGL */
925 current_sgl = scic_sds_stp_request_pio_get_next_sgl(this_request);
926
927 if (current_sgl == NULL)
928 status = SCI_FAILURE;
929 else
930 sgl_offset = 0;
931 } else {
932 dma_addr_t physical_address;
933
934 sci_cb_make_physical_address(
935 physical_address,
936 current_sgl->address_upper,
937 current_sgl->address_lower
938 );
939
940 destination_address = (u8 *)scic_cb_get_virtual_address(
941 this_request->parent.owning_controller,
942 physical_address
943 );
944
945 source_address += data_offset;
946 destination_address += sgl_offset;
947
948 copy_length = min(length, current_sgl->length - sgl_offset);
949
950 memcpy(destination_address, source_address, copy_length);
951
952 length -= copy_length;
953 sgl_offset += copy_length;
954 data_offset += copy_length;
955 } 912 }
913 } else {
914 BUG_ON(task->total_xfer_len < total_len);
915 memcpy(task->scatter, src_addr, total_len);
956 } 916 }
957 917
958 this_request->type.pio.request_current.sgl_offset = sgl_offset; 918 return SCI_SUCCESS;
959
960 return status;
961} 919}
962 920
963/** 921/**
diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.h b/drivers/scsi/isci/core/scic_sds_stp_request.h
index 4a4c68aa56de..c950bb33ee04 100644
--- a/drivers/scsi/isci/core/scic_sds_stp_request.h
+++ b/drivers/scsi/isci/core/scic_sds_stp_request.h
@@ -116,7 +116,7 @@ struct scic_sds_stp_request {
116 */ 116 */
117 u8 sat_protocol; 117 u8 sat_protocol;
118 118
119 struct { 119 struct scic_sds_request_pio_sgl {
120 struct scu_sgl_element_pair *sgl_pair; 120 struct scu_sgl_element_pair *sgl_pair;
121 u8 sgl_set; 121 u8 sgl_set;
122 u32 sgl_offset; 122 u32 sgl_offset;
diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h
index 6c79b29f3102..225764f9d935 100644
--- a/drivers/scsi/isci/isci.h
+++ b/drivers/scsi/isci/isci.h
@@ -84,6 +84,7 @@
84#include "host.h" 84#include "host.h"
85#include "timers.h" 85#include "timers.h"
86#include "sci_status.h" 86#include "sci_status.h"
87#include "request.h"
87 88
88extern struct kmem_cache *isci_kmem_cache; 89extern struct kmem_cache *isci_kmem_cache;
89extern struct isci_firmware *isci_firmware; 90extern struct isci_firmware *isci_firmware;