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

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
Extension
.c
Size
58128 bytes
Lines
2236
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 (qlcnic_sriov_pf_check(adapter)) {
			vp = kzalloc_obj(struct qlcnic_vport);
			if (!vp) {
				err = -ENOMEM;
				goto qlcnic_destroy_async_wq;
			}
			sriov->vf_info[i].vp = vp;
			vp->vlan_mode = QLC_GUEST_VLAN_MODE;
			vp->max_tx_bw = MAX_BW;
			vp->min_tx_bw = MIN_BW;
			vp->spoofchk = false;
			eth_random_addr(vp->mac);
			dev_info(&adapter->pdev->dev,
				 "MAC Address %pM is configured for VF %d\n",
				 vp->mac, i);
		}
	}

	return 0;

qlcnic_destroy_async_wq:
	while (i--)
		kfree(sriov->vf_info[i].vp);
	destroy_workqueue(bc->bc_async_wq);

qlcnic_destroy_trans_wq:
	destroy_workqueue(bc->bc_trans_wq);

qlcnic_free_vf_info:
	kfree(sriov->vf_info);

qlcnic_free_sriov:
	kfree(adapter->ahw->sriov);
	return err;
}

void qlcnic_sriov_cleanup_list(struct qlcnic_trans_list *t_list)
{
	struct qlcnic_bc_trans *trans;
	struct qlcnic_cmd_args cmd;
	unsigned long flags;

	spin_lock_irqsave(&t_list->lock, flags);

	while (!list_empty(&t_list->wait_list)) {
		trans = list_first_entry(&t_list->wait_list,
					 struct qlcnic_bc_trans, list);
		list_del(&trans->list);
		t_list->count--;
		cmd.req.arg = (u32 *)trans->req_pay;
		cmd.rsp.arg = (u32 *)trans->rsp_pay;
		qlcnic_free_mbx_args(&cmd);
		qlcnic_sriov_cleanup_transaction(trans);
	}

	spin_unlock_irqrestore(&t_list->lock, flags);
}

void __qlcnic_sriov_cleanup(struct qlcnic_adapter *adapter)
{
	struct qlcnic_sriov *sriov = adapter->ahw->sriov;
	struct qlcnic_back_channel *bc = &sriov->bc;
	struct qlcnic_vf_info *vf;
	int i;

	if (!qlcnic_sriov_enable_check(adapter))
		return;

	qlcnic_sriov_cleanup_async_list(bc);
	destroy_workqueue(bc->bc_async_wq);

	for (i = 0; i < sriov->num_vfs; i++) {
		vf = &sriov->vf_info[i];
		qlcnic_sriov_cleanup_list(&vf->rcv_pend);
		cancel_work_sync(&vf->trans_work);
		qlcnic_sriov_cleanup_list(&vf->rcv_act);
	}

	destroy_workqueue(bc->bc_trans_wq);

	for (i = 0; i < sriov->num_vfs; i++)
		kfree(sriov->vf_info[i].vp);

	kfree(sriov->vf_info);
	kfree(adapter->ahw->sriov);
}

static void qlcnic_sriov_vf_cleanup(struct qlcnic_adapter *adapter)
{
	qlcnic_sriov_channel_cfg_cmd(adapter, QLCNIC_BC_CMD_CHANNEL_TERM);

Annotation

Implementation Notes