|
171 | 171 | #define CMD_HDR_CMD_OFF 29
|
172 | 172 | #define CMD_HDR_CMD_MSK (0x7 << CMD_HDR_CMD_OFF)
|
173 | 173 | /* dw1 */
|
| 174 | +#define CMD_HDR_UNCON_CMD_OFF 3 |
174 | 175 | #define CMD_HDR_DIR_OFF 5
|
175 | 176 | #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) |
176 | 179 | #define CMD_HDR_VDTL_OFF 10
|
177 | 180 | #define CMD_HDR_VDTL_MSK (0x1 << CMD_HDR_VDTL_OFF)
|
178 | 181 | #define CMD_HDR_FRAME_TYPE_OFF 11
|
|
182 | 185 | /* dw2 */
|
183 | 186 | #define CMD_HDR_CFL_OFF 0
|
184 | 187 | #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) |
185 | 190 | #define CMD_HDR_MRFL_OFF 15
|
186 | 191 | #define CMD_HDR_MRFL_MSK (0x1ff << CMD_HDR_MRFL_OFF)
|
187 | 192 | #define CMD_HDR_SG_MOD_OFF 24
|
@@ -260,6 +265,11 @@ enum {
|
260 | 265 | #define DIR_TO_DEVICE 2
|
261 | 266 | #define DIR_RESERVED 3
|
262 | 267 |
|
| 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 | + |
263 | 273 | static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off)
|
264 | 274 | {
|
265 | 275 | void __iomem *regs = hisi_hba->regs + off;
|
@@ -725,6 +735,101 @@ static int prep_smp_v3_hw(struct hisi_hba *hisi_hba,
|
725 | 735 | return rc;
|
726 | 736 | }
|
727 | 737 |
|
| 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 | + |
728 | 833 | static int phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
|
729 | 834 | {
|
730 | 835 | int i, res = 0;
|
@@ -1299,6 +1404,7 @@ static const struct hisi_sas_hw hisi_sas_v3_hw = {
|
1299 | 1404 | .sl_notify = sl_notify_v3_hw,
|
1300 | 1405 | .prep_ssp = prep_ssp_v3_hw,
|
1301 | 1406 | .prep_smp = prep_smp_v3_hw,
|
| 1407 | + .prep_stp = prep_ata_v3_hw, |
1302 | 1408 | .get_free_slot = get_free_slot_v3_hw,
|
1303 | 1409 | .start_delivery = start_delivery_v3_hw,
|
1304 | 1410 | .slot_complete = slot_complete_v3_hw,
|
|
0 commit comments