Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  hinic3_lld.c  Sprache: unbekannt

 
Spracherkennung für: .c vermutete Sprache: CS {CS[34] C[32] Lisp[31]} [Methode: maximale Elemente, drei Dimensionen]

// SPDX-License-Identifier: GPL-2.0
// Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.

#include <linux/delay.h>
#include <linux/iopoll.h>

#include "hinic3_hw_cfg.h"
#include "hinic3_hwdev.h"
#include "hinic3_lld.h"
#include "hinic3_mgmt.h"

#define HINIC3_VF_PCI_CFG_REG_BAR  0
#define HINIC3_PCI_INTR_REG_BAR    2
#define HINIC3_PCI_DB_BAR          4

#define HINIC3_EVENT_POLL_SLEEP_US   1000
#define HINIC3_EVENT_POLL_TIMEOUT_US 10000000

static struct hinic3_adev_device {
 const char *name;
} hinic3_adev_devices[HINIC3_SERVICE_T_MAX] = {
 [HINIC3_SERVICE_T_NIC] = {
  .name = "nic",
 },
};

static bool hinic3_adev_svc_supported(struct hinic3_hwdev *hwdev,
          enum hinic3_service_type svc_type)
{
 switch (svc_type) {
 case HINIC3_SERVICE_T_NIC:
  return hinic3_support_nic(hwdev);
 default:
  break;
 }

 return false;
}

static void hinic3_comm_adev_release(struct device *dev)
{
 struct hinic3_adev *hadev = container_of(dev, struct hinic3_adev,
       adev.dev);

 kfree(hadev);
}

static struct hinic3_adev *hinic3_add_one_adev(struct hinic3_hwdev *hwdev,
            enum hinic3_service_type svc_type)
{
 struct hinic3_adev *hadev;
 const char *svc_name;
 int ret;

 hadev = kzalloc(sizeof(*hadev), GFP_KERNEL);
 if (!hadev)
  return NULL;

 svc_name = hinic3_adev_devices[svc_type].name;
 hadev->adev.name = svc_name;
 hadev->adev.id = hwdev->dev_id;
 hadev->adev.dev.parent = hwdev->dev;
 hadev->adev.dev.release = hinic3_comm_adev_release;
 hadev->svc_type = svc_type;
 hadev->hwdev = hwdev;

 ret = auxiliary_device_init(&hadev->adev);
 if (ret) {
  dev_err(hwdev->dev, "failed init adev %s %u\n",
   svc_name, hwdev->dev_id);
  kfree(hadev);
  return NULL;
 }

 ret = auxiliary_device_add(&hadev->adev);
 if (ret) {
  dev_err(hwdev->dev, "failed to add adev %s %u\n",
   svc_name, hwdev->dev_id);
  auxiliary_device_uninit(&hadev->adev);
  return NULL;
 }

 return hadev;
}

static void hinic3_del_one_adev(struct hinic3_hwdev *hwdev,
    enum hinic3_service_type svc_type)
{
 struct hinic3_pcidev *pci_adapter = hwdev->adapter;
 struct hinic3_adev *hadev;
 int timeout;
 bool state;

 timeout = read_poll_timeout(test_and_set_bit, state, !state,
        HINIC3_EVENT_POLL_SLEEP_US,
        HINIC3_EVENT_POLL_TIMEOUT_US,
        false, svc_type, &pci_adapter->state);

 hadev = pci_adapter->hadev[svc_type];
 auxiliary_device_delete(&hadev->adev);
 auxiliary_device_uninit(&hadev->adev);
 pci_adapter->hadev[svc_type] = NULL;
 if (!timeout)
  clear_bit(svc_type, &pci_adapter->state);
}

static int hinic3_attach_aux_devices(struct hinic3_hwdev *hwdev)
{
 struct hinic3_pcidev *pci_adapter = hwdev->adapter;
 enum hinic3_service_type svc_type;

 mutex_lock(&pci_adapter->pdev_mutex);

 for (svc_type = 0; svc_type < HINIC3_SERVICE_T_MAX; svc_type++) {
  if (!hinic3_adev_svc_supported(hwdev, svc_type))
   continue;

  pci_adapter->hadev[svc_type] = hinic3_add_one_adev(hwdev,
           svc_type);
  if (!pci_adapter->hadev[svc_type])
   goto err_del_adevs;
 }
 mutex_unlock(&pci_adapter->pdev_mutex);
 return 0;

err_del_adevs:
 while (svc_type > 0) {
  svc_type--;
  if (pci_adapter->hadev[svc_type]) {
   hinic3_del_one_adev(hwdev, svc_type);
   pci_adapter->hadev[svc_type] = NULL;
  }
 }
 mutex_unlock(&pci_adapter->pdev_mutex);
 return -ENOMEM;
}

static void hinic3_detach_aux_devices(struct hinic3_hwdev *hwdev)
{
 struct hinic3_pcidev *pci_adapter = hwdev->adapter;
 int i;

 mutex_lock(&pci_adapter->pdev_mutex);
 for (i = 0; i < ARRAY_SIZE(hinic3_adev_devices); i++) {
  if (pci_adapter->hadev[i])
   hinic3_del_one_adev(hwdev, i);
 }
 mutex_unlock(&pci_adapter->pdev_mutex);
}

struct hinic3_hwdev *hinic3_adev_get_hwdev(struct auxiliary_device *adev)
{
 struct hinic3_adev *hadev;

 hadev = container_of(adev, struct hinic3_adev, adev);
 return hadev->hwdev;
}

void hinic3_adev_event_register(struct auxiliary_device *adev,
    void (*event_handler)(struct auxiliary_device *adev,
            struct hinic3_event_info *event))
{
 struct hinic3_adev *hadev;

 hadev = container_of(adev, struct hinic3_adev, adev);
 hadev->event = event_handler;
}

void hinic3_adev_event_unregister(struct auxiliary_device *adev)
{
 struct hinic3_adev *hadev;

 hadev = container_of(adev, struct hinic3_adev, adev);
 hadev->event = NULL;
}

static int hinic3_mapping_bar(struct pci_dev *pdev,
         struct hinic3_pcidev *pci_adapter)
{
 pci_adapter->cfg_reg_base = pci_ioremap_bar(pdev,
          HINIC3_VF_PCI_CFG_REG_BAR);
 if (!pci_adapter->cfg_reg_base) {
  dev_err(&pdev->dev, "Failed to map configuration regs\n");
  return -ENOMEM;
 }

 pci_adapter->intr_reg_base = pci_ioremap_bar(pdev,
           HINIC3_PCI_INTR_REG_BAR);
 if (!pci_adapter->intr_reg_base) {
  dev_err(&pdev->dev, "Failed to map interrupt regs\n");
  goto err_unmap_cfg_reg_base;
 }

 pci_adapter->db_base_phy = pci_resource_start(pdev, HINIC3_PCI_DB_BAR);
 pci_adapter->db_dwqe_len = pci_resource_len(pdev, HINIC3_PCI_DB_BAR);
 pci_adapter->db_base = pci_ioremap_bar(pdev, HINIC3_PCI_DB_BAR);
 if (!pci_adapter->db_base) {
  dev_err(&pdev->dev, "Failed to map doorbell regs\n");
  goto err_unmap_intr_reg_base;
 }

 return 0;

err_unmap_intr_reg_base:
 iounmap(pci_adapter->intr_reg_base);

err_unmap_cfg_reg_base:
 iounmap(pci_adapter->cfg_reg_base);

 return -ENOMEM;
}

static void hinic3_unmapping_bar(struct hinic3_pcidev *pci_adapter)
{
 iounmap(pci_adapter->db_base);
 iounmap(pci_adapter->intr_reg_base);
 iounmap(pci_adapter->cfg_reg_base);
}

static int hinic3_pci_init(struct pci_dev *pdev)
{
 struct hinic3_pcidev *pci_adapter;
 int err;

 pci_adapter = kzalloc(sizeof(*pci_adapter), GFP_KERNEL);
 if (!pci_adapter)
  return -ENOMEM;

 pci_adapter->pdev = pdev;
 mutex_init(&pci_adapter->pdev_mutex);

 pci_set_drvdata(pdev, pci_adapter);

 err = pci_enable_device(pdev);
 if (err) {
  dev_err(&pdev->dev, "Failed to enable PCI device\n");
  goto err_free_pci_adapter;
 }

 err = pci_request_regions(pdev, HINIC3_NIC_DRV_NAME);
 if (err) {
  dev_err(&pdev->dev, "Failed to request regions\n");
  goto err_disable_device;
 }

 pci_set_master(pdev);

 err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
 if (err) {
  dev_err(&pdev->dev, "Failed to set DMA mask\n");
  goto err_release_regions;
 }

 return 0;

err_release_regions:
 pci_clear_master(pdev);
 pci_release_regions(pdev);

err_disable_device:
 pci_disable_device(pdev);

err_free_pci_adapter:
 pci_set_drvdata(pdev, NULL);
 mutex_destroy(&pci_adapter->pdev_mutex);
 kfree(pci_adapter);

 return err;
}

static void hinic3_pci_uninit(struct pci_dev *pdev)
{
 struct hinic3_pcidev *pci_adapter = pci_get_drvdata(pdev);

 pci_clear_master(pdev);
 pci_release_regions(pdev);
 pci_disable_device(pdev);
 pci_set_drvdata(pdev, NULL);
 mutex_destroy(&pci_adapter->pdev_mutex);
 kfree(pci_adapter);
}

static int hinic3_func_init(struct pci_dev *pdev,
       struct hinic3_pcidev *pci_adapter)
{
 int err;

 err = hinic3_init_hwdev(pdev);
 if (err) {
  dev_err(&pdev->dev, "Failed to initialize hardware device\n");
  return err;
 }

 err = hinic3_attach_aux_devices(pci_adapter->hwdev);
 if (err)
  goto err_free_hwdev;

 return 0;

err_free_hwdev:
 hinic3_free_hwdev(pci_adapter->hwdev);

 return err;
}

static void hinic3_func_uninit(struct pci_dev *pdev)
{
 struct hinic3_pcidev *pci_adapter = pci_get_drvdata(pdev);

 hinic3_detach_aux_devices(pci_adapter->hwdev);
 hinic3_free_hwdev(pci_adapter->hwdev);
}

static int hinic3_probe_func(struct hinic3_pcidev *pci_adapter)
{
 struct pci_dev *pdev = pci_adapter->pdev;
 int err;

 err = hinic3_mapping_bar(pdev, pci_adapter);
 if (err) {
  dev_err(&pdev->dev, "Failed to map bar\n");
  goto err_out;
 }

 err = hinic3_func_init(pdev, pci_adapter);
 if (err)
  goto err_unmap_bar;

 return 0;

err_unmap_bar:
 hinic3_unmapping_bar(pci_adapter);

err_out:
 dev_err(&pdev->dev, "PCIe device probe function failed\n");
 return err;
}

static void hinic3_remove_func(struct hinic3_pcidev *pci_adapter)
{
 struct pci_dev *pdev = pci_adapter->pdev;

 hinic3_func_uninit(pdev);
 hinic3_unmapping_bar(pci_adapter);
}

static int hinic3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
 struct hinic3_pcidev *pci_adapter;
 int err;

 err = hinic3_pci_init(pdev);
 if (err)
  goto err_out;

 pci_adapter = pci_get_drvdata(pdev);
 err = hinic3_probe_func(pci_adapter);
 if (err)
  goto err_uninit_pci;

 return 0;

err_uninit_pci:
 hinic3_pci_uninit(pdev);

err_out:
 dev_err(&pdev->dev, "PCIe device probe failed\n");
 return err;
}

static void hinic3_remove(struct pci_dev *pdev)
{
 struct hinic3_pcidev *pci_adapter = pci_get_drvdata(pdev);

 hinic3_remove_func(pci_adapter);
 hinic3_pci_uninit(pdev);
}

static const struct pci_device_id hinic3_pci_table[] = {
 /* Completed by later submission due to LoC limit. */
 {0, 0}

};

MODULE_DEVICE_TABLE(pci, hinic3_pci_table);

static void hinic3_shutdown(struct pci_dev *pdev)
{
 struct hinic3_pcidev *pci_adapter = pci_get_drvdata(pdev);

 pci_disable_device(pdev);

 if (pci_adapter)
  hinic3_set_api_stop(pci_adapter->hwdev);
}

static struct pci_driver hinic3_driver = {
 .name            = HINIC3_NIC_DRV_NAME,
 .id_table        = hinic3_pci_table,
 .probe           = hinic3_probe,
 .remove          = hinic3_remove,
 .shutdown        = hinic3_shutdown,
 .sriov_configure = pci_sriov_configure_simple
};

int hinic3_lld_init(void)
{
 return pci_register_driver(&hinic3_driver);
}

void hinic3_lld_exit(void)
{
 pci_unregister_driver(&hinic3_driver);
}

[Dauer der Verarbeitung: 0.9 Sekunden]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Statistik
#Sources=1127926
#Domains=2039723