18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 28c2ecf20Sopenharmony_ci// Copyright 2019 IBM Corp. 38c2ecf20Sopenharmony_ci#include <linux/module.h> 48c2ecf20Sopenharmony_ci#include "ocxl_internal.h" 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci/* 78c2ecf20Sopenharmony_ci * Any opencapi device which wants to use this 'generic' driver should 88c2ecf20Sopenharmony_ci * use the 0x062B device ID. Vendors should define the subsystem 98c2ecf20Sopenharmony_ci * vendor/device ID to help differentiate devices. 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_cistatic const struct pci_device_id ocxl_pci_tbl[] = { 128c2ecf20Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_IBM, 0x062B), }, 138c2ecf20Sopenharmony_ci { } 148c2ecf20Sopenharmony_ci}; 158c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pci, ocxl_pci_tbl); 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_cistatic int ocxl_probe(struct pci_dev *dev, const struct pci_device_id *id) 188c2ecf20Sopenharmony_ci{ 198c2ecf20Sopenharmony_ci int rc; 208c2ecf20Sopenharmony_ci struct ocxl_afu *afu, *tmp; 218c2ecf20Sopenharmony_ci struct ocxl_fn *fn; 228c2ecf20Sopenharmony_ci struct list_head *afu_list; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci fn = ocxl_function_open(dev); 258c2ecf20Sopenharmony_ci if (IS_ERR(fn)) 268c2ecf20Sopenharmony_ci return PTR_ERR(fn); 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci pci_set_drvdata(dev, fn); 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci afu_list = ocxl_function_afu_list(fn); 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci list_for_each_entry_safe(afu, tmp, afu_list, list) { 338c2ecf20Sopenharmony_ci // Cleanup handled within ocxl_file_register_afu() 348c2ecf20Sopenharmony_ci rc = ocxl_file_register_afu(afu); 358c2ecf20Sopenharmony_ci if (rc) { 368c2ecf20Sopenharmony_ci dev_err(&dev->dev, "Failed to register AFU '%s' index %d", 378c2ecf20Sopenharmony_ci afu->config.name, afu->config.idx); 388c2ecf20Sopenharmony_ci } 398c2ecf20Sopenharmony_ci } 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci return 0; 428c2ecf20Sopenharmony_ci} 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_cistatic void ocxl_remove(struct pci_dev *dev) 458c2ecf20Sopenharmony_ci{ 468c2ecf20Sopenharmony_ci struct ocxl_fn *fn; 478c2ecf20Sopenharmony_ci struct ocxl_afu *afu; 488c2ecf20Sopenharmony_ci struct list_head *afu_list; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci fn = pci_get_drvdata(dev); 518c2ecf20Sopenharmony_ci afu_list = ocxl_function_afu_list(fn); 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci list_for_each_entry(afu, afu_list, list) { 548c2ecf20Sopenharmony_ci ocxl_file_unregister_afu(afu); 558c2ecf20Sopenharmony_ci } 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci ocxl_function_close(fn); 588c2ecf20Sopenharmony_ci} 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_cistruct pci_driver ocxl_pci_driver = { 618c2ecf20Sopenharmony_ci .name = "ocxl", 628c2ecf20Sopenharmony_ci .id_table = ocxl_pci_tbl, 638c2ecf20Sopenharmony_ci .probe = ocxl_probe, 648c2ecf20Sopenharmony_ci .remove = ocxl_remove, 658c2ecf20Sopenharmony_ci .shutdown = ocxl_remove, 668c2ecf20Sopenharmony_ci}; 67