Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

scsi: ufs: add a low-level __ufshcd_issue_tm_cmd helper

Add a helper that takes a utp_task_req_desc and issues it, which will
be useful for UFS bsg support. Rewrite ufshcd_issue_tm_cmd0x to use
this new helper.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Avri Altman <avri.altman@wdc.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Christoph Hellwig and committed by
Martin K. Petersen
c6049cd9 391e388f

+61 -80
+61 -80
drivers/scsi/ufs/ufshcd.c
··· 634 634 } 635 635 636 636 /** 637 - * ufshcd_get_tmr_ocs - Get the UTMRD Overall Command Status 638 - * @task_req_descp: pointer to utp_task_req_desc structure 639 - * 640 - * This function is used to get the OCS field from UTMRD 641 - * Returns the OCS field in the UTMRD 642 - */ 643 - static inline int 644 - ufshcd_get_tmr_ocs(struct utp_task_req_desc *task_req_descp) 645 - { 646 - return le32_to_cpu(task_req_descp->header.dword_2) & MASK_OCS; 647 - } 648 - 649 - /** 650 637 * ufshcd_get_tm_free_slot - get a free slot for task management request 651 638 * @hba: per adapter instance 652 639 * @free_slot: pointer to variable with available slot value ··· 4604 4617 } 4605 4618 4606 4619 /** 4607 - * ufshcd_task_req_compl - handle task management request completion 4608 - * @hba: per adapter instance 4609 - * @index: index of the completed request 4610 - * @resp: task management service response 4611 - * 4612 - * Returns non-zero value on error, zero on success 4613 - */ 4614 - static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index, u8 *resp) 4615 - { 4616 - struct utp_task_req_desc *treq = hba->utmrdl_base_addr + index; 4617 - unsigned long flags; 4618 - int ocs_value; 4619 - 4620 - spin_lock_irqsave(hba->host->host_lock, flags); 4621 - 4622 - /* Clear completed tasks from outstanding_tasks */ 4623 - __clear_bit(index, &hba->outstanding_tasks); 4624 - 4625 - ocs_value = ufshcd_get_tmr_ocs(treq); 4626 - 4627 - if (ocs_value != OCS_SUCCESS) 4628 - dev_err(hba->dev, "%s: failed, ocs = 0x%x\n", 4629 - __func__, ocs_value); 4630 - else if (resp) 4631 - *resp = be32_to_cpu(treq->output_param1) & MASK_TM_SERVICE_RESP; 4632 - spin_unlock_irqrestore(hba->host->host_lock, flags); 4633 - 4634 - return ocs_value; 4635 - } 4636 - 4637 - /** 4638 4620 * ufshcd_scsi_cmd_status - Update SCSI command result based on SCSI status 4639 4621 * @lrbp: pointer to local reference block of completed command 4640 4622 * @scsi_status: SCSI command status ··· 5560 5604 return err; 5561 5605 } 5562 5606 5563 - /** 5564 - * ufshcd_issue_tm_cmd - issues task management commands to controller 5565 - * @hba: per adapter instance 5566 - * @lun_id: LUN ID to which TM command is sent 5567 - * @task_id: task ID to which the TM command is applicable 5568 - * @tm_function: task management function opcode 5569 - * @tm_response: task management service response return value 5570 - * 5571 - * Returns non-zero value on error, zero on success. 5572 - */ 5573 - static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id, 5574 - u8 tm_function, u8 *tm_response) 5607 + static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba, 5608 + struct utp_task_req_desc *treq, u8 tm_function) 5575 5609 { 5576 - struct utp_task_req_desc *treq; 5577 - struct Scsi_Host *host; 5610 + struct Scsi_Host *host = hba->host; 5578 5611 unsigned long flags; 5579 - int free_slot; 5580 - int err; 5581 - int task_tag; 5582 - 5583 - host = hba->host; 5612 + int free_slot, task_tag, err; 5584 5613 5585 5614 /* 5586 5615 * Get free slot, sleep if slots are unavailable. ··· 5576 5635 ufshcd_hold(hba, false); 5577 5636 5578 5637 spin_lock_irqsave(host->host_lock, flags); 5579 - treq = hba->utmrdl_base_addr + free_slot; 5580 - 5581 - /* Configure task request descriptor */ 5582 - treq->header.dword_0 = cpu_to_le32(UTP_REQ_DESC_INT_CMD); 5583 - treq->header.dword_2 = cpu_to_le32(OCS_INVALID_COMMAND_STATUS); 5584 - 5585 - /* Configure task request UPIU */ 5586 5638 task_tag = hba->nutrs + free_slot; 5587 - treq->req_header.dword_0 = UPIU_HEADER_DWORD(UPIU_TRANSACTION_TASK_REQ, 5588 - 0, lun_id, task_tag); 5589 - treq->req_header.dword_1 = UPIU_HEADER_DWORD(0, tm_function, 0, 0); 5590 - /* 5591 - * The host shall provide the same value for LUN field in the basic 5592 - * header and for Input Parameter. 5593 - */ 5594 - treq->input_param1 = cpu_to_be32(lun_id); 5595 - treq->input_param2 = cpu_to_be32(task_id); 5596 5639 5640 + treq->req_header.dword_0 |= cpu_to_be32(task_tag); 5641 + 5642 + memcpy(hba->utmrdl_base_addr + free_slot, treq, sizeof(*treq)); 5597 5643 ufshcd_vops_setup_task_mgmt(hba, free_slot, tm_function); 5598 5644 5599 5645 /* send command to the controller */ ··· 5610 5682 __func__, free_slot); 5611 5683 err = -ETIMEDOUT; 5612 5684 } else { 5613 - err = ufshcd_task_req_compl(hba, free_slot, tm_response); 5685 + err = 0; 5686 + memcpy(treq, hba->utmrdl_base_addr + free_slot, sizeof(*treq)); 5687 + 5614 5688 ufshcd_add_tm_upiu_trace(hba, task_tag, "tm_complete"); 5689 + 5690 + spin_lock_irqsave(hba->host->host_lock, flags); 5691 + __clear_bit(free_slot, &hba->outstanding_tasks); 5692 + spin_unlock_irqrestore(hba->host->host_lock, flags); 5693 + 5615 5694 } 5616 5695 5617 5696 clear_bit(free_slot, &hba->tm_condition); ··· 5626 5691 wake_up(&hba->tm_tag_wq); 5627 5692 5628 5693 ufshcd_release(hba); 5694 + return err; 5695 + } 5696 + 5697 + /** 5698 + * ufshcd_issue_tm_cmd - issues task management commands to controller 5699 + * @hba: per adapter instance 5700 + * @lun_id: LUN ID to which TM command is sent 5701 + * @task_id: task ID to which the TM command is applicable 5702 + * @tm_function: task management function opcode 5703 + * @tm_response: task management service response return value 5704 + * 5705 + * Returns non-zero value on error, zero on success. 5706 + */ 5707 + static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id, 5708 + u8 tm_function, u8 *tm_response) 5709 + { 5710 + struct utp_task_req_desc treq = { { 0 }, }; 5711 + int ocs_value, err; 5712 + 5713 + /* Configure task request descriptor */ 5714 + treq.header.dword_0 = cpu_to_le32(UTP_REQ_DESC_INT_CMD); 5715 + treq.header.dword_2 = cpu_to_le32(OCS_INVALID_COMMAND_STATUS); 5716 + 5717 + /* Configure task request UPIU */ 5718 + treq.req_header.dword_0 = cpu_to_be32(lun_id << 8) | 5719 + cpu_to_be32(UPIU_TRANSACTION_TASK_REQ << 24); 5720 + treq.req_header.dword_1 = cpu_to_be32(tm_function << 16); 5721 + 5722 + /* 5723 + * The host shall provide the same value for LUN field in the basic 5724 + * header and for Input Parameter. 5725 + */ 5726 + treq.input_param1 = cpu_to_be32(lun_id); 5727 + treq.input_param2 = cpu_to_be32(task_id); 5728 + 5729 + err = __ufshcd_issue_tm_cmd(hba, &treq, tm_function); 5730 + if (err == -ETIMEDOUT) 5731 + return err; 5732 + 5733 + ocs_value = le32_to_cpu(treq.header.dword_2) & MASK_OCS; 5734 + if (ocs_value != OCS_SUCCESS) 5735 + dev_err(hba->dev, "%s: failed, ocs = 0x%x\n", 5736 + __func__, ocs_value); 5737 + else if (tm_response) 5738 + *tm_response = be32_to_cpu(treq.output_param1) & 5739 + MASK_TM_SERVICE_RESP; 5629 5740 return err; 5630 5741 } 5631 5742