1 #include <linux/module.h>
2 #include <linux/interrupt.h>
4 #include <linux/slab.h>
5 #include <scsc/scsc_logring.h>
6 #include "pcie_mif_module.h"
10 #include "scsc_mif_abs.h"
13 struct list_head list
;
14 struct scsc_mif_abs
*mif_abs
;
17 struct mif_driver_node
{
18 struct list_head list
;
19 struct scsc_mif_abs_driver
*driver
; /* list of drivers (in practice just the core_module) */
22 struct mif_mmap_node
{
23 struct list_head list
;
24 struct scsc_mif_mmap_driver
*driver
; /* list of drivers (in practive just the core_module) */
27 static struct pcie_mif_module
{
28 struct list_head mif_abs_list
;
29 struct list_head mif_driver_list
;
30 struct list_head mif_mmap_list
;
32 .mif_abs_list
= LIST_HEAD_INIT(mif_module
.mif_abs_list
),
33 .mif_driver_list
= LIST_HEAD_INIT(mif_module
.mif_driver_list
),
34 .mif_mmap_list
= LIST_HEAD_INIT(mif_module
.mif_mmap_list
),
38 static const struct pci_device_id pcie_mif_module_tbl
[] = {
39 { PCI_DEVICE(PCI_VENDOR_ID_XILINX
, PCI_DEVICE_ID_SAMSUNG_SCSC
) },
40 { /*End: all zeroes */ }
43 MODULE_DEVICE_TABLE(pci
, pcie_mif_module_tbl
);
45 static void pcie_mif_module_probe_registered_clients(struct scsc_mif_abs
*mif_abs
)
47 struct mif_driver_node
*mif_driver_node
, *next
;
49 bool driver_registered
= false;
51 /* Traverse Linked List for each mif_driver node */
52 list_for_each_entry_safe(mif_driver_node
, next
, &mif_module
.mif_driver_list
, list
) {
53 SCSC_TAG_INFO(PCIE_MIF
, "node %p\n", mif_driver_node
);
55 dev
= pcie_mif_get_dev(mif_abs
);
56 mif_driver_node
->driver
->probe(mif_driver_node
->driver
, mif_abs
);
57 driver_registered
= true;
59 if (driver_registered
== false)
60 SCSC_TAG_INFO(PCIE_MIF
, "No mif drivers registered\n");
63 static int pcie_mif_module_probe(struct pci_dev
*pdev
, const struct pci_device_id
*id
)
65 struct mif_abs_node
*mif_node
;
66 struct scsc_mif_abs
*mif_abs
;
68 mif_node
= kzalloc(sizeof(*mif_node
), GFP_KERNEL
);
72 mif_abs
= pcie_mif_create(pdev
, id
);
74 SCSC_TAG_INFO(PCIE_MIF
, "Error creating PCIe interface\n");
79 mif_node
->mif_abs
= mif_abs
;
80 SCSC_TAG_INFO(PCIE_MIF
, "mif_node A %p\n", mif_node
);
81 list_add_tail(&mif_node
->list
, &mif_module
.mif_abs_list
);
83 pcie_mif_module_probe_registered_clients(mif_abs
);
88 static void pcie_mif_module_remove(struct pci_dev
*pdev
)
90 struct mif_abs_node
*mif_node
, *next
;
94 list_for_each_entry_safe(mif_node
, next
, &mif_module
.mif_abs_list
, list
) {
95 if (pcie_mif_get_pci_dev(mif_node
->mif_abs
) == pdev
) {
97 SCSC_TAG_INFO(PCIE_MIF
, "Match, destroy pcie_mif\n");
98 pcie_mif_destroy_pcie(pdev
, mif_node
->mif_abs
);
99 list_del(&mif_node
->list
);
104 SCSC_TAG_INFO(PCIE_MIF
, "FATAL, no match for given scsc_mif_abs\n");
107 static struct pci_driver scsc_pcie
= {
109 .id_table
= pcie_mif_module_tbl
,
110 .probe
= pcie_mif_module_probe
,
111 .remove
= pcie_mif_module_remove
,
114 void scsc_mif_abs_register(struct scsc_mif_abs_driver
*driver
)
116 struct mif_driver_node
*mif_driver_node
;
117 struct mif_abs_node
*mif_node
;
120 /* Add node in driver linked list */
121 mif_driver_node
= kzalloc(sizeof(*mif_driver_node
), GFP_KERNEL
);
122 if (!mif_driver_node
)
125 mif_driver_node
->driver
= driver
;
126 list_add_tail(&mif_driver_node
->list
, &mif_module
.mif_driver_list
);
128 /* Traverse Linked List for each mif_abs node */
129 list_for_each_entry(mif_node
, &mif_module
.mif_abs_list
, list
) {
130 dev
= pcie_mif_get_dev(mif_node
->mif_abs
);
131 driver
->probe(driver
, mif_node
->mif_abs
);
134 EXPORT_SYMBOL(scsc_mif_abs_register
);
136 void scsc_mif_abs_unregister(struct scsc_mif_abs_driver
*driver
)
138 struct mif_driver_node
*mif_driver_node
, *next
;
140 /* Traverse Linked List for each mif_driver node */
141 list_for_each_entry_safe(mif_driver_node
, next
, &mif_module
.mif_driver_list
, list
) {
142 if (mif_driver_node
->driver
== driver
) {
143 list_del(&mif_driver_node
->list
);
144 kfree(mif_driver_node
);
148 EXPORT_SYMBOL(scsc_mif_abs_unregister
);
150 /* Register a mmap - debug driver - for this specific transport*/
151 void scsc_mif_mmap_register(struct scsc_mif_mmap_driver
*mmap_driver
)
153 struct mif_mmap_node
*mif_mmap_node
;
154 struct mif_abs_node
*mif_node
;
156 /* Add node in driver linked list */
157 mif_mmap_node
= kzalloc(sizeof(*mif_mmap_node
), GFP_KERNEL
);
161 mif_mmap_node
->driver
= mmap_driver
;
162 list_add_tail(&mif_mmap_node
->list
, &mif_module
.mif_mmap_list
);
164 /* Traverse Linked List for each mif_abs node */
165 list_for_each_entry(mif_node
, &mif_module
.mif_abs_list
, list
) {
166 mmap_driver
->probe(mmap_driver
, mif_node
->mif_abs
);
169 EXPORT_SYMBOL(scsc_mif_mmap_register
);
171 /* Unregister a mmap - debug driver - for this specific transport*/
172 void scsc_mif_mmap_unregister(struct scsc_mif_mmap_driver
*mmap_driver
)
174 struct mif_mmap_node
*mif_mmap_node
, *next
;
176 /* Traverse Linked List for each mif_mmap_driver node */
177 list_for_each_entry_safe(mif_mmap_node
, next
, &mif_module
.mif_mmap_list
, list
) {
178 if (mif_mmap_node
->driver
== mmap_driver
) {
179 list_del(&mif_mmap_node
->list
);
180 kfree(mif_mmap_node
);
184 EXPORT_SYMBOL(scsc_mif_mmap_unregister
);
186 module_pci_driver(scsc_pcie
);
188 MODULE_DESCRIPTION("SLSI PCIe mx140 MIF abstraction");
189 MODULE_AUTHOR("SLSI");
190 MODULE_LICENSE("GPL");