aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/memstick/core/mspro_block.c
diff options
context:
space:
mode:
authorAlex Dubov <oakad@yahoo.com>2011-01-12 20:01:05 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-13 11:03:22 -0500
commit496fc1a68a45ae159d26331775411f6fea36d4d3 (patch)
treec93203cad7f470c7f1b4bac49582d3c150e2e5f6 /drivers/memstick/core/mspro_block.c
parentedb50b3b1d9bf6d51dc68f7f885e78285f8d6f18 (diff)
memstick: factor out transfer initiating functionality in mspro_block.c
Apart from currently used standard memstick data transfer method, Sony introduced several newer ones, to uncover full bandwidth/capacity of its Pro, HG and XC media formats. This patch lays a foundation to enable those methods as made possible by host/media capabilities. As a side effect of this patch, mspro_block_read_attributes became more streamlined and readable. [akpm@linux-foundation.org: fix printk warning] Signed-off-by: Alex Dubov <oakad@yahoo.com> Reported-by: Maxim Levitsky <maximlevitsky@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/memstick/core/mspro_block.c')
-rw-r--r--drivers/memstick/core/mspro_block.c136
1 files changed, 74 insertions, 62 deletions
diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c
index b11b2b89ae22..57b42bfc7d23 100644
--- a/drivers/memstick/core/mspro_block.c
+++ b/drivers/memstick/core/mspro_block.c
@@ -159,6 +159,13 @@ struct mspro_block_data {
159 int (*mrq_handler)(struct memstick_dev *card, 159 int (*mrq_handler)(struct memstick_dev *card,
160 struct memstick_request **mrq); 160 struct memstick_request **mrq);
161 161
162
163 /* Default request setup function for data access method preferred by
164 * this host instance.
165 */
166 void (*setup_transfer)(struct memstick_dev *card,
167 u64 offset, size_t length);
168
162 struct attribute_group attr_group; 169 struct attribute_group attr_group;
163 170
164 struct scatterlist req_sg[MSPRO_BLOCK_MAX_SEGS]; 171 struct scatterlist req_sg[MSPRO_BLOCK_MAX_SEGS];
@@ -656,14 +663,43 @@ has_int_reg:
656 } 663 }
657} 664}
658 665
666/*** Transfer setup functions for different access methods. ***/
667
668/** Setup data transfer request for SET_CMD TPC with arguments in card
669 * registers.
670 *
671 * @card Current media instance
672 * @offset Target data offset in bytes
673 * @length Required transfer length in bytes.
674 */
675static void h_mspro_block_setup_cmd(struct memstick_dev *card, u64 offset,
676 size_t length)
677{
678 struct mspro_block_data *msb = memstick_get_drvdata(card);
679 struct mspro_param_register param = {
680 .system = msb->system,
681 .data_count = cpu_to_be16((uint16_t)(length / msb->page_size)),
682 /* ISO C90 warning precludes direct initialization for now. */
683 .data_address = 0,
684 .tpc_param = 0
685 };
686
687 do_div(offset, msb->page_size);
688 param.data_address = cpu_to_be32((uint32_t)offset);
689
690 card->next_request = h_mspro_block_req_init;
691 msb->mrq_handler = h_mspro_block_transfer_data;
692 memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG,
693 &param, sizeof(param));
694}
695
659/*** Data transfer ***/ 696/*** Data transfer ***/
660 697
661static int mspro_block_issue_req(struct memstick_dev *card, int chunk) 698static int mspro_block_issue_req(struct memstick_dev *card, int chunk)
662{ 699{
663 struct mspro_block_data *msb = memstick_get_drvdata(card); 700 struct mspro_block_data *msb = memstick_get_drvdata(card);
664 sector_t t_sec; 701 u64 t_off;
665 unsigned int count; 702 unsigned int count;
666 struct mspro_param_register param;
667 703
668try_again: 704try_again:
669 while (chunk) { 705 while (chunk) {
@@ -678,30 +714,17 @@ try_again:
678 continue; 714 continue;
679 } 715 }
680 716
681 t_sec = blk_rq_pos(msb->block_req) << 9; 717 t_off = blk_rq_pos(msb->block_req);
682 sector_div(t_sec, msb->page_size); 718 t_off <<= 9;
683
684 count = blk_rq_bytes(msb->block_req); 719 count = blk_rq_bytes(msb->block_req);
685 count /= msb->page_size;
686 720
687 param.system = msb->system; 721 msb->setup_transfer(card, t_off, count);
688 param.data_count = cpu_to_be16(count);
689 param.data_address = cpu_to_be32((uint32_t)t_sec);
690 param.tpc_param = 0;
691 722
692 msb->data_dir = rq_data_dir(msb->block_req); 723 msb->data_dir = rq_data_dir(msb->block_req);
693 msb->transfer_cmd = msb->data_dir == READ 724 msb->transfer_cmd = msb->data_dir == READ
694 ? MSPRO_CMD_READ_DATA 725 ? MSPRO_CMD_READ_DATA
695 : MSPRO_CMD_WRITE_DATA; 726 : MSPRO_CMD_WRITE_DATA;
696 727
697 dev_dbg(&card->dev, "data transfer: cmd %x, "
698 "lba %x, count %x\n", msb->transfer_cmd,
699 be32_to_cpu(param.data_address), count);
700
701 card->next_request = h_mspro_block_req_init;
702 msb->mrq_handler = h_mspro_block_transfer_data;
703 memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG,
704 &param, sizeof(param));
705 memstick_new_req(card->host); 728 memstick_new_req(card->host);
706 return 0; 729 return 0;
707 } 730 }
@@ -956,18 +979,16 @@ try_again:
956static int mspro_block_read_attributes(struct memstick_dev *card) 979static int mspro_block_read_attributes(struct memstick_dev *card)
957{ 980{
958 struct mspro_block_data *msb = memstick_get_drvdata(card); 981 struct mspro_block_data *msb = memstick_get_drvdata(card);
959 struct mspro_param_register param = {
960 .system = msb->system,
961 .data_count = cpu_to_be16(1),
962 .data_address = 0,
963 .tpc_param = 0
964 };
965 struct mspro_attribute *attr = NULL; 982 struct mspro_attribute *attr = NULL;
966 struct mspro_sys_attr *s_attr = NULL; 983 struct mspro_sys_attr *s_attr = NULL;
967 unsigned char *buffer = NULL; 984 unsigned char *buffer = NULL;
968 int cnt, rc, attr_count; 985 int cnt, rc, attr_count;
969 unsigned int addr; 986 /* While normally physical device offsets, represented here by
970 unsigned short page_count; 987 * attr_offset and attr_len will be of large numeric types, we can be
988 * sure, that attributes are close enough to the beginning of the
989 * device, to save ourselves some trouble.
990 */
991 unsigned int addr, attr_offset = 0, attr_len = msb->page_size;
971 992
972 attr = kmalloc(msb->page_size, GFP_KERNEL); 993 attr = kmalloc(msb->page_size, GFP_KERNEL);
973 if (!attr) 994 if (!attr)
@@ -980,10 +1001,8 @@ static int mspro_block_read_attributes(struct memstick_dev *card)
980 msb->data_dir = READ; 1001 msb->data_dir = READ;
981 msb->transfer_cmd = MSPRO_CMD_READ_ATRB; 1002 msb->transfer_cmd = MSPRO_CMD_READ_ATRB;
982 1003
983 card->next_request = h_mspro_block_req_init; 1004 msb->setup_transfer(card, attr_offset, attr_len);
984 msb->mrq_handler = h_mspro_block_transfer_data; 1005
985 memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG, &param,
986 sizeof(param));
987 memstick_new_req(card->host); 1006 memstick_new_req(card->host);
988 wait_for_completion(&card->mrq_complete); 1007 wait_for_completion(&card->mrq_complete);
989 if (card->current_mrq.error) { 1008 if (card->current_mrq.error) {
@@ -1014,13 +1033,12 @@ static int mspro_block_read_attributes(struct memstick_dev *card)
1014 } 1033 }
1015 msb->attr_group.name = "media_attributes"; 1034 msb->attr_group.name = "media_attributes";
1016 1035
1017 buffer = kmalloc(msb->page_size, GFP_KERNEL); 1036 buffer = kmalloc(attr_len, GFP_KERNEL);
1018 if (!buffer) { 1037 if (!buffer) {
1019 rc = -ENOMEM; 1038 rc = -ENOMEM;
1020 goto out_free_attr; 1039 goto out_free_attr;
1021 } 1040 }
1022 memcpy(buffer, (char *)attr, msb->page_size); 1041 memcpy(buffer, (char *)attr, attr_len);
1023 page_count = 1;
1024 1042
1025 for (cnt = 0; cnt < attr_count; ++cnt) { 1043 for (cnt = 0; cnt < attr_count; ++cnt) {
1026 s_attr = kzalloc(sizeof(struct mspro_sys_attr), GFP_KERNEL); 1044 s_attr = kzalloc(sizeof(struct mspro_sys_attr), GFP_KERNEL);
@@ -1031,9 +1049,10 @@ static int mspro_block_read_attributes(struct memstick_dev *card)
1031 1049
1032 msb->attr_group.attrs[cnt] = &s_attr->dev_attr.attr; 1050 msb->attr_group.attrs[cnt] = &s_attr->dev_attr.attr;
1033 addr = be32_to_cpu(attr->entries[cnt].address); 1051 addr = be32_to_cpu(attr->entries[cnt].address);
1034 rc = be32_to_cpu(attr->entries[cnt].size); 1052 s_attr->size = be32_to_cpu(attr->entries[cnt].size);
1035 dev_dbg(&card->dev, "adding attribute %d: id %x, address %x, " 1053 dev_dbg(&card->dev, "adding attribute %d: id %x, address %x, "
1036 "size %x\n", cnt, attr->entries[cnt].id, addr, rc); 1054 "size %zx\n", cnt, attr->entries[cnt].id, addr,
1055 s_attr->size);
1037 s_attr->id = attr->entries[cnt].id; 1056 s_attr->id = attr->entries[cnt].id;
1038 if (mspro_block_attr_name(s_attr->id)) 1057 if (mspro_block_attr_name(s_attr->id))
1039 snprintf(s_attr->name, sizeof(s_attr->name), "%s", 1058 snprintf(s_attr->name, sizeof(s_attr->name), "%s",
@@ -1047,57 +1066,47 @@ static int mspro_block_read_attributes(struct memstick_dev *card)
1047 s_attr->dev_attr.attr.mode = S_IRUGO; 1066 s_attr->dev_attr.attr.mode = S_IRUGO;
1048 s_attr->dev_attr.show = mspro_block_attr_show(s_attr->id); 1067 s_attr->dev_attr.show = mspro_block_attr_show(s_attr->id);
1049 1068
1050 if (!rc) 1069 if (!s_attr->size)
1051 continue; 1070 continue;
1052 1071
1053 s_attr->size = rc; 1072 s_attr->data = kmalloc(s_attr->size, GFP_KERNEL);
1054 s_attr->data = kmalloc(rc, GFP_KERNEL);
1055 if (!s_attr->data) { 1073 if (!s_attr->data) {
1056 rc = -ENOMEM; 1074 rc = -ENOMEM;
1057 goto out_free_buffer; 1075 goto out_free_buffer;
1058 } 1076 }
1059 1077
1060 if (((addr / msb->page_size) 1078 if (((addr / msb->page_size) == (attr_offset / msb->page_size))
1061 == be32_to_cpu(param.data_address)) 1079 && (((addr + s_attr->size - 1) / msb->page_size)
1062 && (((addr + rc - 1) / msb->page_size) 1080 == (attr_offset / msb->page_size))) {
1063 == be32_to_cpu(param.data_address))) {
1064 memcpy(s_attr->data, buffer + addr % msb->page_size, 1081 memcpy(s_attr->data, buffer + addr % msb->page_size,
1065 rc); 1082 s_attr->size);
1066 continue; 1083 continue;
1067 } 1084 }
1068 1085
1069 if (page_count <= (rc / msb->page_size)) { 1086 attr_offset = (addr / msb->page_size) * msb->page_size;
1087
1088 if ((attr_offset + attr_len) < (addr + s_attr->size)) {
1070 kfree(buffer); 1089 kfree(buffer);
1071 page_count = (rc / msb->page_size) + 1; 1090 attr_len = (((addr + s_attr->size) / msb->page_size)
1072 buffer = kmalloc(page_count * msb->page_size, 1091 + 1 ) * msb->page_size - attr_offset;
1073 GFP_KERNEL); 1092 buffer = kmalloc(attr_len, GFP_KERNEL);
1074 if (!buffer) { 1093 if (!buffer) {
1075 rc = -ENOMEM; 1094 rc = -ENOMEM;
1076 goto out_free_attr; 1095 goto out_free_attr;
1077 } 1096 }
1078 } 1097 }
1079 1098
1080 param.system = msb->system; 1099 sg_init_one(&msb->req_sg[0], buffer, attr_len);
1081 param.data_count = cpu_to_be16((rc / msb->page_size) + 1);
1082 param.data_address = cpu_to_be32(addr / msb->page_size);
1083 param.tpc_param = 0;
1084
1085 sg_init_one(&msb->req_sg[0], buffer,
1086 be16_to_cpu(param.data_count) * msb->page_size);
1087 msb->seg_count = 1; 1100 msb->seg_count = 1;
1088 msb->current_seg = 0; 1101 msb->current_seg = 0;
1089 msb->current_page = 0; 1102 msb->current_page = 0;
1090 msb->data_dir = READ; 1103 msb->data_dir = READ;
1091 msb->transfer_cmd = MSPRO_CMD_READ_ATRB; 1104 msb->transfer_cmd = MSPRO_CMD_READ_ATRB;
1092 1105
1093 dev_dbg(&card->dev, "reading attribute pages %x, %x\n", 1106 dev_dbg(&card->dev, "reading attribute range %x, %x\n",
1094 be32_to_cpu(param.data_address), 1107 attr_offset, attr_len);
1095 be16_to_cpu(param.data_count));
1096 1108
1097 card->next_request = h_mspro_block_req_init; 1109 msb->setup_transfer(card, attr_offset, attr_len);
1098 msb->mrq_handler = h_mspro_block_transfer_data;
1099 memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG,
1100 (char *)&param, sizeof(param));
1101 memstick_new_req(card->host); 1110 memstick_new_req(card->host);
1102 wait_for_completion(&card->mrq_complete); 1111 wait_for_completion(&card->mrq_complete);
1103 if (card->current_mrq.error) { 1112 if (card->current_mrq.error) {
@@ -1105,7 +1114,8 @@ static int mspro_block_read_attributes(struct memstick_dev *card)
1105 goto out_free_buffer; 1114 goto out_free_buffer;
1106 } 1115 }
1107 1116
1108 memcpy(s_attr->data, buffer + addr % msb->page_size, rc); 1117 memcpy(s_attr->data, buffer + addr % msb->page_size,
1118 s_attr->size);
1109 } 1119 }
1110 1120
1111 rc = 0; 1121 rc = 0;
@@ -1123,6 +1133,8 @@ static int mspro_block_init_card(struct memstick_dev *card)
1123 int rc = 0; 1133 int rc = 0;
1124 1134
1125 msb->system = MEMSTICK_SYS_SERIAL; 1135 msb->system = MEMSTICK_SYS_SERIAL;
1136 msb->setup_transfer = h_mspro_block_setup_cmd;
1137
1126 card->reg_addr.r_offset = offsetof(struct mspro_register, status); 1138 card->reg_addr.r_offset = offsetof(struct mspro_register, status);
1127 card->reg_addr.r_length = sizeof(struct ms_status_register); 1139 card->reg_addr.r_length = sizeof(struct ms_status_register);
1128 card->reg_addr.w_offset = offsetof(struct mspro_register, param); 1140 card->reg_addr.w_offset = offsetof(struct mspro_register, param);