net: hns3: split out hclgevf_cmd_send()

hclgevf_cmd_send() is bloated, so split it into separate
functions for readability and maintainability.

Signed-off-by: Yufeng Mo <moyufeng@huawei.com>
Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Yufeng Mo 2021-02-12 11:24:14 +08:00 committed by David S. Miller
parent 76f82fd9b1
commit eb0faf32b8

View File

@ -181,6 +181,22 @@ struct vf_errcode {
int common_errno; int common_errno;
}; };
static void hclgevf_cmd_copy_desc(struct hclgevf_hw *hw,
struct hclgevf_desc *desc, int num)
{
struct hclgevf_desc *desc_to_use;
int handle = 0;
while (handle < num) {
desc_to_use = &hw->cmq.csq.desc[hw->cmq.csq.next_to_use];
*desc_to_use = desc[handle];
(hw->cmq.csq.next_to_use)++;
if (hw->cmq.csq.next_to_use == hw->cmq.csq.desc_num)
hw->cmq.csq.next_to_use = 0;
handle++;
}
}
static int hclgevf_cmd_convert_err_code(u16 desc_ret) static int hclgevf_cmd_convert_err_code(u16 desc_ret)
{ {
struct vf_errcode hclgevf_cmd_errcode[] = { struct vf_errcode hclgevf_cmd_errcode[] = {
@ -207,6 +223,66 @@ static int hclgevf_cmd_convert_err_code(u16 desc_ret)
return -EIO; return -EIO;
} }
static int hclgevf_cmd_check_retval(struct hclgevf_hw *hw,
struct hclgevf_desc *desc, int num, int ntc)
{
u16 opcode, desc_ret;
int handle;
opcode = le16_to_cpu(desc[0].opcode);
for (handle = 0; handle < num; handle++) {
/* Get the result of hardware write back */
desc[handle] = hw->cmq.csq.desc[ntc];
ntc++;
if (ntc == hw->cmq.csq.desc_num)
ntc = 0;
}
if (likely(!hclgevf_is_special_opcode(opcode)))
desc_ret = le16_to_cpu(desc[num - 1].retval);
else
desc_ret = le16_to_cpu(desc[0].retval);
hw->cmq.last_status = desc_ret;
return hclgevf_cmd_convert_err_code(desc_ret);
}
static int hclgevf_cmd_check_result(struct hclgevf_hw *hw,
struct hclgevf_desc *desc, int num, int ntc)
{
struct hclgevf_dev *hdev = (struct hclgevf_dev *)hw->hdev;
bool is_completed = false;
u32 timeout = 0;
int handle, ret;
/* If the command is sync, wait for the firmware to write back,
* if multi descriptors to be sent, use the first one to check
*/
if (HCLGEVF_SEND_SYNC(le16_to_cpu(desc->flag))) {
do {
if (hclgevf_cmd_csq_done(hw)) {
is_completed = true;
break;
}
udelay(1);
timeout++;
} while (timeout < hw->cmq.tx_timeout);
}
if (!is_completed)
ret = -EBADE;
else
ret = hclgevf_cmd_check_retval(hw, desc, num, ntc);
/* Clean the command send queue */
handle = hclgevf_cmd_csq_clean(hw);
if (handle < 0)
ret = handle;
else if (handle != num)
dev_warn(&hdev->pdev->dev,
"cleaned %d, need to clean %d\n", handle, num);
return ret;
}
/* hclgevf_cmd_send - send command to command queue /* hclgevf_cmd_send - send command to command queue
* @hw: pointer to the hw struct * @hw: pointer to the hw struct
* @desc: prefilled descriptor for describing the command * @desc: prefilled descriptor for describing the command
@ -219,13 +295,7 @@ int hclgevf_cmd_send(struct hclgevf_hw *hw, struct hclgevf_desc *desc, int num)
{ {
struct hclgevf_dev *hdev = (struct hclgevf_dev *)hw->hdev; struct hclgevf_dev *hdev = (struct hclgevf_dev *)hw->hdev;
struct hclgevf_cmq_ring *csq = &hw->cmq.csq; struct hclgevf_cmq_ring *csq = &hw->cmq.csq;
struct hclgevf_desc *desc_to_use; int ret;
bool complete = false;
u32 timeout = 0;
int handle = 0;
int status = 0;
u16 retval;
u16 opcode;
int ntc; int ntc;
spin_lock_bh(&hw->cmq.csq.lock); spin_lock_bh(&hw->cmq.csq.lock);
@ -249,67 +319,18 @@ int hclgevf_cmd_send(struct hclgevf_hw *hw, struct hclgevf_desc *desc, int num)
* which will be use for hardware to write back * which will be use for hardware to write back
*/ */
ntc = hw->cmq.csq.next_to_use; ntc = hw->cmq.csq.next_to_use;
opcode = le16_to_cpu(desc[0].opcode);
while (handle < num) { hclgevf_cmd_copy_desc(hw, desc, num);
desc_to_use = &hw->cmq.csq.desc[hw->cmq.csq.next_to_use];
*desc_to_use = desc[handle];
(hw->cmq.csq.next_to_use)++;
if (hw->cmq.csq.next_to_use == hw->cmq.csq.desc_num)
hw->cmq.csq.next_to_use = 0;
handle++;
}
/* Write to hardware */ /* Write to hardware */
hclgevf_write_dev(hw, HCLGEVF_NIC_CSQ_TAIL_REG, hclgevf_write_dev(hw, HCLGEVF_NIC_CSQ_TAIL_REG,
hw->cmq.csq.next_to_use); hw->cmq.csq.next_to_use);
/* If the command is sync, wait for the firmware to write back, ret = hclgevf_cmd_check_result(hw, desc, num, ntc);
* if multi descriptors to be sent, use the first one to check
*/
if (HCLGEVF_SEND_SYNC(le16_to_cpu(desc->flag))) {
do {
if (hclgevf_cmd_csq_done(hw))
break;
udelay(1);
timeout++;
} while (timeout < hw->cmq.tx_timeout);
}
if (hclgevf_cmd_csq_done(hw)) {
complete = true;
handle = 0;
while (handle < num) {
/* Get the result of hardware write back */
desc_to_use = &hw->cmq.csq.desc[ntc];
desc[handle] = *desc_to_use;
if (likely(!hclgevf_is_special_opcode(opcode)))
retval = le16_to_cpu(desc[handle].retval);
else
retval = le16_to_cpu(desc[0].retval);
status = hclgevf_cmd_convert_err_code(retval);
hw->cmq.last_status = (enum hclgevf_cmd_status)retval;
ntc++;
handle++;
if (ntc == hw->cmq.csq.desc_num)
ntc = 0;
}
}
if (!complete)
status = -EBADE;
/* Clean the command send queue */
handle = hclgevf_cmd_csq_clean(hw);
if (handle != num)
dev_warn(&hdev->pdev->dev,
"cleaned %d, need to clean %d\n", handle, num);
spin_unlock_bh(&hw->cmq.csq.lock); spin_unlock_bh(&hw->cmq.csq.lock);
return status; return ret;
} }
static void hclgevf_set_default_capability(struct hclgevf_dev *hdev) static void hclgevf_set_default_capability(struct hclgevf_dev *hdev)