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

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/huawei/hinic3/hinic3_hw_cfg.c
Extension
.c
Size
6872 bytes
Lines
277
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 (err) {
			dev_err(hwdev->dev, "Failed to get FW capability\n");
			return err;
		}
		break;
	default:
		dev_err(hwdev->dev, "Unsupported PCI Function type: %d\n",
			type);
		return -EINVAL;
	}

	return 0;
}

static int hinic3_init_irq_info(struct hinic3_hwdev *hwdev)
{
	struct hinic3_cfg_mgmt_info *cfg_mgmt = hwdev->cfg_mgmt;
	struct hinic3_hwif *hwif = hwdev->hwif;
	u16 intr_num = hwif->attr.num_irqs;
	struct hinic3_irq_info *irq_info;
	u16 intr_needed;

	intr_needed = hwif->attr.msix_flex_en ? (hwif->attr.num_aeqs +
		      hwif->attr.num_ceqs + hwif->attr.num_sq) : intr_num;
	if (intr_needed > intr_num) {
		dev_warn(hwdev->dev, "Irq num cfg %d is less than the needed irq num %d msix_flex_en %d\n",
			 intr_num, intr_needed, hwdev->hwif->attr.msix_flex_en);
		intr_needed = intr_num;
	}

	irq_info = &cfg_mgmt->irq_info;
	irq_info->irq = kzalloc_objs(struct hinic3_irq, intr_num);
	if (!irq_info->irq)
		return -ENOMEM;

	irq_info->num_irq_hw = intr_needed;
	mutex_init(&irq_info->irq_mutex);

	return 0;
}

static int hinic3_init_irq_alloc_info(struct hinic3_hwdev *hwdev)
{
	struct hinic3_cfg_mgmt_info *cfg_mgmt = hwdev->cfg_mgmt;
	struct hinic3_irq *irq = cfg_mgmt->irq_info.irq;
	u16 nreq = cfg_mgmt->irq_info.num_irq_hw;
	struct pci_dev *pdev = hwdev->pdev;
	int actual_irq;
	u16 i;

	actual_irq = pci_alloc_irq_vectors(pdev, 2, nreq, PCI_IRQ_MSIX);
	if (actual_irq < 0) {
		dev_err(hwdev->dev, "Alloc msix entries with threshold 2 failed. actual_irq: %d\n",
			actual_irq);
		return -ENOMEM;
	}

	nreq = actual_irq;
	cfg_mgmt->irq_info.num_irq = nreq;

	for (i = 0; i < nreq; ++i) {
		irq[i].msix_entry_idx = i;
		irq[i].irq_id = pci_irq_vector(pdev, i);
		irq[i].allocated = false;
	}

	return 0;
}

int hinic3_init_cfg_mgmt(struct hinic3_hwdev *hwdev)
{
	struct hinic3_cfg_mgmt_info *cfg_mgmt;
	int err;

	cfg_mgmt = kzalloc_obj(*cfg_mgmt);
	if (!cfg_mgmt)
		return -ENOMEM;

	hwdev->cfg_mgmt = cfg_mgmt;

	err = hinic3_init_irq_info(hwdev);
	if (err) {
		dev_err(hwdev->dev, "Failed to init hinic3_irq_mgmt_info, err: %d\n",
			err);
		goto err_free_cfg_mgmt;
	}

	err = hinic3_init_irq_alloc_info(hwdev);
	if (err) {
		dev_err(hwdev->dev, "Failed to init hinic3_irq_info, err: %d\n",

Annotation

Implementation Notes