drivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c
Extension
.c
Size
28288 bytes
Lines
1081
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

switch (cmd_info->cmd_type) {
		case HINIC3_CMD_TYPE_NONE:
			return;
		case HINIC3_CMD_TYPE_TIMEOUT:
			dev_warn(hwdev->dev, "Cmdq timeout, q_id: %u, ci: %u\n",
				 cmdq_type, ci);
			hinic3_dump_cmdq_wqe_head(hwdev, wqe);
			fallthrough;
		case HINIC3_CMD_TYPE_FAKE_TIMEOUT:
			cmdq_clear_cmd_buf(cmd_info, hwdev);
			clear_wqe_complete_bit(cmdq, wqe, ci);
			break;
		case HINIC3_CMD_TYPE_SET_ARM:
			/* arm_bit was set until here */
			if (cmdq_arm_ceq_handler(cmdq, wqe, ci))
				return;
			break;
		default:
			/* only arm bit is using scmd wqe,
			 * the other wqe is lcmd
			 */
			wqe_lcmd = &wqe->wqe_lcmd;
			ctrl_info = wqe_lcmd->ctrl.ctrl_info;
			if (!CMDQ_WQE_COMPLETED(ctrl_info))
				return;

			dma_rmb();
			/* For FORCE_STOP cmd_type, we also need to wait for
			 * the firmware processing to complete to prevent the
			 * firmware from accessing the released cmd_buf
			 */
			if (cmd_info->cmd_type == HINIC3_CMD_TYPE_FORCE_STOP) {
				cmdq_clear_cmd_buf(cmd_info, hwdev);
				clear_wqe_complete_bit(cmdq, wqe, ci);
			} else {
				cmdq_sync_cmd_handler(cmdq, wqe, ci);
			}

			break;
		}
	}
}

static int cmdq_params_valid(const struct hinic3_hwdev *hwdev,
			     const struct hinic3_cmd_buf *buf_in)
{
	if (le16_to_cpu(buf_in->size) > CMDQ_BUF_SIZE) {
		dev_err(hwdev->dev, "Invalid CMDQ buffer size: 0x%x\n",
			le16_to_cpu(buf_in->size));
		return -EINVAL;
	}

	return 0;
}

static int wait_cmdqs_enable(struct hinic3_cmdqs *cmdqs)
{
	unsigned long end;

	end = jiffies + msecs_to_jiffies(CMDQ_ENABLE_WAIT_TIMEOUT);
	do {
		if (cmdqs->status & HINIC3_CMDQ_ENABLE)
			return 0;
		usleep_range(1000, 2000);
	} while (time_before(jiffies, end) && !cmdqs->disable_flag &&
		 cmdqs->hwdev->chip_present_flag);

	cmdqs->disable_flag = 1;

	return -EBUSY;
}

static void cmdq_set_completion(struct cmdq_completion *complete,
				struct hinic3_cmd_buf *buf_out)
{
	struct hinic3_sge *sge = &complete->resp.sge;

	hinic3_set_sge(sge, buf_out->dma_addr, cpu_to_le32(CMDQ_BUF_SIZE));
}

static struct cmdq_wqe *cmdq_get_wqe(struct hinic3_wq *wq, u16 *pi)
{
	if (!hinic3_wq_free_wqebbs(wq))
		return NULL;

	return hinic3_wq_get_one_wqebb(wq, pi);
}

static void cmdq_set_lcmd_bufdesc(struct cmdq_wqe_lcmd *wqe,
				  struct hinic3_cmd_buf *buf_in)

Annotation

Implementation Notes