drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
Extension
.c
Size
186342 bytes
Lines
6564
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 bnx2x_mcast_mac_elem {
	struct list_head link;
	u8 mac[ETH_ALEN];
	u8 pad[2]; /* For a natural alignment of the following buffer */
};

struct bnx2x_mcast_bin_elem {
	struct list_head link;
	int bin;
	int type; /* BNX2X_MCAST_CMD_SET_{ADD, DEL} */
};

union bnx2x_mcast_elem {
	struct bnx2x_mcast_bin_elem bin_elem;
	struct bnx2x_mcast_mac_elem mac_elem;
};

struct bnx2x_mcast_elem_group {
	struct list_head mcast_group_link;
	union bnx2x_mcast_elem mcast_elems[];
};

#define MCAST_MAC_ELEMS_PER_PG \
	((PAGE_SIZE - sizeof(struct bnx2x_mcast_elem_group)) / \
	sizeof(union bnx2x_mcast_elem))

struct bnx2x_pending_mcast_cmd {
	struct list_head link;
	struct list_head group_head;
	int type; /* BNX2X_MCAST_CMD_X */
	union {
		struct list_head macs_head;
		u32 macs_num; /* Needed for DEL command */
		int next_bin; /* Needed for RESTORE flow with aprox match */
	} data;

	bool set_convert; /* in case type == BNX2X_MCAST_CMD_SET, this is set
			   * when macs_head had been converted to a list of
			   * bnx2x_mcast_bin_elem.
			   */

	bool done; /* set to true, when the command has been handled,
		    * practically used in 57712 handling only, where one pending
		    * command may be handled in a few operations. As long as for
		    * other chips every operation handling is completed in a
		    * single ramrod, there is no need to utilize this field.
		    */
};

static int bnx2x_mcast_wait(struct bnx2x *bp,
			    struct bnx2x_mcast_obj *o)
{
	if (bnx2x_state_wait(bp, o->sched_state, o->raw.pstate) ||
			o->raw.wait_comp(bp, &o->raw))
		return -EBUSY;

	return 0;
}

static void bnx2x_free_groups(struct list_head *mcast_group_list)
{
	struct bnx2x_mcast_elem_group *current_mcast_group;

	while (!list_empty(mcast_group_list)) {
		current_mcast_group = list_first_entry(mcast_group_list,
				      struct bnx2x_mcast_elem_group,
				      mcast_group_link);
		list_del(&current_mcast_group->mcast_group_link);
		free_page((unsigned long)current_mcast_group);
	}
}

static int bnx2x_mcast_enqueue_cmd(struct bnx2x *bp,
				   struct bnx2x_mcast_obj *o,
				   struct bnx2x_mcast_ramrod_params *p,
				   enum bnx2x_mcast_cmd cmd)
{
	struct bnx2x_pending_mcast_cmd *new_cmd;
	struct bnx2x_mcast_list_elem *pos;
	struct bnx2x_mcast_elem_group *elem_group;
	struct bnx2x_mcast_mac_elem *mac_elem;
	int total_elems = 0, macs_list_len = 0, offset = 0;

	/* When adding MACs we'll need to store their values */
	if (cmd == BNX2X_MCAST_CMD_ADD || cmd == BNX2X_MCAST_CMD_SET)
		macs_list_len = p->mcast_list_len;

	/* If the command is empty ("handle pending commands only"), break */
	if (!p->mcast_list_len)
		return 0;

Annotation

Implementation Notes