mirror of
https://github.com/torvalds/linux.git
synced 2024-11-29 15:41:36 +00:00
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:
parent
76f82fd9b1
commit
eb0faf32b8
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user