drivers/net/ethernet/qlogic/qed/qed_dev.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/qlogic/qed/qed_dev.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/qlogic/qed/qed_dev.c
Extension
.c
Size
147646 bytes
Lines
5505
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

struct qed_db_recovery_entry {
	struct list_head list_entry;
	void __iomem *db_addr;
	void *db_data;
	enum qed_db_rec_width db_width;
	enum qed_db_rec_space db_space;
	u8 hwfn_idx;
};

/* Display a single doorbell recovery entry */
static void qed_db_recovery_dp_entry(struct qed_hwfn *p_hwfn,
				     struct qed_db_recovery_entry *db_entry,
				     char *action)
{
	DP_VERBOSE(p_hwfn,
		   QED_MSG_SPQ,
		   "(%s: db_entry %p, addr %p, data %p, width %s, %s space, hwfn %d)\n",
		   action,
		   db_entry,
		   db_entry->db_addr,
		   db_entry->db_data,
		   db_entry->db_width == DB_REC_WIDTH_32B ? "32b" : "64b",
		   db_entry->db_space == DB_REC_USER ? "user" : "kernel",
		   db_entry->hwfn_idx);
}

/* Doorbell address sanity (address within doorbell bar range) */
static bool qed_db_rec_sanity(struct qed_dev *cdev,
			      void __iomem *db_addr,
			      enum qed_db_rec_width db_width,
			      void *db_data)
{
	u32 width = (db_width == DB_REC_WIDTH_32B) ? 32 : 64;

	/* Make sure doorbell address is within the doorbell bar */
	if (db_addr < cdev->doorbells ||
	    (u8 __iomem *)db_addr + width >
	    (u8 __iomem *)cdev->doorbells + cdev->db_size) {
		WARN(true,
		     "Illegal doorbell address: %p. Legal range for doorbell addresses is [%p..%p]\n",
		     db_addr,
		     cdev->doorbells,
		     (u8 __iomem *)cdev->doorbells + cdev->db_size);
		return false;
	}

	/* ake sure doorbell data pointer is not null */
	if (!db_data) {
		WARN(true, "Illegal doorbell data pointer: %p", db_data);
		return false;
	}

	return true;
}

/* Find hwfn according to the doorbell address */
static struct qed_hwfn *qed_db_rec_find_hwfn(struct qed_dev *cdev,
					     void __iomem *db_addr)
{
	struct qed_hwfn *p_hwfn;

	/* In CMT doorbell bar is split down the middle between engine 0 and enigne 1 */
	if (cdev->num_hwfns > 1)
		p_hwfn = db_addr < cdev->hwfns[1].doorbells ?
		    &cdev->hwfns[0] : &cdev->hwfns[1];
	else
		p_hwfn = QED_LEADING_HWFN(cdev);

	return p_hwfn;
}

/* Add a new entry to the doorbell recovery mechanism */
int qed_db_recovery_add(struct qed_dev *cdev,
			void __iomem *db_addr,
			void *db_data,
			enum qed_db_rec_width db_width,
			enum qed_db_rec_space db_space)
{
	struct qed_db_recovery_entry *db_entry;
	struct qed_hwfn *p_hwfn;

	/* Shortcircuit VFs, for now */
	if (IS_VF(cdev)) {
		DP_VERBOSE(cdev,
			   QED_MSG_IOV, "db recovery - skipping VF doorbell\n");
		return 0;
	}

	/* Sanitize doorbell address */
	if (!qed_db_rec_sanity(cdev, db_addr, db_width, db_data))

Annotation

Implementation Notes