// SPDX-License-Identifier: GPL-2.0+ 
 | 
// Copyright 2019 IBM Corp. 
 | 
#include <linux/module.h> 
 | 
#include "ocxl_internal.h" 
 | 
  
 | 
/* 
 | 
 * Any opencapi device which wants to use this 'generic' driver should 
 | 
 * use the 0x062B device ID. Vendors should define the subsystem 
 | 
 * vendor/device ID to help differentiate devices. 
 | 
 */ 
 | 
static const struct pci_device_id ocxl_pci_tbl[] = { 
 | 
    { PCI_DEVICE(PCI_VENDOR_ID_IBM, 0x062B), }, 
 | 
    { } 
 | 
}; 
 | 
MODULE_DEVICE_TABLE(pci, ocxl_pci_tbl); 
 | 
  
 | 
static int ocxl_probe(struct pci_dev *dev, const struct pci_device_id *id) 
 | 
{ 
 | 
    int rc; 
 | 
    struct ocxl_afu *afu, *tmp; 
 | 
    struct ocxl_fn *fn; 
 | 
    struct list_head *afu_list; 
 | 
  
 | 
    fn = ocxl_function_open(dev); 
 | 
    if (IS_ERR(fn)) 
 | 
        return PTR_ERR(fn); 
 | 
  
 | 
    pci_set_drvdata(dev, fn); 
 | 
  
 | 
    afu_list = ocxl_function_afu_list(fn); 
 | 
  
 | 
    list_for_each_entry_safe(afu, tmp, afu_list, list) { 
 | 
        // Cleanup handled within ocxl_file_register_afu() 
 | 
        rc = ocxl_file_register_afu(afu); 
 | 
        if (rc) { 
 | 
            dev_err(&dev->dev, "Failed to register AFU '%s' index %d", 
 | 
                    afu->config.name, afu->config.idx); 
 | 
        } 
 | 
    } 
 | 
  
 | 
    return 0; 
 | 
} 
 | 
  
 | 
static void ocxl_remove(struct pci_dev *dev) 
 | 
{ 
 | 
    struct ocxl_fn *fn; 
 | 
    struct ocxl_afu *afu; 
 | 
    struct list_head *afu_list; 
 | 
  
 | 
    fn = pci_get_drvdata(dev); 
 | 
    afu_list = ocxl_function_afu_list(fn); 
 | 
  
 | 
    list_for_each_entry(afu, afu_list, list) { 
 | 
        ocxl_file_unregister_afu(afu); 
 | 
    } 
 | 
  
 | 
    ocxl_function_close(fn); 
 | 
} 
 | 
  
 | 
struct pci_driver ocxl_pci_driver = { 
 | 
    .name = "ocxl", 
 | 
    .id_table = ocxl_pci_tbl, 
 | 
    .probe = ocxl_probe, 
 | 
    .remove = ocxl_remove, 
 | 
    .shutdown = ocxl_remove, 
 | 
}; 
 |