Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

dibs: Register ism as dibs device

Register ism devices with the dibs layer. Follow-on patches will move
functionality to the dibs layer.

As DIBS is only a shim layer without any dependencies, we can depend ISM
on DIBS without adding indirect dependencies. A follow-on patch will
remove implication of SMC by ISM.

Define struct dibs_dev. Follow-on patches will move more content into
dibs_dev. The goal of follow-on patches is that ism_dev will only
contain fields that are special for this device driver. The same concept
will apply to other dibs device drivers.

Define dibs_dev_alloc(), dibs_dev_add() and dibs_dev_del() to be called
by dibs device drivers and call them from ism_drv.c
Use ism_dev.dibs for a pointer to dibs_dev.

Signed-off-by: Alexandra Winter <wintera@linux.ibm.com>
Link: https://patch.msgid.link/20250918110500.1731261-6-wintera@linux.ibm.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Alexandra Winter and committed by
Paolo Abeni
26972696 d324a2ca

+131 -32
+38
drivers/dibs/dibs_main.c
··· 11 11 12 12 #include <linux/module.h> 13 13 #include <linux/types.h> 14 + #include <linux/slab.h> 14 15 #include <linux/err.h> 15 16 #include <linux/dibs.h> 16 17 ··· 22 21 static struct dibs_client *clients[MAX_DIBS_CLIENTS]; 23 22 static u8 max_client; 24 23 static DEFINE_MUTEX(clients_lock); 24 + struct dibs_dev_list { 25 + struct list_head list; 26 + struct mutex mutex; /* protects dibs device list */ 27 + }; 28 + 29 + static struct dibs_dev_list dibs_dev_list = { 30 + .list = LIST_HEAD_INIT(dibs_dev_list.list), 31 + .mutex = __MUTEX_INITIALIZER(dibs_dev_list.mutex), 32 + }; 25 33 26 34 int dibs_register_client(struct dibs_client *client) 27 35 { ··· 65 55 return rc; 66 56 } 67 57 EXPORT_SYMBOL_GPL(dibs_unregister_client); 58 + 59 + struct dibs_dev *dibs_dev_alloc(void) 60 + { 61 + struct dibs_dev *dibs; 62 + 63 + dibs = kzalloc(sizeof(*dibs), GFP_KERNEL); 64 + 65 + return dibs; 66 + } 67 + EXPORT_SYMBOL_GPL(dibs_dev_alloc); 68 + 69 + int dibs_dev_add(struct dibs_dev *dibs) 70 + { 71 + mutex_lock(&dibs_dev_list.mutex); 72 + list_add(&dibs->list, &dibs_dev_list.list); 73 + mutex_unlock(&dibs_dev_list.mutex); 74 + 75 + return 0; 76 + } 77 + EXPORT_SYMBOL_GPL(dibs_dev_add); 78 + 79 + void dibs_dev_del(struct dibs_dev *dibs) 80 + { 81 + mutex_lock(&dibs_dev_list.mutex); 82 + list_del_init(&dibs->list); 83 + mutex_unlock(&dibs_dev_list.mutex); 84 + } 85 + EXPORT_SYMBOL_GPL(dibs_dev_del); 68 86 69 87 static int __init dibs_init(void) 70 88 {
+1 -1
drivers/s390/net/Kconfig
··· 81 81 82 82 config ISM 83 83 tristate "Support for ISM vPCI Adapter" 84 - depends on PCI 84 + depends on PCI && DIBS 85 85 imply SMC 86 86 default n 87 87 help
+1
drivers/s390/net/ism.h
··· 5 5 #include <linux/spinlock.h> 6 6 #include <linux/types.h> 7 7 #include <linux/pci.h> 8 + #include <linux/dibs.h> 8 9 #include <linux/ism.h> 9 10 #include <net/smc.h> 10 11 #include <asm/pci_insn.h>
+52 -31
drivers/s390/net/ism_drv.c
··· 599 599 kfree(ism); 600 600 } 601 601 602 + static void ism_dev_exit(struct ism_dev *ism) 603 + { 604 + struct pci_dev *pdev = ism->pdev; 605 + unsigned long flags; 606 + int i; 607 + 608 + spin_lock_irqsave(&ism->lock, flags); 609 + for (i = 0; i < max_client; ++i) 610 + ism->subs[i] = NULL; 611 + spin_unlock_irqrestore(&ism->lock, flags); 612 + 613 + mutex_lock(&ism_dev_list.mutex); 614 + mutex_lock(&clients_lock); 615 + for (i = 0; i < max_client; ++i) { 616 + if (clients[i]) 617 + clients[i]->remove(ism); 618 + } 619 + mutex_unlock(&clients_lock); 620 + 621 + if (ism_v2_capable) 622 + ism_del_vlan_id(ism, ISM_RESERVED_VLANID); 623 + unregister_ieq(ism); 624 + unregister_sba(ism); 625 + free_irq(pci_irq_vector(pdev, 0), ism); 626 + kfree(ism->sba_client_arr); 627 + pci_free_irq_vectors(pdev); 628 + list_del_init(&ism->list); 629 + mutex_unlock(&ism_dev_list.mutex); 630 + } 631 + 602 632 static int ism_probe(struct pci_dev *pdev, const struct pci_device_id *id) 603 633 { 634 + struct dibs_dev *dibs; 604 635 struct ism_dev *ism; 605 636 int ret; 606 637 ··· 667 636 dma_set_max_seg_size(&pdev->dev, SZ_1M); 668 637 pci_set_master(pdev); 669 638 639 + dibs = dibs_dev_alloc(); 640 + if (!dibs) { 641 + ret = -ENOMEM; 642 + goto err_resource; 643 + } 644 + ism->dibs = dibs; 645 + 670 646 ret = ism_dev_init(ism); 671 647 if (ret) 672 - goto err_resource; 648 + goto err_dibs; 649 + 650 + ret = dibs_dev_add(dibs); 651 + if (ret) 652 + goto err_ism; 673 653 674 654 return 0; 675 655 656 + err_ism: 657 + ism_dev_exit(ism); 658 + err_dibs: 659 + /* pairs with dibs_dev_alloc() */ 660 + kfree(dibs); 676 661 err_resource: 677 662 pci_release_mem_regions(pdev); 678 663 err_disable: ··· 702 655 return ret; 703 656 } 704 657 705 - static void ism_dev_exit(struct ism_dev *ism) 706 - { 707 - struct pci_dev *pdev = ism->pdev; 708 - unsigned long flags; 709 - int i; 710 - 711 - spin_lock_irqsave(&ism->lock, flags); 712 - for (i = 0; i < max_client; ++i) 713 - ism->subs[i] = NULL; 714 - spin_unlock_irqrestore(&ism->lock, flags); 715 - 716 - mutex_lock(&ism_dev_list.mutex); 717 - mutex_lock(&clients_lock); 718 - for (i = 0; i < max_client; ++i) { 719 - if (clients[i]) 720 - clients[i]->remove(ism); 721 - } 722 - mutex_unlock(&clients_lock); 723 - 724 - if (ism_v2_capable) 725 - ism_del_vlan_id(ism, ISM_RESERVED_VLANID); 726 - unregister_ieq(ism); 727 - unregister_sba(ism); 728 - free_irq(pci_irq_vector(pdev, 0), ism); 729 - kfree(ism->sba_client_arr); 730 - pci_free_irq_vectors(pdev); 731 - list_del_init(&ism->list); 732 - mutex_unlock(&ism_dev_list.mutex); 733 - } 734 - 735 658 static void ism_remove(struct pci_dev *pdev) 736 659 { 737 660 struct ism_dev *ism = dev_get_drvdata(&pdev->dev); 661 + struct dibs_dev *dibs = ism->dibs; 738 662 663 + dibs_dev_del(dibs); 739 664 ism_dev_exit(ism); 665 + /* pairs with dibs_dev_alloc() */ 666 + kfree(dibs); 740 667 741 668 pci_release_mem_regions(pdev); 742 669 pci_disable_device(pdev);
+38
include/linux/dibs.h
··· 9 9 #ifndef _DIBS_H 10 10 #define _DIBS_H 11 11 12 + #include <linux/device.h> 12 13 /* DIBS - Direct Internal Buffer Sharing - concept 13 14 * ----------------------------------------------- 14 15 * In the case of multiple system sharing the same hardware, dibs fabrics can ··· 62 61 * Return: zero on success. 63 62 */ 64 63 int dibs_unregister_client(struct dibs_client *client); 64 + 65 + /* DIBS devices 66 + * ------------ 67 + */ 68 + struct dibs_dev { 69 + struct list_head list; 70 + }; 71 + 72 + /* ------- End of client-only functions ----------- */ 73 + 74 + /* 75 + * Functions to be called by dibs device drivers: 76 + */ 77 + /** 78 + * dibs_dev_alloc() - allocate and reference device structure 79 + * 80 + * The following fields will be valid upon successful return: dev 81 + * NOTE: Use put_device(dibs_get_dev(@dibs)) to give up your reference instead 82 + * of freeing @dibs @dev directly once you have successfully called this 83 + * function. 84 + * Return: Pointer to dibs device structure 85 + */ 86 + struct dibs_dev *dibs_dev_alloc(void); 87 + /** 88 + * dibs_dev_add() - register with dibs layer and all clients 89 + * @dibs: dibs device 90 + * 91 + * The following fields must be valid upon entry: dev, ops, drv_priv 92 + * All fields will be valid upon successful return. 93 + * Return: zero on success 94 + */ 95 + int dibs_dev_add(struct dibs_dev *dibs); 96 + /** 97 + * dibs_dev_del() - unregister from dibs layer and all clients 98 + * @dibs: dibs device 99 + */ 100 + void dibs_dev_del(struct dibs_dev *dibs); 65 101 66 102 #endif /* _DIBS_H */
+1
include/linux/ism.h
··· 30 30 spinlock_t lock; /* protects the ism device */ 31 31 spinlock_t cmd_lock; /* serializes cmds */ 32 32 struct list_head list; 33 + struct dibs_dev *dibs; 33 34 struct pci_dev *pdev; 34 35 35 36 struct ism_sba *sba;