aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorJohn Garry <john.garry@huawei.com>2016-01-25 13:47:20 -0500
committerMartin K. Petersen <martin.petersen@oracle.com>2016-02-23 21:27:02 -0500
commit6f2ff1a1311e618836a8d1b8a3a6ca4af8509820 (patch)
tree890f26a2dd499b3e78f828c43e9bbf6a7eb5952b /drivers/scsi
parent85b2c3c040ccb15109bb286139b03ce8817b2c7c (diff)
hisi_sas: add v2 path to send ATA command
Signed-off-by: John Garry <john.garry@huawei.com> Reviewed-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas.h4
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_main.c8
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_v2_hw.c162
3 files changed, 174 insertions, 0 deletions
diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index b2e4b26fd6c7..f00b55b241e5 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -18,6 +18,7 @@
18#include <linux/of_address.h> 18#include <linux/of_address.h>
19#include <linux/platform_device.h> 19#include <linux/platform_device.h>
20#include <linux/regmap.h> 20#include <linux/regmap.h>
21#include <scsi/sas_ata.h>
21#include <scsi/libsas.h> 22#include <scsi/libsas.h>
22 23
23#define DRV_VERSION "v1.0" 24#define DRV_VERSION "v1.0"
@@ -35,6 +36,7 @@
35 36
36#define HISI_SAS_MAX_SSP_RESP_SZ (sizeof(struct ssp_frame_hdr) + 1024) 37#define HISI_SAS_MAX_SSP_RESP_SZ (sizeof(struct ssp_frame_hdr) + 1024)
37#define HISI_SAS_MAX_SMP_RESP_SZ 1028 38#define HISI_SAS_MAX_SMP_RESP_SZ 1028
39#define HISI_SAS_MAX_STP_RESP_SZ 28
38 40
39#define DEV_IS_EXPANDER(type) \ 41#define DEV_IS_EXPANDER(type) \
40 ((type == SAS_EDGE_EXPANDER_DEVICE) || \ 42 ((type == SAS_EDGE_EXPANDER_DEVICE) || \
@@ -135,6 +137,8 @@ struct hisi_sas_hw {
135 struct hisi_sas_tmf_task *tmf); 137 struct hisi_sas_tmf_task *tmf);
136 int (*prep_smp)(struct hisi_hba *hisi_hba, 138 int (*prep_smp)(struct hisi_hba *hisi_hba,
137 struct hisi_sas_slot *slot); 139 struct hisi_sas_slot *slot);
140 int (*prep_stp)(struct hisi_hba *hisi_hba,
141 struct hisi_sas_slot *slot);
138 int (*slot_complete)(struct hisi_hba *hisi_hba, 142 int (*slot_complete)(struct hisi_hba *hisi_hba,
139 struct hisi_sas_slot *slot, int abort); 143 struct hisi_sas_slot *slot, int abort);
140 void (*phy_enable)(struct hisi_hba *hisi_hba, int phy_no); 144 void (*phy_enable)(struct hisi_hba *hisi_hba, int phy_no);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
index c48df6df1ff8..406b515a54bb 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -107,6 +107,12 @@ static int hisi_sas_task_prep_ssp(struct hisi_hba *hisi_hba,
107 return hisi_hba->hw->prep_ssp(hisi_hba, slot, is_tmf, tmf); 107 return hisi_hba->hw->prep_ssp(hisi_hba, slot, is_tmf, tmf);
108} 108}
109 109
110static int hisi_sas_task_prep_ata(struct hisi_hba *hisi_hba,
111 struct hisi_sas_slot *slot)
112{
113 return hisi_hba->hw->prep_stp(hisi_hba, slot);
114}
115
110static int hisi_sas_task_prep(struct sas_task *task, struct hisi_hba *hisi_hba, 116static int hisi_sas_task_prep(struct sas_task *task, struct hisi_hba *hisi_hba,
111 int is_tmf, struct hisi_sas_tmf_task *tmf, 117 int is_tmf, struct hisi_sas_tmf_task *tmf,
112 int *pass) 118 int *pass)
@@ -230,6 +236,8 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_hba *hisi_hba,
230 case SAS_PROTOCOL_SATA: 236 case SAS_PROTOCOL_SATA:
231 case SAS_PROTOCOL_STP: 237 case SAS_PROTOCOL_STP:
232 case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: 238 case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
239 rc = hisi_sas_task_prep_ata(hisi_hba, slot);
240 break;
233 default: 241 default:
234 dev_err(dev, "task prep: unknown/unsupported proto (0x%x)\n", 242 dev_err(dev, "task prep: unknown/unsupported proto (0x%x)\n",
235 task->task_proto); 243 task->task_proto);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 8b51acf9e23d..cea0b369df5c 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -269,6 +269,12 @@ enum {
269#define DIR_TO_DEVICE 2 269#define DIR_TO_DEVICE 2
270#define DIR_RESERVED 3 270#define DIR_RESERVED 3
271 271
272#define SATA_PROTOCOL_NONDATA 0x1
273#define SATA_PROTOCOL_PIO 0x2
274#define SATA_PROTOCOL_DMA 0x4
275#define SATA_PROTOCOL_FPDMA 0x8
276#define SATA_PROTOCOL_ATAPI 0x10
277
272static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off) 278static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off)
273{ 279{
274 void __iomem *regs = hisi_hba->regs + off; 280 void __iomem *regs = hisi_hba->regs + off;
@@ -994,6 +1000,19 @@ static int prep_ssp_v2_hw(struct hisi_hba *hisi_hba,
994 return 0; 1000 return 0;
995} 1001}
996 1002
1003static void sata_done_v2_hw(struct hisi_hba *hisi_hba, struct sas_task *task,
1004 struct hisi_sas_slot *slot)
1005{
1006 struct task_status_struct *ts = &task->task_status;
1007 struct ata_task_resp *resp = (struct ata_task_resp *)ts->buf;
1008 struct dev_to_host_fis *d2h = slot->status_buffer +
1009 sizeof(struct hisi_sas_err_record);
1010
1011 resp->frame_len = sizeof(struct dev_to_host_fis);
1012 memcpy(&resp->ending_fis[0], d2h, sizeof(struct dev_to_host_fis));
1013
1014 ts->buf_valid_size = sizeof(*resp);
1015}
997static int 1016static int
998slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot, 1017slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot,
999 int abort) 1018 int abort)
@@ -1070,6 +1089,11 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot,
1070 case SAS_PROTOCOL_SATA: 1089 case SAS_PROTOCOL_SATA:
1071 case SAS_PROTOCOL_STP: 1090 case SAS_PROTOCOL_STP:
1072 case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: 1091 case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
1092 {
1093 ts->stat = SAM_STAT_GOOD;
1094 sata_done_v2_hw(hisi_hba, task, slot);
1095 break;
1096 }
1073 default: 1097 default:
1074 ts->stat = SAM_STAT_CHECK_CONDITION; 1098 ts->stat = SAM_STAT_CHECK_CONDITION;
1075 break; 1099 break;
@@ -1094,6 +1118,143 @@ out:
1094 return sts; 1118 return sts;
1095} 1119}
1096 1120
1121static u8 get_ata_protocol(u8 cmd, int direction)
1122{
1123 switch (cmd) {
1124 case ATA_CMD_FPDMA_WRITE:
1125 case ATA_CMD_FPDMA_READ:
1126 return SATA_PROTOCOL_FPDMA;
1127
1128 case ATA_CMD_ID_ATA:
1129 case ATA_CMD_PMP_READ:
1130 case ATA_CMD_READ_LOG_EXT:
1131 case ATA_CMD_PIO_READ:
1132 case ATA_CMD_PIO_READ_EXT:
1133 case ATA_CMD_PMP_WRITE:
1134 case ATA_CMD_WRITE_LOG_EXT:
1135 case ATA_CMD_PIO_WRITE:
1136 case ATA_CMD_PIO_WRITE_EXT:
1137 return SATA_PROTOCOL_PIO;
1138
1139 case ATA_CMD_READ:
1140 case ATA_CMD_READ_EXT:
1141 case ATA_CMD_READ_LOG_DMA_EXT:
1142 case ATA_CMD_WRITE:
1143 case ATA_CMD_WRITE_EXT:
1144 case ATA_CMD_WRITE_QUEUED:
1145 case ATA_CMD_WRITE_LOG_DMA_EXT:
1146 return SATA_PROTOCOL_DMA;
1147
1148 case ATA_CMD_DOWNLOAD_MICRO:
1149 case ATA_CMD_DEV_RESET:
1150 case ATA_CMD_CHK_POWER:
1151 case ATA_CMD_FLUSH:
1152 case ATA_CMD_FLUSH_EXT:
1153 case ATA_CMD_VERIFY:
1154 case ATA_CMD_VERIFY_EXT:
1155 case ATA_CMD_SET_FEATURES:
1156 case ATA_CMD_STANDBY:
1157 case ATA_CMD_STANDBYNOW1:
1158 return SATA_PROTOCOL_NONDATA;
1159 default:
1160 if (direction == DMA_NONE)
1161 return SATA_PROTOCOL_NONDATA;
1162 return SATA_PROTOCOL_PIO;
1163 }
1164}
1165
1166static int get_ncq_tag_v2_hw(struct sas_task *task, u32 *tag)
1167{
1168 struct ata_queued_cmd *qc = task->uldd_task;
1169
1170 if (qc) {
1171 if (qc->tf.command == ATA_CMD_FPDMA_WRITE ||
1172 qc->tf.command == ATA_CMD_FPDMA_READ) {
1173 *tag = qc->tag;
1174 return 1;
1175 }
1176 }
1177 return 0;
1178}
1179
1180static int prep_ata_v2_hw(struct hisi_hba *hisi_hba,
1181 struct hisi_sas_slot *slot)
1182{
1183 struct sas_task *task = slot->task;
1184 struct domain_device *device = task->dev;
1185 struct domain_device *parent_dev = device->parent;
1186 struct hisi_sas_device *sas_dev = device->lldd_dev;
1187 struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr;
1188 struct hisi_sas_port *port = device->port->lldd_port;
1189 u8 *buf_cmd;
1190 int has_data = 0, rc = 0, hdr_tag = 0;
1191 u32 dw1 = 0, dw2 = 0;
1192
1193 /* create header */
1194 /* dw0 */
1195 hdr->dw0 = cpu_to_le32(port->id << CMD_HDR_PORT_OFF);
1196 if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type))
1197 hdr->dw0 |= cpu_to_le32(3 << CMD_HDR_CMD_OFF);
1198 else
1199 hdr->dw0 |= cpu_to_le32(4 << CMD_HDR_CMD_OFF);
1200
1201 /* dw1 */
1202 switch (task->data_dir) {
1203 case DMA_TO_DEVICE:
1204 has_data = 1;
1205 dw1 |= DIR_TO_DEVICE << CMD_HDR_DIR_OFF;
1206 break;
1207 case DMA_FROM_DEVICE:
1208 has_data = 1;
1209 dw1 |= DIR_TO_INI << CMD_HDR_DIR_OFF;
1210 break;
1211 default:
1212 dw1 &= ~CMD_HDR_DIR_MSK;
1213 }
1214
1215 if (0 == task->ata_task.fis.command)
1216 dw1 |= 1 << CMD_HDR_RESET_OFF;
1217
1218 dw1 |= (get_ata_protocol(task->ata_task.fis.command, task->data_dir))
1219 << CMD_HDR_FRAME_TYPE_OFF;
1220 dw1 |= sas_dev->device_id << CMD_HDR_DEV_ID_OFF;
1221 hdr->dw1 = cpu_to_le32(dw1);
1222
1223 /* dw2 */
1224 if (task->ata_task.use_ncq && get_ncq_tag_v2_hw(task, &hdr_tag)) {
1225 task->ata_task.fis.sector_count |= (u8) (hdr_tag << 3);
1226 dw2 |= hdr_tag << CMD_HDR_NCQ_TAG_OFF;
1227 }
1228
1229 dw2 |= (HISI_SAS_MAX_STP_RESP_SZ / 4) << CMD_HDR_CFL_OFF |
1230 2 << CMD_HDR_SG_MOD_OFF;
1231 hdr->dw2 = cpu_to_le32(dw2);
1232
1233 /* dw3 */
1234 hdr->transfer_tags = cpu_to_le32(slot->idx);
1235
1236 if (has_data) {
1237 rc = prep_prd_sge_v2_hw(hisi_hba, slot, hdr, task->scatter,
1238 slot->n_elem);
1239 if (rc)
1240 return rc;
1241 }
1242
1243
1244 hdr->data_transfer_len = cpu_to_le32(task->total_xfer_len);
1245 hdr->cmd_table_addr = cpu_to_le64(slot->command_table_dma);
1246 hdr->sts_buffer_addr = cpu_to_le64(slot->status_buffer_dma);
1247
1248 buf_cmd = slot->command_table;
1249
1250 if (likely(!task->ata_task.device_control_reg_update))
1251 task->ata_task.fis.flags |= 0x80; /* C=1: update ATA cmd reg */
1252 /* fill in command FIS */
1253 memcpy(buf_cmd, &task->ata_task.fis, sizeof(struct host_to_dev_fis));
1254
1255 return 0;
1256}
1257
1097static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba) 1258static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
1098{ 1259{
1099 int i, res = 0; 1260 int i, res = 0;
@@ -1559,6 +1720,7 @@ static const struct hisi_sas_hw hisi_sas_v2_hw = {
1559 .free_device = free_device_v2_hw, 1720 .free_device = free_device_v2_hw,
1560 .prep_smp = prep_smp_v2_hw, 1721 .prep_smp = prep_smp_v2_hw,
1561 .prep_ssp = prep_ssp_v2_hw, 1722 .prep_ssp = prep_ssp_v2_hw,
1723 .prep_stp = prep_ata_v2_hw,
1562 .get_free_slot = get_free_slot_v2_hw, 1724 .get_free_slot = get_free_slot_v2_hw,
1563 .start_delivery = start_delivery_v2_hw, 1725 .start_delivery = start_delivery_v2_hw,
1564 .slot_complete = slot_complete_v2_hw, 1726 .slot_complete = slot_complete_v2_hw,