drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
Extension
.c
Size
61047 bytes
Lines
2227
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

if (tmp_fil) {
			time = tmp_fil->ftime;
			if (time_after(jiffies, QLCNIC_READD_AGE * HZ + time))
				tmp_fil->ftime = jiffies;
			return;
		}

		fil = kzalloc_obj(struct qlcnic_filter, GFP_ATOMIC);
		if (!fil)
			return;

		fil->ftime = jiffies;
		memcpy(fil->faddr, &src_addr, ETH_ALEN);
		fil->vlan_id = vlan_id;
		spin_lock(&adapter->rx_mac_learn_lock);
		hlist_add_head(&(fil->fnode), head);
		adapter->rx_fhash.fnum++;
		spin_unlock(&adapter->rx_mac_learn_lock);
	} else {
		head = &adapter->fhash.fhead[hindex];

		spin_lock(&adapter->mac_learn_lock);

		tmp_fil = qlcnic_find_mac_filter(head, &src_addr, vlan_id);
		if (tmp_fil) {
			op = vlan_id ? QLCNIC_MAC_VLAN_DEL : QLCNIC_MAC_DEL;
			ret = qlcnic_sre_macaddr_change(adapter,
							(u8 *)&src_addr,
							vlan_id, op);
			if (!ret) {
				hlist_del(&tmp_fil->fnode);
				adapter->fhash.fnum--;
			}

			spin_unlock(&adapter->mac_learn_lock);

			return;
		}

		spin_unlock(&adapter->mac_learn_lock);

		head = &adapter->rx_fhash.fhead[hindex];

		spin_lock(&adapter->rx_mac_learn_lock);

		tmp_fil = qlcnic_find_mac_filter(head, &src_addr, vlan_id);
		if (tmp_fil)
			qlcnic_delete_rx_list_mac(adapter, tmp_fil, &src_addr,
						  vlan_id);

		spin_unlock(&adapter->rx_mac_learn_lock);
	}
}

void qlcnic_82xx_change_filter(struct qlcnic_adapter *adapter, u64 *uaddr,
			       u16 vlan_id, struct qlcnic_host_tx_ring *tx_ring)
{
	struct cmd_desc_type0 *hwdesc;
	struct qlcnic_nic_req *req;
	struct qlcnic_mac_req *mac_req;
	struct qlcnic_vlan_req *vlan_req;
	u32 producer;
	u64 word;

	producer = tx_ring->producer;
	hwdesc = &tx_ring->desc_head[tx_ring->producer];

	req = (struct qlcnic_nic_req *)hwdesc;
	memset(req, 0, sizeof(struct qlcnic_nic_req));
	req->qhdr = cpu_to_le64(QLCNIC_REQUEST << 23);

	word = QLCNIC_MAC_EVENT | ((u64)(adapter->portnum) << 16);
	req->req_hdr = cpu_to_le64(word);

	mac_req = (struct qlcnic_mac_req *)&(req->words[0]);
	mac_req->op = vlan_id ? QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_ADD;
	memcpy(mac_req->mac_addr, uaddr, ETH_ALEN);

	vlan_req = (struct qlcnic_vlan_req *)&req->words[1];
	vlan_req->vlan_id = cpu_to_le16(vlan_id);

	tx_ring->producer = get_next_index(producer, tx_ring->num_desc);
	smp_mb();
}

static void qlcnic_send_filter(struct qlcnic_adapter *adapter,
			       struct cmd_desc_type0 *first_desc,
			       struct sk_buff *skb,
			       struct qlcnic_host_tx_ring *tx_ring)
{

Annotation

Implementation Notes