|
186 | 186 | #define CMD_HDR_MRFL_MSK (0x1ff << CMD_HDR_MRFL_OFF)
|
187 | 187 | #define CMD_HDR_SG_MOD_OFF 24
|
188 | 188 | #define CMD_HDR_SG_MOD_MSK (0x3 << CMD_HDR_SG_MOD_OFF)
|
| 189 | +/* dw3 */ |
| 190 | +#define CMD_HDR_IPTT_OFF 0 |
| 191 | +#define CMD_HDR_IPTT_MSK (0xffff << CMD_HDR_IPTT_OFF) |
189 | 192 | /* dw6 */
|
190 | 193 | #define CMD_HDR_DIF_SGL_LEN_OFF 0
|
191 | 194 | #define CMD_HDR_DIF_SGL_LEN_MSK (0xffff << CMD_HDR_DIF_SGL_LEN_OFF)
|
@@ -652,6 +655,76 @@ static int prep_ssp_v3_hw(struct hisi_hba *hisi_hba,
|
652 | 655 | return 0;
|
653 | 656 | }
|
654 | 657 |
|
| 658 | +static int prep_smp_v3_hw(struct hisi_hba *hisi_hba, |
| 659 | + struct hisi_sas_slot *slot) |
| 660 | +{ |
| 661 | + struct sas_task *task = slot->task; |
| 662 | + struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr; |
| 663 | + struct domain_device *device = task->dev; |
| 664 | + struct device *dev = hisi_hba->dev; |
| 665 | + struct hisi_sas_port *port = slot->port; |
| 666 | + struct scatterlist *sg_req, *sg_resp; |
| 667 | + struct hisi_sas_device *sas_dev = device->lldd_dev; |
| 668 | + dma_addr_t req_dma_addr; |
| 669 | + unsigned int req_len, resp_len; |
| 670 | + int elem, rc; |
| 671 | + |
| 672 | + /* |
| 673 | + * DMA-map SMP request, response buffers |
| 674 | + */ |
| 675 | + /* req */ |
| 676 | + sg_req = &task->smp_task.smp_req; |
| 677 | + elem = dma_map_sg(dev, sg_req, 1, DMA_TO_DEVICE); |
| 678 | + if (!elem) |
| 679 | + return -ENOMEM; |
| 680 | + req_len = sg_dma_len(sg_req); |
| 681 | + req_dma_addr = sg_dma_address(sg_req); |
| 682 | + |
| 683 | + /* resp */ |
| 684 | + sg_resp = &task->smp_task.smp_resp; |
| 685 | + elem = dma_map_sg(dev, sg_resp, 1, DMA_FROM_DEVICE); |
| 686 | + if (!elem) { |
| 687 | + rc = -ENOMEM; |
| 688 | + goto err_out_req; |
| 689 | + } |
| 690 | + resp_len = sg_dma_len(sg_resp); |
| 691 | + if ((req_len & 0x3) || (resp_len & 0x3)) { |
| 692 | + rc = -EINVAL; |
| 693 | + goto err_out_resp; |
| 694 | + } |
| 695 | + |
| 696 | + /* create header */ |
| 697 | + /* dw0 */ |
| 698 | + hdr->dw0 = cpu_to_le32((port->id << CMD_HDR_PORT_OFF) | |
| 699 | + (1 << CMD_HDR_PRIORITY_OFF) | /* high pri */ |
| 700 | + (2 << CMD_HDR_CMD_OFF)); /* smp */ |
| 701 | + |
| 702 | + /* map itct entry */ |
| 703 | + hdr->dw1 = cpu_to_le32((sas_dev->device_id << CMD_HDR_DEV_ID_OFF) | |
| 704 | + (1 << CMD_HDR_FRAME_TYPE_OFF) | |
| 705 | + (DIR_NO_DATA << CMD_HDR_DIR_OFF)); |
| 706 | + |
| 707 | + /* dw2 */ |
| 708 | + hdr->dw2 = cpu_to_le32((((req_len - 4) / 4) << CMD_HDR_CFL_OFF) | |
| 709 | + (HISI_SAS_MAX_SMP_RESP_SZ / 4 << |
| 710 | + CMD_HDR_MRFL_OFF)); |
| 711 | + |
| 712 | + hdr->transfer_tags = cpu_to_le32(slot->idx << CMD_HDR_IPTT_OFF); |
| 713 | + |
| 714 | + hdr->cmd_table_addr = cpu_to_le64(req_dma_addr); |
| 715 | + hdr->sts_buffer_addr = cpu_to_le64(slot->status_buffer_dma); |
| 716 | + |
| 717 | + return 0; |
| 718 | + |
| 719 | +err_out_resp: |
| 720 | + dma_unmap_sg(dev, &slot->task->smp_task.smp_resp, 1, |
| 721 | + DMA_FROM_DEVICE); |
| 722 | +err_out_req: |
| 723 | + dma_unmap_sg(dev, &slot->task->smp_task.smp_req, 1, |
| 724 | + DMA_TO_DEVICE); |
| 725 | + return rc; |
| 726 | +} |
| 727 | + |
655 | 728 | static int phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
|
656 | 729 | {
|
657 | 730 | int i, res = 0;
|
@@ -1225,6 +1298,7 @@ static const struct hisi_sas_hw hisi_sas_v3_hw = {
|
1225 | 1298 | .complete_hdr_size = sizeof(struct hisi_sas_complete_v3_hdr),
|
1226 | 1299 | .sl_notify = sl_notify_v3_hw,
|
1227 | 1300 | .prep_ssp = prep_ssp_v3_hw,
|
| 1301 | + .prep_smp = prep_smp_v3_hw, |
1228 | 1302 | .get_free_slot = get_free_slot_v3_hw,
|
1229 | 1303 | .start_delivery = start_delivery_v3_hw,
|
1230 | 1304 | .slot_complete = slot_complete_v3_hw,
|
|
0 commit comments