Skip to content

Commit ce60689

Browse files
Xiang Chenmartinkpetersen
authored andcommitted
scsi: hisi_sas: add v3 code to send ATA frame
Add code to prepare ATA frame for v3 hw Signed-off-by: John Garry <[email protected]> Signed-off-by: Xiang Chen <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent fa913de commit ce60689

File tree

1 file changed

+106
-0
lines changed

1 file changed

+106
-0
lines changed

drivers/scsi/hisi_sas/hisi_sas_v3_hw.c

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,11 @@
171171
#define CMD_HDR_CMD_OFF 29
172172
#define CMD_HDR_CMD_MSK (0x7 << CMD_HDR_CMD_OFF)
173173
/* dw1 */
174+
#define CMD_HDR_UNCON_CMD_OFF 3
174175
#define CMD_HDR_DIR_OFF 5
175176
#define CMD_HDR_DIR_MSK (0x3 << CMD_HDR_DIR_OFF)
177+
#define CMD_HDR_RESET_OFF 7
178+
#define CMD_HDR_RESET_MSK (0x1 << CMD_HDR_RESET_OFF)
176179
#define CMD_HDR_VDTL_OFF 10
177180
#define CMD_HDR_VDTL_MSK (0x1 << CMD_HDR_VDTL_OFF)
178181
#define CMD_HDR_FRAME_TYPE_OFF 11
@@ -182,6 +185,8 @@
182185
/* dw2 */
183186
#define CMD_HDR_CFL_OFF 0
184187
#define CMD_HDR_CFL_MSK (0x1ff << CMD_HDR_CFL_OFF)
188+
#define CMD_HDR_NCQ_TAG_OFF 10
189+
#define CMD_HDR_NCQ_TAG_MSK (0x1f << CMD_HDR_NCQ_TAG_OFF)
185190
#define CMD_HDR_MRFL_OFF 15
186191
#define CMD_HDR_MRFL_MSK (0x1ff << CMD_HDR_MRFL_OFF)
187192
#define CMD_HDR_SG_MOD_OFF 24
@@ -260,6 +265,11 @@ enum {
260265
#define DIR_TO_DEVICE 2
261266
#define DIR_RESERVED 3
262267

268+
#define CMD_IS_UNCONSTRAINT(cmd) \
269+
((cmd == ATA_CMD_READ_LOG_EXT) || \
270+
(cmd == ATA_CMD_READ_LOG_DMA_EXT) || \
271+
(cmd == ATA_CMD_DEV_RESET))
272+
263273
static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off)
264274
{
265275
void __iomem *regs = hisi_hba->regs + off;
@@ -725,6 +735,101 @@ static int prep_smp_v3_hw(struct hisi_hba *hisi_hba,
725735
return rc;
726736
}
727737

738+
static int get_ncq_tag_v3_hw(struct sas_task *task, u32 *tag)
739+
{
740+
struct ata_queued_cmd *qc = task->uldd_task;
741+
742+
if (qc) {
743+
if (qc->tf.command == ATA_CMD_FPDMA_WRITE ||
744+
qc->tf.command == ATA_CMD_FPDMA_READ) {
745+
*tag = qc->tag;
746+
return 1;
747+
}
748+
}
749+
return 0;
750+
}
751+
752+
static int prep_ata_v3_hw(struct hisi_hba *hisi_hba,
753+
struct hisi_sas_slot *slot)
754+
{
755+
struct sas_task *task = slot->task;
756+
struct domain_device *device = task->dev;
757+
struct domain_device *parent_dev = device->parent;
758+
struct hisi_sas_device *sas_dev = device->lldd_dev;
759+
struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr;
760+
struct asd_sas_port *sas_port = device->port;
761+
struct hisi_sas_port *port = to_hisi_sas_port(sas_port);
762+
u8 *buf_cmd;
763+
int has_data = 0, rc = 0, hdr_tag = 0;
764+
u32 dw1 = 0, dw2 = 0;
765+
766+
hdr->dw0 = cpu_to_le32(port->id << CMD_HDR_PORT_OFF);
767+
if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type))
768+
hdr->dw0 |= cpu_to_le32(3 << CMD_HDR_CMD_OFF);
769+
else
770+
hdr->dw0 |= cpu_to_le32(4 << CMD_HDR_CMD_OFF);
771+
772+
switch (task->data_dir) {
773+
case DMA_TO_DEVICE:
774+
has_data = 1;
775+
dw1 |= DIR_TO_DEVICE << CMD_HDR_DIR_OFF;
776+
break;
777+
case DMA_FROM_DEVICE:
778+
has_data = 1;
779+
dw1 |= DIR_TO_INI << CMD_HDR_DIR_OFF;
780+
break;
781+
default:
782+
dw1 &= ~CMD_HDR_DIR_MSK;
783+
}
784+
785+
if ((task->ata_task.fis.command == ATA_CMD_DEV_RESET) &&
786+
(task->ata_task.fis.control & ATA_SRST))
787+
dw1 |= 1 << CMD_HDR_RESET_OFF;
788+
789+
dw1 |= (hisi_sas_get_ata_protocol(
790+
task->ata_task.fis.command, task->data_dir))
791+
<< CMD_HDR_FRAME_TYPE_OFF;
792+
dw1 |= sas_dev->device_id << CMD_HDR_DEV_ID_OFF;
793+
794+
if (CMD_IS_UNCONSTRAINT(task->ata_task.fis.command))
795+
dw1 |= 1 << CMD_HDR_UNCON_CMD_OFF;
796+
797+
hdr->dw1 = cpu_to_le32(dw1);
798+
799+
/* dw2 */
800+
if (task->ata_task.use_ncq && get_ncq_tag_v3_hw(task, &hdr_tag)) {
801+
task->ata_task.fis.sector_count |= (u8) (hdr_tag << 3);
802+
dw2 |= hdr_tag << CMD_HDR_NCQ_TAG_OFF;
803+
}
804+
805+
dw2 |= (HISI_SAS_MAX_STP_RESP_SZ / 4) << CMD_HDR_CFL_OFF |
806+
2 << CMD_HDR_SG_MOD_OFF;
807+
hdr->dw2 = cpu_to_le32(dw2);
808+
809+
/* dw3 */
810+
hdr->transfer_tags = cpu_to_le32(slot->idx);
811+
812+
if (has_data) {
813+
rc = prep_prd_sge_v3_hw(hisi_hba, slot, hdr, task->scatter,
814+
slot->n_elem);
815+
if (rc)
816+
return rc;
817+
}
818+
819+
hdr->data_transfer_len = cpu_to_le32(task->total_xfer_len);
820+
hdr->cmd_table_addr = cpu_to_le64(slot->command_table_dma);
821+
hdr->sts_buffer_addr = cpu_to_le64(slot->status_buffer_dma);
822+
823+
buf_cmd = slot->command_table;
824+
825+
if (likely(!task->ata_task.device_control_reg_update))
826+
task->ata_task.fis.flags |= 0x80; /* C=1: update ATA cmd reg */
827+
/* fill in command FIS */
828+
memcpy(buf_cmd, &task->ata_task.fis, sizeof(struct host_to_dev_fis));
829+
830+
return 0;
831+
}
832+
728833
static int phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
729834
{
730835
int i, res = 0;
@@ -1299,6 +1404,7 @@ static const struct hisi_sas_hw hisi_sas_v3_hw = {
12991404
.sl_notify = sl_notify_v3_hw,
13001405
.prep_ssp = prep_ssp_v3_hw,
13011406
.prep_smp = prep_smp_v3_hw,
1407+
.prep_stp = prep_ata_v3_hw,
13021408
.get_free_slot = get_free_slot_v3_hw,
13031409
.start_delivery = start_delivery_v3_hw,
13041410
.slot_complete = slot_complete_v3_hw,

0 commit comments

Comments
 (0)